diff --git a/dll/win32/Irrlicht.dll b/dll/win32/Irrlicht.dll new file mode 100644 index 0000000..693a011 Binary files /dev/null and b/dll/win32/Irrlicht.dll differ diff --git a/dll/win64/Irrlicht.dll b/dll/win64/Irrlicht.dll new file mode 100644 index 0000000..fe69b31 Binary files /dev/null and b/dll/win64/Irrlicht.dll differ diff --git a/inc/CDynamicMeshBuffer.h b/inc/CDynamicMeshBuffer.h new file mode 100644 index 0000000..016af9c --- /dev/null +++ b/inc/CDynamicMeshBuffer.h @@ -0,0 +1,116 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_DYNAMIC_MESHBUFFER_H_INCLUDED__ +#define __C_DYNAMIC_MESHBUFFER_H_INCLUDED__ + +#include "IDynamicMeshBuffer.h" + +#include "CVertexBuffer.h" +#include "CIndexBuffer.h" + +namespace irr +{ +namespace scene +{ + + class CDynamicMeshBuffer: public IDynamicMeshBuffer + { + public: + //! constructor + CDynamicMeshBuffer(video::E_VERTEX_TYPE vertexType, video::E_INDEX_TYPE indexType) + { + VertexBuffer=new CVertexBuffer(vertexType); + IndexBuffer=new CIndexBuffer(indexType); + } + + //! destructor + virtual ~CDynamicMeshBuffer() + { + if (VertexBuffer) + VertexBuffer->drop(); + if (IndexBuffer) + IndexBuffer->drop(); + } + + virtual IVertexBuffer& getVertexBuffer() const + { + return *VertexBuffer; + } + + virtual IIndexBuffer& getIndexBuffer() const + { + return *IndexBuffer; + } + + virtual void setVertexBuffer(IVertexBuffer *newVertexBuffer) + { + if (newVertexBuffer) + newVertexBuffer->grab(); + if (VertexBuffer) + VertexBuffer->drop(); + + VertexBuffer=newVertexBuffer; + } + + virtual void setIndexBuffer(IIndexBuffer *newIndexBuffer) + { + if (newIndexBuffer) + newIndexBuffer->grab(); + if (IndexBuffer) + IndexBuffer->drop(); + + IndexBuffer=newIndexBuffer; + } + + //! Get Material of this buffer. + virtual const video::SMaterial& getMaterial() const + { + return Material; + } + + //! Get Material of this buffer. + virtual video::SMaterial& getMaterial() + { + return Material; + } + + //! Get bounding box + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + //! Set bounding box + virtual void setBoundingBox( const core::aabbox3df& box) + { + BoundingBox = box; + } + + //! Recalculate bounding box + virtual void recalculateBoundingBox() + { + if (!getVertexBuffer().size()) + BoundingBox.reset(0,0,0); + else + { + BoundingBox.reset(getVertexBuffer()[0].Pos); + for (u32 i=1; i BoundingBox; + private: + IVertexBuffer *VertexBuffer; + IIndexBuffer *IndexBuffer; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/CIndexBuffer.h b/inc/CIndexBuffer.h new file mode 100644 index 0000000..4ecadb7 --- /dev/null +++ b/inc/CIndexBuffer.h @@ -0,0 +1,226 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_INDEX_BUFFER_H_INCLUDED__ +#define __C_INDEX_BUFFER_H_INCLUDED__ + +#include "IIndexBuffer.h" + +namespace irr +{ +namespace scene +{ + + class CIndexBuffer : public IIndexBuffer + { + + class IIndexList + { + public: + virtual ~IIndexList(){}; + + virtual u32 stride() const =0; + virtual u32 size() const =0; + virtual void push_back(const u32 &element) =0; + virtual u32 operator [](u32 index) const =0; + virtual u32 getLast() =0; + virtual void setValue(u32 index, u32 value) =0; + virtual void set_used(u32 usedNow) =0; + virtual void reallocate(u32 new_size) =0; + virtual u32 allocated_size() const =0; + virtual void* pointer() =0; + virtual video::E_INDEX_TYPE getType() const =0; + }; + + template + class CSpecificIndexList : public IIndexList + { + public: + core::array Indices; + + virtual u32 stride() const {return sizeof(T);} + + virtual u32 size() const {return Indices.size();} + + virtual void push_back(const u32 &element) + { + // push const ref due to compiler problem with gcc 4.6, big endian + Indices.push_back((const T&)element); + } + + virtual u32 operator [](u32 index) const + { + return (u32)(Indices[index]); + } + + virtual u32 getLast() {return (u32)Indices.getLast();} + + virtual void setValue(u32 index, u32 value) + { + Indices[index]=(T)value; + } + + virtual void set_used(u32 usedNow) + { + Indices.set_used(usedNow); + } + + virtual void reallocate(u32 new_size) + { + Indices.reallocate(new_size); + } + + virtual u32 allocated_size() const + { + return Indices.allocated_size(); + } + + virtual void* pointer() {return Indices.pointer();} + + virtual video::E_INDEX_TYPE getType() const + { + if (sizeof(T)==sizeof(u16)) + return video::EIT_16BIT; + else + return video::EIT_32BIT; + } + }; + + public: + IIndexList *Indices; + + CIndexBuffer(video::E_INDEX_TYPE IndexType) :Indices(0), MappingHint(EHM_NEVER), ChangedID(1) + { + setType(IndexType); + } + + CIndexBuffer(const IIndexBuffer &IndexBufferCopy) :Indices(0), MappingHint(EHM_NEVER), ChangedID(1) + { + setType(IndexBufferCopy.getType()); + reallocate(IndexBufferCopy.size()); + + for (u32 n=0;n; + break; + } + case video::EIT_32BIT: + { + NewIndices=new CSpecificIndexList; + break; + } + } + + if (Indices) + { + NewIndices->reallocate( Indices->size() ); + + for(u32 n=0;nsize();++n) + NewIndices->push_back((*Indices)[n]); + + delete Indices; + } + + Indices=NewIndices; + } + + virtual void* getData() {return Indices->pointer();} + + virtual video::E_INDEX_TYPE getType() const {return Indices->getType();} + + virtual u32 stride() const {return Indices->stride();} + + virtual u32 size() const + { + return Indices->size(); + } + + virtual void push_back(const u32 &element) + { + Indices->push_back(element); + } + + virtual u32 operator [](u32 index) const + { + return (*Indices)[index]; + } + + virtual u32 getLast() + { + return Indices->getLast(); + } + + virtual void setValue(u32 index, u32 value) + { + Indices->setValue(index, value); + } + + virtual void set_used(u32 usedNow) + { + Indices->set_used(usedNow); + } + + virtual void reallocate(u32 new_size) + { + Indices->reallocate(new_size); + } + + virtual u32 allocated_size() const + { + return Indices->allocated_size(); + } + + virtual void* pointer() + { + return Indices->pointer(); + } + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint() const + { + return MappingHint; + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) + { + MappingHint=NewMappingHint; + } + + //! flags the mesh as changed, reloads hardware buffers + virtual void setDirty() + { + ++ChangedID; + } + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID() const {return ChangedID;} + + E_HARDWARE_MAPPING MappingHint; + u32 ChangedID; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/CMeshBuffer.h b/inc/CMeshBuffer.h new file mode 100644 index 0000000..24a95e2 --- /dev/null +++ b/inc/CMeshBuffer.h @@ -0,0 +1,301 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __T_MESH_BUFFER_H_INCLUDED__ +#define __T_MESH_BUFFER_H_INCLUDED__ + +#include "irrArray.h" +#include "IMeshBuffer.h" + +namespace irr +{ +namespace scene +{ + //! Template implementation of the IMeshBuffer interface + template + class CMeshBuffer : public IMeshBuffer + { + public: + //! Default constructor for empty meshbuffer + CMeshBuffer():ChangedID_Vertex(1),ChangedID_Index(1),MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER) + { + #ifdef _DEBUG + setDebugName("SMeshBuffer"); + #endif + } + + + //! Get material of this meshbuffer + /** \return Material of this buffer */ + virtual const video::SMaterial& getMaterial() const + { + return Material; + } + + + //! Get material of this meshbuffer + /** \return Material of this buffer */ + virtual video::SMaterial& getMaterial() + { + return Material; + } + + + //! Get pointer to vertices + /** \return Pointer to vertices. */ + virtual const void* getVertices() const + { + return Vertices.const_pointer(); + } + + + //! Get pointer to vertices + /** \return Pointer to vertices. */ + virtual void* getVertices() + { + return Vertices.pointer(); + } + + + //! Get number of vertices + /** \return Number of vertices. */ + virtual u32 getVertexCount() const + { + return Vertices.size(); + } + + //! Get type of index data which is stored in this meshbuffer. + /** \return Index type of this buffer. */ + virtual video::E_INDEX_TYPE getIndexType() const + { + return video::EIT_16BIT; + } + + //! Get pointer to indices + /** \return Pointer to indices. */ + virtual const u16* getIndices() const + { + return Indices.const_pointer(); + } + + + //! Get pointer to indices + /** \return Pointer to indices. */ + virtual u16* getIndices() + { + return Indices.pointer(); + } + + + //! Get number of indices + /** \return Number of indices. */ + virtual u32 getIndexCount() const + { + return Indices.size(); + } + + + //! Get the axis aligned bounding box + /** \return Axis aligned bounding box of this buffer. */ + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + + //! Set the axis aligned bounding box + /** \param box New axis aligned bounding box for this buffer. */ + //! set user axis aligned bounding box + virtual void setBoundingBox(const core::aabbox3df& box) + { + BoundingBox = box; + } + + + //! Recalculate the bounding box. + /** should be called if the mesh changed. */ + virtual void recalculateBoundingBox() + { + if (Vertices.empty()) + BoundingBox.reset(0,0,0); + else + { + BoundingBox.reset(Vertices[0].Pos); + for (u32 i=1; i(vertices)[i]); + BoundingBox.addInternalPoint(reinterpret_cast(vertices)[i].Pos); + } + + Indices.reallocate(getIndexCount()+numIndices); + for (i=0; igetVertexCount()); + for (i=0; igetVertexCount(); ++i) + { + Vertices.push_back(reinterpret_cast(other->getVertices())[i]); + } + + Indices.reallocate(getIndexCount()+other->getIndexCount()); + for (i=0; igetIndexCount(); ++i) + { + Indices.push_back(other->getIndices()[i]+vertexCount); + } + BoundingBox.addInternalBox(other->getBoundingBox()); + */ + } + + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const + { + return MappingHint_Vertex; + } + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const + { + return MappingHint_Index; + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX ) + { + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) + MappingHint_Vertex=NewMappingHint; + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) + MappingHint_Index=NewMappingHint; + } + + + //! flags the mesh as changed, reloads hardware buffers + virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) + { + if (Buffer==EBT_VERTEX_AND_INDEX ||Buffer==EBT_VERTEX) + ++ChangedID_Vertex; + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) + ++ChangedID_Index; + } + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID_Vertex() const {return ChangedID_Vertex;} + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID_Index() const {return ChangedID_Index;} + + u32 ChangedID_Vertex; + u32 ChangedID_Index; + + //! hardware mapping hint + E_HARDWARE_MAPPING MappingHint_Vertex; + E_HARDWARE_MAPPING MappingHint_Index; + + //! Material for this meshbuffer. + video::SMaterial Material; + //! Vertices of this buffer + core::array Vertices; + //! Indices into the vertices of this buffer. + core::array Indices; + //! Bounding box of this meshbuffer. + core::aabbox3d BoundingBox; + }; + + //! Standard meshbuffer + typedef CMeshBuffer SMeshBuffer; + //! Meshbuffer with two texture coords per vertex, e.g. for lightmaps + typedef CMeshBuffer SMeshBufferLightMap; + //! Meshbuffer with vertices having tangents stored, e.g. for normal mapping + typedef CMeshBuffer SMeshBufferTangents; +} // end namespace scene +} // end namespace irr + +#endif + + diff --git a/inc/CVertexBuffer.h b/inc/CVertexBuffer.h new file mode 100644 index 0000000..975b0e7 --- /dev/null +++ b/inc/CVertexBuffer.h @@ -0,0 +1,210 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_VERTEX_BUFFER_H_INCLUDED__ +#define __C_VERTEX_BUFFER_H_INCLUDED__ + +#include "IVertexBuffer.h" + + +namespace irr +{ +namespace scene +{ + + class CVertexBuffer : public IVertexBuffer + { + class IVertexList + { + public: + virtual ~IVertexList(){}; + + virtual u32 stride() const =0; + + virtual u32 size() const =0; + + virtual void push_back (const video::S3DVertex &element) =0; + virtual video::S3DVertex& operator [](const u32 index) const =0; + virtual video::S3DVertex& getLast() =0; + virtual void set_used(u32 usedNow) =0; + virtual void reallocate(u32 new_size) =0; + virtual u32 allocated_size() const =0; + virtual video::S3DVertex* pointer() =0; + virtual video::E_VERTEX_TYPE getType() const =0; + }; + + template + class CSpecificVertexList : public IVertexList + { + public: + core::array Vertices; + + virtual u32 stride() const {return sizeof(T);} + + virtual u32 size() const {return Vertices.size();} + + virtual void push_back (const video::S3DVertex &element) + {Vertices.push_back((T&)element);} + + virtual video::S3DVertex& operator [](const u32 index) const + {return (video::S3DVertex&)Vertices[index];} + + virtual video::S3DVertex& getLast() + {return (video::S3DVertex&)Vertices.getLast();} + + virtual void set_used(u32 usedNow) + {Vertices.set_used(usedNow);} + + virtual void reallocate(u32 new_size) + {Vertices.reallocate(new_size);} + + virtual u32 allocated_size() const + { + return Vertices.allocated_size(); + } + + virtual video::S3DVertex* pointer() {return Vertices.pointer();} + + virtual video::E_VERTEX_TYPE getType() const {return T().getType();} + }; + + public: + IVertexList *Vertices; + + CVertexBuffer(video::E_VERTEX_TYPE vertexType) : Vertices(0), + MappingHint(EHM_NEVER), ChangedID(1) + { + setType(vertexType); + } + + CVertexBuffer(const IVertexBuffer &VertexBufferCopy) : + Vertices(0), MappingHint(EHM_NEVER), + ChangedID(1) + { + setType(VertexBufferCopy.getType()); + reallocate(VertexBufferCopy.size()); + + for (u32 n=0;n; + break; + } + case video::EVT_2TCOORDS: + { + NewVertices=new CSpecificVertexList; + break; + } + case video::EVT_TANGENTS: + { + NewVertices=new CSpecificVertexList; + break; + } + } + if (Vertices) + { + NewVertices->reallocate( Vertices->size() ); + + for(u32 n=0;nsize();++n) + NewVertices->push_back((*Vertices)[n]); + + delete Vertices; + } + + Vertices=NewVertices; + } + + virtual void* getData() {return Vertices->pointer();} + + virtual video::E_VERTEX_TYPE getType() const {return Vertices->getType();} + + virtual u32 stride() const {return Vertices->stride();} + + virtual u32 size() const + { + return Vertices->size(); + } + + virtual void push_back (const video::S3DVertex &element) + { + Vertices->push_back(element); + } + + virtual video::S3DVertex& operator [](const u32 index) const + { + return (*Vertices)[index]; + } + + virtual video::S3DVertex& getLast() + { + return Vertices->getLast(); + } + + virtual void set_used(u32 usedNow) + { + Vertices->set_used(usedNow); + } + + virtual void reallocate(u32 new_size) + { + Vertices->reallocate(new_size); + } + + virtual u32 allocated_size() const + { + return Vertices->allocated_size(); + } + + virtual video::S3DVertex* pointer() + { + return Vertices->pointer(); + } + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint() const + { + return MappingHint; + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) + { + MappingHint=NewMappingHint; + } + + //! flags the mesh as changed, reloads hardware buffers + virtual void setDirty() + { + ++ChangedID; + } + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID() const {return ChangedID;} + + E_HARDWARE_MAPPING MappingHint; + u32 ChangedID; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/EAttributes.h b/inc/EAttributes.h new file mode 100644 index 0000000..121b6b3 --- /dev/null +++ b/inc/EAttributes.h @@ -0,0 +1,101 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_ATTRIBUTES_H_INCLUDED__ +#define __E_ATTRIBUTES_H_INCLUDED__ + +namespace irr +{ +namespace io +{ + +//! Types of attributes available for IAttributes +enum E_ATTRIBUTE_TYPE +{ + // integer attribute + EAT_INT = 0, + + // float attribute + EAT_FLOAT, + + // string attribute + EAT_STRING, + + // boolean attribute + EAT_BOOL, + + // enumeration attribute + EAT_ENUM, + + // color attribute + EAT_COLOR, + + // floating point color attribute + EAT_COLORF, + + // 3d vector attribute + EAT_VECTOR3D, + + // 2d position attribute + EAT_POSITION2D, + + // vector 2d attribute + EAT_VECTOR2D, + + // rectangle attribute + EAT_RECT, + + // matrix attribute + EAT_MATRIX, + + // quaternion attribute + EAT_QUATERNION, + + // 3d bounding box + EAT_BBOX, + + // plane + EAT_PLANE, + + // 3d triangle + EAT_TRIANGLE3D, + + // line 2d + EAT_LINE2D, + + // line 3d + EAT_LINE3D, + + // array of stringws attribute + EAT_STRINGWARRAY, + + // array of float + EAT_FLOATARRAY, + + // array of int + EAT_INTARRAY, + + // binary data attribute + EAT_BINARY, + + // texture reference attribute + EAT_TEXTURE, + + // user pointer void* + EAT_USER_POINTER, + + // dimension attribute + EAT_DIMENSION2D, + + // known attribute type count + EAT_COUNT, + + // unknown attribute + EAT_UNKNOWN +}; + +} // end namespace io +} // end namespace irr + +#endif diff --git a/inc/ECullingTypes.h b/inc/ECullingTypes.h new file mode 100644 index 0000000..7178c05 --- /dev/null +++ b/inc/ECullingTypes.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_CULLING_TYPES_H_INCLUDED__ +#define __E_CULLING_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace scene +{ + + //! An enumeration for all types of automatic culling for built-in scene nodes + enum E_CULLING_TYPE + { + EAC_OFF = 0, + EAC_BOX = 1, + EAC_FRUSTUM_BOX = 2, + EAC_FRUSTUM_SPHERE = 4, + EAC_OCC_QUERY = 8 + }; + + //! Names for culling type + const c8* const AutomaticCullingNames[] = + { + "false", + "box", // camera box against node box + "frustum_box", // camera frustum against node box + "frustum_sphere", // camera frustum against node sphere + "occ_query", // occlusion query + 0 + }; + +} // end namespace scene +} // end namespace irr + + +#endif // __E_CULLING_TYPES_H_INCLUDED__ + diff --git a/inc/EDebugSceneTypes.h b/inc/EDebugSceneTypes.h new file mode 100644 index 0000000..64ebcaa --- /dev/null +++ b/inc/EDebugSceneTypes.h @@ -0,0 +1,50 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DEBUG_SCENE_TYPES_H_INCLUDED__ +#define __E_DEBUG_SCENE_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + //! An enumeration for all types of debug data for built-in scene nodes (flags) + enum E_DEBUG_SCENE_TYPE + { + //! No Debug Data ( Default ) + EDS_OFF = 0, + + //! Show Bounding Boxes of SceneNode + EDS_BBOX = 1, + + //! Show Vertex Normals + EDS_NORMALS = 2, + + //! Shows Skeleton/Tags + EDS_SKELETON = 4, + + //! Overlays Mesh Wireframe + EDS_MESH_WIRE_OVERLAY = 8, + + //! Temporary use transparency Material Type + EDS_HALF_TRANSPARENCY = 16, + + //! Show Bounding Boxes of all MeshBuffers + EDS_BBOX_BUFFERS = 32, + + //! EDS_BBOX | EDS_BBOX_BUFFERS + EDS_BBOX_ALL = EDS_BBOX | EDS_BBOX_BUFFERS, + + //! Show all debug infos + EDS_FULL = 0xffffffff + }; + + +} // end namespace scene +} // end namespace irr + + +#endif // __E_DEBUG_SCENE_TYPES_H_INCLUDED__ + diff --git a/inc/EDeviceTypes.h b/inc/EDeviceTypes.h new file mode 100644 index 0000000..d7e9627 --- /dev/null +++ b/inc/EDeviceTypes.h @@ -0,0 +1,60 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DEVICE_TYPES_H_INCLUDED__ +#define __E_DEVICE_TYPES_H_INCLUDED__ + +namespace irr +{ + + //! An enum for the different device types supported by the Irrlicht Engine. + enum E_DEVICE_TYPE + { + + //! A device native to Microsoft Windows + /** This device uses the Win32 API and works in all versions of Windows. */ + EIDT_WIN32, + + //! A device native to Windows CE devices + /** This device works on Windows Mobile, Pocket PC and Microsoft SmartPhone devices */ + EIDT_WINCE, + + //! A device native to Unix style operating systems. + /** This device uses the X11 windowing system and works in Linux, Solaris, FreeBSD, OSX and + other operating systems which support X11. */ + EIDT_X11, + + //! A device native to Mac OSX + /** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */ + EIDT_OSX, + + //! A device which uses Simple DirectMedia Layer + /** The SDL device works under all platforms supported by SDL but first must be compiled + in by defining the IRR_USE_SDL_DEVICE macro in IrrCompileConfig.h */ + EIDT_SDL, + + //! A device for raw framebuffer access + /** Best used with embedded devices and mobile systems. + Does not need X11 or other graphical subsystems. + May support hw-acceleration via OpenGL-ES for FBDirect */ + EIDT_FRAMEBUFFER, + + //! A simple text only device supported by all platforms. + /** This device allows applications to run from the command line without opening a window. + It can render the output of the software drivers to the console as ASCII. It only supports + mouse and keyboard in Windows operating systems. */ + EIDT_CONSOLE, + + //! This selection allows Irrlicht to choose the best device from the ones available. + /** If this selection is chosen then Irrlicht will try to use the IrrlichtDevice native + to your operating system. If this is unavailable then the X11, SDL and then console device + will be tried. This ensures that Irrlicht will run even if your platform is unsupported, + although it may not be able to render anything. */ + EIDT_BEST + }; + +} // end namespace irr + +#endif // __E_DEVICE_TYPES_H_INCLUDED__ + diff --git a/inc/EDriverFeatures.h b/inc/EDriverFeatures.h new file mode 100644 index 0000000..931314e --- /dev/null +++ b/inc/EDriverFeatures.h @@ -0,0 +1,133 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DRIVER_FEATURES_H_INCLUDED__ +#define __E_DRIVER_FEATURES_H_INCLUDED__ + +namespace irr +{ +namespace video +{ + + //! enumeration for querying features of the video driver. + enum E_VIDEO_DRIVER_FEATURE + { + //! Is driver able to render to a surface? + EVDF_RENDER_TO_TARGET = 0, + + //! Is hardeware transform and lighting supported? + EVDF_HARDWARE_TL, + + //! Are multiple textures per material possible? + EVDF_MULTITEXTURE, + + //! Is driver able to render with a bilinear filter applied? + EVDF_BILINEAR_FILTER, + + //! Can the driver handle mip maps? + EVDF_MIP_MAP, + + //! Can the driver update mip maps automatically? + EVDF_MIP_MAP_AUTO_UPDATE, + + //! Are stencilbuffers switched on and does the device support stencil buffers? + EVDF_STENCIL_BUFFER, + + //! Is Vertex Shader 1.1 supported? + EVDF_VERTEX_SHADER_1_1, + + //! Is Vertex Shader 2.0 supported? + EVDF_VERTEX_SHADER_2_0, + + //! Is Vertex Shader 3.0 supported? + EVDF_VERTEX_SHADER_3_0, + + //! Is Pixel Shader 1.1 supported? + EVDF_PIXEL_SHADER_1_1, + + //! Is Pixel Shader 1.2 supported? + EVDF_PIXEL_SHADER_1_2, + + //! Is Pixel Shader 1.3 supported? + EVDF_PIXEL_SHADER_1_3, + + //! Is Pixel Shader 1.4 supported? + EVDF_PIXEL_SHADER_1_4, + + //! Is Pixel Shader 2.0 supported? + EVDF_PIXEL_SHADER_2_0, + + //! Is Pixel Shader 3.0 supported? + EVDF_PIXEL_SHADER_3_0, + + //! Are ARB vertex programs v1.0 supported? + EVDF_ARB_VERTEX_PROGRAM_1, + + //! Are ARB fragment programs v1.0 supported? + EVDF_ARB_FRAGMENT_PROGRAM_1, + + //! Is GLSL supported? + EVDF_ARB_GLSL, + + //! Is HLSL supported? + EVDF_HLSL, + + //! Are non-square textures supported? + EVDF_TEXTURE_NSQUARE, + + //! Are non-power-of-two textures supported? + EVDF_TEXTURE_NPOT, + + //! Are framebuffer objects supported? + EVDF_FRAMEBUFFER_OBJECT, + + //! Are vertex buffer objects supported? + EVDF_VERTEX_BUFFER_OBJECT, + + //! Supports Alpha To Coverage + EVDF_ALPHA_TO_COVERAGE, + + //! Supports Color masks (disabling color planes in output) + EVDF_COLOR_MASK, + + //! Supports multiple render targets at once + EVDF_MULTIPLE_RENDER_TARGETS, + + //! Supports separate blend settings for multiple render targets + EVDF_MRT_BLEND, + + //! Supports separate color masks for multiple render targets + EVDF_MRT_COLOR_MASK, + + //! Supports separate blend functions for multiple render targets + EVDF_MRT_BLEND_FUNC, + + //! Supports geometry shaders + EVDF_GEOMETRY_SHADER, + + //! Supports occlusion queries + EVDF_OCCLUSION_QUERY, + + //! Supports polygon offset/depth bias for avoiding z-fighting + EVDF_POLYGON_OFFSET, + + //! Support for different blend functions. Without, only ADD is available + EVDF_BLEND_OPERATIONS, + + //! Support for texture coord transformation via texture matrix + EVDF_TEXTURE_MATRIX, + + //! Support for NVidia's CG shader language + EVDF_CG, + + //! Only used for counting the elements of this enum + EVDF_COUNT + }; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/inc/EDriverTypes.h b/inc/EDriverTypes.h new file mode 100644 index 0000000..609e261 --- /dev/null +++ b/inc/EDriverTypes.h @@ -0,0 +1,64 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DRIVER_TYPES_H_INCLUDED__ +#define __E_DRIVER_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace video +{ + + //! An enum for all types of drivers the Irrlicht Engine supports. + enum E_DRIVER_TYPE + { + //! Null driver, useful for applications to run the engine without visualisation. + /** The null device is able to load textures, but does not + render and display any graphics. */ + EDT_NULL, + + //! The Irrlicht Engine Software renderer. + /** Runs on all platforms, with every hardware. It should only + be used for 2d graphics, but it can also perform some primitive + 3d functions. These 3d drawing functions are quite fast, but + very inaccurate, and don't even support clipping in 3D mode. */ + EDT_SOFTWARE, + + //! The Burning's Software Renderer, an alternative software renderer + /** Basically it can be described as the Irrlicht Software + renderer on steroids. It rasterizes 3D geometry perfectly: It + is able to perform correct 3d clipping, perspective correct + texture mapping, perspective correct color mapping, and renders + sub pixel correct, sub texel correct primitives. In addition, + it does bilinear texel filtering and supports more materials + than the EDT_SOFTWARE driver. This renderer has been written + entirely by Thomas Alten, thanks a lot for this huge + contribution. */ + EDT_BURNINGSVIDEO, + + //! Direct3D8 device, only available on Win32 platforms. + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ + EDT_DIRECT3D8, + + //! Direct3D 9 device, only available on Win32 platforms. + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ + EDT_DIRECT3D9, + + //! OpenGL device, available on most platforms. + /** Performs hardware accelerated rendering of 3D and 2D + primitives. */ + EDT_OPENGL, + + //! No driver, just for counting the elements + EDT_COUNT + }; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/inc/EGUIAlignment.h b/inc/EGUIAlignment.h new file mode 100644 index 0000000..d4caeea --- /dev/null +++ b/inc/EGUIAlignment.h @@ -0,0 +1,38 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_GUI_ALIGNMENT_H_INCLUDED__ +#define __E_GUI_ALIGNMENT_H_INCLUDED__ + +namespace irr +{ +namespace gui +{ +enum EGUI_ALIGNMENT +{ + //! Aligned to parent's top or left side (default) + EGUIA_UPPERLEFT=0, + //! Aligned to parent's bottom or right side + EGUIA_LOWERRIGHT, + //! Aligned to the center of parent + EGUIA_CENTER, + //! Stretched to fit parent + EGUIA_SCALE +}; + +//! Names for alignments +const c8* const GUIAlignmentNames[] = +{ + "upperLeft", + "lowerRight", + "center", + "scale", + 0 +}; + +} // namespace gui +} // namespace irr + +#endif // __E_GUI_ALIGNMENT_H_INCLUDED__ + diff --git a/inc/EGUIElementTypes.h b/inc/EGUIElementTypes.h new file mode 100644 index 0000000..aace9e1 --- /dev/null +++ b/inc/EGUIElementTypes.h @@ -0,0 +1,140 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_GUI_ELEMENT_TYPES_H_INCLUDED__ +#define __E_GUI_ELEMENT_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace gui +{ + +//! List of all basic Irrlicht GUI elements. +/** An IGUIElement returns this when calling IGUIElement::getType(); */ +enum EGUI_ELEMENT_TYPE +{ + //! A button (IGUIButton) + EGUIET_BUTTON = 0, + + //! A check box (IGUICheckBox) + EGUIET_CHECK_BOX, + + //! A combo box (IGUIComboBox) + EGUIET_COMBO_BOX, + + //! A context menu (IGUIContextMenu) + EGUIET_CONTEXT_MENU, + + //! A menu (IGUIMenu) + EGUIET_MENU, + + //! An edit box (IGUIEditBox) + EGUIET_EDIT_BOX, + + //! A file open dialog (IGUIFileOpenDialog) + EGUIET_FILE_OPEN_DIALOG, + + //! A color select open dialog (IGUIColorSelectDialog) + EGUIET_COLOR_SELECT_DIALOG, + + //! A in/out fader (IGUIInOutFader) + EGUIET_IN_OUT_FADER, + + //! An image (IGUIImage) + EGUIET_IMAGE, + + //! A list box (IGUIListBox) + EGUIET_LIST_BOX, + + //! A mesh viewer (IGUIMeshViewer) + EGUIET_MESH_VIEWER, + + //! A message box (IGUIWindow) + EGUIET_MESSAGE_BOX, + + //! A modal screen + EGUIET_MODAL_SCREEN, + + //! A scroll bar (IGUIScrollBar) + EGUIET_SCROLL_BAR, + + //! A spin box (IGUISpinBox) + EGUIET_SPIN_BOX, + + //! A static text (IGUIStaticText) + EGUIET_STATIC_TEXT, + + //! A tab (IGUITab) + EGUIET_TAB, + + //! A tab control + EGUIET_TAB_CONTROL, + + //! A Table + EGUIET_TABLE, + + //! A tool bar (IGUIToolBar) + EGUIET_TOOL_BAR, + + //! A Tree View + EGUIET_TREE_VIEW, + + //! A window + EGUIET_WINDOW, + + //! Unknown type. + EGUIET_ELEMENT, + + //! The root of the GUI + EGUIET_ROOT, + + //! Not an element, amount of elements in there + EGUIET_COUNT, + + //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. + EGUIET_FORCE_32_BIT = 0x7fffffff + +}; + +//! Names for built-in element types +const c8* const GUIElementTypeNames[] = +{ + "button", + "checkBox", + "comboBox", + "contextMenu", + "menu", + "editBox", + "fileOpenDialog", + "colorSelectDialog", + "inOutFader", + "image", + "listBox", + "meshViewer", + "messageBox", + "modalScreen", + "scrollBar", + "spinBox", + "staticText", + "tab", + "tabControl", + "table", + "toolBar", + "treeview", + "window", + "element", + "root", + 0 +}; + +} // end namespace gui +} // end namespace irr + +#endif + + + + diff --git a/inc/EHardwareBufferFlags.h b/inc/EHardwareBufferFlags.h new file mode 100644 index 0000000..27d5610 --- /dev/null +++ b/inc/EHardwareBufferFlags.h @@ -0,0 +1,44 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ +#define __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + enum E_HARDWARE_MAPPING + { + //! Don't store on the hardware + EHM_NEVER=0, + + //! Rarely changed, usually stored completely on the hardware + EHM_STATIC, + + //! Sometimes changed, driver optimized placement + EHM_DYNAMIC, + + //! Always changed, cache optimizing on the GPU + EHM_STREAM + }; + + enum E_BUFFER_TYPE + { + //! Does not change anything + EBT_NONE=0, + //! Change the vertex mapping + EBT_VERTEX, + //! Change the index mapping + EBT_INDEX, + //! Change both vertex and index mapping to the same value + EBT_VERTEX_AND_INDEX + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/EMaterialFlags.h b/inc/EMaterialFlags.h new file mode 100644 index 0000000..e336adc --- /dev/null +++ b/inc/EMaterialFlags.h @@ -0,0 +1,95 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_MATERIAL_FLAGS_H_INCLUDED__ +#define __E_MATERIAL_FLAGS_H_INCLUDED__ + +namespace irr +{ +namespace video +{ + + //! Material flags + enum E_MATERIAL_FLAG + { + //! Draw as wireframe or filled triangles? Default: false + EMF_WIREFRAME = 0x1, + + //! Draw as point cloud or filled triangles? Default: false + EMF_POINTCLOUD = 0x2, + + //! Flat or Gouraud shading? Default: true + EMF_GOURAUD_SHADING = 0x4, + + //! Will this material be lighted? Default: true + EMF_LIGHTING = 0x8, + + //! Is the ZBuffer enabled? Default: true + EMF_ZBUFFER = 0x10, + + //! May be written to the zbuffer or is it readonly. Default: true + /** This flag is ignored, if the material type is a transparent type. */ + EMF_ZWRITE_ENABLE = 0x20, + + //! Is backface culling enabled? Default: true + EMF_BACK_FACE_CULLING = 0x40, + + //! Is frontface culling enabled? Default: false + /** Overrides EMF_BACK_FACE_CULLING if both are enabled. */ + EMF_FRONT_FACE_CULLING = 0x80, + + //! Is bilinear filtering enabled? Default: true + EMF_BILINEAR_FILTER = 0x100, + + //! Is trilinear filtering enabled? Default: false + /** If the trilinear filter flag is enabled, + the bilinear filtering flag is ignored. */ + EMF_TRILINEAR_FILTER = 0x200, + + //! Is anisotropic filtering? Default: false + /** In Irrlicht you can use anisotropic texture filtering in + conjunction with bilinear or trilinear texture filtering + to improve rendering results. Primitives will look less + blurry with this flag switched on. */ + EMF_ANISOTROPIC_FILTER = 0x400, + + //! Is fog enabled? Default: false + EMF_FOG_ENABLE = 0x800, + + //! Normalizes normals. Default: false + /** You can enable this if you need to scale a dynamic lighted + model. Usually, its normals will get scaled too then and it + will get darker. If you enable the EMF_NORMALIZE_NORMALS flag, + the normals will be normalized again, and the model will look + as bright as it should. */ + EMF_NORMALIZE_NORMALS = 0x1000, + + //! Access to all layers texture wrap settings. Overwrites separate layer settings. + EMF_TEXTURE_WRAP = 0x2000, + + //! AntiAliasing mode + EMF_ANTI_ALIASING = 0x4000, + + //! ColorMask bits, for enabling the color planes + EMF_COLOR_MASK = 0x8000, + + //! ColorMaterial enum for vertex color interpretation + EMF_COLOR_MATERIAL = 0x10000, + + //! Flag for enabling/disabling mipmap usage + EMF_USE_MIP_MAPS = 0x20000, + + //! Flag for blend operation + EMF_BLEND_OPERATION = 0x40000, + + //! Flag for polygon offset + EMF_POLYGON_OFFSET = 0x80000 + }; + +} // end namespace video +} // end namespace irr + + +#endif // __E_MATERIAL_FLAGS_H_INCLUDED__ + diff --git a/inc/EMaterialTypes.h b/inc/EMaterialTypes.h new file mode 100644 index 0000000..5e5e075 --- /dev/null +++ b/inc/EMaterialTypes.h @@ -0,0 +1,234 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_MATERIAL_TYPES_H_INCLUDED__ +#define __E_MATERIAL_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace video +{ + + //! Abstracted and easy to use fixed function/programmable pipeline material modes. + enum E_MATERIAL_TYPE + { + //! Standard solid material. + /** Only first texture is used, which is supposed to be the + diffuse material. */ + EMT_SOLID = 0, + + //! Solid material with 2 texture layers. + /** The second is blended onto the first using the alpha value + of the vertex colors. This material is currently not implemented in OpenGL. + */ + EMT_SOLID_2_LAYER, + + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. */ + EMT_LIGHTMAP, + + //! Material type with lightmap technique like EMT_LIGHTMAP. + /** But lightmap and diffuse texture are added instead of modulated. */ + EMT_LIGHTMAP_ADD, + + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. The texture colors are effectively multiplied by 2 + for brightening. Like known in DirectX as D3DTOP_MODULATE2X. */ + EMT_LIGHTMAP_M2, + + //! Material type with standard lightmap technique + /** There should be 2 textures: The first texture layer is a + diffuse map, the second is a light map. Dynamic light is + ignored. The texture colors are effectively multiplyied by 4 + for brightening. Like known in DirectX as D3DTOP_MODULATE4X. */ + EMT_LIGHTMAP_M4, + + //! Like EMT_LIGHTMAP, but also supports dynamic lighting. + EMT_LIGHTMAP_LIGHTING, + + //! Like EMT_LIGHTMAP_M2, but also supports dynamic lighting. + EMT_LIGHTMAP_LIGHTING_M2, + + //! Like EMT_LIGHTMAP_4, but also supports dynamic lighting. + EMT_LIGHTMAP_LIGHTING_M4, + + //! Detail mapped material. + /** The first texture is diffuse color map, the second is added + to this and usually displayed with a bigger scale value so that + it adds more detail. The detail map is added to the diffuse map + using ADD_SIGNED, so that it is possible to add and substract + color from the diffuse map. For example a value of + (127,127,127) will not change the appearance of the diffuse map + at all. Often used for terrain rendering. */ + EMT_DETAIL_MAP, + + //! Look like a reflection of the environment around it. + /** To make this possible, a texture called 'sphere map' is + used, which must be set as the first texture. */ + EMT_SPHERE_MAP, + + //! A reflecting material with an optional non reflecting texture layer. + /** The reflection map should be set as first texture. */ + EMT_REFLECTION_2_LAYER, + + //! A transparent material. + /** Only the first texture is used. The new color is calculated + by simply adding the source color and the dest color. This + means if for example a billboard using a texture with black + background and a red circle on it is drawn with this material, + the result is that only the red circle will be drawn a little + bit transparent, and everything which was black is 100% + transparent and not visible. This material type is useful for + particle effects. */ + EMT_TRANSPARENT_ADD_COLOR, + + //! Makes the material transparent based on the texture alpha channel. + /** The final color is blended together from the destination + color and the texture color, using the alpha channel value as + blend factor. Only first texture is used. If you are using + this material with small textures, it is a good idea to load + the texture in 32 bit mode + (video::IVideoDriver::setTextureCreationFlag()). Also, an alpha + ref is used, which can be manipulated using + SMaterial::MaterialTypeParam. This value controls how sharp the + edges become when going from a transparent to a solid spot on + the texture. */ + EMT_TRANSPARENT_ALPHA_CHANNEL, + + //! Makes the material transparent based on the texture alpha channel. + /** If the alpha channel value is greater than 127, a + pixel is written to the target, otherwise not. This + material does not use alpha blending and is a lot faster + than EMT_TRANSPARENT_ALPHA_CHANNEL. It is ideal for drawing + stuff like leafes of plants, because the borders are not + blurry but sharp. Only first texture is used. If you are + using this material with small textures and 3d object, it + is a good idea to load the texture in 32 bit mode + (video::IVideoDriver::setTextureCreationFlag()). */ + EMT_TRANSPARENT_ALPHA_CHANNEL_REF, + + //! Makes the material transparent based on the vertex alpha value. + EMT_TRANSPARENT_VERTEX_ALPHA, + + //! A transparent reflecting material with an optional additional non reflecting texture layer. + /** The reflection map should be set as first texture. The + transparency depends on the alpha value in the vertex colors. A + texture which will not reflect can be set as second texture. + Please note that this material type is currently not 100% + implemented in OpenGL. */ + EMT_TRANSPARENT_REFLECTION_2_LAYER, + + //! A solid normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ + EMT_NORMAL_MAP_SOLID, + + //! A transparent normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ + EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, + + //! A transparent (based on the vertex alpha value) normal map renderer. + /** First texture is the color map, the second should be the + normal map. Note that you should use this material only when + drawing geometry consisting of vertices of type + S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into + this format using IMeshManipulator::createMeshWithTangents() + (See SpecialFX2 Tutorial). This shader runs on vertex shader + 1.1 and pixel shader 1.1 capable hardware and falls back to a + fixed function lighted material if this hardware is not + available. Only two lights are supported by this shader, if + there are more, the nearest two are chosen. */ + EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, + + //! Just like EMT_NORMAL_MAP_SOLID, but uses parallax mapping. + /** Looks a lot more realistic. This only works when the + hardware supports at least vertex shader 1.1 and pixel shader + 1.4. First texture is the color map, the second should be the + normal map. The normal map texture should contain the height + value in the alpha component. The + IVideoDriver::makeNormalMapTexture() method writes this value + automatically when creating normal maps from a heightmap when + using a 32 bit texture. The height scale of the material + (affecting the bumpiness) is being controlled by the + SMaterial::MaterialTypeParam member. If set to zero, the + default value (0.02f) will be applied. Otherwise the value set + in SMaterial::MaterialTypeParam is taken. This value depends on + with which scale the texture is mapped on the material. Too + high or low values of MaterialTypeParam can result in strange + artifacts. */ + EMT_PARALLAX_MAP_SOLID, + + //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. + /** Using EMT_TRANSPARENT_ADD_COLOR as base material. */ + EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, + + //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. + /** Using EMT_TRANSPARENT_VERTEX_ALPHA as base material. */ + EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, + + //! BlendFunc = source * sourceFactor + dest * destFactor ( E_BLEND_FUNC ) + /** Using only first texture. Generic blending method. */ + EMT_ONETEXTURE_BLEND, + + //! This value is not used. It only forces this enumeration to compile to 32 bit. + EMT_FORCE_32BIT = 0x7fffffff + }; + + //! Array holding the built in material type names + const char* const sBuiltInMaterialTypeNames[] = + { + "solid", + "solid_2layer", + "lightmap", + "lightmap_add", + "lightmap_m2", + "lightmap_m4", + "lightmap_light", + "lightmap_light_m2", + "lightmap_light_m4", + "detail_map", + "sphere_map", + "reflection_2layer", + "trans_add", + "trans_alphach", + "trans_alphach_ref", + "trans_vertex_alpha", + "trans_reflection_2layer", + "normalmap_solid", + "normalmap_trans_add", + "normalmap_trans_vertexalpha", + "parallaxmap_solid", + "parallaxmap_trans_add", + "parallaxmap_trans_vertexalpha", + "onetexture_blend", + 0 + }; + +} // end namespace video +} // end namespace irr + + +#endif // __E_MATERIAL_TYPES_H_INCLUDED__ + diff --git a/inc/EMeshWriterEnums.h b/inc/EMeshWriterEnums.h new file mode 100644 index 0000000..ceeaa7a --- /dev/null +++ b/inc/EMeshWriterEnums.h @@ -0,0 +1,59 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_MESH_WRITER_ENUMS_H_INCLUDED__ +#define __E_MESH_WRITER_ENUMS_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace scene +{ + + //! An enumeration for all supported types of built-in mesh writers + /** A scene mesh writers is represented by a four character code + such as 'irrm' or 'coll' instead of simple numbers, to avoid + name clashes with external mesh writers.*/ + enum EMESH_WRITER_TYPE + { + //! Irrlicht native mesh writer, for static .irrmesh files. + EMWT_IRR_MESH = MAKE_IRR_ID('i','r','r','m'), + + //! COLLADA mesh writer for .dae and .xml files + EMWT_COLLADA = MAKE_IRR_ID('c','o','l','l'), + + //! STL mesh writer for .stl files + EMWT_STL = MAKE_IRR_ID('s','t','l',0), + + //! OBJ mesh writer for .obj files + EMWT_OBJ = MAKE_IRR_ID('o','b','j',0), + + //! PLY mesh writer for .ply files + EMWT_PLY = MAKE_IRR_ID('p','l','y',0) + }; + + + //! flags configuring mesh writing + enum E_MESH_WRITER_FLAGS + { + //! no writer flags + EMWF_NONE = 0, + + //! write lightmap textures out if possible + EMWF_WRITE_LIGHTMAPS = 0x1, + + //! write in a way that consumes less disk space + EMWF_WRITE_COMPRESSED = 0x2, + + //! write in binary format rather than text + EMWF_WRITE_BINARY = 0x4 + }; + +} // end namespace scene +} // end namespace irr + + +#endif // __E_MESH_WRITER_ENUMS_H_INCLUDED__ + diff --git a/inc/EMessageBoxFlags.h b/inc/EMessageBoxFlags.h new file mode 100644 index 0000000..ed2d766 --- /dev/null +++ b/inc/EMessageBoxFlags.h @@ -0,0 +1,36 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_MESSAGE_BOX_FLAGS_H_INCLUDED__ +#define __E_MESSAGE_BOX_FLAGS_H_INCLUDED__ + +namespace irr +{ +namespace gui +{ + +//! enumeration for message box layout flags +enum EMESSAGE_BOX_FLAG +{ + //! Flag for the ok button + EMBF_OK = 0x1, + + //! Flag for the cancel button + EMBF_CANCEL = 0x2, + + //! Flag for the yes button + EMBF_YES = 0x4, + + //! Flag for the no button + EMBF_NO = 0x8, + + //! This value is not used. It only forces this enumeration to compile in 32 bit. + EMBF_FORCE_32BIT = 0x7fffffff +}; + +} // namespace gui +} // namespace irr + +#endif + diff --git a/inc/EPrimitiveTypes.h b/inc/EPrimitiveTypes.h new file mode 100644 index 0000000..7c61d42 --- /dev/null +++ b/inc/EPrimitiveTypes.h @@ -0,0 +1,56 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_PRIMITIVE_TYPES_H_INCLUDED__ +#define __E_PRIMITIVE_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + //! Enumeration for all primitive types there are. + enum E_PRIMITIVE_TYPE + { + //! All vertices are non-connected points. + EPT_POINTS=0, + + //! All vertices form a single connected line. + EPT_LINE_STRIP, + + //! Just as LINE_STRIP, but the last and the first vertex is also connected. + EPT_LINE_LOOP, + + //! Every two vertices are connected creating n/2 lines. + EPT_LINES, + + //! After the first two vertices each vertex defines a new triangle. + //! Always the two last and the new one form a new triangle. + EPT_TRIANGLE_STRIP, + + //! After the first two vertices each vertex defines a new triangle. + //! All around the common first vertex. + EPT_TRIANGLE_FAN, + + //! Explicitly set all vertices for each triangle. + EPT_TRIANGLES, + + //! After the first two vertices each further tw vetices create a quad with the preceding two. + EPT_QUAD_STRIP, + + //! Every four vertices create a quad. + EPT_QUADS, + + //! Just as LINE_LOOP, but filled. + EPT_POLYGON, + + //! The single vertices are expanded to quad billboards on the GPU. + EPT_POINT_SPRITES + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ESceneNodeAnimatorTypes.h b/inc/ESceneNodeAnimatorTypes.h new file mode 100644 index 0000000..078739d --- /dev/null +++ b/inc/ESceneNodeAnimatorTypes.h @@ -0,0 +1,58 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_SCENE_NODE_ANIMATOR_TYPES_H_INCLUDED__ +#define __E_SCENE_NODE_ANIMATOR_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + //! An enumeration for all types of built-in scene node animators + enum ESCENE_NODE_ANIMATOR_TYPE + { + //! Fly circle scene node animator + ESNAT_FLY_CIRCLE = 0, + + //! Fly straight scene node animator + ESNAT_FLY_STRAIGHT, + + //! Follow spline scene node animator + ESNAT_FOLLOW_SPLINE, + + //! Rotation scene node animator + ESNAT_ROTATION, + + //! Texture scene node animator + ESNAT_TEXTURE, + + //! Deletion scene node animator + ESNAT_DELETION, + + //! Collision respose scene node animator + ESNAT_COLLISION_RESPONSE, + + //! FPS camera animator + ESNAT_CAMERA_FPS, + + //! Maya camera animator + ESNAT_CAMERA_MAYA, + + //! Amount of built-in scene node animators + ESNAT_COUNT, + + //! Unknown scene node animator + ESNAT_UNKNOWN, + + //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. + ESNAT_FORCE_32_BIT = 0x7fffffff + }; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/ESceneNodeTypes.h b/inc/ESceneNodeTypes.h new file mode 100644 index 0000000..3d43105 --- /dev/null +++ b/inc/ESceneNodeTypes.h @@ -0,0 +1,106 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_SCENE_NODE_TYPES_H_INCLUDED__ +#define __E_SCENE_NODE_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace scene +{ + + //! An enumeration for all types of built-in scene nodes + /** A scene node type is represented by a four character code + such as 'cube' or 'mesh' instead of simple numbers, to avoid + name clashes with external scene nodes.*/ + enum ESCENE_NODE_TYPE + { + //! of type CSceneManager (note that ISceneManager is not(!) an ISceneNode) + ESNT_SCENE_MANAGER = MAKE_IRR_ID('s','m','n','g'), + + //! simple cube scene node + ESNT_CUBE = MAKE_IRR_ID('c','u','b','e'), + + //! Sphere scene node + ESNT_SPHERE = MAKE_IRR_ID('s','p','h','r'), + + //! Text Scene Node + ESNT_TEXT = MAKE_IRR_ID('t','e','x','t'), + + //! Water Surface Scene Node + ESNT_WATER_SURFACE = MAKE_IRR_ID('w','a','t','r'), + + //! Terrain Scene Node + ESNT_TERRAIN = MAKE_IRR_ID('t','e','r','r'), + + //! Sky Box Scene Node + ESNT_SKY_BOX = MAKE_IRR_ID('s','k','y','_'), + + //! Sky Dome Scene Node + ESNT_SKY_DOME = MAKE_IRR_ID('s','k','y','d'), + + //! Shadow Volume Scene Node + ESNT_SHADOW_VOLUME = MAKE_IRR_ID('s','h','d','w'), + + //! Octree Scene Node + ESNT_OCTREE = MAKE_IRR_ID('o','c','t','r'), + + //! Mesh Scene Node + ESNT_MESH = MAKE_IRR_ID('m','e','s','h'), + + //! Light Scene Node + ESNT_LIGHT = MAKE_IRR_ID('l','g','h','t'), + + //! Empty Scene Node + ESNT_EMPTY = MAKE_IRR_ID('e','m','t','y'), + + //! Dummy Transformation Scene Node + ESNT_DUMMY_TRANSFORMATION = MAKE_IRR_ID('d','m','m','y'), + + //! Camera Scene Node + ESNT_CAMERA = MAKE_IRR_ID('c','a','m','_'), + + //! Billboard Scene Node + ESNT_BILLBOARD = MAKE_IRR_ID('b','i','l','l'), + + //! Animated Mesh Scene Node + ESNT_ANIMATED_MESH = MAKE_IRR_ID('a','m','s','h'), + + //! Particle System Scene Node + ESNT_PARTICLE_SYSTEM = MAKE_IRR_ID('p','t','c','l'), + + //! Quake3 Shader Scene Node + ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), + + //! Quake3 Model Scene Node ( has tag to link to ) + ESNT_MD3_SCENE_NODE = MAKE_IRR_ID('m','d','3','_'), + + //! Volume Light Scene Node + ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), + + //! Maya Camera Scene Node + /** Legacy, for loading version <= 1.4.x .irr files */ + ESNT_CAMERA_MAYA = MAKE_IRR_ID('c','a','m','M'), + + //! First Person Shooter Camera + /** Legacy, for loading version <= 1.4.x .irr files */ + ESNT_CAMERA_FPS = MAKE_IRR_ID('c','a','m','F'), + + //! Unknown scene node + ESNT_UNKNOWN = MAKE_IRR_ID('u','n','k','n'), + + //! Will match with any scene node when checking types + ESNT_ANY = MAKE_IRR_ID('a','n','y','_') + }; + + + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/EShaderTypes.h b/inc/EShaderTypes.h new file mode 100644 index 0000000..691930c --- /dev/null +++ b/inc/EShaderTypes.h @@ -0,0 +1,90 @@ +#ifndef __E_SHADER_TYPES_H_INCLUDED__ +#define __E_SHADER_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace video +{ + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_VERTEX_SHADER_TYPE +{ + EVST_VS_1_1 = 0, + EVST_VS_2_0, + EVST_VS_2_a, + EVST_VS_3_0, + EVST_VS_4_0, + EVST_VS_4_1, + EVST_VS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EVST_COUNT +}; + +//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. +const c8* const VERTEX_SHADER_TYPE_NAMES[] = { + "vs_1_1", + "vs_2_0", + "vs_2_a", + "vs_3_0", + "vs_4_0", + "vs_4_1", + "vs_5_0", + 0 }; + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_PIXEL_SHADER_TYPE +{ + EPST_PS_1_1 = 0, + EPST_PS_1_2, + EPST_PS_1_3, + EPST_PS_1_4, + EPST_PS_2_0, + EPST_PS_2_a, + EPST_PS_2_b, + EPST_PS_3_0, + EPST_PS_4_0, + EPST_PS_4_1, + EPST_PS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EPST_COUNT +}; + +//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. +const c8* const PIXEL_SHADER_TYPE_NAMES[] = { + "ps_1_1", + "ps_1_2", + "ps_1_3", + "ps_1_4", + "ps_2_0", + "ps_2_a", + "ps_2_b", + "ps_3_0", + "ps_4_0", + "ps_4_1", + "ps_5_0", + 0 }; + +//! Enum for supported geometry shader types +enum E_GEOMETRY_SHADER_TYPE +{ + EGST_GS_4_0 = 0, + + //! This is not a type, but a value indicating how much types there are. + EGST_COUNT +}; + +//! String names for supported geometry shader types +const c8* const GEOMETRY_SHADER_TYPE_NAMES[] = { + "gs_4_0", + 0 }; + + +} // end namespace video +} // end namespace irr + +#endif // __E_SHADER_TYPES_H_INCLUDED__ + diff --git a/inc/ETerrainElements.h b/inc/ETerrainElements.h new file mode 100644 index 0000000..b09ac39 --- /dev/null +++ b/inc/ETerrainElements.h @@ -0,0 +1,36 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_TERRAIN_ELEMENTS_H__ +#define __E_TERRAIN_ELEMENTS_H__ + +namespace irr +{ +namespace scene +{ + + //! enumeration for patch sizes specifying the size of patches in the TerrainSceneNode + enum E_TERRAIN_PATCH_SIZE + { + //! patch size of 9, at most, use 4 levels of detail with this patch size. + ETPS_9 = 9, + + //! patch size of 17, at most, use 5 levels of detail with this patch size. + ETPS_17 = 17, + + //! patch size of 33, at most, use 6 levels of detail with this patch size. + ETPS_33 = 33, + + //! patch size of 65, at most, use 7 levels of detail with this patch size. + ETPS_65 = 65, + + //! patch size of 129, at most, use 8 levels of detail with this patch size. + ETPS_129 = 129 + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IAnimatedMesh.h b/inc/IAnimatedMesh.h new file mode 100644 index 0000000..ec6eee0 --- /dev/null +++ b/inc/IAnimatedMesh.h @@ -0,0 +1,115 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ANIMATED_MESH_H_INCLUDED__ +#define __I_ANIMATED_MESH_H_INCLUDED__ + +#include "aabbox3d.h" +#include "IMesh.h" + +namespace irr +{ +namespace scene +{ + //! Possible types of (animated) meshes. + enum E_ANIMATED_MESH_TYPE + { + //! Unknown animated mesh type. + EAMT_UNKNOWN = 0, + + //! Quake 2 MD2 model file + EAMT_MD2, + + //! Quake 3 MD3 model file + EAMT_MD3, + + //! Maya .obj static model + EAMT_OBJ, + + //! Quake 3 .bsp static Map + EAMT_BSP, + + //! 3D Studio .3ds file + EAMT_3DS, + + //! My3D Mesh, the file format by Zhuck Dimitry + EAMT_MY3D, + + //! Pulsar LMTools .lmts file. This Irrlicht loader was written by Jonas Petersen + EAMT_LMTS, + + //! Cartography Shop .csm file. This loader was created by Saurav Mohapatra. + EAMT_CSM, + + //! .oct file for Paul Nette's FSRad or from Murphy McCauley's Blender .oct exporter. + /** The oct file format contains 3D geometry and lightmaps and + can be loaded directly by Irrlicht */ + EAMT_OCT, + + //! Halflife MDL model file + EAMT_MDL_HALFLIFE, + + //! generic skinned mesh + EAMT_SKINNED + }; + + //! Interface for an animated mesh. + /** There are already simple implementations of this interface available so + you don't have to implement this interface on your own if you need to: + You might want to use irr::scene::SAnimatedMesh, irr::scene::SMesh, + irr::scene::SMeshBuffer etc. */ + class IAnimatedMesh : public IMesh + { + public: + + //! Gets the frame count of the animated mesh. + /** \return The amount of frames. If the amount is 1, + it is a static, non animated mesh. */ + virtual u32 getFrameCount() const = 0; + + //! Gets the animation speed of the animated mesh. + /** \return The number of frames per second to play the + animation with by default. If the amount is 0, + it is a static, non animated mesh. */ + virtual f32 getAnimationSpeed() const = 0; + + //! Sets the animation speed of the animated mesh. + /** \param fps Number of frames per second to play the + animation with by default. If the amount is 0, + it is not animated. The actual speed is set in the + scene node the mesh is instantiated in.*/ + virtual void setAnimationSpeed(f32 fps) =0; + + //! Returns the IMesh interface for a frame. + /** \param frame: Frame number as zero based index. The maximum + frame number is getFrameCount() - 1; + \param detailLevel: Level of detail. 0 is the lowest, 255 the + highest level of detail. Most meshes will ignore the detail level. + \param startFrameLoop: Because some animated meshes (.MD2) are + blended between 2 static frames, and maybe animated in a loop, + the startFrameLoop and the endFrameLoop have to be defined, to + prevent the animation to be blended between frames which are + outside of this loop. + If startFrameLoop and endFrameLoop are both -1, they are ignored. + \param endFrameLoop: see startFrameLoop. + \return Returns the animated mesh based on a detail level. */ + virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1) = 0; + + //! Returns the type of the animated mesh. + /** In most cases it is not neccessary to use this method. + This is useful for making a safe downcast. For example, + if getMeshType() returns EAMT_MD2 it's safe to cast the + IAnimatedMesh to IAnimatedMeshMD2. + \returns Type of the mesh. */ + virtual E_ANIMATED_MESH_TYPE getMeshType() const + { + return EAMT_UNKNOWN; + } + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IAnimatedMeshMD2.h b/inc/IAnimatedMeshMD2.h new file mode 100644 index 0000000..333394e --- /dev/null +++ b/inc/IAnimatedMeshMD2.h @@ -0,0 +1,79 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ANIMATED_MESH_MD2_H_INCLUDED__ +#define __I_ANIMATED_MESH_MD2_H_INCLUDED__ + +#include "IAnimatedMesh.h" + +namespace irr +{ +namespace scene +{ + + //! Types of standard md2 animations + enum EMD2_ANIMATION_TYPE + { + EMAT_STAND = 0, + EMAT_RUN, + EMAT_ATTACK, + EMAT_PAIN_A, + EMAT_PAIN_B, + EMAT_PAIN_C, + EMAT_JUMP, + EMAT_FLIP, + EMAT_SALUTE, + EMAT_FALLBACK, + EMAT_WAVE, + EMAT_POINT, + EMAT_CROUCH_STAND, + EMAT_CROUCH_WALK, + EMAT_CROUCH_ATTACK, + EMAT_CROUCH_PAIN, + EMAT_CROUCH_DEATH, + EMAT_DEATH_FALLBACK, + EMAT_DEATH_FALLFORWARD, + EMAT_DEATH_FALLBACKSLOW, + EMAT_BOOM, + + //! Not an animation, but amount of animation types. + EMAT_COUNT + }; + + //! Interface for using some special functions of MD2 meshes + class IAnimatedMeshMD2 : public IAnimatedMesh + { + public: + + //! Get frame loop data for a default MD2 animation type. + /** \param l The EMD2_ANIMATION_TYPE to get the frames for. + \param outBegin The returned beginning frame for animation type specified. + \param outEnd The returned ending frame for the animation type specified. + \param outFPS The number of frames per second, this animation should be played at. + \return beginframe, endframe and frames per second for a default MD2 animation type. */ + virtual void getFrameLoop(EMD2_ANIMATION_TYPE l, s32& outBegin, + s32& outEnd, s32& outFPS) const = 0; + + //! Get frame loop data for a special MD2 animation type, identified by name. + /** \param name Name of the animation. + \param outBegin The returned beginning frame for animation type specified. + \param outEnd The returned ending frame for the animation type specified. + \param outFPS The number of frames per second, this animation should be played at. + \return beginframe, endframe and frames per second for a special MD2 animation type. */ + virtual bool getFrameLoop(const c8* name, + s32& outBegin, s32& outEnd, s32& outFPS) const = 0; + + //! Get amount of md2 animations in this file. + virtual s32 getAnimationCount() const = 0; + + //! Get name of md2 animation. + /** \param nr: Zero based index of animation. */ + virtual const c8* getAnimationName(s32 nr) const = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IAnimatedMeshMD3.h b/inc/IAnimatedMeshMD3.h new file mode 100644 index 0000000..93b24c1 --- /dev/null +++ b/inc/IAnimatedMeshMD3.h @@ -0,0 +1,304 @@ +// Copyright (C) 2007-2012 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__ +#define __I_ANIMATED_MESH_MD3_H_INCLUDED__ + +#include "IAnimatedMesh.h" +#include "IQ3Shader.h" +#include "quaternion.h" + +namespace irr +{ +namespace scene +{ + + enum eMD3Models + { + EMD3_HEAD = 0, + EMD3_UPPER, + EMD3_LOWER, + EMD3_WEAPON, + EMD3_NUMMODELS + }; + + //! Animation list + enum EMD3_ANIMATION_TYPE + { + // Animations for both lower and upper parts of the player + EMD3_BOTH_DEATH_1 = 0, + EMD3_BOTH_DEAD_1, + EMD3_BOTH_DEATH_2, + EMD3_BOTH_DEAD_2, + EMD3_BOTH_DEATH_3, + EMD3_BOTH_DEAD_3, + + // Animations for the upper part + EMD3_TORSO_GESTURE, + EMD3_TORSO_ATTACK_1, + EMD3_TORSO_ATTACK_2, + EMD3_TORSO_DROP, + EMD3_TORSO_RAISE, + EMD3_TORSO_STAND_1, + EMD3_TORSO_STAND_2, + + // Animations for the lower part + EMD3_LEGS_WALK_CROUCH, + EMD3_LEGS_WALK, + EMD3_LEGS_RUN, + EMD3_LEGS_BACK, + EMD3_LEGS_SWIM, + EMD3_LEGS_JUMP_1, + EMD3_LEGS_LAND_1, + EMD3_LEGS_JUMP_2, + EMD3_LEGS_LAND_2, + EMD3_LEGS_IDLE, + EMD3_LEGS_IDLE_CROUCH, + EMD3_LEGS_TURN, + + //! Not an animation, but amount of animation types. + EMD3_ANIMATION_COUNT + }; + + struct SMD3AnimationInfo + { + //! First frame + s32 first; + //! Last frame + s32 num; + //! Looping frames + s32 looping; + //! Frames per second + s32 fps; + }; + + +// byte-align structures +#include "irrpack.h" + + //! this holds the header info of the MD3 file + struct SMD3Header + { + c8 headerID[4]; //id of file, always "IDP3" + s32 Version; //this is a version number, always 15 + s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars + s32 numFrames; //number of KeyFrames + s32 numTags; //number of 'tags' per frame + s32 numMeshes; //number of meshes/skins + s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2 + s32 frameStart; //starting position of frame-structur + s32 tagStart; //starting position of tag-structures + s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures + s32 fileSize; + } PACK_STRUCT; + + //! this holds the header info of an MD3 mesh section + struct SMD3MeshHeader + { + c8 meshID[4]; //id, must be IDP3 + c8 meshName[68]; //name of mesh 65 chars, 32 bit aligned == 68 chars + + s32 numFrames; //number of meshframes in mesh + s32 numShader; //number of skins in mesh + s32 numVertices; //number of vertices + s32 numTriangles; //number of Triangles + + s32 offset_triangles; //starting position of Triangle data, relative to start of Mesh_Header + s32 offset_shaders; //size of header + s32 offset_st; //starting position of texvector data, relative to start of Mesh_Header + s32 vertexStart; //starting position of vertex data,relative to start of Mesh_Header + s32 offset_end; + } PACK_STRUCT; + + + //! Compressed Vertex Data + struct SMD3Vertex + { + s16 position[3]; + u8 normal[2]; + } PACK_STRUCT; + + //! Texture Coordinate + struct SMD3TexCoord + { + f32 u; + f32 v; + } PACK_STRUCT; + + //! Triangle Index + struct SMD3Face + { + s32 Index[3]; + } PACK_STRUCT; + + +// Default alignment +#include "irrunpack.h" + + //! Holding Frame Data for a Mesh + struct SMD3MeshBuffer : public IReferenceCounted + { + SMD3MeshHeader MeshHeader; + + core::stringc Shader; + core::array < s32 > Indices; + core::array < SMD3Vertex > Vertices; + core::array < SMD3TexCoord > Tex; + }; + + //! hold a tag info for connecting meshes + /** Basically its an alternate way to describe a transformation. */ + struct SMD3QuaternionTag + { + virtual ~SMD3QuaternionTag() + { + position.X = 0.f; + } + + // construct copy constructor + SMD3QuaternionTag( const SMD3QuaternionTag & copyMe ) + { + *this = copyMe; + } + + // construct for searching + SMD3QuaternionTag( const core::stringc& name ) + : Name ( name ) {} + + // construct from a position and euler angles in degrees + SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle ) + : position(pos), rotation(angle * core::DEGTORAD) {} + + // set to matrix + void setto ( core::matrix4 &m ) + { + rotation.getMatrix ( m, position ); + } + + bool operator == ( const SMD3QuaternionTag &other ) const + { + return Name == other.Name; + } + + SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe ) + { + Name = copyMe.Name; + position = copyMe.position; + rotation = copyMe.rotation; + return *this; + } + + core::stringc Name; + core::vector3df position; + core::quaternion rotation; + }; + + //! holds a associative list of named quaternions + struct SMD3QuaternionTagList + { + SMD3QuaternionTagList() + { + Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE); + } + + // construct copy constructor + SMD3QuaternionTagList(const SMD3QuaternionTagList& copyMe) + { + *this = copyMe; + } + + virtual ~SMD3QuaternionTagList() {} + + SMD3QuaternionTag* get(const core::stringc& name) + { + SMD3QuaternionTag search ( name ); + s32 index = Container.linear_search ( search ); + if ( index >= 0 ) + return &Container[index]; + return 0; + } + + u32 size () const + { + return Container.size(); + } + + void set_used(u32 new_size) + { + s32 diff = (s32) new_size - (s32) Container.allocated_size(); + if ( diff > 0 ) + { + SMD3QuaternionTag e(""); + for ( s32 i = 0; i < diff; ++i ) + Container.push_back(e); + } + } + + const SMD3QuaternionTag& operator[](u32 index) const + { + return Container[index]; + } + + SMD3QuaternionTag& operator[](u32 index) + { + return Container[index]; + } + + void push_back(const SMD3QuaternionTag& other) + { + Container.push_back(other); + } + + SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe) + { + Container = copyMe.Container; + return *this; + } + + private: + core::array < SMD3QuaternionTag > Container; + }; + + + //! Holding Frames Buffers and Tag Infos + struct SMD3Mesh: public IReferenceCounted + { + SMD3Mesh () + { + MD3Header.numFrames = 0; + } + + virtual ~SMD3Mesh() + { + for (u32 i=0; idrop(); + } + + core::stringc Name; + core::array Buffer; + SMD3QuaternionTagList TagList; + SMD3Header MD3Header; + }; + + + //! Interface for using some special functions of MD3 meshes + class IAnimatedMeshMD3 : public IAnimatedMesh + { + public: + + //! tune how many frames you want to render inbetween. + virtual void setInterpolationShift(u32 shift, u32 loopMode) =0; + + //! get the tag list of the mesh. + virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) =0; + + //! get the original md3 mesh. + virtual SMD3Mesh* getOriginalMesh() =0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IAnimatedMeshSceneNode.h b/inc/IAnimatedMeshSceneNode.h new file mode 100644 index 0000000..f34161e --- /dev/null +++ b/inc/IAnimatedMeshSceneNode.h @@ -0,0 +1,228 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ +#define __I_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" +#include "IBoneSceneNode.h" +#include "IAnimatedMeshMD2.h" +#include "IAnimatedMeshMD3.h" + +namespace irr +{ +namespace scene +{ + class IShadowVolumeSceneNode; + + enum E_JOINT_UPDATE_ON_RENDER + { + //! do nothing + EJUOR_NONE = 0, + + //! get joints positions from the mesh (for attached nodes, etc) + EJUOR_READ, + + //! control joint positions in the mesh (eg. ragdolls, or set the animation from animateJoints() ) + EJUOR_CONTROL + }; + + + class IAnimatedMeshSceneNode; + + //! Callback interface for catching events of ended animations. + /** Implement this interface and use + IAnimatedMeshSceneNode::setAnimationEndCallback to be able to + be notified if an animation playback has ended. + **/ + class IAnimationEndCallBack : public virtual IReferenceCounted + { + public: + + //! Will be called when the animation playback has ended. + /** See IAnimatedMeshSceneNode::setAnimationEndCallback for + more informations. + \param node: Node of which the animation has ended. */ + virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node) = 0; + }; + + //! Scene node capable of displaying an animated mesh and its shadow. + /** The shadow is optional: If a shadow should be displayed too, just + invoke the IAnimatedMeshSceneNode::createShadowVolumeSceneNode().*/ + class IAnimatedMeshSceneNode : public ISceneNode + { + public: + + //! Constructor + IAnimatedMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) + : ISceneNode(parent, mgr, id, position, rotation, scale) {} + + //! Destructor + virtual ~IAnimatedMeshSceneNode() {} + + //! Sets the current frame number. + /** From now on the animation is played from this frame. + \param frame: Number of the frame to let the animation be started from. + The frame number must be a valid frame number of the IMesh used by this + scene node. Set IAnimatedMesh::getMesh() for details. */ + virtual void setCurrentFrame(f32 frame) = 0; + + //! Sets the frame numbers between the animation is looped. + /** The default is 0 - MaximalFrameCount of the mesh. + \param begin: Start frame number of the loop. + \param end: End frame number of the loop. + \return True if successful, false if not. */ + virtual bool setFrameLoop(s32 begin, s32 end) = 0; + + //! Sets the speed with which the animation is played. + /** \param framesPerSecond: Frames per second played. */ + virtual void setAnimationSpeed(f32 framesPerSecond) = 0; + + //! Gets the speed with which the animation is played. + /** \return Frames per second played. */ + virtual f32 getAnimationSpeed() const =0; + + //! Creates shadow volume scene node as child of this node. + /** The shadow can be rendered using the ZPass or the zfail + method. ZPass is a little bit faster because the shadow volume + creation is easier, but with this method there occur ugly + looking artifacs when the camera is inside the shadow volume. + These error do not occur with the ZFail method. + \param shadowMesh: Optional custom mesh for shadow volume. + \param id: Id of the shadow scene node. This id can be used to + identify the node later. + \param zfailmethod: If set to true, the shadow will use the + zfail method, if not, zpass is used. + \param infinity: Value used by the shadow volume algorithm to + scale the shadow volume (for zfail shadow volume we support only + finite shadows, so camera zfar must be larger than shadow back cap, + which is depend on infinity parameter). + \return Pointer to the created shadow scene node. This pointer + should not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, + s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0; + + + //! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh). + /** With this method it is possible to attach scene nodes to + joints for example possible to attach a weapon to the left hand + of an animated model. This example shows how: + \code + ISceneNode* hand = + yourAnimatedMeshSceneNode->getJointNode("LeftHand"); + hand->addChild(weaponSceneNode); + \endcode + Please note that the joint returned by this method may not exist + before this call and the joints in the node were created by it. + \param jointName: Name of the joint. + \return Pointer to the scene node which represents the joint + with the specified name. Returns 0 if the contained mesh is not + an skinned mesh or the name of the joint could not be found. */ + virtual IBoneSceneNode* getJointNode(const c8* jointName)=0; + + //! same as getJointNode(const c8* jointName), but based on id + virtual IBoneSceneNode* getJointNode(u32 jointID) = 0; + + //! Gets joint count. + /** \return Amount of joints in the mesh. */ + virtual u32 getJointCount() const = 0; + + //! Starts a default MD2 animation. + /** With this method it is easily possible to start a Run, + Attack, Die or whatever animation, if the mesh contained in + this scene node is an md2 mesh. Otherwise, nothing happens. + \param anim: An MD2 animation type, which should be played, for + example EMAT_STAND for the standing animation. + \return True if successful, and false if not, for example if + the mesh in the scene node is not a md2 mesh. */ + virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim) = 0; + + //! Starts a special MD2 animation. + /** With this method it is easily possible to start a Run, + Attack, Die or whatever animation, if the mesh contained in + this scene node is an md2 mesh. Otherwise, nothing happens. + This method uses a character string to identify the animation. + If the animation is a standard md2 animation, you might want to + start this animation with the EMD2_ANIMATION_TYPE enumeration + instead. + \param animationName: Name of the animation which should be + played. + \return Returns true if successful, and false if not, for + example if the mesh in the scene node is not an md2 mesh, or no + animation with this name could be found. */ + virtual bool setMD2Animation(const c8* animationName) = 0; + + //! Returns the currently displayed frame number. + virtual f32 getFrameNr() const = 0; + //! Returns the current start frame number. + virtual s32 getStartFrame() const = 0; + //! Returns the current end frame number. + virtual s32 getEndFrame() const = 0; + + //! Sets looping mode which is on by default. + /** If set to false, animations will not be played looped. */ + virtual void setLoopMode(bool playAnimationLooped) = 0; + + //! returns the current loop mode + /** When true the animations are played looped */ + virtual bool getLoopMode() const = 0; + + //! Sets a callback interface which will be called if an animation playback has ended. + /** Set this to 0 to disable the callback again. + Please note that this will only be called when in non looped + mode, see IAnimatedMeshSceneNode::setLoopMode(). */ + virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0) = 0; + + //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. + /** In this way it is possible to change the materials a mesh + causing all mesh scene nodes referencing this mesh to change + too. */ + virtual void setReadOnlyMaterials(bool readonly) = 0; + + //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style + virtual bool isReadOnlyMaterials() const = 0; + + //! Sets a new mesh + virtual void setMesh(IAnimatedMesh* mesh) = 0; + + //! Returns the current mesh + virtual IAnimatedMesh* getMesh(void) = 0; + + //! Get the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, or the absolutetransformation if it's a normal scenenode + virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; + + //! Set how the joints should be updated on render + virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode)=0; + + //! Sets the transition time in seconds + /** Note: This needs to enable joints, and setJointmode set to + EJUOR_CONTROL. You must call animateJoints(), or the mesh will + not animate. */ + virtual void setTransitionTime(f32 Time) =0; + + //! animates the joints in the mesh based on the current frame. + /** Also takes in to account transitions. */ + virtual void animateJoints(bool CalculateAbsolutePositions=true) = 0; + + //! render mesh ignoring its transformation. + /** Culling is unaffected. */ + virtual void setRenderFromIdentity( bool On )=0; + + //! Creates a clone of this scene node and its children. + /** \param newParent An optional new parent. + \param newManager An optional new scene manager. + \return The newly created clone of this node. */ + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0; + + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IAttributeExchangingObject.h b/inc/IAttributeExchangingObject.h new file mode 100644 index 0000000..9c64b7d --- /dev/null +++ b/inc/IAttributeExchangingObject.h @@ -0,0 +1,71 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ATTRIBUTE_EXCHANGING_OBJECT_H_INCLUDED__ +#define __I_ATTRIBUTE_EXCHANGING_OBJECT_H_INCLUDED__ + +#include "IReferenceCounted.h" + + +namespace irr +{ + +namespace io +{ + +class IAttributes; + +//! Enumeration flags passed through SAttributeReadWriteOptions to the IAttributeExchangingObject object +enum E_ATTRIBUTE_READ_WRITE_FLAGS +{ + //! Serialization/Deserializion is done for an xml file + EARWF_FOR_FILE = 0x00000001, + + //! Serialization/Deserializion is done for an editor property box + EARWF_FOR_EDITOR = 0x00000002, + + //! When writing filenames, relative paths should be used + EARWF_USE_RELATIVE_PATHS = 0x00000004 +}; + + +//! struct holding data describing options +struct SAttributeReadWriteOptions +{ + //! Constructor + SAttributeReadWriteOptions() + : Flags(0), Filename(0) + { + } + + //! Combination of E_ATTRIBUTE_READ_WRITE_FLAGS or other, custom ones + s32 Flags; + + //! Optional filename + const fschar_t* Filename; +}; + + +//! An object which is able to serialize and deserialize its attributes into an attributes object +class IAttributeExchangingObject : virtual public IReferenceCounted +{ +public: + + //! Writes attributes of the object. + /** Implement this to expose the attributes of your scene node animator for + scripting languages, editors, debuggers or xml serialization purposes. */ + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} + + //! Reads attributes of the object. + /** Implement this to set the attributes of your scene node animator for + scripting languages, editors, debuggers or xml deserialization purposes. */ + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) {} + +}; + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IAttributes.h b/inc/IAttributes.h new file mode 100644 index 0000000..bc77180 --- /dev/null +++ b/inc/IAttributes.h @@ -0,0 +1,738 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ATTRIBUTES_H_INCLUDED__ +#define __I_ATTRIBUTES_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SColor.h" +#include "vector3d.h" +#include "vector2d.h" +#include "line2d.h" +#include "line3d.h" +#include "triangle3d.h" +#include "position2d.h" +#include "rect.h" +#include "dimension2d.h" +#include "matrix4.h" +#include "quaternion.h" +#include "plane3d.h" +#include "triangle3d.h" +#include "line2d.h" +#include "line3d.h" +#include "irrString.h" +#include "irrArray.h" +#include "IXMLReader.h" +#include "EAttributes.h" +#include "path.h" + +namespace irr +{ +namespace video +{ + class ITexture; +} // end namespace video +namespace io +{ + class IXMLWriter; + +//! Provides a generic interface for attributes and their values and the possiblity to serialize them +class IAttributes : public virtual IReferenceCounted +{ +public: + + //! Returns amount of attributes in this collection of attributes. + virtual u32 getAttributeCount() const = 0; + + //! Returns attribute name by index. + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual const c8* getAttributeName(s32 index) = 0; + + //! Returns the type of an attribute + //! \param attributeName: Name for the attribute + virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName) = 0; + + //! Returns attribute type by index. + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index) = 0; + + //! Returns the type string of the attribute + //! \param attributeName: String for the attribute type + virtual const wchar_t* getAttributeTypeString(const c8* attributeName) = 0; + + //! Returns the type string of the attribute by index. + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual const wchar_t* getAttributeTypeString(s32 index) = 0; + + //! Returns if an attribute with a name exists + virtual bool existsAttribute(const c8* attributeName) = 0; + + //! Returns attribute index from name, -1 if not found + virtual s32 findAttribute(const c8* attributeName) const =0; + + //! Removes all attributes + virtual void clear() = 0; + + //! Reads attributes from a xml file. + //! \param reader The XML reader to read from + //! \param readCurrentElementOnly If set to true, reading only works if current element has the name 'attributes' or + //! the name specified using elementName. + //! \param elementName The surrounding element name. If it is null, the default one, "attributes" will be taken. + //! If set to false, the first appearing list of attributes are read. + virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false, const wchar_t* elementName=0) = 0; + + //! Write these attributes into a xml file + //! \param writer: The XML writer to write to + //! \param writeXMLHeader: Writes a header to the XML file, required if at the beginning of the file + //! \param elementName: The surrounding element name. If it is null, the default one, "attributes" will be taken. + virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* elementName=0) = 0; + + + /* + + Integer Attribute + + */ + + //! Adds an attribute as integer + virtual void addInt(const c8* attributeName, s32 value) = 0; + + //! Sets an attribute as integer value + virtual void setAttribute(const c8* attributeName, s32 value) = 0; + + //! Gets an attribute as integer value + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual s32 getAttributeAsInt(const c8* attributeName) const =0; + + //! Gets an attribute as integer value + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual s32 getAttributeAsInt(s32 index) const =0; + + //! Sets an attribute as integer value + virtual void setAttribute(s32 index, s32 value) = 0; + + /* + + Float Attribute + + */ + + //! Adds an attribute as float + virtual void addFloat(const c8* attributeName, f32 value) = 0; + + //! Sets a attribute as float value + virtual void setAttribute(const c8* attributeName, f32 value) = 0; + + //! Gets an attribute as float value + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual f32 getAttributeAsFloat(const c8* attributeName) = 0; + + //! Gets an attribute as float value + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual f32 getAttributeAsFloat(s32 index) = 0; + + //! Sets an attribute as float value + virtual void setAttribute(s32 index, f32 value) = 0; + + /* + + String Attribute + + */ + + //! Adds an attribute as string + virtual void addString(const c8* attributeName, const c8* value) = 0; + + //! Sets an attribute value as string. + //! \param attributeName: Name for the attribute + //! \param value: Value for the attribute. Set this to 0 to delete the attribute + virtual void setAttribute(const c8* attributeName, const c8* value) = 0; + + //! Gets an attribute as string. + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + //! or 0 if attribute is not set. + virtual core::stringc getAttributeAsString(const c8* attributeName) = 0; + + //! Gets an attribute as string. + //! \param attributeName Name of the attribute to get. + //! \param target Buffer where the string is copied to. + virtual void getAttributeAsString(const c8* attributeName, c8* target) = 0; + + //! Returns attribute value as string by index. + //! \param index Index value, must be between 0 and getAttributeCount()-1. + virtual core::stringc getAttributeAsString(s32 index) = 0; + + //! Sets an attribute value as string. + //! \param index Index value, must be between 0 and getAttributeCount()-1. + //! \param value String to which the attribute is set. + virtual void setAttribute(s32 index, const c8* value) = 0; + + // wide strings + + //! Adds an attribute as string + virtual void addString(const c8* attributeName, const wchar_t* value) = 0; + + //! Sets an attribute value as string. + //! \param attributeName: Name for the attribute + //! \param value: Value for the attribute. Set this to 0 to delete the attribute + virtual void setAttribute(const c8* attributeName, const wchar_t* value) = 0; + + //! Gets an attribute as string. + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + //! or 0 if attribute is not set. + virtual core::stringw getAttributeAsStringW(const c8* attributeName) = 0; + + //! Gets an attribute as string. + //! \param attributeName: Name of the attribute to get. + //! \param target: Buffer where the string is copied to. + virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target) = 0; + + //! Returns attribute value as string by index. + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::stringw getAttributeAsStringW(s32 index) = 0; + + //! Sets an attribute value as string. + //! \param index Index value, must be between 0 and getAttributeCount()-1. + //! \param value String to which the attribute is set. + virtual void setAttribute(s32 index, const wchar_t* value) = 0; + + /* + + Binary Data Attribute + + */ + + //! Adds an attribute as binary data + virtual void addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes) = 0; + + //! Sets an attribute as binary data + virtual void setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes ) = 0; + + //! Gets an attribute as binary data + /** \param attributeName: Name of the attribute to get. + \param outData Pointer to buffer where data shall be stored. + \param maxSizeInBytes Maximum number of bytes to write into outData. + */ + virtual void getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes) = 0; + + //! Gets an attribute as binary data + /** \param index: Index value, must be between 0 and getAttributeCount()-1. + \param outData Pointer to buffer where data shall be stored. + \param maxSizeInBytes Maximum number of bytes to write into outData. + */ + virtual void getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes) = 0; + + //! Sets an attribute as binary data + virtual void setAttribute(s32 index, void* data, s32 dataSizeInBytes ) = 0; + + + /* + Array Attribute + */ + + //! Adds an attribute as wide string array + virtual void addArray(const c8* attributeName, const core::array& value) = 0; + + //! Sets an attribute value as a wide string array. + //! \param attributeName: Name for the attribute + //! \param value: Value for the attribute. Set this to 0 to delete the attribute + virtual void setAttribute(const c8* attributeName, const core::array& value) = 0; + + //! Gets an attribute as an array of wide strings. + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + //! or 0 if attribute is not set. + virtual core::array getAttributeAsArray(const c8* attributeName) = 0; + + //! Returns attribute value as an array of wide strings by index. + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::array getAttributeAsArray(s32 index) = 0; + + //! Sets an attribute as an array of wide strings + virtual void setAttribute(s32 index, const core::array& value) = 0; + + + /* + + Bool Attribute + + */ + + //! Adds an attribute as bool + virtual void addBool(const c8* attributeName, bool value) = 0; + + //! Sets an attribute as boolean value + virtual void setAttribute(const c8* attributeName, bool value) = 0; + + //! Gets an attribute as boolean value + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual bool getAttributeAsBool(const c8* attributeName) = 0; + + //! Gets an attribute as boolean value + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual bool getAttributeAsBool(s32 index) = 0; + + //! Sets an attribute as boolean value + virtual void setAttribute(s32 index, bool value) = 0; + + /* + + Enumeration Attribute + + */ + + //! Adds an attribute as enum + virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) = 0; + + //! Adds an attribute as enum + virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals) = 0; + + //! Sets an attribute as enumeration + virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) = 0; + + //! Gets an attribute as enumeration + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual const c8* getAttributeAsEnumeration(const c8* attributeName) = 0; + + //! Gets an attribute as enumeration + /** \param attributeName: Name of the attribute to get. + \param enumerationLiteralsToUse: Use these enumeration literals to get + the index value instead of the set ones. This is useful when the + attribute list maybe was read from an xml file, and only contains the + enumeration string, but no information about its index. + \return Returns value of the attribute previously set by setAttribute() + */ + virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse) = 0; + + //! Gets an attribute as enumeration + /** \param index: Index value, must be between 0 and getAttributeCount()-1. + \param enumerationLiteralsToUse: Use these enumeration literals to get + the index value instead of the set ones. This is useful when the + attribute list maybe was read from an xml file, and only contains the + enumeration string, but no information about its index. + \return Returns value of the attribute previously set by setAttribute() + */ + virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse) = 0; + + //! Gets an attribute as enumeration + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual const c8* getAttributeAsEnumeration(s32 index) = 0; + + //! Gets the list of enumeration literals of an enumeration attribute + //! \param attributeName Name of the attribute to get. + //! \param outLiterals Set of strings to choose the enum name from. + virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array& outLiterals) = 0; + + //! Gets the list of enumeration literals of an enumeration attribute + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + //! \param outLiterals Set of strings to choose the enum name from. + virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array& outLiterals) = 0; + + //! Sets an attribute as enumeration + virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals) = 0; + + + /* + + SColor Attribute + + */ + + //! Adds an attribute as color + virtual void addColor(const c8* attributeName, video::SColor value) = 0; + + + //! Sets a attribute as color + virtual void setAttribute(const c8* attributeName, video::SColor color) = 0; + + //! Gets an attribute as color + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual video::SColor getAttributeAsColor(const c8* attributeName) = 0; + + //! Gets an attribute as color + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual video::SColor getAttributeAsColor(s32 index) = 0; + + //! Sets an attribute as color + virtual void setAttribute(s32 index, video::SColor color) = 0; + + /* + + SColorf Attribute + + */ + + //! Adds an attribute as floating point color + virtual void addColorf(const c8* attributeName, video::SColorf value) = 0; + + //! Sets a attribute as floating point color + virtual void setAttribute(const c8* attributeName, video::SColorf color) = 0; + + //! Gets an attribute as floating point color + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual video::SColorf getAttributeAsColorf(const c8* attributeName) = 0; + + //! Gets an attribute as floating point color + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual video::SColorf getAttributeAsColorf(s32 index) = 0; + + //! Sets an attribute as floating point color + virtual void setAttribute(s32 index, video::SColorf color) = 0; + + + /* + + Vector3d Attribute + + */ + + //! Adds an attribute as 3d vector + virtual void addVector3d(const c8* attributeName, core::vector3df value) = 0; + + //! Sets a attribute as 3d vector + virtual void setAttribute(const c8* attributeName, core::vector3df v) = 0; + + //! Gets an attribute as 3d vector + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::vector3df getAttributeAsVector3d(const c8* attributeName) = 0; + + //! Gets an attribute as 3d vector + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::vector3df getAttributeAsVector3d(s32 index) = 0; + + //! Sets an attribute as vector + virtual void setAttribute(s32 index, core::vector3df v) = 0; + + /* + + Vector2d Attribute + + */ + + //! Adds an attribute as 2d vector + virtual void addVector2d(const c8* attributeName, core::vector2df value) = 0; + + //! Sets a attribute as 2d vector + virtual void setAttribute(const c8* attributeName, core::vector2df v) = 0; + + //! Gets an attribute as vector + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::vector2df getAttributeAsVector2d(const c8* attributeName) = 0; + + //! Gets an attribute as position + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::vector2df getAttributeAsVector2d(s32 index) = 0; + + //! Sets an attribute as 2d vector + virtual void setAttribute(s32 index, core::vector2df v) = 0; + + /* + + Position2d Attribute + + */ + + //! Adds an attribute as 2d position + virtual void addPosition2d(const c8* attributeName, core::position2di value) = 0; + + //! Sets a attribute as 2d position + virtual void setAttribute(const c8* attributeName, core::position2di v) = 0; + + //! Gets an attribute as position + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::position2di getAttributeAsPosition2d(const c8* attributeName) = 0; + + //! Gets an attribute as position + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::position2di getAttributeAsPosition2d(s32 index) = 0; + + //! Sets an attribute as 2d position + virtual void setAttribute(s32 index, core::position2di v) = 0; + + /* + + Rectangle Attribute + + */ + + //! Adds an attribute as rectangle + virtual void addRect(const c8* attributeName, core::rect value) = 0; + + //! Sets an attribute as rectangle + virtual void setAttribute(const c8* attributeName, core::rect v) = 0; + + //! Gets an attribute as rectangle + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::rect getAttributeAsRect(const c8* attributeName) = 0; + + //! Gets an attribute as rectangle + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::rect getAttributeAsRect(s32 index) = 0; + + //! Sets an attribute as rectangle + virtual void setAttribute(s32 index, core::rect v) = 0; + + + /* + + Dimension2d Attribute + + */ + + //! Adds an attribute as dimension2d + virtual void addDimension2d(const c8* attributeName, core::dimension2d value) = 0; + + //! Sets an attribute as dimension2d + virtual void setAttribute(const c8* attributeName, core::dimension2d v) = 0; + + //! Gets an attribute as dimension2d + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::dimension2d getAttributeAsDimension2d(const c8* attributeName) = 0; + + //! Gets an attribute as dimension2d + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::dimension2d getAttributeAsDimension2d(s32 index) = 0; + + //! Sets an attribute as dimension2d + virtual void setAttribute(s32 index, core::dimension2d v) = 0; + + + /* + matrix attribute + */ + + //! Adds an attribute as matrix + virtual void addMatrix(const c8* attributeName, const core::matrix4& v) = 0; + + //! Sets an attribute as matrix + virtual void setAttribute(const c8* attributeName, const core::matrix4& v) = 0; + + //! Gets an attribute as a matrix4 + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName) = 0; + + //! Gets an attribute as matrix + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::matrix4 getAttributeAsMatrix(s32 index) = 0; + + //! Sets an attribute as matrix + virtual void setAttribute(s32 index, const core::matrix4& v) = 0; + + /* + quaternion attribute + + */ + + //! Adds an attribute as quaternion + virtual void addQuaternion(const c8* attributeName, core::quaternion v) = 0; + + //! Sets an attribute as quaternion + virtual void setAttribute(const c8* attributeName, core::quaternion v) = 0; + + //! Gets an attribute as a quaternion + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName) = 0; + + //! Gets an attribute as quaternion + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::quaternion getAttributeAsQuaternion(s32 index) = 0; + + //! Sets an attribute as quaternion + virtual void setAttribute(s32 index, core::quaternion v) = 0; + + /* + + 3d bounding box + + */ + + //! Adds an attribute as axis aligned bounding box + virtual void addBox3d(const c8* attributeName, core::aabbox3df v) = 0; + + //! Sets an attribute as axis aligned bounding box + virtual void setAttribute(const c8* attributeName, core::aabbox3df v) = 0; + + //! Gets an attribute as a axis aligned bounding box + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName) = 0; + + //! Gets an attribute as axis aligned bounding box + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::aabbox3df getAttributeAsBox3d(s32 index) = 0; + + //! Sets an attribute as axis aligned bounding box + virtual void setAttribute(s32 index, core::aabbox3df v) = 0; + + /* + + plane + + */ + + //! Adds an attribute as 3d plane + virtual void addPlane3d(const c8* attributeName, core::plane3df v) = 0; + + //! Sets an attribute as 3d plane + virtual void setAttribute(const c8* attributeName, core::plane3df v) = 0; + + //! Gets an attribute as a 3d plane + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName) = 0; + + //! Gets an attribute as 3d plane + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::plane3df getAttributeAsPlane3d(s32 index) = 0; + + //! Sets an attribute as 3d plane + virtual void setAttribute(s32 index, core::plane3df v) = 0; + + + /* + + 3d triangle + + */ + + //! Adds an attribute as 3d triangle + virtual void addTriangle3d(const c8* attributeName, core::triangle3df v) = 0; + + //! Sets an attribute as 3d trianle + virtual void setAttribute(const c8* attributeName, core::triangle3df v) = 0; + + //! Gets an attribute as a 3d triangle + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName) = 0; + + //! Gets an attribute as 3d triangle + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::triangle3df getAttributeAsTriangle3d(s32 index) = 0; + + //! Sets an attribute as 3d triangle + virtual void setAttribute(s32 index, core::triangle3df v) = 0; + + + /* + + line 2d + + */ + + //! Adds an attribute as a 2d line + virtual void addLine2d(const c8* attributeName, core::line2df v) = 0; + + //! Sets an attribute as a 2d line + virtual void setAttribute(const c8* attributeName, core::line2df v) = 0; + + //! Gets an attribute as a 2d line + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::line2df getAttributeAsLine2d(const c8* attributeName) = 0; + + //! Gets an attribute as a 2d line + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::line2df getAttributeAsLine2d(s32 index) = 0; + + //! Sets an attribute as a 2d line + virtual void setAttribute(s32 index, core::line2df v) = 0; + + + /* + + line 3d + + */ + + //! Adds an attribute as a 3d line + virtual void addLine3d(const c8* attributeName, core::line3df v) = 0; + + //! Sets an attribute as a 3d line + virtual void setAttribute(const c8* attributeName, core::line3df v) = 0; + + //! Gets an attribute as a 3d line + //! \param attributeName: Name of the attribute to get. + //! \return Returns value of the attribute previously set by setAttribute() + virtual core::line3df getAttributeAsLine3d(const c8* attributeName) = 0; + + //! Gets an attribute as a 3d line + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual core::line3df getAttributeAsLine3d(s32 index) = 0; + + //! Sets an attribute as a 3d line + virtual void setAttribute(s32 index, core::line3df v) = 0; + + + /* + + Texture Attribute + + */ + + //! Adds an attribute as texture reference + virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") = 0; + + //! Sets an attribute as texture reference + virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") = 0; + + //! Gets an attribute as texture reference + //! \param attributeName: Name of the attribute to get. + virtual video::ITexture* getAttributeAsTexture(const c8* attributeName) = 0; + + //! Gets an attribute as texture reference + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual video::ITexture* getAttributeAsTexture(s32 index) = 0; + + //! Sets an attribute as texture reference + virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = "") = 0; + + + /* + + User Pointer Attribute + + */ + + //! Adds an attribute as user pointner + virtual void addUserPointer(const c8* attributeName, void* userPointer) = 0; + + //! Sets an attribute as user pointer + virtual void setAttribute(const c8* attributeName, void* userPointer) = 0; + + //! Gets an attribute as user pointer + //! \param attributeName: Name of the attribute to get. + virtual void* getAttributeAsUserPointer(const c8* attributeName) = 0; + + //! Gets an attribute as user pointer + //! \param index: Index value, must be between 0 and getAttributeCount()-1. + virtual void* getAttributeAsUserPointer(s32 index) = 0; + + //! Sets an attribute as user pointer + virtual void setAttribute(s32 index, void* userPointer) = 0; + +}; + +} // end namespace io +} // end namespace irr + +#endif + + + diff --git a/inc/IBillboardSceneNode.h b/inc/IBillboardSceneNode.h new file mode 100644 index 0000000..1c931d7 --- /dev/null +++ b/inc/IBillboardSceneNode.h @@ -0,0 +1,75 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_BILLBOARD_SCENE_NODE_H_INCLUDED__ +#define __I_BILLBOARD_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! A billboard scene node. +/** A billboard is like a 3d sprite: A 2d element, +which always looks to the camera. It is usually used for explosions, fire, +lensflares, particles and things like that. +*/ +class IBillboardSceneNode : public ISceneNode +{ +public: + + //! Constructor + IBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0)) + : ISceneNode(parent, mgr, id, position) {} + + //! Sets the size of the billboard, making it rectangular. + virtual void setSize(const core::dimension2d& size) = 0; + + //! Sets the size of the billboard with independent widths of the bottom and top edges. + /** \param[in] height The height of the billboard. + \param[in] bottomEdgeWidth The width of the bottom edge of the billboard. + \param[in] topEdgeWidth The width of the top edge of the billboard. + */ + virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) = 0; + + //! Returns the size of the billboard. + /** This will return the width of the bottom edge of the billboard. + Use getWidths() to retrieve the bottom and top edges independently. + \return Size of the billboard. + */ + virtual const core::dimension2d& getSize() const = 0; + + //! Gets the size of the the billboard and handles independent top and bottom edge widths correctly. + /** \param[out] height The height of the billboard. + \param[out] bottomEdgeWidth The width of the bottom edge of the billboard. + \param[out] topEdgeWidth The width of the top edge of the billboard. + */ + virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const =0; + + //! Set the color of all vertices of the billboard + /** \param[in] overallColor Color to set */ + virtual void setColor(const video::SColor& overallColor) = 0; + + //! Set the color of the top and bottom vertices of the billboard + /** \param[in] topColor Color to set the top vertices + \param[in] bottomColor Color to set the bottom vertices */ + virtual void setColor(const video::SColor& topColor, + const video::SColor& bottomColor) = 0; + + //! Gets the color of the top and bottom vertices of the billboard + /** \param[out] topColor Stores the color of the top vertices + \param[out] bottomColor Stores the color of the bottom vertices */ + virtual void getColor(video::SColor& topColor, + video::SColor& bottomColor) const = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IBillboardTextSceneNode.h b/inc/IBillboardTextSceneNode.h new file mode 100644 index 0000000..30925da --- /dev/null +++ b/inc/IBillboardTextSceneNode.h @@ -0,0 +1,62 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_BILLBOARD_TEXT_SCENE_NODE_H_INCLUDED__ +#define __I_BILLBOARD_TEXT_SCENE_NODE_H_INCLUDED__ + +#include "IBillboardSceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! A billboard text scene node. +/** Acts like a billboard which displays the currently set text. + Due to the exclusion of RTTI in Irrlicht we have to avoid multiple + inheritance. Hence, changes to the ITextSceneNode interface have + to be copied here manually. +*/ +class IBillboardTextSceneNode : public IBillboardSceneNode +{ +public: + + //! Constructor + IBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0)) + : IBillboardSceneNode(parent, mgr, id, position) {} + + //! Sets the size of the billboard. + virtual void setSize(const core::dimension2d& size) = 0; + + //! Returns the size of the billboard. + virtual const core::dimension2d& getSize() const = 0; + + //! Set the color of all vertices of the billboard + /** \param overallColor: the color to set */ + virtual void setColor(const video::SColor & overallColor) = 0; + + //! Set the color of the top and bottom vertices of the billboard + /** \param topColor: the color to set the top vertices + \param bottomColor: the color to set the bottom vertices */ + virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor) = 0; + + //! Gets the color of the top and bottom vertices of the billboard + /** \param topColor: stores the color of the top vertices + \param bottomColor: stores the color of the bottom vertices */ + virtual void getColor(video::SColor & topColor, video::SColor & bottomColor) const = 0; + + //! sets the text string + virtual void setText(const wchar_t* text) = 0; + + //! sets the color of the text + virtual void setTextColor(video::SColor color) = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IBoneSceneNode.h b/inc/IBoneSceneNode.h new file mode 100644 index 0000000..d0063b4 --- /dev/null +++ b/inc/IBoneSceneNode.h @@ -0,0 +1,108 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_BONE_SCENE_NODE_H_INCLUDED__ +#define __I_BONE_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + + //! Enumeration for different bone animation modes + enum E_BONE_ANIMATION_MODE + { + //! The bone is usually animated, unless it's parent is not animated + EBAM_AUTOMATIC=0, + + //! The bone is animated by the skin, if it's parent is not animated then animation will resume from this bone onward + EBAM_ANIMATED, + + //! The bone is not animated by the skin + EBAM_UNANIMATED, + + //! Not an animation mode, just here to count the available modes + EBAM_COUNT + + }; + + enum E_BONE_SKINNING_SPACE + { + //! local skinning, standard + EBSS_LOCAL=0, + + //! global skinning + EBSS_GLOBAL, + + EBSS_COUNT + }; + + //! Names for bone animation modes + const c8* const BoneAnimationModeNames[] = + { + "automatic", + "animated", + "unanimated", + 0, + }; + + + //! Interface for bones used for skeletal animation. + /** Used with ISkinnedMesh and IAnimatedMeshSceneNode. */ + class IBoneSceneNode : public ISceneNode + { + public: + + IBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id=-1) : + ISceneNode(parent, mgr, id),positionHint(-1),scaleHint(-1),rotationHint(-1) { } + + //! Get the name of the bone + /** \deprecated Use getName instead. This method may be removed by Irrlicht 1.9 */ + _IRR_DEPRECATED_ virtual const c8* getBoneName() const { return getName(); } + + //! Get the index of the bone + virtual u32 getBoneIndex() const = 0; + + //! Sets the animation mode of the bone. + /** \return True if successful. (Unused) */ + virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode) = 0; + + //! Gets the current animation mode of the bone + virtual E_BONE_ANIMATION_MODE getAnimationMode() const = 0; + + //! Get the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const = 0; + + //! Returns the relative transformation of the scene node. + //virtual core::matrix4 getRelativeTransformation() const = 0; + + //! The animation method. + virtual void OnAnimate(u32 timeMs) =0; + + //! The render method. + /** Does nothing as bones are not visible. */ + virtual void render() { } + + //! How the relative transformation of the bone is used + virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space ) =0; + + //! How the relative transformation of the bone is used + virtual E_BONE_SKINNING_SPACE getSkinningSpace() const =0; + + //! Updates the absolute position based on the relative and the parents position + virtual void updateAbsolutePositionOfAllChildren()=0; + + s32 positionHint; + s32 scaleHint; + s32 rotationHint; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ICameraSceneNode.h b/inc/ICameraSceneNode.h new file mode 100644 index 0000000..dfc1b7a --- /dev/null +++ b/inc/ICameraSceneNode.h @@ -0,0 +1,207 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_CAMERA_SCENE_NODE_H_INCLUDED__ +#define __I_CAMERA_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" +#include "IEventReceiver.h" + +namespace irr +{ +namespace scene +{ + struct SViewFrustum; + + //! Scene Node which is a (controlable) camera. + /** The whole scene will be rendered from the cameras point of view. + Because the ICameraScenNode is a SceneNode, it can be attached to any + other scene node, and will follow its parents movement, rotation and so + on. + */ + class ICameraSceneNode : public ISceneNode, public IEventReceiver + { + public: + + //! Constructor + ICameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f)) + : ISceneNode(parent, mgr, id, position, rotation, scale), IsOrthogonal(false) {} + + //! Sets the projection matrix of the camera. + /** The core::matrix4 class has some methods to build a + projection matrix. e.g: + core::matrix4::buildProjectionMatrixPerspectiveFovLH. + Note that the matrix will only stay as set by this method until + one of the following Methods are called: setNearValue, + setFarValue, setAspectRatio, setFOV. + \param projection The new projection matrix of the camera. + \param isOrthogonal Set this to true if the matrix is an + orthogonal one (e.g. from matrix4::buildProjectionMatrixOrtho). + */ + virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal=false) =0; + + //! Gets the current projection matrix of the camera. + /** \return The current projection matrix of the camera. */ + virtual const core::matrix4& getProjectionMatrix() const =0; + + //! Gets the current view matrix of the camera. + /** \return The current view matrix of the camera. */ + virtual const core::matrix4& getViewMatrix() const =0; + + //! Sets a custom view matrix affector. + /** The matrix passed here, will be multiplied with the view + matrix when it gets updated. This allows for custom camera + setups like, for example, a reflection camera. + \param affector The affector matrix. */ + virtual void setViewMatrixAffector(const core::matrix4& affector) =0; + + //! Get the custom view matrix affector. + /** \return The affector matrix. */ + virtual const core::matrix4& getViewMatrixAffector() const =0; + + //! It is possible to send mouse and key events to the camera. + /** Most cameras may ignore this input, but camera scene nodes + which are created for example with + ISceneManager::addCameraSceneNodeMaya or + ISceneManager::addCameraSceneNodeFPS, may want to get + this input for changing their position, look at target or + whatever. */ + virtual bool OnEvent(const SEvent& event) =0; + + //! Sets the look at target of the camera + /** If the camera's target and rotation are bound ( @see + bindTargetAndRotation() ) then calling this will also change + the camera's scene node rotation to match the target. + Note that setTarget uses the current absolute position + internally, so if you changed setPosition since last rendering you must + call updateAbsolutePosition before using this function. + \param pos Look at target of the camera, in world co-ordinates. */ + virtual void setTarget(const core::vector3df& pos) =0; + + //! Sets the rotation of the node. + /** This only modifies the relative rotation of the node. + If the camera's target and rotation are bound ( @see + bindTargetAndRotation() ) then calling this will also change + the camera's target to match the rotation. + \param rotation New rotation of the node in degrees. */ + virtual void setRotation(const core::vector3df& rotation) =0; + + //! Gets the current look at target of the camera + /** \return The current look at target of the camera, in world co-ordinates */ + virtual const core::vector3df& getTarget() const =0; + + //! Sets the up vector of the camera. + /** \param pos: New upvector of the camera. */ + virtual void setUpVector(const core::vector3df& pos) =0; + + //! Gets the up vector of the camera. + /** \return The up vector of the camera, in world space. */ + virtual const core::vector3df& getUpVector() const =0; + + //! Gets the value of the near plane of the camera. + /** \return The value of the near plane of the camera. */ + virtual f32 getNearValue() const =0; + + //! Gets the value of the far plane of the camera. + /** \return The value of the far plane of the camera. */ + virtual f32 getFarValue() const =0; + + //! Gets the aspect ratio of the camera. + /** \return The aspect ratio of the camera. */ + virtual f32 getAspectRatio() const =0; + + //! Gets the field of view of the camera. + /** \return The field of view of the camera in radians. */ + virtual f32 getFOV() const =0; + + //! Sets the value of the near clipping plane. (default: 1.0f) + /** \param zn: New z near value. */ + virtual void setNearValue(f32 zn) =0; + + //! Sets the value of the far clipping plane (default: 2000.0f) + /** \param zf: New z far value. */ + virtual void setFarValue(f32 zf) =0; + + //! Sets the aspect ratio (default: 4.0f / 3.0f) + /** \param aspect: New aspect ratio. */ + virtual void setAspectRatio(f32 aspect) =0; + + //! Sets the field of view (Default: PI / 2.5f) + /** \param fovy: New field of view in radians. */ + virtual void setFOV(f32 fovy) =0; + + //! Get the view frustum. + /** Needed sometimes by bspTree or LOD render nodes. + \return The current view frustum. */ + virtual const SViewFrustum* getViewFrustum() const =0; + + //! Disables or enables the camera to get key or mouse inputs. + /** If this is set to true, the camera will respond to key + inputs otherwise not. */ + virtual void setInputReceiverEnabled(bool enabled) =0; + + //! Checks if the input receiver of the camera is currently enabled. + virtual bool isInputReceiverEnabled() const =0; + + //! Checks if a camera is orthogonal. + virtual bool isOrthogonal() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsOrthogonal; + } + + //! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them. + /** When bound, calling setRotation() will update the camera's + target position to be along its +Z axis, and likewise calling + setTarget() will update its rotation so that its +Z axis will + point at the target point. FPS camera use this binding by + default; other cameras do not. + \param bound True to bind the camera's scene node rotation + and targetting, false to unbind them. + @see getTargetAndRotationBinding() */ + virtual void bindTargetAndRotation(bool bound) =0; + + //! Queries if the camera scene node's rotation and its target position are bound together. + /** @see bindTargetAndRotation() */ + virtual bool getTargetAndRotationBinding(void) const =0; + + //! Writes attributes of the camera node + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const + { + ISceneNode::serializeAttributes(out, options); + + if (!out) + return; + out->addBool ("IsOrthogonal", IsOrthogonal ); + } + + //! Reads attributes of the camera node + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) + { + ISceneNode::deserializeAttributes(in, options); + if (!in) + return; + + if ( in->findAttribute("IsOrthogonal") ) + IsOrthogonal = in->getAttributeAsBool("IsOrthogonal"); + } + + protected: + + void cloneMembers(ICameraSceneNode* toCopyFrom) + { + IsOrthogonal = toCopyFrom->IsOrthogonal; + } + + bool IsOrthogonal; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IColladaMeshWriter.h b/inc/IColladaMeshWriter.h new file mode 100644 index 0000000..6b16319 --- /dev/null +++ b/inc/IColladaMeshWriter.h @@ -0,0 +1,405 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ +#define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ + +#include "IMeshWriter.h" +#include "ISceneNode.h" +#include "IAnimatedMesh.h" +#include "SMaterial.h" + +namespace irr +{ +namespace io +{ + class IWriteFile; +} // end namespace io + +namespace scene +{ + //! Lighting models - more or less the way Collada categorizes materials + enum E_COLLADA_TECHNIQUE_FX + { + //! Blinn-phong which is default for opengl and dx fixed function pipelines. + //! But several well-known renderers don't support it and prefer phong. + ECTF_BLINN, + //! Phong shading, default in many external renderers. + ECTF_PHONG, + //! diffuse shaded surface that is independent of lighting. + ECTF_LAMBERT, + // constantly shaded surface that is independent of lighting. + ECTF_CONSTANT + }; + + //! How to interpret the opacity in collada + enum E_COLLADA_TRANSPARENT_FX + { + //! default - only alpha channel of color or texture is used. + ECOF_A_ONE = 0, + + //! Alpha values for each RGB channel of color or texture are used. + ECOF_RGB_ZERO = 1 + }; + + //! Color names collada uses in it's color samplers + enum E_COLLADA_COLOR_SAMPLER + { + ECCS_DIFFUSE, + ECCS_AMBIENT, + ECCS_EMISSIVE, + ECCS_SPECULAR, + ECCS_TRANSPARENT, + ECCS_REFLECTIVE + }; + + //! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values + enum E_COLLADA_IRR_COLOR + { + //! Don't write this element at all + ECIC_NONE, + + //! Check IColladaMeshWriterProperties for custom color + ECIC_CUSTOM, + + //! Use SMaterial::DiffuseColor + ECIC_DIFFUSE, + + //! Use SMaterial::AmbientColor + ECIC_AMBIENT, + + //! Use SMaterial::EmissiveColor + ECIC_EMISSIVE, + + //! Use SMaterial::SpecularColor + ECIC_SPECULAR + }; + + //! Control when geometry elements are created + enum E_COLLADA_GEOMETRY_WRITING + { + //! Default - write each mesh exactly once to collada. Optimal but will not work with many tools. + ECGI_PER_MESH, + + //! Write each mesh as often as it's used with different materials-names in the scene. + //! Material names which are used here are created on export, so using the IColladaMeshWriterNames + //! interface you have some control over how many geometries are written. + ECGI_PER_MESH_AND_MATERIAL + }; + + //! Callback interface for properties which can be used to influence collada writing + class IColladaMeshWriterProperties : public virtual IReferenceCounted + { + public: + virtual ~IColladaMeshWriterProperties () {} + + //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) + virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0; + + //! Which texture index should be used when writing the texture of the given sampler color. + /** \return the index to the texture-layer or -1 if that texture should never be exported + Note: for ECCS_TRANSPARENT by default the alpha channel is used, if you want to use RGB you have to set + also the ECOF_RGB_ZERO flag in getTransparentFx. */ + virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; + + //! Return which color from Irrlicht should be used for the color requested by collada + /** Note that collada allows exporting either texture or color, not both. + So color mapping is only checked if we have no valid texture already. + By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE. + When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */ + virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; + + //! Return custom colors for certain color types requested by collada. + /** Only used when getColorMapping returns ECIC_CUSTOM for the same paramters. */ + virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; + + //! Return the transparence color interpretation. + /** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */ + virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0; + + //! Transparency value for that material. + /** This value is additional to transparent settings, if both are set they will be multiplicated. + \return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */ + virtual f32 getTransparency(const video::SMaterial& material) const = 0; + + //! Reflectivity value for that material + /** The amount of perfect mirror reflection to be added to the reflected light + \return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */ + virtual f32 getReflectivity(const video::SMaterial& material) const = 0; + + //! Return index of refraction for that material + /** By default we don't write that. + \return a value greater equal 0.f to write \ when it is lesser than 0 nothing will be written */ + virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0; + + //! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing) + //! By default all visible nodes are exported. + virtual bool isExportable(const irr::scene::ISceneNode * node) const = 0; + + //! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh + //! you can return 0 in which case only the transformation matrix of the node will be used. + // Note: Function is not const because there is no const getMesh() function. + virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0; + + //! Return if the node has it's own material overwriting the mesh-materials + /** Usually true except for mesh-nodes which have isReadOnlyMaterials set. + This is mostly important for naming (as ISceneNode::getMaterial() already returns the correct material). + You have to override it when exporting custom scenenodes with own materials. + \return true => The node's own material is used, false => ignore node material and use the one from the mesh */ + virtual bool useNodeMaterial(const scene::ISceneNode* node) const = 0; + + }; + + //! Callback interface to use custom names on collada writing. + /** You can either modify names and id's written to collada or you can use + this interface to just find out which names are used on writing. + */ + class IColladaMeshWriterNames : public virtual IReferenceCounted + { + public: + + virtual ~IColladaMeshWriterNames () {} + + //! Return a unique name for the given mesh + /** Note that names really must be unique here per mesh-pointer, so + mostly it's a good idea to return the nameForMesh from + IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow + the xs::NCName standard to be valid, you can run them through + IColladaMeshWriter::toNCName to ensure that. + \param mesh Pointer to the mesh which needs a name + \param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then + several instances of the same mesh can be written and this counts them. + */ + virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) = 0; + + //! Return a unique name for the given node + /** Note that names really must be unique here per node-pointer, so + mostly it's a good idea to return the nameForNode from + IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow + the xs::NCName standard to be valid, you can run them through + IColladaMeshWriter::toNCName to ensure that. + */ + virtual irr::core::stringw nameForNode(const scene::ISceneNode* node) = 0; + + //! Return a name for the material + /** There is one material created in the writer for each unique name. + So you can use this to control the number of materials which get written. + For example Irrlicht does by default write one material for each material + instanced by a node. So if you know that in your application material + instances per node are identical between different nodes you can reduce + the number of exported materials using that knowledge by using identical + names for such shared materials. + Names must follow the xs::NCName standard to be valid, you can run them + through IColladaMeshWriter::toNCName to ensure that. + */ + virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0; + }; + + + //! Interface for writing meshes + class IColladaMeshWriter : public IMeshWriter + { + public: + + IColladaMeshWriter() + : Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0) + , WriteTextures(true), WriteDefaultScene(true), ExportSMaterialOnce(true) + , AmbientLight(0.f, 0.f, 0.f, 1.f) + , GeometryWriting(ECGI_PER_MESH) + { + } + + //! Destructor + virtual ~IColladaMeshWriter() + { + if ( Properties ) + Properties->drop(); + if ( DefaultProperties ) + DefaultProperties->drop(); + if ( NameGenerator ) + NameGenerator->drop(); + if ( DefaultNameGenerator ) + DefaultNameGenerator->drop(); + } + + //! writes a scene starting with the given node + virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root) = 0; + + + //! Set if texture information should be written + virtual void setWriteTextures(bool write) + { + WriteTextures = write; + } + + //! Get if texture information should be written + virtual bool getWriteTextures() const + { + return WriteTextures; + } + + //! Set if a default scene should be written when writing meshes. + /** Many collada readers fail to read a mesh if the collada files doesn't contain a scene as well. + The scene is doing an instantiation of the mesh. + When using writeScene this flag is ignored (as we have scene there already) + */ + virtual void setWriteDefaultScene(bool write) + { + WriteDefaultScene = write; + } + + //! Get if a default scene should be written + virtual bool getWriteDefaultScene() const + { + return WriteDefaultScene; + } + + //! Sets ambient color of the scene to write + virtual void setAmbientLight(const video::SColorf &ambientColor) + { + AmbientLight = ambientColor; + } + + //! Return ambient light of the scene which is written + virtual video::SColorf getAmbientLight() const + { + return AmbientLight; + } + + //! Control when and how often a mesh is written + /** Optimally ECGI_PER_MESH would be always sufficent - writing geometry once per mesh. + Unfortunately many tools (at the time of writing this nearly all of them) have trouble + on import when different materials are used per node. So when you override materials + per node and importing the resuling collada has materials problems in other tools try + using other values here. + \param writeStyle One of the E_COLLADA_GEOMETRY_WRITING settings. + */ + virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle) + { + GeometryWriting = writeStyle; + } + + //! Get the current style of geometry writing. + virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const + { + return GeometryWriting; + } + + //! Make certain there is only one collada material generated per Irrlicht material + /** Checks before creating a collada material-name if an identical + irr:::video::SMaterial has been exported already. If so don't export it with + another name. This is set by default and leads to way smaller .dae files. + Note that if you need to disable this flag for some reason you can still + get a similar effect using the IColladaMeshWriterNames::nameForMaterial + by returning identical names for identical materials there. + */ + virtual void setExportSMaterialsOnlyOnce(bool exportOnce) + { + ExportSMaterialOnce = exportOnce; + } + + virtual bool getExportSMaterialsOnlyOnce() const + { + return ExportSMaterialOnce; + } + + //! Set properties to use by the meshwriter instead of it's default properties. + /** Overloading properties with an own class allows modifying the writing process in certain ways. + By default properties are set to the DefaultProperties. */ + virtual void setProperties(IColladaMeshWriterProperties * p) + { + if ( p == Properties ) + return; + if ( p ) + p->grab(); + if ( Properties ) + Properties->drop(); + Properties = p; + } + + //! Get properties which are currently used. + virtual IColladaMeshWriterProperties * getProperties() const + { + return Properties; + } + + //! Return the original default properties of the writer. + /** You can use this pointer in your own properties to access and return default values. */ + IColladaMeshWriterProperties * getDefaultProperties() const + { + return DefaultProperties; + } + + //! Install a generator to create custom names on export. + virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator) + { + if ( nameGenerator == NameGenerator ) + return; + if ( nameGenerator ) + nameGenerator->grab(); + if ( NameGenerator ) + NameGenerator->drop(); + NameGenerator = nameGenerator; + } + + //! Get currently used name generator + virtual IColladaMeshWriterNames * getNameGenerator() const + { + return NameGenerator; + } + + //! Return the original default name generator of the writer. + /** You can use this pointer in your own generator to access and return default values. */ + IColladaMeshWriterNames * getDefaultNameGenerator() const + { + return DefaultNameGenerator; + } + + //! Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix. + /** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */ + virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const = 0; + + + protected: + // NOTE: You usually should also call setProperties with the same paraemter when using setDefaultProperties + virtual void setDefaultProperties(IColladaMeshWriterProperties * p) + { + if ( p == DefaultProperties ) + return; + if ( p ) + p->grab(); + if ( DefaultProperties ) + DefaultProperties->drop(); + DefaultProperties = p; + } + + // NOTE: You usually should also call setNameGenerator with the same paraemter when using setDefaultProperties + virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p) + { + if ( p == DefaultNameGenerator ) + return; + if ( p ) + p->grab(); + if ( DefaultNameGenerator ) + DefaultNameGenerator->drop(); + DefaultNameGenerator = p; + } + + private: + IColladaMeshWriterProperties * Properties; + IColladaMeshWriterProperties * DefaultProperties; + IColladaMeshWriterNames * NameGenerator; + IColladaMeshWriterNames * DefaultNameGenerator; + bool WriteTextures; + bool WriteDefaultScene; + bool ExportSMaterialOnce; + video::SColorf AmbientLight; + E_COLLADA_GEOMETRY_WRITING GeometryWriting; + }; + + +} // end namespace +} // end namespace + +#endif diff --git a/inc/ICursorControl.h b/inc/ICursorControl.h new file mode 100644 index 0000000..8e6bc1e --- /dev/null +++ b/inc/ICursorControl.h @@ -0,0 +1,192 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_CURSOR_CONTROL_H_INCLUDED__ +#define __I_CURSOR_CONTROL_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "position2d.h" +#include "rect.h" + +namespace irr +{ +namespace gui +{ + + class IGUISpriteBank; + + //! Default icons for cursors + enum ECURSOR_ICON + { + // Following cursors might be system specific, or might use an Irrlicht icon-set. No guarantees so far. + ECI_NORMAL, // arrow + ECI_CROSS, // Crosshair + ECI_HAND, // Hand + ECI_HELP, // Arrow and question mark + ECI_IBEAM, // typical text-selection cursor + ECI_NO, // should not click icon + ECI_WAIT, // hourclass + ECI_SIZEALL, // arrow in all directions + ECI_SIZENESW, // resizes in direction north-east or south-west + ECI_SIZENWSE, // resizes in direction north-west or south-east + ECI_SIZENS, // resizes in direction north or south + ECI_SIZEWE, // resizes in direction west or east + ECI_UP, // up-arrow + + // Implementer note: Should we add system specific cursors, which use guaranteed the system icons, + // then I would recommend using a naming scheme like ECI_W32_CROSS, ECI_X11_CROSSHAIR and adding those + // additionally. + + ECI_COUNT // maximal of defined cursors. Note that higher values can be created at runtime + }; + + //! Names for ECURSOR_ICON + const c8* const GUICursorIconNames[ECI_COUNT+1] = + { + "normal", + "cross", + "hand", + "help", + "ibeam", + "no", + "wait", + "sizeall", + "sizenesw", + "sizenwse", + "sizens", + "sizewe", + "sizeup", + 0 + }; + + //! structure used to set sprites as cursors. + struct SCursorSprite + { + SCursorSprite() + : SpriteBank(0), SpriteId(-1) + { + } + + SCursorSprite( gui::IGUISpriteBank * spriteBank, s32 spriteId, const core::position2d &hotspot=(core::position2d(0,0)) ) + : SpriteBank(spriteBank), SpriteId(spriteId), HotSpot(hotspot) + { + } + + IGUISpriteBank * SpriteBank; + s32 SpriteId; + core::position2d HotSpot; + }; + + //! platform specific behavior flags for the cursor + enum ECURSOR_PLATFORM_BEHAVIOR + { + //! default - no platform specific behavior + ECPB_NONE = 0, + + //! On X11 try caching cursor updates as XQueryPointer calls can be expensive. + /** Update cursor positions only when the irrlicht timer has been updated or the timer is stopped. + This means you usually get one cursor update per device->run() which will be fine in most cases. + See this forum-thread for a more detailed explanation: + http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=45525 + */ + ECPB_X11_CACHE_UPDATES = 1 + }; + + //! Interface to manipulate the mouse cursor. + class ICursorControl : public virtual IReferenceCounted + { + public: + + //! Changes the visible state of the mouse cursor. + /** \param visible: The new visible state. If true, the cursor will be visible, + if false, it will be invisible. */ + virtual void setVisible(bool visible) = 0; + + //! Returns if the cursor is currently visible. + /** \return True if the cursor is visible, false if not. */ + virtual bool isVisible() const = 0; + + //! Sets the new position of the cursor. + /** The position must be + between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is + the top left corner and (1.0f, 1.0f) is the bottom right corner of the + render window. + \param pos New position of the cursor. */ + virtual void setPosition(const core::position2d &pos) = 0; + + //! Sets the new position of the cursor. + /** The position must be + between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is + the top left corner and (1.0f, 1.0f) is the bottom right corner of the + render window. + \param x New x-coord of the cursor. + \param y New x-coord of the cursor. */ + virtual void setPosition(f32 x, f32 y) = 0; + + //! Sets the new position of the cursor. + /** \param pos: New position of the cursor. The coordinates are pixel units. */ + virtual void setPosition(const core::position2d &pos) = 0; + + //! Sets the new position of the cursor. + /** \param x New x-coord of the cursor. The coordinates are pixel units. + \param y New y-coord of the cursor. The coordinates are pixel units. */ + virtual void setPosition(s32 x, s32 y) = 0; + + //! Returns the current position of the mouse cursor. + /** \return Returns the current position of the cursor. The returned position + is the position of the mouse cursor in pixel units. */ + virtual const core::position2d& getPosition() = 0; + + //! Returns the current position of the mouse cursor. + /** \return Returns the current position of the cursor. The returned position + is a value between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is + the top left corner and (1.0f, 1.0f) is the bottom right corner of the + render window. */ + virtual core::position2d getRelativePosition() = 0; + + //! Sets an absolute reference rect for setting and retrieving the cursor position. + /** If this rect is set, the cursor position is not being calculated relative to + the rendering window but to this rect. You can set the rect pointer to 0 to disable + this feature again. This feature is useful when rendering into parts of foreign windows + for example in an editor. + \param rect: A pointer to an reference rectangle or 0 to disable the reference rectangle.*/ + virtual void setReferenceRect(core::rect* rect=0) = 0; + + + //! Sets the active cursor icon + /** Setting cursor icons is so far only supported on Win32 and Linux */ + virtual void setActiveIcon(ECURSOR_ICON iconId) {} + + //! Gets the currently active icon + virtual ECURSOR_ICON getActiveIcon() const { return gui::ECI_NORMAL; } + + //! Add a custom sprite as cursor icon. + /** \return Identification for the icon */ + virtual ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) { return gui::ECI_NORMAL; } + + //! replace a cursor icon. + /** Changing cursor icons is so far only supported on Win32 and Linux + Note that this only changes the icons within your application, system cursors outside your + application will not be affected. + */ + virtual void changeIcon(ECURSOR_ICON iconId, const gui::SCursorSprite& sprite) {} + + //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. + virtual core::dimension2di getSupportedIconSize() const { return core::dimension2di(0,0); } + + //! Set platform specific behavior flags. + virtual void setPlatformBehavior(ECURSOR_PLATFORM_BEHAVIOR behavior) {} + + //! Return platform specific behavior. + /** \return Behavior set by setPlatformBehavior or ECPB_NONE for platforms not implementing specific behaviors. + */ + virtual ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const { return ECPB_NONE; } + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IDummyTransformationSceneNode.h b/inc/IDummyTransformationSceneNode.h new file mode 100644 index 0000000..d5e7f00 --- /dev/null +++ b/inc/IDummyTransformationSceneNode.h @@ -0,0 +1,42 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ +#define __I_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! Dummy scene node for adding additional transformations to the scene graph. +/** This scene node does not render itself, and does not respond to set/getPosition, +set/getRotation and set/getScale. Its just a simple scene node that takes a +matrix as relative transformation, making it possible to insert any transformation +anywhere into the scene graph. +This scene node is for example used by the IAnimatedMeshSceneNode for emulating +joint scene nodes when playing skeletal animations. +*/ +class IDummyTransformationSceneNode : public ISceneNode +{ +public: + + //! Constructor + IDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) + : ISceneNode(parent, mgr, id) {} + + //! Returns a reference to the current relative transformation matrix. + /** This is the matrix, this scene node uses instead of scale, translation + and rotation. */ + virtual core::matrix4& getRelativeTransformationMatrix() = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IDynamicMeshBuffer.h b/inc/IDynamicMeshBuffer.h new file mode 100644 index 0000000..24434df --- /dev/null +++ b/inc/IDynamicMeshBuffer.h @@ -0,0 +1,211 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_DYNAMIC_MESH_BUFFER_H_INCLUDED__ +#define __I_DYNAMIC_MESH_BUFFER_H_INCLUDED__ + +#include "IMeshBuffer.h" +#include "IVertexBuffer.h" +#include "IIndexBuffer.h" + +namespace irr +{ +namespace scene +{ + + /** a dynamic meshBuffer */ + class IDynamicMeshBuffer : public IMeshBuffer + { + public: + virtual IVertexBuffer &getVertexBuffer() const =0; + virtual IIndexBuffer &getIndexBuffer() const =0; + + virtual void setVertexBuffer(IVertexBuffer *vertexBuffer) =0; + virtual void setIndexBuffer(IIndexBuffer *indexBuffer) =0; + + //! Get the material of this meshbuffer + /** \return Material of this buffer. */ + virtual video::SMaterial& getMaterial() =0; + + //! Get the material of this meshbuffer + /** \return Material of this buffer. */ + virtual const video::SMaterial& getMaterial() const =0; + + //! Get the axis aligned bounding box of this meshbuffer. + /** \return Axis aligned bounding box of this buffer. */ + virtual const core::aabbox3df& getBoundingBox() const =0; + + //! Set axis aligned bounding box + /** \param box User defined axis aligned bounding box to use + for this buffer. */ + virtual void setBoundingBox(const core::aabbox3df& box) =0; + + //! Recalculates the bounding box. Should be called if the mesh changed. + virtual void recalculateBoundingBox() =0; + + //! Append the vertices and indices to the current buffer + /** Only works for compatible vertex types. + \param vertices Pointer to a vertex array. + \param numVertices Number of vertices in the array. + \param indices Pointer to index array. + \param numIndices Number of indices in array. */ + virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) + { + + } + + //! Append the meshbuffer to the current buffer + /** Only works for compatible vertex types + \param other Buffer to append to this one. */ + virtual void append(const IMeshBuffer* const other) + { + + } + + // ------------------- To be removed? ------------------- // + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const + { + return getVertexBuffer().getHardwareMappingHint(); + } + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const + { + return getIndexBuffer().getHardwareMappingHint(); + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX ) + { + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) + getVertexBuffer().setHardwareMappingHint(NewMappingHint); + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) + getIndexBuffer().setHardwareMappingHint(NewMappingHint); + } + + //! flags the mesh as changed, reloads hardware buffers + virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) + { + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) + getVertexBuffer().setDirty(); + if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) + getIndexBuffer().setDirty(); + } + + virtual u32 getChangedID_Vertex() const + { + return getVertexBuffer().getChangedID(); + } + + virtual u32 getChangedID_Index() const + { + return getIndexBuffer().getChangedID(); + } + + // ------------------- Old interface ------------------- // + + //! Get type of vertex data which is stored in this meshbuffer. + /** \return Vertex type of this buffer. */ + virtual video::E_VERTEX_TYPE getVertexType() const + { + return getVertexBuffer().getType(); + } + + //! Get access to vertex data. The data is an array of vertices. + /** Which vertex type is used can be determined by getVertexType(). + \return Pointer to array of vertices. */ + virtual const void* getVertices() const + { + return getVertexBuffer().getData(); + } + + //! Get access to vertex data. The data is an array of vertices. + /** Which vertex type is used can be determined by getVertexType(). + \return Pointer to array of vertices. */ + virtual void* getVertices() + { + return getVertexBuffer().getData(); + } + + //! Get amount of vertices in meshbuffer. + /** \return Number of vertices in this buffer. */ + virtual u32 getVertexCount() const + { + return getVertexBuffer().size(); + } + + //! Get type of index data which is stored in this meshbuffer. + /** \return Index type of this buffer. */ + virtual video::E_INDEX_TYPE getIndexType() const + { + return getIndexBuffer().getType(); + } + + //! Get access to Indices. + /** \return Pointer to indices array. */ + virtual const u16* getIndices() const + { + return (u16*)getIndexBuffer().getData(); + } + + //! Get access to Indices. + /** \return Pointer to indices array. */ + virtual u16* getIndices() + { + return (u16*)getIndexBuffer().getData(); + } + + //! Get amount of indices in this meshbuffer. + /** \return Number of indices in this buffer. */ + virtual u32 getIndexCount() const + { + return getIndexBuffer().size(); + } + + //! returns position of vertex i + virtual const core::vector3df& getPosition(u32 i) const + { + return getVertexBuffer()[i].Pos; + } + + //! returns position of vertex i + virtual core::vector3df& getPosition(u32 i) + { + return getVertexBuffer()[i].Pos; + } + + //! returns texture coords of vertex i + virtual const core::vector2df& getTCoords(u32 i) const + { + return getVertexBuffer()[i].TCoords; + } + + //! returns texture coords of vertex i + virtual core::vector2df& getTCoords(u32 i) + { + return getVertexBuffer()[i].TCoords; + } + + //! returns normal of vertex i + virtual const core::vector3df& getNormal(u32 i) const + { + return getVertexBuffer()[i].Normal; + } + + //! returns normal of vertex i + virtual core::vector3df& getNormal(u32 i) + { + return getVertexBuffer()[i].Normal; + } + }; + + +} // end namespace scene +} // end namespace irr + +#endif + + diff --git a/inc/IEventReceiver.h b/inc/IEventReceiver.h new file mode 100644 index 0000000..9c7813f --- /dev/null +++ b/inc/IEventReceiver.h @@ -0,0 +1,490 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_EVENT_RECEIVER_H_INCLUDED__ +#define __I_EVENT_RECEIVER_H_INCLUDED__ + +#include "ILogger.h" +#include "Keycodes.h" +#include "irrString.h" + +namespace irr +{ + //! Enumeration for all event types there are. + enum EEVENT_TYPE + { + //! An event of the graphical user interface. + /** GUI events are created by the GUI environment or the GUI elements in response + to mouse or keyboard events. When a GUI element receives an event it will either + process it and return true, or pass the event to its parent. If an event is not absorbed + before it reaches the root element then it will then be passed to the user receiver. */ + EET_GUI_EVENT = 0, + + //! A mouse input event. + /** Mouse events are created by the device and passed to IrrlichtDevice::postEventFromUser + in response to mouse input received from the operating system. + Mouse events are first passed to the user receiver, then to the GUI environment and its elements, + then finally the input receiving scene manager where it is passed to the active camera. + */ + EET_MOUSE_INPUT_EVENT, + + //! A key input event. + /** Like mouse events, keyboard events are created by the device and passed to + IrrlichtDevice::postEventFromUser. They take the same path as mouse events. */ + EET_KEY_INPUT_EVENT, + + //! A joystick (joypad, gamepad) input event. + /** Joystick events are created by polling all connected joysticks once per + device run() and then passing the events to IrrlichtDevice::postEventFromUser. + They take the same path as mouse events. + Windows, SDL: Implemented. + Linux: Implemented, with POV hat issues. + MacOS / Other: Not yet implemented. + */ + EET_JOYSTICK_INPUT_EVENT, + + //! A log event + /** Log events are only passed to the user receiver if there is one. If they are absorbed by the + user receiver then no text will be sent to the console. */ + EET_LOG_TEXT_EVENT, + + //! A user event with user data. + /** This is not used by Irrlicht and can be used to send user + specific data though the system. The Irrlicht 'window handle' + can be obtained from IrrlichtDevice::getExposedVideoData() + The usage and behavior depends on the operating system: + Windows: send a WM_USER message to the Irrlicht Window; the + wParam and lParam will be used to populate the + UserData1 and UserData2 members of the SUserEvent. + Linux: send a ClientMessage via XSendEvent to the Irrlicht + Window; the data.l[0] and data.l[1] members will be + casted to s32 and used as UserData1 and UserData2. + MacOS: Not yet implemented + */ + EET_USER_EVENT, + + //! This enum is never used, it only forces the compiler to + //! compile these enumeration values to 32 bit. + EGUIET_FORCE_32_BIT = 0x7fffffff + + }; + + //! Enumeration for all mouse input events + enum EMOUSE_INPUT_EVENT + { + //! Left mouse button was pressed down. + EMIE_LMOUSE_PRESSED_DOWN = 0, + + //! Right mouse button was pressed down. + EMIE_RMOUSE_PRESSED_DOWN, + + //! Middle mouse button was pressed down. + EMIE_MMOUSE_PRESSED_DOWN, + + //! Left mouse button was left up. + EMIE_LMOUSE_LEFT_UP, + + //! Right mouse button was left up. + EMIE_RMOUSE_LEFT_UP, + + //! Middle mouse button was left up. + EMIE_MMOUSE_LEFT_UP, + + //! The mouse cursor changed its position. + EMIE_MOUSE_MOVED, + + //! The mouse wheel was moved. Use Wheel value in event data to find out + //! in what direction and how fast. + EMIE_MOUSE_WHEEL, + + //! Left mouse button double click. + //! This event is generated after the second EMIE_LMOUSE_PRESSED_DOWN event. + EMIE_LMOUSE_DOUBLE_CLICK, + + //! Right mouse button double click. + //! This event is generated after the second EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_DOUBLE_CLICK, + + //! Middle mouse button double click. + //! This event is generated after the second EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_DOUBLE_CLICK, + + //! Left mouse button triple click. + //! This event is generated after the third EMIE_LMOUSE_PRESSED_DOWN event. + EMIE_LMOUSE_TRIPLE_CLICK, + + //! Right mouse button triple click. + //! This event is generated after the third EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_TRIPLE_CLICK, + + //! Middle mouse button triple click. + //! This event is generated after the third EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_TRIPLE_CLICK, + + //! No real event. Just for convenience to get number of events + EMIE_COUNT + }; + + //! Masks for mouse button states + enum E_MOUSE_BUTTON_STATE_MASK + { + EMBSM_LEFT = 0x01, + EMBSM_RIGHT = 0x02, + EMBSM_MIDDLE = 0x04, + + //! currently only on windows + EMBSM_EXTRA1 = 0x08, + + //! currently only on windows + EMBSM_EXTRA2 = 0x10, + + EMBSM_FORCE_32_BIT = 0x7fffffff + }; + + namespace gui + { + + class IGUIElement; + + //! Enumeration for all events which are sendable by the gui system + enum EGUI_EVENT_TYPE + { + //! A gui element has lost its focus. + /** GUIEvent.Caller is losing the focus to GUIEvent.Element. + If the event is absorbed then the focus will not be changed. */ + EGET_ELEMENT_FOCUS_LOST = 0, + + //! A gui element has got the focus. + /** If the event is absorbed then the focus will not be changed. */ + EGET_ELEMENT_FOCUSED, + + //! The mouse cursor hovered over a gui element. + /** If an element has sub-elements you also get this message for the subelements */ + EGET_ELEMENT_HOVERED, + + //! The mouse cursor left the hovered element. + /** If an element has sub-elements you also get this message for the subelements */ + EGET_ELEMENT_LEFT, + + //! An element would like to close. + /** Windows and context menus use this event when they would like to close, + this can be cancelled by absorbing the event. */ + EGET_ELEMENT_CLOSED, + + //! A button was clicked. + EGET_BUTTON_CLICKED, + + //! A scrollbar has changed its position. + EGET_SCROLL_BAR_CHANGED, + + //! A checkbox has changed its check state. + EGET_CHECKBOX_CHANGED, + + //! A new item in a listbox was selected. + /** NOTE: You also get this event currently when the same item was clicked again after more than 500 ms. */ + EGET_LISTBOX_CHANGED, + + //! An item in the listbox was selected, which was already selected. + /** NOTE: You get the event currently only if the item was clicked again within 500 ms or selected by "enter" or "space". */ + EGET_LISTBOX_SELECTED_AGAIN, + + //! A file has been selected in the file dialog + EGET_FILE_SELECTED, + + //! A directory has been selected in the file dialog + EGET_DIRECTORY_SELECTED, + + //! A file open dialog has been closed without choosing a file + EGET_FILE_CHOOSE_DIALOG_CANCELLED, + + //! 'Yes' was clicked on a messagebox + EGET_MESSAGEBOX_YES, + + //! 'No' was clicked on a messagebox + EGET_MESSAGEBOX_NO, + + //! 'OK' was clicked on a messagebox + EGET_MESSAGEBOX_OK, + + //! 'Cancel' was clicked on a messagebox + EGET_MESSAGEBOX_CANCEL, + + //! In an editbox 'ENTER' was pressed + EGET_EDITBOX_ENTER, + + //! The text in an editbox was changed. This does not include automatic changes in text-breaking. + EGET_EDITBOX_CHANGED, + + //! The marked area in an editbox was changed. + EGET_EDITBOX_MARKING_CHANGED, + + //! The tab was changed in an tab control + EGET_TAB_CHANGED, + + //! A menu item was selected in a (context) menu + EGET_MENU_ITEM_SELECTED, + + //! The selection in a combo box has been changed + EGET_COMBO_BOX_CHANGED, + + //! The value of a spin box has changed + EGET_SPINBOX_CHANGED, + + //! A table has changed + EGET_TABLE_CHANGED, + EGET_TABLE_HEADER_CHANGED, + EGET_TABLE_SELECTED_AGAIN, + + //! A tree view node lost selection. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_DESELECT, + + //! A tree view node was selected. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_SELECT, + + //! A tree view node was expanded. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_EXPAND, + + //! A tree view node was collapsed. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_COLLAPSE, + + //! deprecated - use EGET_TREEVIEW_NODE_COLLAPSE instead. This + //! may be removed by Irrlicht 1.9 + EGET_TREEVIEW_NODE_COLLAPS = EGET_TREEVIEW_NODE_COLLAPSE, + + //! No real event. Just for convenience to get number of events + EGET_COUNT + }; + } // end namespace gui + + +//! SEvents hold information about an event. See irr::IEventReceiver for details on event handling. +struct SEvent +{ + //! Any kind of GUI event. + struct SGUIEvent + { + //! IGUIElement who called the event + gui::IGUIElement* Caller; + + //! If the event has something to do with another element, it will be held here. + gui::IGUIElement* Element; + + //! Type of GUI Event + gui::EGUI_EVENT_TYPE EventType; + + }; + + //! Any kind of mouse event. + struct SMouseInput + { + //! X position of mouse cursor + s32 X; + + //! Y position of mouse cursor + s32 Y; + + //! mouse wheel delta, often 1.0 or -1.0, but can have other values < 0.f or > 0.f; + /** Only valid if event was EMIE_MOUSE_WHEEL */ + f32 Wheel; + + //! True if shift was also pressed + bool Shift:1; + + //! True if ctrl was also pressed + bool Control:1; + + //! A bitmap of button states. You can use isButtonPressed() to determine + //! if a button is pressed or not. + //! Currently only valid if the event was EMIE_MOUSE_MOVED + u32 ButtonStates; + + //! Is the left button pressed down? + bool isLeftPressed() const { return 0 != ( ButtonStates & EMBSM_LEFT ); } + + //! Is the right button pressed down? + bool isRightPressed() const { return 0 != ( ButtonStates & EMBSM_RIGHT ); } + + //! Is the middle button pressed down? + bool isMiddlePressed() const { return 0 != ( ButtonStates & EMBSM_MIDDLE ); } + + //! Type of mouse event + EMOUSE_INPUT_EVENT Event; + }; + + //! Any kind of keyboard event. + struct SKeyInput + { + //! Character corresponding to the key (0, if not a character) + wchar_t Char; + + //! Key which has been pressed or released + EKEY_CODE Key; + + //! If not true, then the key was left up + bool PressedDown:1; + + //! True if shift was also pressed + bool Shift:1; + + //! True if ctrl was also pressed + bool Control:1; + }; + + //! A joystick event. + /** Unlike other events, joystick events represent the result of polling + * each connected joystick once per run() of the device. Joystick events will + * not be generated by default. If joystick support is available for the + * active device, _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, and + * @ref irr::IrrlichtDevice::activateJoysticks() has been called, an event of + * this type will be generated once per joystick per @ref IrrlichtDevice::run() + * regardless of whether the state of the joystick has actually changed. */ + struct SJoystickEvent + { + enum + { + NUMBER_OF_BUTTONS = 32, + + AXIS_X = 0, // e.g. analog stick 1 left to right + AXIS_Y, // e.g. analog stick 1 top to bottom + AXIS_Z, // e.g. throttle, or analog 2 stick 2 left to right + AXIS_R, // e.g. rudder, or analog 2 stick 2 top to bottom + AXIS_U, + AXIS_V, + NUMBER_OF_AXES + }; + + /** A bitmap of button states. You can use IsButtonPressed() to + ( check the state of each button from 0 to (NUMBER_OF_BUTTONS - 1) */ + u32 ButtonStates; + + /** For AXIS_X, AXIS_Y, AXIS_Z, AXIS_R, AXIS_U and AXIS_V + * Values are in the range -32768 to 32767, with 0 representing + * the center position. You will receive the raw value from the + * joystick, and so will usually want to implement a dead zone around + * the center of the range. Axes not supported by this joystick will + * always have a value of 0. On Linux, POV hats are represented as axes, + * usually the last two active axis. + */ + s16 Axis[NUMBER_OF_AXES]; + + /** The POV represents the angle of the POV hat in degrees * 100, + * from 0 to 35,900. A value of 65535 indicates that the POV hat + * is centered (or not present). + * This value is only supported on Windows. On Linux, the POV hat + * will be sent as 2 axes instead. */ + u16 POV; + + //! The ID of the joystick which generated this event. + /** This is an internal Irrlicht index; it does not map directly + * to any particular hardware joystick. */ + u8 Joystick; + + //! A helper function to check if a button is pressed. + bool IsButtonPressed(u32 button) const + { + if(button >= (u32)NUMBER_OF_BUTTONS) + return false; + + return (ButtonStates & (1 << button)) ? true : false; + } + }; + + + //! Any kind of log event. + struct SLogEvent + { + //! Pointer to text which has been logged + const c8* Text; + + //! Log level in which the text has been logged + ELOG_LEVEL Level; + }; + + //! Any kind of user event. + struct SUserEvent + { + //! Some user specified data as int + s32 UserData1; + + //! Another user specified data as int + s32 UserData2; + }; + + EEVENT_TYPE EventType; + union + { + struct SGUIEvent GUIEvent; + struct SMouseInput MouseInput; + struct SKeyInput KeyInput; + struct SJoystickEvent JoystickEvent; + struct SLogEvent LogEvent; + struct SUserEvent UserEvent; + }; + +}; + +//! Interface of an object which can receive events. +/** Many of the engine's classes inherit IEventReceiver so they are able to +process events. Events usually start at a postEventFromUser function and are +passed down through a chain of event receivers until OnEvent returns true. See +irr::EEVENT_TYPE for a description of where each type of event starts, and the +path it takes through the system. */ +class IEventReceiver +{ +public: + + //! Destructor + virtual ~IEventReceiver() {} + + //! Called if an event happened. + /** Please take care that you should only return 'true' when you want to _prevent_ Irrlicht + * from processing the event any further. So 'true' does mean that an event is completely done. + * Therefore your return value for all unprocessed events should be 'false'. + \return True if the event was processed. + */ + virtual bool OnEvent(const SEvent& event) = 0; +}; + + +//! Information on a joystick, returned from @ref irr::IrrlichtDevice::activateJoysticks() +struct SJoystickInfo +{ + //! The ID of the joystick + /** This is an internal Irrlicht index; it does not map directly + * to any particular hardware joystick. It corresponds to the + * irr::SJoystickEvent Joystick ID. */ + u8 Joystick; + + //! The name that the joystick uses to identify itself. + core::stringc Name; + + //! The number of buttons that the joystick has. + u32 Buttons; + + //! The number of axes that the joystick has, i.e. X, Y, Z, R, U, V. + /** Note: with a Linux device, the POV hat (if any) will use two axes. These + * will be included in this count. */ + u32 Axes; + + //! An indication of whether the joystick has a POV hat. + /** A Windows device will identify the presence or absence or the POV hat. A + * Linux device cannot, and will always return POV_HAT_UNKNOWN. */ + enum + { + //! A hat is definitely present. + POV_HAT_PRESENT, + + //! A hat is definitely not present. + POV_HAT_ABSENT, + + //! The presence or absence of a hat cannot be determined. + POV_HAT_UNKNOWN + } PovHat; +}; // struct SJoystickInfo + + +} // end namespace irr + +#endif + diff --git a/inc/IFileArchive.h b/inc/IFileArchive.h new file mode 100644 index 0000000..8bf8cad --- /dev/null +++ b/inc/IFileArchive.h @@ -0,0 +1,132 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt/ Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_FILE_ARCHIVE_H_INCLUDED__ +#define __I_FILE_ARCHIVE_H_INCLUDED__ + +#include "IReadFile.h" +#include "IFileList.h" + +namespace irr +{ + +namespace io +{ + +//! FileSystemType: which Filesystem should be used for e.g. browsing +enum EFileSystemType +{ + FILESYSTEM_NATIVE = 0, // Native OS FileSystem + FILESYSTEM_VIRTUAL // Virtual FileSystem +}; + +//! Contains the different types of archives +enum E_FILE_ARCHIVE_TYPE +{ + //! A PKZIP archive + EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0), + + //! A gzip archive + EFAT_GZIP = MAKE_IRR_ID('g','z','i','p'), + + //! A virtual directory + EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'), + + //! An ID Software PAK archive + EFAT_PAK = MAKE_IRR_ID('P','A','K', 0), + + //! A Nebula Device archive + EFAT_NPK = MAKE_IRR_ID('N','P','K', 0), + + //! A Tape ARchive + EFAT_TAR = MAKE_IRR_ID('T','A','R', 0), + + //! A wad Archive, Quake2, Halflife + EFAT_WAD = MAKE_IRR_ID('W','A','D', 0), + + //! The type of this archive is unknown + EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n') +}; + +//! The FileArchive manages archives and provides access to files inside them. +class IFileArchive : public virtual IReferenceCounted +{ +public: + + //! Opens a file based on its name + /** Creates and returns a new IReadFile for a file in the archive. + \param filename The file to open + \return Returns A pointer to the created file on success, + or 0 on failure. */ + virtual IReadFile* createAndOpenFile(const path& filename) =0; + + //! Opens a file based on its position in the file list. + /** Creates and returns + \param index The zero based index of the file. + \return Returns a pointer to the created file on success, or 0 on failure. */ + virtual IReadFile* createAndOpenFile(u32 index) =0; + + //! Returns the complete file tree + /** \return Returns the complete directory tree for the archive, + including all files and folders */ + virtual const IFileList* getFileList() const =0; + + //! get the archive type + virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; } + + //! An optionally used password string + /** This variable is publicly accessible from the interface in order to + avoid single access patterns to this place, and hence allow some more + obscurity. + */ + core::stringc Password; +}; + +//! Class which is able to create an archive from a file. +/** If you want the Irrlicht Engine be able to load archives of +currently unsupported file formats (e.g .wad), then implement +this and add your new Archive loader with +IFileSystem::addArchiveLoader() to the engine. */ +class IArchiveLoader : public virtual IReferenceCounted +{ +public: + //! Check if the file might be loaded by this class + /** Check based on the file extension (e.g. ".zip") + \param filename Name of file to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(const path& filename) const =0; + + //! Check if the file might be loaded by this class + /** This check may look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const =0; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const =0; + + //! Creates an archive from the filename + /** \param filename File to use. + \param ignoreCase Searching is performed without regarding the case + \param ignorePaths Files are searched for without checking for the directories + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const path& filename, bool ignoreCase, bool ignorePaths) const =0; + + //! Creates an archive from the file + /** \param file File handle to use. + \param ignoreCase Searching is performed without regarding the case + \param ignorePaths Files are searched for without checking for the directories + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const =0; +}; + + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IFileList.h b/inc/IFileList.h new file mode 100644 index 0000000..2eabd7c --- /dev/null +++ b/inc/IFileList.h @@ -0,0 +1,94 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_FILE_LIST_H_INCLUDED__ +#define __I_FILE_LIST_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "path.h" + +namespace irr +{ +namespace io +{ + +//! Provides a list of files and folders. +/** File lists usually contain a list of all files in a given folder, +but can also contain a complete directory structure. */ +class IFileList : public virtual IReferenceCounted +{ +public: + //! Get the number of files in the filelist. + /** \return Amount of files and directories in the file list. */ + virtual u32 getFileCount() const = 0; + + //! Gets the name of a file in the list, based on an index. + /** The path is not included in this name. Use getFullFileName for this. + \param index is the zero based index of the file which name should + be returned. The index must be less than the amount getFileCount() returns. + \return File name of the file. Returns 0, if an error occured. */ + virtual const io::path& getFileName(u32 index) const = 0; + + //! Gets the full name of a file in the list including the path, based on an index. + /** \param index is the zero based index of the file which name should + be returned. The index must be less than the amount getFileCount() returns. + \return File name of the file. Returns 0 if an error occured. */ + virtual const io::path& getFullFileName(u32 index) const = 0; + + //! Returns the size of a file in the file list, based on an index. + /** \param index is the zero based index of the file which should be returned. + The index must be less than the amount getFileCount() returns. + \return The size of the file in bytes. */ + virtual u32 getFileSize(u32 index) const = 0; + + //! Returns the file offset of a file in the file list, based on an index. + /** \param index is the zero based index of the file which should be returned. + The index must be less than the amount getFileCount() returns. + \return The offset of the file in bytes. */ + virtual u32 getFileOffset(u32 index) const = 0; + + //! Returns the ID of a file in the file list, based on an index. + /** This optional ID can be used to link the file list entry to information held + elsewhere. For example this could be an index in an IFileArchive, linking the entry + to its data offset, uncompressed size and CRC. + \param index is the zero based index of the file which should be returned. + The index must be less than the amount getFileCount() returns. + \return The ID of the file. */ + virtual u32 getID(u32 index) const = 0; + + //! Check if the file is a directory + /** \param index The zero based index which will be checked. The index + must be less than the amount getFileCount() returns. + \return True if the file is a directory, else false. */ + virtual bool isDirectory(u32 index) const = 0; + + //! Searches for a file or folder in the list + /** Searches for a file by name + \param filename The name of the file to search for. + \param isFolder True if you are searching for a directory path, false if you are searching for a file + \return Returns the index of the file in the file list, or -1 if + no matching name name was found. */ + virtual s32 findFile(const io::path& filename, bool isFolder=false) const = 0; + + //! Returns the base path of the file list + virtual const io::path& getPath() const = 0; + + //! Add as a file or folder to the list + /** \param fullPath The file name including path, from the root of the file list. + \param isDirectory True if this is a directory rather than a file. + \param offset The file offset inside an archive + \param size The size of the file in bytes. + \param id The ID of the file in the archive which owns it */ + virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0) = 0; + + //! Sorts the file list. You should call this after adding any items to the file list + virtual void sort() = 0; +}; + +} // end namespace irr +} // end namespace io + + +#endif + diff --git a/inc/IFileSystem.h b/inc/IFileSystem.h new file mode 100644 index 0000000..0c5244d --- /dev/null +++ b/inc/IFileSystem.h @@ -0,0 +1,385 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_FILE_SYSTEM_H_INCLUDED__ +#define __I_FILE_SYSTEM_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IXMLReader.h" +#include "IFileArchive.h" + +namespace irr +{ +namespace video +{ + class IVideoDriver; +} // end namespace video +namespace io +{ + +class IReadFile; +class IWriteFile; +class IFileList; +class IXMLWriter; +class IAttributes; + + +//! The FileSystem manages files and archives and provides access to them. +/** It manages where files are, so that modules which use the the IO do not +need to know where every file is located. A file could be in a .zip-Archive or +as file on disk, using the IFileSystem makes no difference to this. */ +class IFileSystem : public virtual IReferenceCounted +{ +public: + + //! Opens a file for read access. + /** \param filename: Name of file to open. + \return Pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. */ + virtual IReadFile* createAndOpenFile(const path& filename) =0; + + //! Creates an IReadFile interface for accessing memory like a file. + /** This allows you to use a pointer to memory where an IReadFile is requested. + \param memory: A pointer to the start of the file in memory + \param len: The length of the memory in bytes + \param fileName: The name given to this file + \param deleteMemoryWhenDropped: True if the memory should be deleted + along with the IReadFile when it is dropped. + \return Pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. + */ + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + + //! Creates an IReadFile interface for accessing files inside files. + /** This is useful e.g. for archives. + \param fileName: The name given to this file + \param alreadyOpenedFile: Pointer to the enclosing file + \param pos: Start of the file inside alreadyOpenedFile + \param areaSize: The length of the file + \return A pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. + */ + virtual IReadFile* createLimitReadFile(const path& fileName, + IReadFile* alreadyOpenedFile, long pos, long areaSize) =0; + + //! Creates an IWriteFile interface for accessing memory like a file. + /** This allows you to use a pointer to memory where an IWriteFile is requested. + You are responsible for allocating enough memory. + \param memory: A pointer to the start of the file in memory (allocated by you) + \param len: The length of the memory in bytes + \param fileName: The name given to this file + \param deleteMemoryWhenDropped: True if the memory should be deleted + along with the IWriteFile when it is dropped. + \return Pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. + */ + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + + + //! Opens a file for write access. + /** \param filename: Name of file to open. + \param append: If the file already exist, all write operations are + appended to the file. + \return Pointer to the created file interface. 0 is returned, if the + file could not created or opened for writing. + The returned pointer should be dropped when no longer needed. + See IReferenceCounted::drop() for more information. */ + virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; + + //! Adds an archive to the file system. + /** After calling this, the Irrlicht Engine will also search and open + files directly from this archive. This is useful for hiding data from + the end user, speeding up file access and making it possible to access + for example Quake3 .pk3 files, which are just renamed .zip files. By + default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as + archives. You can provide your own archive types by implementing + IArchiveLoader and passing an instance to addArchiveLoader. + Irrlicht supports AES-encrypted zip files, and the advanced compression + techniques lzma and bzip2. + \param filename: Filename of the archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then + the type of archive will depend on the extension of the file name. If + you use a different extension then you can use this parameter to force + a specific type of archive. + \param password An optional password, which is used in case of encrypted archives. + \param retArchive A pointer that will be set to the archive that is added. + \return True if the archive was added successfully, false if not. */ + virtual bool addFileArchive(const path& filename, bool ignoreCase=true, + bool ignorePaths=true, + E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, + const core::stringc& password="", + IFileArchive** retArchive=0) =0; + + //! Adds an archive to the file system. + /** After calling this, the Irrlicht Engine will also search and open + files directly from this archive. This is useful for hiding data from + the end user, speeding up file access and making it possible to access + for example Quake3 .pk3 files, which are just renamed .zip files. By + default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as + archives. You can provide your own archive types by implementing + IArchiveLoader and passing an instance to addArchiveLoader. + Irrlicht supports AES-encrypted zip files, and the advanced compression + techniques lzma and bzip2. + If you want to add a directory as an archive, prefix its name with a + slash in order to let Irrlicht recognize it as a folder mount (mypath/). + Using this technique one can build up a search order, because archives + are read first, and can be used more easily with relative filenames. + \param file: Archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then + the type of archive will depend on the extension of the file name. If + you use a different extension then you can use this parameter to force + a specific type of archive. + \param password An optional password, which is used in case of encrypted archives. + \param retArchive A pointer that will be set to the archive that is added. + \return True if the archive was added successfully, false if not. */ + virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true, + bool ignorePaths=true, + E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, + const core::stringc& password="", + IFileArchive** retArchive=0) =0; + + //! Adds an archive to the file system. + /** \param archive: The archive to add to the file system. + \return True if the archive was added successfully, false if not. */ + virtual bool addFileArchive(IFileArchive* archive) =0; + + //! Get the number of archives currently attached to the file system + virtual u32 getFileArchiveCount() const =0; + + //! Removes an archive from the file system. + /** This will close the archive and free any file handles, but will not + close resources which have already been loaded and are now cached, for + example textures and meshes. + \param index: The index of the archive to remove + \return True on success, false on failure */ + virtual bool removeFileArchive(u32 index) =0; + + //! Removes an archive from the file system. + /** This will close the archive and free any file handles, but will not + close resources which have already been loaded and are now cached, for + example textures and meshes. Note that a relative filename might be + interpreted differently on each call, depending on the current working + directory. In case you want to remove an archive that was added using + a relative path name, you have to change to the same working directory + again. This means, that the filename given on creation is not an + identifier for the archive, but just a usual filename that is used for + locating the archive to work with. + \param filename The archive pointed to by the name will be removed + \return True on success, false on failure */ + virtual bool removeFileArchive(const path& filename) =0; + + //! Removes an archive from the file system. + /** This will close the archive and free any file handles, but will not + close resources which have already been loaded and are now cached, for + example textures and meshes. + \param archive The archive to remove. + \return True on success, false on failure */ + virtual bool removeFileArchive(const IFileArchive* archive) =0; + + //! Changes the search order of attached archives. + /** + \param sourceIndex: The index of the archive to change + \param relative: The relative change in position, archives with a lower index are searched first */ + virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0; + + //! Get the archive at a given index. + virtual IFileArchive* getFileArchive(u32 index) =0; + + //! Adds an external archive loader to the engine. + /** Use this function to add support for new archive types to the + engine, for example proprietary or encrypted file storage. */ + virtual void addArchiveLoader(IArchiveLoader* loader) =0; + + //! Gets the number of archive loaders currently added + virtual u32 getArchiveLoaderCount() const = 0; + + //! Retrieve the given archive loader + /** \param index The index of the loader to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified loader, 0 if the index is incorrect. */ + virtual IArchiveLoader* getArchiveLoader(u32 index) const = 0; + + //! Adds a zip archive to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in Irrlicht 1.9, + you should use addFileArchive instead. + After calling this, the Irrlicht Engine will search and open files directly from this archive too. + This is useful for hiding data from the end user, speeding up file access and making it possible to + access for example Quake3 .pk3 files, which are no different than .zip files. + \param filename: Filename of the zip archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \return True if the archive was added successfully, false if not. */ + _IRR_DEPRECATED_ virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_ZIP); + } + + //! Adds an unzipped archive (or basedirectory with subdirectories..) to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in Irrlicht 1.9, + you should use addFileArchive instead. + Useful for handling data which will be in a zip file + \param filename: Filename of the unzipped zip archive base directory to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \return True if the archive was added successful, false if not. */ + _IRR_DEPRECATED_ virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_FOLDER); + } + + //! Adds a pak archive to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in Irrlicht 1.9, + you should use addFileArchive instead. + After calling this, the Irrlicht Engine will search and open files directly from this archive too. + This is useful for hiding data from the end user, speeding up file access and making it possible to + access for example Quake2/KingPin/Hexen2 .pak files + \param filename: Filename of the pak archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path.(should not use with Quake2 paks + \return True if the archive was added successful, false if not. */ + _IRR_DEPRECATED_ virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + { + return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_PAK); + } + + //! Get the current working directory. + /** \return Current working directory as a string. */ + virtual const path& getWorkingDirectory() =0; + + //! Changes the current working directory. + /** \param newDirectory: A string specifying the new working directory. + The string is operating system dependent. Under Windows it has + the form ":\\\<..>". An example would be: "C:\Windows\" + \return True if successful, otherwise false. */ + virtual bool changeWorkingDirectoryTo(const path& newDirectory) =0; + + //! Converts a relative path to an absolute (unique) path, resolving symbolic links if required + /** \param filename Possibly relative file or directory name to query. + \result Absolute filename which points to the same file. */ + virtual path getAbsolutePath(const path& filename) const =0; + + //! Get the directory a file is located in. + /** \param filename: The file to get the directory from. + \return String containing the directory of the file. */ + virtual path getFileDir(const path& filename) const =0; + + //! Get the base part of a filename, i.e. the name without the directory part. + /** If no directory is prefixed, the full name is returned. + \param filename: The file to get the basename from + \param keepExtension True if filename with extension is returned otherwise everything + after the final '.' is removed as well. */ + virtual path getFileBasename(const path& filename, bool keepExtension=true) const =0; + + //! flatten a path and file name for example: "/you/me/../." becomes "/you" + virtual path& flattenFilename(path& directory, const path& root="/") const =0; + + //! Get the relative filename, relative to the given directory + virtual path getRelativeFilename(const path& filename, const path& directory) const =0; + + //! Creates a list of files and directories in the current working directory and returns it. + /** \return a Pointer to the created IFileList is returned. After the list has been used + it has to be deleted using its IFileList::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IFileList* createFileList() =0; + + //! Creates an empty filelist + /** \return a Pointer to the created IFileList is returned. After the list has been used + it has to be deleted using its IFileList::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) =0; + + //! Set the active type of file system. + virtual EFileSystemType setFileListSystem(EFileSystemType listType) =0; + + //! Determines if a file exists and could be opened. + /** \param filename is the string identifying the file which should be tested for existence. + \return True if file exists, and false if it does not exist or an error occured. */ + virtual bool existFile(const path& filename) const =0; + + //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). + /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for + more information on how to use the parser. + \return 0, if file could not be opened, otherwise a pointer to the created + IXMLReader is returned. After use, the reader + has to be deleted using its IXMLReader::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLReader* createXMLReader(const path& filename) =0; + + //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). + /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for + more information on how to use the parser. + \return 0, if file could not be opened, otherwise a pointer to the created + IXMLReader is returned. After use, the reader + has to be deleted using its IXMLReader::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLReader* createXMLReader(IReadFile* file) =0; + + //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). + /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for + more information on how to use the parser. + \return 0, if file could not be opened, otherwise a pointer to the created + IXMLReader is returned. After use, the reader + has to be deleted using its IXMLReaderUTF8::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLReaderUTF8* createXMLReaderUTF8(const path& filename) =0; + + //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). + /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for + more information on how to use the parser. + \return 0, if file could not be opened, otherwise a pointer to the created + IXMLReader is returned. After use, the reader + has to be deleted using its IXMLReaderUTF8::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) =0; + + //! Creates a XML Writer from a file. + /** \return 0, if file could not be opened, otherwise a pointer to the created + IXMLWriter is returned. After use, the reader + has to be deleted using its IXMLWriter::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLWriter* createXMLWriter(const path& filename) =0; + + //! Creates a XML Writer from a file. + /** \return 0, if file could not be opened, otherwise a pointer to the created + IXMLWriter is returned. After use, the reader + has to be deleted using its IXMLWriter::drop() method. + See IReferenceCounted::drop() for more information. */ + virtual IXMLWriter* createXMLWriter(IWriteFile* file) =0; + + //! Creates a new empty collection of attributes, usable for serialization and more. + /** \param driver: Video driver to be used to load textures when specified as attribute values. + Can be null to prevent automatic texture loading by attributes. + \return Pointer to the created object. + If you no longer need the object, you should call IAttributes::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver=0) =0; +}; + + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IGPUProgrammingServices.h b/inc/IGPUProgrammingServices.h new file mode 100644 index 0000000..28717d5 --- /dev/null +++ b/inc/IGPUProgrammingServices.h @@ -0,0 +1,474 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ +#define __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ + +#include "EShaderTypes.h" +#include "EMaterialTypes.h" +#include "EPrimitiveTypes.h" +#include "path.h" + +namespace irr +{ + +namespace io +{ + class IReadFile; +} // end namespace io + +namespace video +{ + +class IVideoDriver; +class IShaderConstantSetCallBack; + +//! Enumeration for different types of shading languages +enum E_GPU_SHADING_LANGUAGE +{ + //! The default language, so HLSL for Direct3D and GLSL for OpenGL. + EGSL_DEFAULT = 0, + + //! Cg shading language.*/ + EGSL_CG +}; + +//! Interface making it possible to create and use programs running on the GPU. +class IGPUProgrammingServices +{ +public: + + //! Destructor + virtual ~IGPUProgrammingServices() {} + + //! Adds a new high-level shading material renderer to the VideoDriver. + /** Currently only HLSL/D3D9 and GLSL/OpenGL are supported. + \param vertexShaderProgram String containing the source of the vertex + shader program. This can be 0 if no vertex program shall be used. + \param vertexShaderEntryPointName Name of the entry function of the + vertexShaderProgram (p.e. "main") + \param vsCompileTarget Vertex shader version the high level shader + shall be compiled to. + \param pixelShaderProgram String containing the source of the pixel + shader program. This can be 0 if no pixel shader shall be used. + \param pixelShaderEntryPointName Entry name of the function of the + pixelShaderProgram (p.e. "main") + \param psCompileTarget Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram String containing the source of the + geometry shader program. This can be 0 if no geometry shader shall be + used. + \param geometryShaderEntryPointName Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. + \param callback Pointer to an implementation of + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. + \param baseMaterial Base material which renderstates will be used to + shade the material. + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \param shaderLang a type of shading language used in current shader. + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ + virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName="main", + E_VERTEX_SHADER_TYPE vsCompileTarget=EVST_VS_1_1, + const c8* pixelShaderProgram=0, + const c8* pixelShaderEntryPointName="main", + E_PIXEL_SHADER_TYPE psCompileTarget=EPST_PS_1_1, + IShaderConstantSetCallBack* callback=0, + E_MATERIAL_TYPE baseMaterial=video::EMT_SOLID, + s32 userData=0, + E_GPU_SHADING_LANGUAGE shadingLang=EGSL_DEFAULT) + { + return addHighLevelShaderMaterial( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData, shadingLang); + } + + //! convenience function for use with many defaults, without geometry shader + /** All shader names are set to "main" and compile targets are shader + type 1.1. + */ + s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* pixelShaderProgram=0, + IShaderConstantSetCallBack* callback=0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData=0) + { + return addHighLevelShaderMaterial( + vertexShaderProgram, "main", + EVST_VS_1_1, pixelShaderProgram, + "main", EPST_PS_1_1, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } + + //! convenience function for use with many defaults, with geometry shader + /** All shader names are set to "main" and compile targets are shader + type 1.1 and geometry shader 4.0. + */ + s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* pixelShaderProgram = 0, + const c8* geometryShaderProgram = 0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0 ) + { + return addHighLevelShaderMaterial( + vertexShaderProgram, "main", + EVST_VS_1_1, pixelShaderProgram, + "main", EPST_PS_1_1, + geometryShaderProgram, "main", EGST_GS_4_0, + inType, outType, verticesOut, + callback, baseMaterial, userData); + } + + //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. + /** \param vertexShaderProgramFileName Text file containing the source + of the vertex shader program. Set to empty string if no vertex shader + shall be created. + \param vertexShaderEntryPointName Name of the entry function of the + vertexShaderProgram (p.e. "main") + \param vsCompileTarget Vertex shader version the high level shader + shall be compiled to. + \param pixelShaderProgramFileName Text file containing the source of + the pixel shader program. Set to empty string if no pixel shader shall + be created. + \param pixelShaderEntryPointName Entry name of the function of the + pixelShaderProgram (p.e. "main") + \param psCompileTarget Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgramFileName Name of the source of + the geometry shader program. Set to empty string if no geometry shader + shall be created. + \param geometryShaderEntryPointName Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. + \param callback Pointer to an implementation of + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. + \param baseMaterial Base material which renderstates will be used to + shade the material. + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \param shaderLang a type of shading language used in current shader. + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ + virtual s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const io::path& pixelShaderProgramFileName, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const io::path& geometryShaderProgramFileName, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const io::path& pixelShaderProgramFileName = "", + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgramFileName, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgramFileName, + pixelShaderEntryPointName, psCompileTarget, + "", "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData, shadingLang); + } + + //! convenience function for use with many defaults, without geometry shader + /** All shader names are set to "main" and compile targets are shader + type 1.1. + */ + s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName = "", + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0 ) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgramFileName, "main", + EVST_VS_1_1, pixelShaderProgramFileName, + "main", EPST_PS_1_1, + "", "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } + + //! convenience function for use with many defaults, with geometry shader + /** All shader names are set to "main" and compile targets are shader + type 1.1 and geometry shader 4.0. + */ + s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName = "", + const io::path& geometryShaderProgramFileName = "", + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0 ) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgramFileName, "main", + EVST_VS_1_1, pixelShaderProgramFileName, + "main", EPST_PS_1_1, + geometryShaderProgramFileName, "main", EGST_GS_4_0, + inType, outType, verticesOut, + callback, baseMaterial, userData); + } + + //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. + /** \param vertexShaderProgram Text file handle containing the source + of the vertex shader program. Set to 0 if no vertex shader shall be + created. + \param vertexShaderEntryPointName Name of the entry function of the + vertexShaderProgram + \param vsCompileTarget Vertex shader version the high level shader + shall be compiled to. + \param pixelShaderProgram Text file handle containing the source of + the pixel shader program. Set to 0 if no pixel shader shall be created. + \param pixelShaderEntryPointName Entry name of the function of the + pixelShaderProgram (p.e. "main") + \param psCompileTarget Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram Text file handle containing the source of + the geometry shader program. Set to 0 if no geometry shader shall be + created. + \param geometryShaderEntryPointName Entry name of the function of the + geometryShaderProgram (p.e. "main") + \param gsCompileTarget Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. + \param callback Pointer to an implementation of + IShaderConstantSetCallBack in which you can set the needed vertex and + pixel shader program constants. Set this to 0 if you don't need this. + \param baseMaterial Base material which renderstates will be used to + shade the material. + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \param shaderLang a type of shading language used in current shader. + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an + error occured, e.g. if a shader program could not be compiled or a + compile target is not reachable. The error strings are then printed to + the error log and can be catched with a custom event receiver. */ + virtual s32 addHighLevelShaderMaterialFromFiles( + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + io::IReadFile* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + io::IReadFile* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + io::IReadFile* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData, shadingLang); + } + + //! Adds a new ASM shader material renderer to the VideoDriver + /** Note that it is a good idea to call IVideoDriver::queryFeature() in + advance to check if the IVideoDriver supports the vertex and/or pixel + shader version your are using. + + The material is added to the VideoDriver like with + IVideoDriver::addMaterialRenderer() and can be used like it had been + added with that method. + \param vertexShaderProgram String containing the source of the vertex + shader program. This can be 0 if no vertex program shall be used. + + For DX8 programs, the will always input registers look like this: v0: + position, v1: normal, v2: color, v3: texture cooridnates, v4: texture + coordinates 2 if available. + + For DX9 programs, you can manually set the registers using the dcl_ + statements. + \param pixelShaderProgram String containing the source of the pixel + shader program. This can be 0 if you don't want to use a pixel shader. + \param callback Pointer to an implementation of + IShaderConstantSetCallBack in which you can set the needed vertex and + pixel shader program constants. Set this to 0 if you don't need this. + \param baseMaterial Base material which renderstates will be used to + shade the material. + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \return Returns the number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an + error occured. -1 is returned for example if a vertex or pixel shader + program could not be compiled, the error strings are then printed out + into the error log, and can be catched with a custom event receiver. */ + virtual s32 addShaderMaterial(const c8* vertexShaderProgram = 0, + const c8* pixelShaderProgram = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + + //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. + /** \param vertexShaderProgram Text file containing the source of the + vertex shader program. Set to 0 if no shader shall be created. + \param pixelShaderProgram Text file containing the source of the pixel + shader program. Set to 0 if no shader shall be created. + \param callback Pointer to an IShaderConstantSetCallback object to + which the OnSetConstants function is called. + \param baseMaterial baseMaterial + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \return Returns the number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an + error occured. -1 is returned for example if a vertex or pixel shader + program could not be compiled, the error strings are then printed out + into the error log, and can be catched with a custom event receiver. */ + virtual s32 addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, + io::IReadFile* pixelShaderProgram, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + + //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. + /** \param vertexShaderProgramFileName Text file name containing the + source of the vertex shader program. Set to 0 if no shader shall be + created. + \param pixelShaderProgramFileName Text file name containing the source + of the pixel shader program. Set to 0 if no shader shall be created. + \param callback Pointer to an IShaderConstantSetCallback object on + which the OnSetConstants function is called. + \param baseMaterial baseMaterial + \param userData a user data int. This int can be set to any value and + will be set as parameter in the callback method when calling + OnSetConstants(). In this way it is easily possible to use the same + callback method for multiple materials and distinguish between them + during the call. + \return Returns the number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an + error occured. -1 is returned for example if a vertex or pixel shader + program could not be compiled, the error strings are then printed out + into the error log, and can be catched with a custom event receiver. */ + virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IGUIButton.h b/inc/IGUIButton.h new file mode 100644 index 0000000..cc0ada1 --- /dev/null +++ b/inc/IGUIButton.h @@ -0,0 +1,151 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_BUTTON_H_INCLUDED__ +#define __I_GUI_BUTTON_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ + +namespace video +{ + class ITexture; +} // end namespace video + +namespace gui +{ + class IGUIFont; + class IGUISpriteBank; + + enum EGUI_BUTTON_STATE + { + //! The button is not pressed + EGBS_BUTTON_UP=0, + //! The button is currently pressed down + EGBS_BUTTON_DOWN, + //! The mouse cursor is over the button + EGBS_BUTTON_MOUSE_OVER, + //! The mouse cursor is not over the button + EGBS_BUTTON_MOUSE_OFF, + //! The button has the focus + EGBS_BUTTON_FOCUSED, + //! The button doesn't have the focus + EGBS_BUTTON_NOT_FOCUSED, + //! not used, counts the number of enumerated items + EGBS_COUNT + }; + + //! Names for gui button state icons + const c8* const GUIButtonStateNames[] = + { + "buttonUp", + "buttonDown", + "buttonMouseOver", + "buttonMouseOff", + "buttonFocused", + "buttonNotFocused", + 0, + 0, + }; + + //! GUI Button interface. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_BUTTON_CLICKED + */ + class IGUIButton : public IGUIElement + { + public: + + //! constructor + IGUIButton(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_BUTTON, environment, parent, id, rectangle) {} + + //! Sets another skin independent font. + /** If this is set to zero, the button uses the font of the skin. + \param font: New font to set. */ + virtual void setOverrideFont(IGUIFont* font=0) = 0; + + //! Gets the override font (if any) + /** \return The override font (may be 0) */ + virtual IGUIFont* getOverrideFont(void) const = 0; + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont* getActiveFont() const = 0; + + //! Sets an image which should be displayed on the button when it is in normal state. + /** \param image: Image to be displayed */ + virtual void setImage(video::ITexture* image=0) = 0; + + //! Sets a background image for the button when it is in normal state. + /** \param image: Texture containing the image to be displayed + \param pos: Position in the texture, where the image is located */ + virtual void setImage(video::ITexture* image, const core::rect& pos) = 0; + + //! Sets a background image for the button when it is in pressed state. + /** If no images is specified for the pressed state via + setPressedImage(), this image is also drawn in pressed state. + \param image: Image to be displayed */ + virtual void setPressedImage(video::ITexture* image=0) = 0; + + //! Sets an image which should be displayed on the button when it is in pressed state. + /** \param image: Texture containing the image to be displayed + \param pos: Position in the texture, where the image is located */ + virtual void setPressedImage(video::ITexture* image, const core::rect& pos) = 0; + + //! Sets the sprite bank used by the button + virtual void setSpriteBank(IGUISpriteBank* bank=0) = 0; + + //! Sets the animated sprite for a specific button state + /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite + \param state: State of the button to set the sprite for + \param index: The sprite number from the current sprite bank + \param color: The color of the sprite + \param loop: True if the animation should loop, false if not + */ + virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, + video::SColor color=video::SColor(255,255,255,255), bool loop=false) = 0; + + //! Sets if the button should behave like a push button. + /** Which means it can be in two states: Normal or Pressed. With a click on the button, + the user can change the state of the button. */ + virtual void setIsPushButton(bool isPushButton=true) = 0; + + //! Sets the pressed state of the button if this is a pushbutton + virtual void setPressed(bool pressed=true) = 0; + + //! Returns if the button is currently pressed + virtual bool isPressed() const = 0; + + //! Sets if the alpha channel should be used for drawing background images on the button (default is false) + virtual void setUseAlphaChannel(bool useAlphaChannel=true) = 0; + + //! Returns if the alpha channel should be used for drawing background images on the button + virtual bool isAlphaChannelUsed() const = 0; + + //! Returns whether the button is a push button + virtual bool isPushButton() const = 0; + + //! Sets if the button should use the skin to draw its border and button face (default is true) + virtual void setDrawBorder(bool border=true) = 0; + + //! Returns if the border and button face are being drawn using the skin + virtual bool isDrawingBorder() const = 0; + + //! Sets if the button should scale the button images to fit + virtual void setScaleImage(bool scaleImage=true) = 0; + + //! Checks whether the button scales the used images + virtual bool isScalingImage() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUICheckBox.h b/inc/IGUICheckBox.h new file mode 100644 index 0000000..d965ef6 --- /dev/null +++ b/inc/IGUICheckBox.h @@ -0,0 +1,38 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_CHECKBOX_H_INCLUDED__ +#define __I_GUI_CHECKBOX_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + + //! GUI Check box interface. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_CHECKBOX_CHANGED + */ + class IGUICheckBox : public IGUIElement + { + public: + + //! constructor + IGUICheckBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_CHECK_BOX, environment, parent, id, rectangle) {} + + //! Set if box is checked. + virtual void setChecked(bool checked) = 0; + + //! Returns true if box is checked. + virtual bool isChecked() const = 0; + }; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIColorSelectDialog.h b/inc/IGUIColorSelectDialog.h new file mode 100644 index 0000000..0788dbc --- /dev/null +++ b/inc/IGUIColorSelectDialog.h @@ -0,0 +1,30 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ +#define __I_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + + //! Standard color chooser dialog. + class IGUIColorSelectDialog : public IGUIElement + { + public: + + //! constructor + IGUIColorSelectDialog(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_COLOR_SELECT_DIALOG, environment, parent, id, rectangle) {} + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIComboBox.h b/inc/IGUIComboBox.h new file mode 100644 index 0000000..ebee1ec --- /dev/null +++ b/inc/IGUIComboBox.h @@ -0,0 +1,74 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_COMBO_BOX_H_INCLUDED__ +#define __I_GUI_COMBO_BOX_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + + //! Combobox widget + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_COMBO_BOX_CHANGED + */ + class IGUIComboBox : public IGUIElement + { + public: + + //! constructor + IGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_COMBO_BOX, environment, parent, id, rectangle) {} + + //! Returns amount of items in box + virtual u32 getItemCount() const = 0; + + //! Returns string of an item. the idx may be a value from 0 to itemCount-1 + virtual const wchar_t* getItem(u32 idx) const = 0; + + //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 + virtual u32 getItemData(u32 idx) const = 0; + + //! Returns index based on item data + virtual s32 getIndexForItemData(u32 data ) const = 0; + + //! Adds an item and returns the index of it + virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; + + //! Removes an item from the combo box. + /** Warning. This will change the index of all following items */ + virtual void removeItem(u32 idx) = 0; + + //! Deletes all items in the combo box + virtual void clear() = 0; + + //! Returns id of selected item. returns -1 if no item is selected. + virtual s32 getSelected() const = 0; + + //! Sets the selected item. Set this to -1 if no item should be selected + virtual void setSelected(s32 idx) = 0; + + //! Sets text justification of the text area + /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), + EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. + \param vertical: EGUIA_UPPERLEFT to align with top edge, + EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; + + //! Set the maximal number of rows for the selection listbox + virtual void setMaxSelectionRows(u32 max) = 0; + + //! Get the maximimal number of rows for the selection listbox + virtual u32 getMaxSelectionRows() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIContextMenu.h b/inc/IGUIContextMenu.h new file mode 100644 index 0000000..9f5ea25 --- /dev/null +++ b/inc/IGUIContextMenu.h @@ -0,0 +1,162 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_CONTEXT_MENU_H_INCLUDED__ +#define __I_GUI_CONTEXT_MENU_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + //! Close behavior. + //! Default is ECMC_REMOVE + enum ECONTEXT_MENU_CLOSE + { + //! do nothing - menu stays open + ECMC_IGNORE = 0, + + //! remove the gui element + ECMC_REMOVE = 1, + + //! call setVisible(false) + ECMC_HIDE = 2 + + // note to implementors - this is planned as bitset, so continue with 4 if you need to add further flags. + }; + + //! GUI Context menu interface. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_ELEMENT_CLOSED + \li EGET_MENU_ITEM_SELECTED + */ + class IGUIContextMenu : public IGUIElement + { + public: + + //! constructor + IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_CONTEXT_MENU, environment, parent, id, rectangle) {} + + //! set behavior when menus are closed + virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0; + + //! get current behavior when the menu will be closed + virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0; + + //! Get amount of menu items + virtual u32 getItemCount() const = 0; + + //! Adds a menu item. + /** \param text: Text of menu item. Set this to 0 to create + an separator instead of a real item, which is the same like + calling addSeparator(); + \param commandId: Command id of menu item, a simple id you may + set to whatever you want. + \param enabled: Specifies if the menu item should be enabled. + \param hasSubMenu: Set this to true if there should be a submenu + at this item. You can access this submenu via getSubMenu(). + \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking + \return Returns the index of the new item */ + virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, + bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; + + //! Insert a menu item at specified position. + /** \param idx: Position to insert the new element, + should be smaller than itemcount otherwise the item is added to the end. + \param text: Text of menu item. Set this to 0 to create + an separator instead of a real item, which is the same like + calling addSeparator(); + \param commandId: Command id of menu item, a simple id you may + set to whatever you want. + \param enabled: Specifies if the menu item should be enabled. + \param hasSubMenu: Set this to true if there should be a submenu + at this item. You can access this submenu via getSubMenu(). + \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking + \return Returns the index of the new item */ + virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true, + bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; + + //! Find an item by it's CommandID + /** + \param commandId: We are looking for the first item which has this commandID + \param idxStartSearch: Start searching from this index. + \return Returns the index of the item when found or otherwise -1. */ + virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0; + + //! Adds a separator item to the menu + virtual void addSeparator() = 0; + + //! Get text of the menu item. + /** \param idx: Zero based index of the menu item */ + virtual const wchar_t* getItemText(u32 idx) const = 0; + + //! Sets text of the menu item. + /** \param idx: Zero based index of the menu item + \param text: New text of the item. */ + virtual void setItemText(u32 idx, const wchar_t* text) = 0; + + //! Check if a menu item is enabled + /** \param idx: Zero based index of the menu item */ + virtual bool isItemEnabled(u32 idx) const = 0; + + //! Sets if the menu item should be enabled. + /** \param idx: Zero based index of the menu item + \param enabled: True if it is enabled, otherwise false. */ + virtual void setItemEnabled(u32 idx, bool enabled) = 0; + + //! Sets if the menu item should be checked. + /** \param idx: Zero based index of the menu item + \param enabled: True if it is enabled, otherwise false. */ + virtual void setItemChecked(u32 idx, bool enabled) = 0; + + //! Check if a menu item is checked + /** \param idx: Zero based index of the menu item */ + virtual bool isItemChecked(u32 idx) const = 0; + + //! Removes a menu item + /** \param idx: Zero based index of the menu item */ + virtual void removeItem(u32 idx) = 0; + + //! Removes all menu items + virtual void removeAllItems() = 0; + + //! Get the selected item in the menu + /** \return Index of the selected item, -1 if none selected. */ + virtual s32 getSelectedItem() const = 0; + + //! Get the command id of a menu item + /** \param idx: Zero based index of the menu item */ + virtual s32 getItemCommandId(u32 idx) const = 0; + + //! Sets the command id of a menu item + /** \param idx: Zero based index of the menu item + \param id: Command id of menu item, a simple id you may + set to whatever you want. */ + virtual void setItemCommandId(u32 idx, s32 id) = 0; + + //! Get a pointer to the submenu of an item. + /** 0 is returned if there is no submenu + \param idx: Zero based index of the menu item + \return Returns a pointer to the submenu of an item. */ + virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0; + + //! should the element change the checked status on clicking + virtual void setItemAutoChecking(u32 idx, bool autoChecking) = 0; + + //! does the element change the checked status on clicking + virtual bool getItemAutoChecking(u32 idx) const = 0; + + //! When an eventparent is set it receives events instead of the usual parent element + virtual void setEventParent(IGUIElement *parent) = 0; + }; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIEditBox.h b/inc/IGUIEditBox.h new file mode 100644 index 0000000..13a9501 --- /dev/null +++ b/inc/IGUIEditBox.h @@ -0,0 +1,135 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_EDIT_BOX_H_INCLUDED__ +#define __I_GUI_EDIT_BOX_H_INCLUDED__ + +#include "IGUIElement.h" +#include "SColor.h" + +namespace irr +{ +namespace gui +{ + class IGUIFont; + + //! Single line edit box for editing simple text. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_EDITBOX_ENTER + \li EGET_EDITBOX_CHANGED + \li EGET_EDITBOX_MARKING_CHANGED + */ + class IGUIEditBox : public IGUIElement + { + public: + + //! constructor + IGUIEditBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_EDIT_BOX, environment, parent, id, rectangle) {} + + //! Sets another skin independent font. + /** If this is set to zero, the button uses the font of the skin. + \param font: New font to set. */ + virtual void setOverrideFont(IGUIFont* font=0) = 0; + + //! Gets the override font (if any) + /** \return The override font (may be 0) */ + virtual IGUIFont* getOverrideFont() const = 0; + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont* getActiveFont() const = 0; + + //! Sets another color for the text. + /** If set, the edit box does not use the EGDC_BUTTON_TEXT color defined + in the skin, but the set color instead. You don't need to call + IGUIEditBox::enableOverrrideColor(true) after this, this is done + by this function. + If you set a color, and you want the text displayed with the color + of the skin again, call IGUIEditBox::enableOverrideColor(false); + \param color: New color of the text. */ + virtual void setOverrideColor(video::SColor color) = 0; + + //! Gets the override color + virtual video::SColor getOverrideColor() const = 0; + + //! Sets if the text should use the override color or the color in the gui skin. + /** \param enable: If set to true, the override color, which can be set + with IGUIEditBox::setOverrideColor is used, otherwise the + EGDC_BUTTON_TEXT color of the skin. */ + virtual void enableOverrideColor(bool enable) = 0; + + //! Checks if an override color is enabled + /** \return true if the override color is enabled, false otherwise */ + virtual bool isOverrideColorEnabled(void) const = 0; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw) = 0; + + //! Turns the border on or off + /** \param border: true if you want the border to be drawn, false if not */ + virtual void setDrawBorder(bool border) = 0; + + //! Sets text justification mode + /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), + EGUIA_LOWERRIGHT for right justified, or EGUIA_CENTER for centered text. + \param vertical: EGUIA_UPPERLEFT to align with top edge, + EGUIA_LOWERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; + + //! Enables or disables word wrap. + /** \param enable: If set to true, words going over one line are + broken to the next line. */ + virtual void setWordWrap(bool enable) = 0; + + //! Checks if word wrap is enabled + /** \return true if word wrap is enabled, false otherwise */ + virtual bool isWordWrapEnabled() const = 0; + + //! Enables or disables newlines. + /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, + instead a newline character will be inserted. */ + virtual void setMultiLine(bool enable) = 0; + + //! Checks if multi line editing is enabled + /** \return true if multi-line is enabled, false otherwise */ + virtual bool isMultiLineEnabled() const = 0; + + //! Enables or disables automatic scrolling with cursor position + /** \param enable: If set to true, the text will move around with the cursor position */ + virtual void setAutoScroll(bool enable) = 0; + + //! Checks to see if automatic scrolling is enabled + /** \return true if automatic scrolling is enabled, false if not */ + virtual bool isAutoScrollEnabled() const = 0; + + //! Sets whether the edit box is a password box. Setting this to true will + /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x + \param passwordBox: true to enable password, false to disable + \param passwordChar: the character that is displayed instead of letters */ + virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*') = 0; + + //! Returns true if the edit box is currently a password box. + virtual bool isPasswordBox() const = 0; + + //! Gets the size area of the text in the edit box + /** \return The size in pixels of the text */ + virtual core::dimension2du getTextDimension() = 0; + + //! Sets the maximum amount of characters which may be entered in the box. + /** \param max: Maximum amount of characters. If 0, the character amount is + infinity. */ + virtual void setMax(u32 max) = 0; + + //! Returns maximum amount of characters, previously set by setMax(); + virtual u32 getMax() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIElement.h b/inc/IGUIElement.h new file mode 100644 index 0000000..098cd79 --- /dev/null +++ b/inc/IGUIElement.h @@ -0,0 +1,1037 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_ELEMENT_H_INCLUDED__ +#define __I_GUI_ELEMENT_H_INCLUDED__ + +#include "IAttributeExchangingObject.h" +#include "irrList.h" +#include "rect.h" +#include "irrString.h" +#include "IEventReceiver.h" +#include "EGUIElementTypes.h" +#include "EGUIAlignment.h" +#include "IAttributes.h" + +namespace irr +{ +namespace gui +{ + +class IGUIEnvironment; + +//! Base class of all GUI elements. +class IGUIElement : public virtual io::IAttributeExchangingObject, public IEventReceiver +{ +public: + + //! Constructor + IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent, + s32 id, const core::rect& rectangle) + : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle), + AbsoluteClippingRect(rectangle), DesiredRect(rectangle), + MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true), + IsSubElement(false), NoClip(false), ID(id), IsTabStop(false), TabOrder(-1), IsTabGroup(false), + AlignLeft(EGUIA_UPPERLEFT), AlignRight(EGUIA_UPPERLEFT), AlignTop(EGUIA_UPPERLEFT), AlignBottom(EGUIA_UPPERLEFT), + Environment(environment), Type(type) + { + #ifdef _DEBUG + setDebugName("IGUIElement"); + #endif + + // if we were given a parent to attach to + if (parent) + { + parent->addChildToEnd(this); + recalculateAbsolutePosition(true); + } + } + + + //! Destructor + virtual ~IGUIElement() + { + // delete all children + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->Parent = 0; + (*it)->drop(); + } + } + + + //! Returns parent of this element. + IGUIElement* getParent() const + { + return Parent; + } + + + //! Returns the relative rectangle of this element. + core::rect getRelativePosition() const + { + return RelativeRect; + } + + + //! Sets the relative rectangle of this element. + /** \param r The absolute position to set */ + void setRelativePosition(const core::rect& r) + { + if (Parent) + { + const core::rect& r2 = Parent->getAbsolutePosition(); + + core::dimension2df d((f32)(r2.getSize().Width), (f32)(r2.getSize().Height)); + + if (AlignLeft == EGUIA_SCALE) + ScaleRect.UpperLeftCorner.X = (f32)r.UpperLeftCorner.X / d.Width; + if (AlignRight == EGUIA_SCALE) + ScaleRect.LowerRightCorner.X = (f32)r.LowerRightCorner.X / d.Width; + if (AlignTop == EGUIA_SCALE) + ScaleRect.UpperLeftCorner.Y = (f32)r.UpperLeftCorner.Y / d.Height; + if (AlignBottom == EGUIA_SCALE) + ScaleRect.LowerRightCorner.Y = (f32)r.LowerRightCorner.Y / d.Height; + } + + DesiredRect = r; + updateAbsolutePosition(); + } + + //! Sets the relative rectangle of this element, maintaining its current width and height + /** \param position The new relative position to set. Width and height will not be changed. */ + void setRelativePosition(const core::position2di & position) + { + const core::dimension2di mySize = RelativeRect.getSize(); + const core::rect rectangle(position.X, position.Y, + position.X + mySize.Width, position.Y + mySize.Height); + setRelativePosition(rectangle); + } + + + //! Sets the relative rectangle of this element as a proportion of its parent's area. + /** \note This method used to be 'void setRelativePosition(const core::rect& r)' + \param r The rectangle to set, interpreted as a proportion of the parent's area. + Meaningful values are in the range [0...1], unless you intend this element to spill + outside its parent. */ + void setRelativePositionProportional(const core::rect& r) + { + if (!Parent) + return; + + const core::dimension2di& d = Parent->getAbsolutePosition().getSize(); + + DesiredRect = core::rect( + core::floor32((f32)d.Width * r.UpperLeftCorner.X), + core::floor32((f32)d.Height * r.UpperLeftCorner.Y), + core::floor32((f32)d.Width * r.LowerRightCorner.X), + core::floor32((f32)d.Height * r.LowerRightCorner.Y)); + + ScaleRect = r; + + updateAbsolutePosition(); + } + + + //! Gets the absolute rectangle of this element + core::rect getAbsolutePosition() const + { + return AbsoluteRect; + } + + + //! Returns the visible area of the element. + core::rect getAbsoluteClippingRect() const + { + return AbsoluteClippingRect; + } + + + //! Sets whether the element will ignore its parent's clipping rectangle + /** \param noClip If true, the element will not be clipped by its parent's clipping rectangle. */ + void setNotClipped(bool noClip) + { + NoClip = noClip; + updateAbsolutePosition(); + } + + + //! Gets whether the element will ignore its parent's clipping rectangle + /** \return true if the element is not clipped by its parent's clipping rectangle. */ + bool isNotClipped() const + { + return NoClip; + } + + + //! Sets the maximum size allowed for this element + /** If set to 0,0, there is no maximum size */ + void setMaxSize(core::dimension2du size) + { + MaxSize = size; + updateAbsolutePosition(); + } + + + //! Sets the minimum size allowed for this element + void setMinSize(core::dimension2du size) + { + MinSize = size; + if (MinSize.Width < 1) + MinSize.Width = 1; + if (MinSize.Height < 1) + MinSize.Height = 1; + updateAbsolutePosition(); + } + + + //! The alignment defines how the borders of this element will be positioned when the parent element is resized. + void setAlignment(EGUI_ALIGNMENT left, EGUI_ALIGNMENT right, EGUI_ALIGNMENT top, EGUI_ALIGNMENT bottom) + { + AlignLeft = left; + AlignRight = right; + AlignTop = top; + AlignBottom = bottom; + + if (Parent) + { + core::rect r(Parent->getAbsolutePosition()); + + core::dimension2df d((f32)r.getSize().Width, (f32)r.getSize().Height); + + if (AlignLeft == EGUIA_SCALE) + ScaleRect.UpperLeftCorner.X = (f32)DesiredRect.UpperLeftCorner.X / d.Width; + if (AlignRight == EGUIA_SCALE) + ScaleRect.LowerRightCorner.X = (f32)DesiredRect.LowerRightCorner.X / d.Width; + if (AlignTop == EGUIA_SCALE) + ScaleRect.UpperLeftCorner.Y = (f32)DesiredRect.UpperLeftCorner.Y / d.Height; + if (AlignBottom == EGUIA_SCALE) + ScaleRect.LowerRightCorner.Y = (f32)DesiredRect.LowerRightCorner.Y / d.Height; + } + } + + + //! Updates the absolute position. + virtual void updateAbsolutePosition() + { + recalculateAbsolutePosition(false); + + // update all children + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->updateAbsolutePosition(); + } + } + + + //! Returns the topmost GUI element at the specific position. + /** + This will check this GUI element and all of its descendants, so it + may return this GUI element. To check all GUI elements, call this + function on device->getGUIEnvironment()->getRootGUIElement(). Note + that the root element is the size of the screen, so doing so (with + an on-screen point) will always return the root element if no other + element is above it at that point. + \param point: The point at which to find a GUI element. + \return The topmost GUI element at that point, or 0 if there are + no candidate elements at this point. + */ + IGUIElement* getElementFromPoint(const core::position2d& point) + { + IGUIElement* target = 0; + + // we have to search from back to front, because later children + // might be drawn over the top of earlier ones. + + core::list::Iterator it = Children.getLast(); + + if (isVisible()) + { + while(it != Children.end()) + { + target = (*it)->getElementFromPoint(point); + if (target) + return target; + + --it; + } + } + + if (isVisible() && isPointInside(point)) + target = this; + + return target; + } + + + //! Returns true if a point is within this element. + /** Elements with a shape other than a rectangle should override this method */ + virtual bool isPointInside(const core::position2d& point) const + { + return AbsoluteClippingRect.isPointInside(point); + } + + + //! Adds a GUI element as new child of this element. + virtual void addChild(IGUIElement* child) + { + addChildToEnd(child); + if (child) + { + child->updateAbsolutePosition(); + } + } + + //! Removes a child. + virtual void removeChild(IGUIElement* child) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + if ((*it) == child) + { + (*it)->Parent = 0; + (*it)->drop(); + Children.erase(it); + return; + } + } + + + //! Removes this element from its parent. + virtual void remove() + { + if (Parent) + Parent->removeChild(this); + } + + + //! Draws the element and its children. + virtual void draw() + { + if ( isVisible() ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->draw(); + } + } + + + //! animate the element and its children. + virtual void OnPostRender(u32 timeMs) + { + if ( isVisible() ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnPostRender( timeMs ); + } + } + + + //! Moves this element. + virtual void move(core::position2d absoluteMovement) + { + setRelativePosition(DesiredRect + absoluteMovement); + } + + + //! Returns true if element is visible. + virtual bool isVisible() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsVisible; + } + + + //! Sets the visible state of this element. + virtual void setVisible(bool visible) + { + IsVisible = visible; + } + + + //! Returns true if this element was created as part of its parent control + virtual bool isSubElement() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsSubElement; + } + + + //! Sets whether this control was created as part of its parent. + /** For example, it is true when a scrollbar is part of a listbox. + SubElements are not saved to disk when calling guiEnvironment->saveGUI() */ + virtual void setSubElement(bool subElement) + { + IsSubElement = subElement; + } + + + //! If set to true, the focus will visit this element when using the tab key to cycle through elements. + /** If this element is a tab group (see isTabGroup/setTabGroup) then + ctrl+tab will be used instead. */ + void setTabStop(bool enable) + { + IsTabStop = enable; + } + + + //! Returns true if this element can be focused by navigating with the tab key + bool isTabStop() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsTabStop; + } + + + //! Sets the priority of focus when using the tab key to navigate between a group of elements. + /** See setTabGroup, isTabGroup and getTabGroup for information on tab groups. + Elements with a lower number are focused first */ + void setTabOrder(s32 index) + { + // negative = autonumber + if (index < 0) + { + TabOrder = 0; + IGUIElement *el = getTabGroup(); + while (IsTabGroup && el && el->Parent) + el = el->Parent; + + IGUIElement *first=0, *closest=0; + if (el) + { + // find the highest element number + el->getNextElement(-1, true, IsTabGroup, first, closest, true); + if (first) + { + TabOrder = first->getTabOrder() + 1; + } + } + + } + else + TabOrder = index; + } + + + //! Returns the number in the tab order sequence + s32 getTabOrder() const + { + return TabOrder; + } + + + //! Sets whether this element is a container for a group of elements which can be navigated using the tab key. + /** For example, windows are tab groups. + Groups can be navigated using ctrl+tab, providing isTabStop is true. */ + void setTabGroup(bool isGroup) + { + IsTabGroup = isGroup; + } + + + //! Returns true if this element is a tab group. + bool isTabGroup() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsTabGroup; + } + + + //! Returns the container element which holds all elements in this element's tab group. + IGUIElement* getTabGroup() + { + IGUIElement *ret=this; + + while (ret && !ret->isTabGroup()) + ret = ret->getParent(); + + return ret; + } + + + //! Returns true if element is enabled + /** Currently elements do _not_ care about parent-states. + So if you want to affect childs you have to enable/disable them all. + The only exception to this are sub-elements which also check their parent. + */ + virtual bool isEnabled() const + { + if ( isSubElement() && IsEnabled && getParent() ) + return getParent()->isEnabled(); + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsEnabled; + } + + + //! Sets the enabled state of this element. + virtual void setEnabled(bool enabled) + { + IsEnabled = enabled; + } + + + //! Sets the new caption of this element. + virtual void setText(const wchar_t* text) + { + Text = text; + } + + + //! Returns caption of this element. + virtual const wchar_t* getText() const + { + return Text.c_str(); + } + + + //! Sets the new caption of this element. + virtual void setToolTipText(const wchar_t* text) + { + ToolTipText = text; + } + + + //! Returns caption of this element. + virtual const core::stringw& getToolTipText() const + { + return ToolTipText; + } + + + //! Returns id. Can be used to identify the element. + virtual s32 getID() const + { + return ID; + } + + + //! Sets the id of this element + virtual void setID(s32 id) + { + ID = id; + } + + + //! Called if an event happened. + virtual bool OnEvent(const SEvent& event) + { + return Parent ? Parent->OnEvent(event) : false; + } + + + //! Brings a child to front + /** \return True if successful, false if not. */ + virtual bool bringToFront(IGUIElement* element) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + if (element == (*it)) + { + Children.erase(it); + Children.push_back(element); + return true; + } + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + + //! Moves a child to the back, so it's siblings are drawn on top of it + /** \return True if successful, false if not. */ + virtual bool sendToBack(IGUIElement* child) + { + core::list::Iterator it = Children.begin(); + if (child == (*it)) // already there + return true; + for (; it != Children.end(); ++it) + { + if (child == (*it)) + { + Children.erase(it); + Children.push_front(child); + return true; + } + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + //! Returns list with children of this element + virtual const core::list& getChildren() const + { + return Children; + } + + + //! Finds the first element with the given id. + /** \param id: Id to search for. + \param searchchildren: Set this to true, if also children of this + element may contain the element with the searched id and they + should be searched too. + \return Returns the first element with the given id. If no element + with this id was found, 0 is returned. */ + virtual IGUIElement* getElementFromId(s32 id, bool searchchildren=false) const + { + IGUIElement* e = 0; + + core::list::ConstIterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + if ((*it)->getID() == id) + return (*it); + + if (searchchildren) + e = (*it)->getElementFromId(id, true); + + if (e) + return e; + } + + return e; + } + + + //! returns true if the given element is a child of this one. + //! \param child: The child element to check + bool isMyChild(IGUIElement* child) const + { + if (!child) + return false; + do + { + if (child->Parent) + child = child->Parent; + + } while (child->Parent && child != this); + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return child == this; + } + + + //! searches elements to find the closest next element to tab to + /** \param startOrder: The TabOrder of the current element, -1 if none + \param reverse: true if searching for a lower number + \param group: true if searching for a higher one + \param first: element with the highest/lowest known tab order depending on search direction + \param closest: the closest match, depending on tab order and direction + \param includeInvisible: includes invisible elements in the search (default=false) + \return true if successfully found an element, false to continue searching/fail */ + bool getNextElement(s32 startOrder, bool reverse, bool group, + IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const + { + // we'll stop searching if we find this number + s32 wanted = startOrder + ( reverse ? -1 : 1 ); + if (wanted==-2) + wanted = 1073741824; // maximum s32 + + core::list::ConstIterator it = Children.begin(); + + s32 closestOrder, currentOrder; + + while(it != Children.end()) + { + // ignore invisible elements and their children + if ( ( (*it)->isVisible() || includeInvisible ) && + (group == true || (*it)->isTabGroup() == false) ) + { + // only check tab stops and those with the same group status + if ((*it)->isTabStop() && ((*it)->isTabGroup() == group)) + { + currentOrder = (*it)->getTabOrder(); + + // is this what we're looking for? + if (currentOrder == wanted) + { + closest = *it; + return true; + } + + // is it closer than the current closest? + if (closest) + { + closestOrder = closest->getTabOrder(); + if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder) + ||(!reverse && currentOrder < closestOrder && currentOrder > startOrder)) + { + closest = *it; + } + } + else + if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) ) + { + closest = *it; + } + + // is it before the current first? + if (first) + { + closestOrder = first->getTabOrder(); + + if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) ) + { + first = *it; + } + } + else + { + first = *it; + } + } + // search within children + if ((*it)->getNextElement(startOrder, reverse, group, first, closest)) + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return true; + } + } + ++it; + } + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + + //! Returns the type of the gui element. + /** This is needed for the .NET wrapper but will be used + later for serializing and deserializing. + If you wrote your own GUIElements, you need to set the type for your element as first parameter + in the constructor of IGUIElement. For own (=unknown) elements, simply use EGUIET_ELEMENT as type */ + EGUI_ELEMENT_TYPE getType() const + { + return Type; + } + + //! Returns true if the gui element supports the given type. + /** This is mostly used to check if you can cast a gui element to the class that goes with the type. + Most gui elements will only support their own type, but if you derive your own classes from interfaces + you can overload this function and add a check for the type of the base-class additionally. + This allows for checks comparable to the dynamic_cast of c++ with enabled rtti. + Note that you can't do that by calling BaseClass::hasType(type), but you have to do an explicit + comparison check, because otherwise the base class usually just checks for the membervariable + Type which contains the type of your derived class. + */ + virtual bool hasType(EGUI_ELEMENT_TYPE type) const + { + return type == Type; + } + + + //! Returns the type name of the gui element. + /** This is needed serializing elements. For serializing your own elements, override this function + and return your own type name which is created by your IGUIElementFactory */ + virtual const c8* getTypeName() const + { + return GUIElementTypeNames[Type]; + } + + //! Returns the name of the element. + /** \return Name as character string. */ + virtual const c8* getName() const + { + return Name.c_str(); + } + + + //! Sets the name of the element. + /** \param name New name of the gui element. */ + virtual void setName(const c8* name) + { + Name = name; + } + + + //! Sets the name of the element. + /** \param name New name of the gui element. */ + virtual void setName(const core::stringc& name) + { + Name = name; + } + + + //! Writes attributes of the scene node. + /** Implement this to expose the attributes of your scene node for + scripting languages, editors, debuggers or xml serialization purposes. */ + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const + { + out->addString("Name", Name.c_str()); + out->addInt("Id", ID ); + out->addString("Caption", getText()); + out->addRect("Rect", DesiredRect); + out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height)); + out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height)); + out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames); + out->addEnum("RightAlign", AlignRight, GUIAlignmentNames); + out->addEnum("TopAlign", AlignTop, GUIAlignmentNames); + out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames); + out->addBool("Visible", IsVisible); + out->addBool("Enabled", IsEnabled); + out->addBool("TabStop", IsTabStop); + out->addBool("TabGroup", IsTabGroup); + out->addInt("TabOrder", TabOrder); + out->addBool("NoClip", NoClip); + } + + + //! Reads attributes of the scene node. + /** Implement this to set the attributes of your scene node for + scripting languages, editors, debuggers or xml deserialization purposes. */ + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) + { + setName(in->getAttributeAsString("Name")); + setID(in->getAttributeAsInt("Id")); + setText(in->getAttributeAsStringW("Caption").c_str()); + setVisible(in->getAttributeAsBool("Visible")); + setEnabled(in->getAttributeAsBool("Enabled")); + IsTabStop = in->getAttributeAsBool("TabStop"); + IsTabGroup = in->getAttributeAsBool("TabGroup"); + TabOrder = in->getAttributeAsInt("TabOrder"); + + core::position2di p = in->getAttributeAsPosition2d("MaxSize"); + setMaxSize(core::dimension2du(p.X,p.Y)); + + p = in->getAttributeAsPosition2d("MinSize"); + setMinSize(core::dimension2du(p.X,p.Y)); + + setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames), + (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames), + (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames), + (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames)); + + setRelativePosition(in->getAttributeAsRect("Rect")); + + setNotClipped(in->getAttributeAsBool("NoClip")); + } + +protected: + // not virtual because needed in constructor + void addChildToEnd(IGUIElement* child) + { + if (child) + { + child->grab(); // prevent destruction when removed + child->remove(); // remove from old parent + child->LastParentRect = getAbsolutePosition(); + child->Parent = this; + Children.push_back(child); + } + } + + // not virtual because needed in constructor + void recalculateAbsolutePosition(bool recursive) + { + core::rect parentAbsolute(0,0,0,0); + core::rect parentAbsoluteClip; + f32 fw=0.f, fh=0.f; + + if (Parent) + { + parentAbsolute = Parent->AbsoluteRect; + + if (NoClip) + { + IGUIElement* p=this; + while (p && p->Parent) + p = p->Parent; + parentAbsoluteClip = p->AbsoluteClippingRect; + } + else + parentAbsoluteClip = Parent->AbsoluteClippingRect; + } + + const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); + const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); + + if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) + fw = (f32)parentAbsolute.getWidth(); + + if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) + fh = (f32)parentAbsolute.getHeight(); + + switch (AlignLeft) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw); + break; + } + + switch (AlignRight) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw); + break; + } + + switch (AlignTop) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh); + break; + } + + switch (AlignBottom) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh); + break; + } + + RelativeRect = DesiredRect; + + const s32 w = RelativeRect.getWidth(); + const s32 h = RelativeRect.getHeight(); + + // make sure the desired rectangle is allowed + if (w < (s32)MinSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; + if (h < (s32)MinSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; + if (MaxSize.Width && w > (s32)MaxSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; + if (MaxSize.Height && h > (s32)MaxSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; + + RelativeRect.repair(); + + AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; + + if (!Parent) + parentAbsoluteClip = AbsoluteRect; + + AbsoluteClippingRect = AbsoluteRect; + AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); + + LastParentRect = parentAbsolute; + + if ( recursive ) + { + // update all children + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->recalculateAbsolutePosition(recursive); + } + } + } + +protected: + + //! List of all children of this element + core::list Children; + + //! Pointer to the parent + IGUIElement* Parent; + + //! relative rect of element + core::rect RelativeRect; + + //! absolute rect of element + core::rect AbsoluteRect; + + //! absolute clipping rect of element + core::rect AbsoluteClippingRect; + + //! the rectangle the element would prefer to be, + //! if it was not constrained by parent or max/min size + core::rect DesiredRect; + + //! for calculating the difference when resizing parent + core::rect LastParentRect; + + //! relative scale of the element inside its parent + core::rect ScaleRect; + + //! maximum and minimum size of the element + core::dimension2du MaxSize, MinSize; + + //! is visible? + bool IsVisible; + + //! is enabled? + bool IsEnabled; + + //! is a part of a larger whole and should not be serialized? + bool IsSubElement; + + //! does this element ignore its parent's clipping rectangle? + bool NoClip; + + //! caption + core::stringw Text; + + //! tooltip + core::stringw ToolTipText; + + //! users can set this for identificating the element by string + core::stringc Name; + + //! users can set this for identificating the element by integer + s32 ID; + + //! tab stop like in windows + bool IsTabStop; + + //! tab order + s32 TabOrder; + + //! tab groups are containers like windows, use ctrl+tab to navigate + bool IsTabGroup; + + //! tells the element how to act when its parent is resized + EGUI_ALIGNMENT AlignLeft, AlignRight, AlignTop, AlignBottom; + + //! GUI Environment + IGUIEnvironment* Environment; + + //! type of element + EGUI_ELEMENT_TYPE Type; +}; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIElementFactory.h b/inc/IGUIElementFactory.h new file mode 100644 index 0000000..ca2df8b --- /dev/null +++ b/inc/IGUIElementFactory.h @@ -0,0 +1,66 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ +#define __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "EGUIElementTypes.h" + +namespace irr +{ + +namespace gui +{ + class IGUIElement; + + //! Interface making it possible to dynamically create GUI elements + /** To be able to add custom elements to Irrlicht and to make it possible for the + scene manager to save and load them, simply implement this interface and register it + in your gui environment via IGUIEnvironment::registerGUIElementFactory. + Note: When implementing your own element factory, don't call IGUIEnvironment::grab() to + increase the reference counter of the environment. This is not necessary because the + it will grab() the factory anyway, and otherwise cyclic references will be created. + */ + class IGUIElementFactory : public virtual IReferenceCounted + { + public: + + //! adds an element to the gui environment based on its type id + /** \param type: Type of the element to add. + \param parent: Parent scene node of the new element, can be null to add to the root. + \return Pointer to the new element or null if not successful. */ + virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0) = 0; + + //! adds a GUI element to the GUI Environment based on its type name + /** \param typeName: Type name of the element to add. + \param parent: Parent scene node of the new element, can be null to add it to the root. + \return Pointer to the new element or null if not successful. */ + virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0) = 0; + + //! Get amount of GUI element types this factory is able to create + virtual s32 getCreatableGUIElementTypeCount() const = 0; + + //! Get type of a createable element type + /** \param idx: Index of the element type in this factory. Must be a value between 0 and + getCreatableGUIElementTypeCount() */ + virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const = 0; + + //! Get type name of a createable GUI element type by index + /** \param idx: Index of the type in this factory. Must be a value between 0 and + getCreatableGUIElementTypeCount() */ + virtual const c8* getCreateableGUIElementTypeName(s32 idx) const = 0; + + //! returns type name of a createable GUI element + /** \param type: Type of GUI element. + \return Name of the type if this factory can create the type, otherwise 0. */ + virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif // __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ + diff --git a/inc/IGUIEnvironment.h b/inc/IGUIEnvironment.h new file mode 100644 index 0000000..219e419 --- /dev/null +++ b/inc/IGUIEnvironment.h @@ -0,0 +1,620 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_ENVIRONMENT_H_INCLUDED__ +#define __I_GUI_ENVIRONMENT_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IGUISkin.h" +#include "rect.h" +#include "EMessageBoxFlags.h" +#include "IEventReceiver.h" +#include "IXMLReader.h" +#include "path.h" + +namespace irr +{ + class IOSOperator; + class IEventReceiver; + + namespace io + { + class IXMLWriter; + class IReadFile; + class IWriteFile; + class IFileSystem; + } // end namespace io + namespace video + { + class IVideoDriver; + class ITexture; + } // end namespace video + +namespace gui +{ + +class IGUIElement; +class IGUIFont; +class IGUISpriteBank; +class IGUIScrollBar; +class IGUIImage; +class IGUIMeshViewer; +class IGUICheckBox; +class IGUIListBox; +class IGUITreeView; +class IGUIImageList; +class IGUIFileOpenDialog; +class IGUIColorSelectDialog; +class IGUIInOutFader; +class IGUIStaticText; +class IGUIEditBox; +class IGUISpinBox; +class IGUITabControl; +class IGUITab; +class IGUITable; +class IGUIContextMenu; +class IGUIComboBox; +class IGUIToolBar; +class IGUIButton; +class IGUIWindow; +class IGUIElementFactory; + +//! GUI Environment. Used as factory and manager of all other GUI elements. +/** \par This element can create the following events of type EGUI_EVENT_TYPE (which are passed on to focused sub-elements): +\li EGET_ELEMENT_FOCUS_LOST +\li EGET_ELEMENT_FOCUSED +\li EGET_ELEMENT_LEFT +\li EGET_ELEMENT_HOVERED +*/ +class IGUIEnvironment : public virtual IReferenceCounted +{ +public: + + //! Draws all gui elements by traversing the GUI environment starting at the root node. + virtual void drawAll() = 0; + + //! Sets the focus to an element. + /** Causes a EGET_ELEMENT_FOCUS_LOST event followed by a + EGET_ELEMENT_FOCUSED event. If someone absorbed either of the events, + then the focus will not be changed. + \param element Pointer to the element which shall get the focus. + \return True on success, false on failure */ + virtual bool setFocus(IGUIElement* element) = 0; + + //! Returns the element which holds the focus. + /** \return Pointer to the element with focus. */ + virtual IGUIElement* getFocus() const = 0; + + //! Returns the element which was last under the mouse cursor + /** NOTE: This information is updated _after_ the user-eventreceiver + received it's mouse-events. To find the hovered element while catching + mouse events you have to use instead: + IGUIEnvironment::getRootGUIElement()->getElementFromPoint(mousePos); + \return Pointer to the element under the mouse. */ + virtual IGUIElement* getHovered() const = 0; + + //! Removes the focus from an element. + /** Causes a EGET_ELEMENT_FOCUS_LOST event. If the event is absorbed + then the focus will not be changed. + \param element Pointer to the element which shall lose the focus. + \return True on success, false on failure */ + virtual bool removeFocus(IGUIElement* element) = 0; + + //! Returns whether the element has focus + /** \param element Pointer to the element which is tested. + \return True if the element has focus, else false. */ + virtual bool hasFocus(IGUIElement* element) const = 0; + + //! Returns the current video driver. + /** \return Pointer to the video driver. */ + virtual video::IVideoDriver* getVideoDriver() const = 0; + + //! Returns the file system. + /** \return Pointer to the file system. */ + virtual io::IFileSystem* getFileSystem() const = 0; + + //! returns a pointer to the OS operator + /** \return Pointer to the OS operator. */ + virtual IOSOperator* getOSOperator() const = 0; + + //! Removes all elements from the environment. + virtual void clear() = 0; + + //! Posts an input event to the environment. + /** Usually you do not have to + use this method, it is used by the engine internally. + \param event The event to post. + \return True if succeeded, else false. */ + virtual bool postEventFromUser(const SEvent& event) = 0; + + //! This sets a new event receiver for gui events. + /** Usually you do not have to + use this method, it is used by the engine internally. + \param evr Pointer to the new receiver. */ + virtual void setUserEventReceiver(IEventReceiver* evr) = 0; + + //! Returns pointer to the current gui skin. + /** \return Pointer to the GUI skin. */ + virtual IGUISkin* getSkin() const = 0; + + //! Sets a new GUI Skin + /** You can use this to change the appearance of the whole GUI + Environment. You can set one of the built-in skins or implement your + own class derived from IGUISkin and enable it using this method. + To set for example the built-in Windows classic skin, use the following + code: + \code + gui::IGUISkin* newskin = environment->createSkin(gui::EGST_WINDOWS_CLASSIC); + environment->setSkin(newskin); + newskin->drop(); + \endcode + \param skin New skin to use. + */ + virtual void setSkin(IGUISkin* skin) = 0; + + //! Creates a new GUI Skin based on a template. + /** Use setSkin() to set the created skin. + \param type The type of the new skin. + \return Pointer to the created skin. + If you no longer need it, you should call IGUISkin::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type) = 0; + + + //! Creates the image list from the given texture. + /** \param texture Texture to split into images + \param imageSize Dimension of each image + \param useAlphaChannel Flag whether alpha channel of the texture should be honored. + \return Pointer to the font. Returns 0 if the font could not be loaded. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, + bool useAlphaChannel ) = 0; + + //! Returns pointer to the font with the specified filename. + /** Loads the font if it was not loaded before. + \param filename Filename of the Font. + \return Pointer to the font. Returns 0 if the font could not be loaded. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIFont* getFont(const io::path& filename) = 0; + + //! Adds an externally loaded font to the font list. + /** This method allows to attach an already loaded font to the list of + existing fonts. The font is grabbed if non-null and adding was successful. + \param name Name the font should be stored as. + \param font Pointer to font to add. + \return Pointer to the font stored. This can differ from given parameter if the name previously existed. */ + virtual IGUIFont* addFont(const io::path& name, IGUIFont* font) = 0; + + //! remove loaded font + virtual void removeFont(IGUIFont* font) = 0; + + //! Returns the default built-in font. + /** \return Pointer to the default built-in font. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIFont* getBuiltInFont() const = 0; + + //! Returns pointer to the sprite bank with the specified file name. + /** Loads the bank if it was not loaded before. + \param filename Filename of the sprite bank's origin. + \return Pointer to the sprite bank. Returns 0 if it could not be loaded. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IGUISpriteBank* getSpriteBank(const io::path& filename) = 0; + + //! Adds an empty sprite bank to the manager + /** \param name Name of the new sprite bank. + \return Pointer to the sprite bank. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name) = 0; + + //! Returns the root gui element. + /** This is the first gui element, the (direct or indirect) parent of all + other gui elements. It is a valid IGUIElement, with dimensions the same + size as the screen. + \return Pointer to the root element of the GUI. The returned pointer + should not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual IGUIElement* getRootGUIElement() = 0; + + //! Adds a button element. + /** \param rectangle Rectangle specifying the borders of the button. + \param parent Parent gui element of the button. + \param id Id with which the gui element can be identified. + \param text Text displayed on the button. + \param tooltiptext Text displayed in the tooltip. + \return Pointer to the created button. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIButton* addButton(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, const wchar_t* tooltiptext = 0) = 0; + + //! Adds an empty window element. + /** \param rectangle Rectangle specifying the borders of the window. + \param modal Defines if the dialog is modal. This means, that all other + gui elements which were created before the window cannot be used until + it is removed. + \param text Text displayed as the window title. + \param parent Parent gui element of the window. + \param id Id with which the gui element can be identified. + \return Pointer to the created window. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, + const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a modal screen. + /** This control stops its parent's members from being able to receive + input until its last child is removed, it then deletes itself. + \param parent Parent gui element of the modal. + \return Pointer to the created modal. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIElement* addModalScreen(IGUIElement* parent) = 0; + + //! Adds a message box. + /** \param caption Text to be displayed the title of the message box. + \param text Text to be displayed in the body of the message box. + \param modal Defines if the dialog is modal. This means, that all other + gui elements which were created before the message box cannot be used + until this messagebox is removed. + \param flags Flags specifying the layout of the message box. For example + to create a message box with an OK and a CANCEL button on it, set this + to (EMBF_OK | EMBF_CANCEL). + \param parent Parent gui element of the message box. + \param id Id with which the gui element can be identified. + \param image Optional texture which will be displayed beside the text as an image + \return Pointer to the created message box. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, + bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0; + + //! Adds a scrollbar. + /** \param horizontal Specifies if the scroll bar is drawn horizontal + or vertical. + \param rectangle Rectangle specifying the borders of the scrollbar. + \param parent Parent gui element of the scroll bar. + \param id Id to identify the gui element. + \return Pointer to the created scrollbar. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds an image element. + /** \param image Image to be displayed. + \param pos Position of the image. The width and height of the image is + taken from the image. + \param useAlphaChannel Sets if the image should use the alpha channel + of the texture to draw itself. + \param parent Parent gui element of the image. + \param id Id to identify the gui element. + \param text Title text of the image. + \return Pointer to the created image element. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, + bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; + + //! Adds an image element. + /** Use IGUIImage::setImage later to set the image to be displayed. + \param rectangle Rectangle specifying the borders of the image. + \param parent Parent gui element of the image. + \param id Id to identify the gui element. + \param text Title text of the image. + \param useAlphaChannel Sets if the image should use the alpha channel + of the texture to draw itself. + \return Pointer to the created image element. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIImage* addImage(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true) = 0; + + //! Adds a checkbox element. + /** \param checked Define the initial state of the check box. + \param rectangle Rectangle specifying the borders of the check box. + \param parent Parent gui element of the check box. + \param id Id to identify the gui element. + \param text Title text of the check box. + \return Pointer to the created check box. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUICheckBox* addCheckBox(bool checked, const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; + + //! Adds a list box element. + /** \param rectangle Rectangle specifying the borders of the list box. + \param parent Parent gui element of the list box. + \param id Id to identify the gui element. + \param drawBackground Flag whether the background should be drawn. + \return Pointer to the created list box. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIListBox* addListBox(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) = 0; + + //! Adds a tree view element. + /** \param rectangle Position and dimension of list box. + \param parent Parent gui element of the list box. + \param id Id to identify the gui element. + \param drawBackground Flag whether the background should be drawn. + \param scrollBarVertical Flag whether a vertical scrollbar should be used + \param scrollBarHorizontal Flag whether a horizontal scrollbar should be used + \return Pointer to the created list box. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; + + //! Adds a mesh viewer. Not 100% implemented yet. + /** \param rectangle Rectangle specifying the borders of the mesh viewer. + \param parent Parent gui element of the mesh viewer. + \param id Id to identify the gui element. + \param text Title text of the mesh viewer. + \return Pointer to the created mesh viewer. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; + + //! Adds a file open dialog. + /** \param title Text to be displayed as the title of the dialog. + \param modal Defines if the dialog is modal. This means, that all other + gui elements which were created before the message box cannot be used + until this messagebox is removed. + \param parent Parent gui element of the dialog. + \param id Id to identify the gui element. + \param restoreCWD If set to true, the current workingn directory will be + restored after the dialog is closed in some way. Otherwise the working + directory will be the one that the file dialog was last showing. + \param startDir Optional path for which the file dialog will be opened. + \return Pointer to the created file open dialog. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title=0, + bool modal=true, IGUIElement* parent=0, s32 id=-1, + bool restoreCWD=false, io::path::char_type* startDir=0) = 0; + + //! Adds a color select dialog. + /** \param title The title of the dialog. + \param modal Defines if the dialog is modal. This means, that all other + gui elements which were created before the dialog cannot be used + until it is removed. + \param parent The parent of the dialog. + \param id The ID of the dialog. + \return Pointer to the created file open dialog. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, + bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a static text. + /** \param text Text to be displayed. Can be altered after creation by SetText(). + \param rectangle Rectangle specifying the borders of the static text + \param border Set to true if the static text should have a 3d border. + \param wordWrap Enable if the text should wrap into multiple lines. + \param parent Parent item of the element, e.g. a window. + \param id The ID of the element. + \param fillBackground Enable if the background shall be filled. + Defaults to false. + \return Pointer to the created static text. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect& rectangle, + bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, + bool fillBackground = false) = 0; + + //! Adds an edit box. + /** Supports unicode input from every keyboard around the world, + scrolling, copying and pasting (exchanging data with the clipboard + directly), maximum character amount, marking, and all shortcuts like + ctrl+X, ctrl+V, ctrl+C, shift+Left, shift+Right, Home, End, and so on. + \param text Text to be displayed. Can be altered after creation + by setText(). + \param rectangle Rectangle specifying the borders of the edit box. + \param border Set to true if the edit box should have a 3d border. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the edit box directly in the environment. + \param id The ID of the element. + \return Pointer to the created edit box. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, + bool border=true, IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a spin box. + /** An edit box with up and down buttons + \param text Text to be displayed. Can be altered after creation by setText(). + \param rectangle Rectangle specifying the borders of the spin box. + \param border Set to true if the spin box should have a 3d border. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the spin box directly in the environment. + \param id The ID of the element. + \return Pointer to the created spin box. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, + bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds an element for fading in or out. + /** \param rectangle Rectangle specifying the borders of the fader. + If the pointer is NULL, the whole screen is used. + \param parent Parent item of the element, e.g. a window. + \param id An identifier for the fader. + \return Pointer to the created in-out-fader. Returns 0 if an error + occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a tab control to the environment. + /** \param rectangle Rectangle specifying the borders of the tab control. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the tab control directly in the environment. + \param fillbackground Specifies if the background of the tab control + should be drawn. + \param border Specifies if a flat 3d border should be drawn. This is + usually not necessary unless you place the control directly into + the environment without a window as parent. + \param id An identifier for the tab control. + \return Pointer to the created tab control element. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUITabControl* addTabControl(const core::rect& rectangle, + IGUIElement* parent=0, bool fillbackground=false, + bool border=true, s32 id=-1) = 0; + + //! Adds tab to the environment. + /** You can use this element to group other elements. This is not used + for creating tabs on tab controls, please use IGUITabControl::addTab() + for this instead. + \param rectangle Rectangle specifying the borders of the tab. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the tab directly in the environment. + \param id An identifier for the tab. + \return Pointer to the created tab. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUITab* addTab(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a context menu to the environment. + /** \param rectangle Rectangle specifying the borders of the menu. + Note that the menu is resizing itself based on what items you add. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the menu directly in the environment. + \param id An identifier for the menu. + \return Pointer to the created context menu. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIContextMenu* addContextMenu(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a menu to the environment. + /** This is like the menu you can find on top of most windows in modern + graphical user interfaces. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the menu directly in the environment. + \param id An identifier for the menu. + \return Pointer to the created menu. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a toolbar to the environment. + /** It is like a menu that is always placed on top of its parent, and + contains buttons. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the tool bar directly in the environment. + \param id An identifier for the tool bar. + \return Pointer to the created tool bar. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a combo box to the environment. + /** \param rectangle Rectangle specifying the borders of the combo box. + \param parent Parent item of the element, e.g. a window. + Set it to 0 to place the combo box directly in the environment. + \param id An identifier for the combo box. + \return Pointer to the created combo box. Returns 0 if an + error occurred. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IGUIComboBox* addComboBox(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1) = 0; + + //! Adds a table to the environment + /** \param rectangle Rectangle specifying the borders of the table. + \param parent Parent item of the element, e.g. a window. Set it to 0 + to place the element directly in the environment. + \param id An identifier for the table. + \param drawBackground Flag whether the background should be drawn. + \return Pointer to the created table. Returns 0 if an error occurred. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUITable* addTable(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) =0; + + //! Get the default element factory which can create all built-in elements + /** \return Pointer to the factory. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIElementFactory* getDefaultGUIElementFactory() const = 0; + + //! Adds an element factory to the gui environment. + /** Use this to extend the gui environment with new element types which + it should be able to create automatically, for example when loading + data from xml files. + \param factoryToAdd Pointer to new factory. */ + virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd) = 0; + + //! Get amount of registered gui element factories. + /** \return Amount of registered gui element factories. */ + virtual u32 getRegisteredGUIElementFactoryCount() const = 0; + + //! Get a gui element factory by index + /** \param index Index of the factory. + \return Factory at given index, or 0 if no such factory exists. */ + virtual IGUIElementFactory* getGUIElementFactory(u32 index) const = 0; + + //! Adds a GUI element by its name + /** Each factory is checked if it can create an element of the given + name. The first match will be created. + \param elementName Name of the element to be created. + \param parent Parent of the new element, if not 0. + \return New GUI element, or 0 if no such element exists. */ + virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0) = 0; + + //! Saves the current gui into a file. + /** \param filename Name of the file. + \param start The GUIElement to start with. Root if 0. + \return True if saving succeeded, else false. */ + virtual bool saveGUI(const io::path& filename, IGUIElement* start=0) = 0; + + //! Saves the current gui into a file. + /** \param file The file to write to. + \param start The GUIElement to start with. Root if 0. + \return True if saving succeeded, else false. */ + virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0) = 0; + + //! Loads the gui. Note that the current gui is not cleared before. + /** When a parent is set the elements will be added below the parent, the parent itself does not deserialize. + When the file contains skin-settings from the gui-environment those are always serialized into the + guienvironment independent of the parent setting. + \param filename Name of the file. + \param parent Parent for the loaded GUI, root if 0. + \return True if loading succeeded, else false. */ + virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0) = 0; + + //! Loads the gui. Note that the current gui is not cleared before. + /** When a parent is set the elements will be added below the parent, the parent itself does not deserialize. + When the file contains skin-settings from the gui-environment those are always serialized into the + guienvironment independent of the parent setting. + \param file The file to load from. + \param parent Parent for the loaded GUI, root if 0. + \return True if loading succeeded, else false. */ + virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0) = 0; + + //! Writes attributes of the gui environment + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const =0; + + //! Reads attributes of the gui environment + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)=0; + + //! writes an element + virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) =0; + + //! reads an element + virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) =0; +}; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIFileOpenDialog.h b/inc/IGUIFileOpenDialog.h new file mode 100644 index 0000000..f89413b --- /dev/null +++ b/inc/IGUIFileOpenDialog.h @@ -0,0 +1,44 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ +#define __I_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ + +#include "IGUIElement.h" +#include "path.h" + +namespace irr +{ +namespace gui +{ + + //! Standard file chooser dialog. + /** \warning When the user selects a folder this does change the current working directory + + \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_DIRECTORY_SELECTED + \li EGET_FILE_SELECTED + \li EGET_FILE_CHOOSE_DIALOG_CANCELLED + */ + class IGUIFileOpenDialog : public IGUIElement + { + public: + + //! constructor + IGUIFileOpenDialog(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_FILE_OPEN_DIALOG, environment, parent, id, rectangle) {} + + //! Returns the filename of the selected file. Returns NULL, if no file was selected. + virtual const wchar_t* getFileName() const = 0; + + //! Returns the directory of the selected file. Returns NULL, if no directory was selected. + virtual const io::path& getDirectoryName() = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIFont.h b/inc/IGUIFont.h new file mode 100644 index 0000000..2e97c82 --- /dev/null +++ b/inc/IGUIFont.h @@ -0,0 +1,104 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_FONT_H_INCLUDED__ +#define __I_GUI_FONT_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SColor.h" +#include "rect.h" +#include "irrString.h" + +namespace irr +{ +namespace gui +{ + +//! An enum for the different types of GUI font. +enum EGUI_FONT_TYPE +{ + //! Bitmap fonts loaded from an XML file or a texture. + EGFT_BITMAP = 0, + + //! Scalable vector fonts loaded from an XML file. + /** These fonts reside in system memory and use no video memory + until they are displayed. These are slower than bitmap fonts + but can be easily scaled and rotated. */ + EGFT_VECTOR, + + //! A font which uses a the native API provided by the operating system. + /** Currently not used. */ + EGFT_OS, + + //! An external font type provided by the user. + EGFT_CUSTOM +}; + +//! Font interface. +class IGUIFont : public virtual IReferenceCounted +{ +public: + + //! Draws some text and clips it to the specified rectangle if wanted. + /** \param text: Text to draw + \param position: Rectangle specifying position where to draw the text. + \param color: Color of the text + \param hcenter: Specifies if the text should be centered horizontally into the rectangle. + \param vcenter: Specifies if the text should be centered vertically into the rectangle. + \param clip: Optional pointer to a rectangle against which the text will be clipped. + If the pointer is null, no clipping will be done. */ + virtual void draw(const core::stringw& text, const core::rect& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect* clip=0) = 0; + + //! Calculates the width and height of a given string of text. + /** \return Returns width and height of the area covered by the text if + it would be drawn. */ + virtual core::dimension2d getDimension(const wchar_t* text) const = 0; + + //! Calculates the index of the character in the text which is on a specific position. + /** \param text: Text string. + \param pixel_x: X pixel position of which the index of the character will be returned. + \return Returns zero based index of the character in the text, and -1 if no no character + is on this position. (=the text is too short). */ + virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const = 0; + + //! Returns the type of this font + virtual EGUI_FONT_TYPE getType() const { return EGFT_CUSTOM; } + + //! Sets global kerning width for the font. + virtual void setKerningWidth (s32 kerning) = 0; + + //! Sets global kerning height for the font. + virtual void setKerningHeight (s32 kerning) = 0; + + //! Gets kerning values (distance between letters) for the font. If no parameters are provided, + /** the global kerning distance is returned. + \param thisLetter: If this parameter is provided, the left side kerning + for this letter is added to the global kerning value. For example, a + space might only be one pixel wide, but it may be displayed as several + pixels. + \param previousLetter: If provided, kerning is calculated for both + letters and added to the global kerning value. For example, in a font + which supports kerning pairs a string such as 'Wo' may have the 'o' + tucked neatly under the 'W'. + */ + virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; + + //! Returns the distance between letters + virtual s32 getKerningHeight() const = 0; + + //! Define which characters should not be drawn by the font. + /** For example " " would not draw any space which is usually blank in + most fonts. + \param s String of symbols which are not send down to the videodriver + */ + virtual void setInvisibleCharacters( const wchar_t *s ) = 0; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIFontBitmap.h b/inc/IGUIFontBitmap.h new file mode 100644 index 0000000..c05a652 --- /dev/null +++ b/inc/IGUIFontBitmap.h @@ -0,0 +1,46 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_FONT_BITMAP_H_INCLUDED__ +#define __I_GUI_FONT_BITMAP_H_INCLUDED__ + +#include "IGUIFont.h" + +namespace irr +{ +namespace gui +{ + class IGUISpriteBank; + +//! Font interface. +class IGUIFontBitmap : public IGUIFont +{ +public: + + //! Returns the type of this font + virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; } + + //! returns the parsed Symbol Information + virtual IGUISpriteBank* getSpriteBank() const = 0; + + //! returns the sprite number from a given character + virtual u32 getSpriteNoFromChar(const wchar_t *c) const = 0; + + //! Gets kerning values (distance between letters) for the font. If no parameters are provided, + /** the global kerning distance is returned. + \param thisLetter: If this parameter is provided, the left side kerning for this letter is added + to the global kerning value. For example, a space might only be one pixel wide, but it may + be displayed as several pixels. + \param previousLetter: If provided, kerning is calculated for both letters and added to the global + kerning value. For example, EGFT_BITMAP will add the right kerning value of previousLetter to the + left side kerning value of thisLetter, then add the global value. + */ + virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIImage.h b/inc/IGUIImage.h new file mode 100644 index 0000000..5e6d347 --- /dev/null +++ b/inc/IGUIImage.h @@ -0,0 +1,58 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_IMAGE_H_INCLUDED__ +#define __I_GUI_IMAGE_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace video +{ + class ITexture; +} +namespace gui +{ + + //! GUI element displaying an image. + class IGUIImage : public IGUIElement + { + public: + + //! constructor + IGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_IMAGE, environment, parent, id, rectangle) {} + + //! Sets an image texture + virtual void setImage(video::ITexture* image) = 0; + + //! Gets the image texture + virtual video::ITexture* getImage() const = 0; + + //! Sets the color of the image + virtual void setColor(video::SColor color) = 0; + + //! Sets if the image should scale to fit the element + virtual void setScaleImage(bool scale) = 0; + + //! Sets if the image should use its alpha channel to draw itself + virtual void setUseAlphaChannel(bool use) = 0; + + //! Gets the color of the image + virtual video::SColor getColor() const = 0; + + //! Returns true if the image is scaled to fit, false if not + virtual bool isImageScaled() const = 0; + + //! Returns true if the image is using the alpha channel, false if not + virtual bool isAlphaChannelUsed() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIImageList.h b/inc/IGUIImageList.h new file mode 100644 index 0000000..fb4ca4b --- /dev/null +++ b/inc/IGUIImageList.h @@ -0,0 +1,45 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __I_GUI_IMAGE_LIST_H_INCLUDED__ +#define __I_GUI_IMAGE_LIST_H_INCLUDED__ + +#include "IGUIElement.h" +#include "rect.h" +#include "irrTypes.h" + +namespace irr +{ +namespace gui +{ + +//! Font interface. +class IGUIImageList : public virtual IReferenceCounted +{ +public: + + //! Destructor + virtual ~IGUIImageList() {}; + + //! Draws an image and clips it to the specified rectangle if wanted + //! \param index: Index of the image + //! \param destPos: Position of the image to draw + //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. + //! If the pointer is null, no clipping will be done. + virtual void draw(s32 index, const core::position2d& destPos, + const core::rect* clip = 0) = 0; + + //! Returns the count of Images in the list. + //! \return Returns the count of Images in the list. + virtual s32 getImageCount() const = 0; + + //! Returns the size of the images in the list. + //! \return Returns the size of the images in the list. + virtual core::dimension2d getImageSize() const = 0; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIInOutFader.h b/inc/IGUIInOutFader.h new file mode 100644 index 0000000..6846d7b --- /dev/null +++ b/inc/IGUIInOutFader.h @@ -0,0 +1,67 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_IN_OUT_FADER_H_INCLUDED__ +#define __I_GUI_IN_OUT_FADER_H_INCLUDED__ + +#include "IGUIElement.h" +#include "SColor.h" + +namespace irr +{ +namespace gui +{ + + //! Element for fading out or in + /** Here is a small example on how the class is used. In this example we fade + in from a total red screen in the beginning. As you can see, the fader is not + only useful for dramatic in and out fading, but also to show that the player + is hit in a first person shooter game for example. + \code + gui::IGUIInOutFader* fader = device->getGUIEnvironment()->addInOutFader(); + fader->setColor(video::SColor(0,255,0,0)); + fader->fadeIn(4000); + \endcode + */ + class IGUIInOutFader : public IGUIElement + { + public: + + //! constructor + IGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_IN_OUT_FADER, environment, parent, id, rectangle) {} + + //! Gets the color to fade out to or to fade in from. + virtual video::SColor getColor() const = 0; + + //! Sets the color to fade out to or to fade in from. + /** \param color: Color to where it is faded out od from it is faded in. */ + virtual void setColor(video::SColor color) = 0; + virtual void setColor(video::SColor source, video::SColor dest) = 0; + + //! Starts the fade in process. + /** In the beginning the whole rect is drawn by the set color + (black by default) and at the end of the overgiven time the + color has faded out. + \param time: Time specifying how long it should need to fade in, + in milliseconds. */ + virtual void fadeIn(u32 time) = 0; + + //! Starts the fade out process. + /** In the beginning everything is visible, and at the end of + the time only the set color (black by the fault) will be drawn. + \param time: Time specifying how long it should need to fade out, + in milliseconds. */ + virtual void fadeOut(u32 time) = 0; + + //! Returns if the fade in or out process is done. + virtual bool isReady() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIListBox.h b/inc/IGUIListBox.h new file mode 100644 index 0000000..de922ce --- /dev/null +++ b/inc/IGUIListBox.h @@ -0,0 +1,138 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_LIST_BOX_H_INCLUDED__ +#define __I_GUI_LIST_BOX_H_INCLUDED__ + +#include "IGUIElement.h" +#include "SColor.h" + +namespace irr +{ +namespace gui +{ + class IGUISpriteBank; + + //! Enumeration for listbox colors + enum EGUI_LISTBOX_COLOR + { + //! Color of text + EGUI_LBC_TEXT=0, + //! Color of selected text + EGUI_LBC_TEXT_HIGHLIGHT, + //! Color of icon + EGUI_LBC_ICON, + //! Color of selected icon + EGUI_LBC_ICON_HIGHLIGHT, + //! Not used, just counts the number of available colors + EGUI_LBC_COUNT + }; + + + //! Default list box GUI element. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_LISTBOX_CHANGED + \li EGET_LISTBOX_SELECTED_AGAIN + */ + class IGUIListBox : public IGUIElement + { + public: + //! constructor + IGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_LIST_BOX, environment, parent, id, rectangle) {} + + //! returns amount of list items + virtual u32 getItemCount() const = 0; + + //! returns string of a list item. the may id be a value from 0 to itemCount-1 + virtual const wchar_t* getListItem(u32 id) const = 0; + + //! adds an list item, returns id of item + virtual u32 addItem(const wchar_t* text) = 0; + + //! adds an list item with an icon + /** \param text Text of list entry + \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon + \return The id of the new created item */ + virtual u32 addItem(const wchar_t* text, s32 icon) = 0; + + //! Removes an item from the list + virtual void removeItem(u32 index) = 0; + + //! get the the id of the item at the given absolute coordinates + /** \return The id of the listitem or -1 when no item is at those coordinates*/ + virtual s32 getItemAt(s32 xpos, s32 ypos) const = 0; + + //! Returns the icon of an item + virtual s32 getIcon(u32 index) const = 0; + + //! Sets the sprite bank which should be used to draw list icons. + /** This font is set to the sprite bank of the built-in-font by + default. A sprite can be displayed in front of every list item. + An icon is an index within the icon sprite bank. Several + default icons are available in the skin through getIcon. */ + virtual void setSpriteBank(IGUISpriteBank* bank) = 0; + + //! clears the list, deletes all items in the listbox + virtual void clear() = 0; + + //! returns id of selected item. returns -1 if no item is selected. + virtual s32 getSelected() const = 0; + + //! sets the selected item. Set this to -1 if no item should be selected + virtual void setSelected(s32 index) = 0; + + //! sets the selected item. Set this to 0 if no item should be selected + virtual void setSelected(const wchar_t *item) = 0; + + //! set whether the listbox should scroll to newly selected items + virtual void setAutoScrollEnabled(bool scroll) = 0; + + //! returns true if automatic scrolling is enabled, false if not. + virtual bool isAutoScrollEnabled() const = 0; + + //! set all item colors at given index to color + virtual void setItemOverrideColor(u32 index, video::SColor color) = 0; + + //! set all item colors of specified type at given index to color + virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) = 0; + + //! clear all item colors at index + virtual void clearItemOverrideColor(u32 index) = 0; + + //! clear item color at index for given colortype + virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) = 0; + + //! has the item at index its color overwritten? + virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const = 0; + + //! return the overwrite color at given item index. + virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const = 0; + + //! return the default color which is used for the given colorType + virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const = 0; + + //! set the item at the given index + virtual void setItem(u32 index, const wchar_t* text, s32 icon) = 0; + + //! Insert the item at the given index + /** \return The index on success or -1 on failure. */ + virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon) = 0; + + //! Swap the items at the given indices + virtual void swapItems(u32 index1, u32 index2) = 0; + + //! set global itemHeight + virtual void setItemHeight( s32 height ) = 0; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw) = 0; +}; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIMeshViewer.h b/inc/IGUIMeshViewer.h new file mode 100644 index 0000000..62ff1ab --- /dev/null +++ b/inc/IGUIMeshViewer.h @@ -0,0 +1,53 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_MESH_VIEWER_H_INCLUDED__ +#define __I_GUI_MESH_VIEWER_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ + +namespace video +{ + class SMaterial; +} // end namespace video + +namespace scene +{ + class IAnimatedMesh; +} // end namespace scene + +namespace gui +{ + + //! 3d mesh viewing GUI element. + class IGUIMeshViewer : public IGUIElement + { + public: + + //! constructor + IGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_MESH_VIEWER, environment, parent, id, rectangle) {} + + //! Sets the mesh to be shown + virtual void setMesh(scene::IAnimatedMesh* mesh) = 0; + + //! Gets the displayed mesh + virtual scene::IAnimatedMesh* getMesh() const = 0; + + //! Sets the material + virtual void setMaterial(const video::SMaterial& material) = 0; + + //! Gets the material + virtual const video::SMaterial& getMaterial() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIScrollBar.h b/inc/IGUIScrollBar.h new file mode 100644 index 0000000..4064ef9 --- /dev/null +++ b/inc/IGUIScrollBar.h @@ -0,0 +1,65 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_SCROLL_BAR_H_INCLUDED__ +#define __I_GUI_SCROLL_BAR_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + + //! Default scroll bar GUI element. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_SCROLL_BAR_CHANGED + */ + class IGUIScrollBar : public IGUIElement + { + public: + + //! constructor + IGUIScrollBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_SCROLL_BAR, environment, parent, id, rectangle) {} + + //! sets the maximum value of the scrollbar. + virtual void setMax(s32 max) = 0; + //! gets the maximum value of the scrollbar. + virtual s32 getMax() const = 0; + + //! sets the minimum value of the scrollbar. + virtual void setMin(s32 min) = 0; + //! gets the minimum value of the scrollbar. + virtual s32 getMin() const = 0; + + //! gets the small step value + virtual s32 getSmallStep() const = 0; + + //! Sets the small step + /** That is the amount that the value changes by when clicking + on the buttons or using the cursor keys. */ + virtual void setSmallStep(s32 step) = 0; + + //! gets the large step value + virtual s32 getLargeStep() const = 0; + + //! Sets the large step + /** That is the amount that the value changes by when clicking + in the tray, or using the page up and page down keys. */ + virtual void setLargeStep(s32 step) = 0; + + //! gets the current position of the scrollbar + virtual s32 getPos() const = 0; + + //! sets the current position of the scrollbar + virtual void setPos(s32 pos) = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUISkin.h b/inc/IGUISkin.h new file mode 100644 index 0000000..a7cd2d2 --- /dev/null +++ b/inc/IGUISkin.h @@ -0,0 +1,574 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_SKIN_H_INCLUDED__ +#define __I_GUI_SKIN_H_INCLUDED__ + +#include "IAttributeExchangingObject.h" +#include "EGUIAlignment.h" +#include "SColor.h" +#include "rect.h" + +namespace irr +{ +namespace gui +{ + class IGUIFont; + class IGUISpriteBank; + class IGUIElement; + + //! Enumeration of available default skins. + /** To set one of the skins, use the following code, for example to set + the Windows classic skin: + \code + gui::IGUISkin* newskin = environment->createSkin(gui::EGST_WINDOWS_CLASSIC); + environment->setSkin(newskin); + newskin->drop(); + \endcode + */ + enum EGUI_SKIN_TYPE + { + //! Default windows look and feel + EGST_WINDOWS_CLASSIC=0, + + //! Like EGST_WINDOWS_CLASSIC, but with metallic shaded windows and buttons + EGST_WINDOWS_METALLIC, + + //! Burning's skin + EGST_BURNING_SKIN, + + //! An unknown skin, not serializable at present + EGST_UNKNOWN, + + //! this value is not used, it only specifies the number of skin types + EGST_COUNT + }; + + //! Names for gui element types + const c8* const GUISkinTypeNames[EGST_COUNT+1] = + { + "windowsClassic", + "windowsMetallic", + "burning", + "unknown", + 0, + }; + + + //! Enumeration for skin colors + enum EGUI_DEFAULT_COLOR + { + //! Dark shadow for three-dimensional display elements. + EGDC_3D_DARK_SHADOW = 0, + //! Shadow color for three-dimensional display elements (for edges facing away from the light source). + EGDC_3D_SHADOW, + //! Face color for three-dimensional display elements and for dialog box backgrounds. + EGDC_3D_FACE, + //! Highlight color for three-dimensional display elements (for edges facing the light source.) + EGDC_3D_HIGH_LIGHT, + //! Light color for three-dimensional display elements (for edges facing the light source.) + EGDC_3D_LIGHT, + //! Active window border. + EGDC_ACTIVE_BORDER, + //! Active window title bar text. + EGDC_ACTIVE_CAPTION, + //! Background color of multiple document interface (MDI) applications. + EGDC_APP_WORKSPACE, + //! Text on a button + EGDC_BUTTON_TEXT, + //! Grayed (disabled) text. + EGDC_GRAY_TEXT, + //! Item(s) selected in a control. + EGDC_HIGH_LIGHT, + //! Text of item(s) selected in a control. + EGDC_HIGH_LIGHT_TEXT, + //! Inactive window border. + EGDC_INACTIVE_BORDER, + //! Inactive window caption. + EGDC_INACTIVE_CAPTION, + //! Tool tip text color + EGDC_TOOLTIP, + //! Tool tip background color + EGDC_TOOLTIP_BACKGROUND, + //! Scrollbar gray area + EGDC_SCROLLBAR, + //! Window background + EGDC_WINDOW, + //! Window symbols like on close buttons, scroll bars and check boxes + EGDC_WINDOW_SYMBOL, + //! Icons in a list or tree + EGDC_ICON, + //! Selected icons in a list or tree + EGDC_ICON_HIGH_LIGHT, + //! Grayed (disabled) window symbols like on close buttons, scroll bars and check boxes + EGDC_GRAY_WINDOW_SYMBOL, + //! Window background for editable field (editbox, checkbox-field) + EGDC_EDITABLE, + //! Grayed (disabled) window background for editable field (editbox, checkbox-field) + EGDC_GRAY_EDITABLE, + //! Show focus of window background for editable field (editbox or when checkbox-field is pressed) + EGDC_FOCUSED_EDITABLE, + + //! this value is not used, it only specifies the amount of default colors + //! available. + EGDC_COUNT + }; + + //! Names for default skin colors + const c8* const GUISkinColorNames[EGDC_COUNT+1] = + { + "3DDarkShadow", + "3DShadow", + "3DFace", + "3DHighlight", + "3DLight", + "ActiveBorder", + "ActiveCaption", + "AppWorkspace", + "ButtonText", + "GrayText", + "Highlight", + "HighlightText", + "InactiveBorder", + "InactiveCaption", + "ToolTip", + "ToolTipBackground", + "ScrollBar", + "Window", + "WindowSymbol", + "Icon", + "IconHighlight", + "GrayWindowSymbol", + "Editable", + "GrayEditable", + "FocusedEditable", + 0, + }; + + //! Enumeration for default sizes. + enum EGUI_DEFAULT_SIZE + { + //! default with / height of scrollbar + EGDS_SCROLLBAR_SIZE = 0, + //! height of menu + EGDS_MENU_HEIGHT, + //! width of a window button + EGDS_WINDOW_BUTTON_WIDTH, + //! width of a checkbox check + EGDS_CHECK_BOX_WIDTH, + //! \deprecated This may be removed by Irrlicht 1.9 + EGDS_MESSAGE_BOX_WIDTH, + //! \deprecated This may be removed by Irrlicht 1.9 + EGDS_MESSAGE_BOX_HEIGHT, + //! width of a default button + EGDS_BUTTON_WIDTH, + //! height of a default button + EGDS_BUTTON_HEIGHT, + //! distance for text from background + EGDS_TEXT_DISTANCE_X, + //! distance for text from background + EGDS_TEXT_DISTANCE_Y, + //! distance for text in the title bar, from the left of the window rect + EGDS_TITLEBARTEXT_DISTANCE_X, + //! distance for text in the title bar, from the top of the window rect + EGDS_TITLEBARTEXT_DISTANCE_Y, + //! free space in a messagebox between borders and contents on all sides + EGDS_MESSAGE_BOX_GAP_SPACE, + //! minimal space to reserve for messagebox text-width + EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH, + //! maximal space to reserve for messagebox text-width + EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH, + //! minimal space to reserve for messagebox text-height + EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT, + //! maximal space to reserve for messagebox text-height + EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT, + //! pixels to move the button image to the right when a pushbutton is pressed + EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X, + //! pixels to move the button image down when a pushbutton is pressed + EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y, + //! pixels to move the button text to the right when a pushbutton is pressed + EGDS_BUTTON_PRESSED_TEXT_OFFSET_X, + //! pixels to move the button text down when a pushbutton is pressed + EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y, + + //! this value is not used, it only specifies the amount of default sizes + //! available. + EGDS_COUNT + }; + + + //! Names for default skin sizes + const c8* const GUISkinSizeNames[EGDS_COUNT+1] = + { + "ScrollBarSize", + "MenuHeight", + "WindowButtonWidth", + "CheckBoxWidth", + "MessageBoxWidth", + "MessageBoxHeight", + "ButtonWidth", + "ButtonHeight", + "TextDistanceX", + "TextDistanceY", + "TitleBarTextX", + "TitleBarTextY", + "MessageBoxGapSpace", + "MessageBoxMinTextWidth", + "MessageBoxMaxTextWidth", + "MessageBoxMinTextHeight", + "MessageBoxMaxTextHeight", + "ButtonPressedImageOffsetX", + "ButtonPressedImageOffsetY", + "ButtonPressedTextOffsetX", + "ButtonPressedTextOffsetY", + 0 + }; + + + enum EGUI_DEFAULT_TEXT + { + //! Text for the OK button on a message box + EGDT_MSG_BOX_OK = 0, + //! Text for the Cancel button on a message box + EGDT_MSG_BOX_CANCEL, + //! Text for the Yes button on a message box + EGDT_MSG_BOX_YES, + //! Text for the No button on a message box + EGDT_MSG_BOX_NO, + //! Tooltip text for window close button + EGDT_WINDOW_CLOSE, + //! Tooltip text for window maximize button + EGDT_WINDOW_MAXIMIZE, + //! Tooltip text for window minimize button + EGDT_WINDOW_MINIMIZE, + //! Tooltip text for window restore button + EGDT_WINDOW_RESTORE, + + //! this value is not used, it only specifies the number of default texts + EGDT_COUNT + }; + + //! Names for default skin sizes + const c8* const GUISkinTextNames[EGDT_COUNT+1] = + { + "MessageBoxOkay", + "MessageBoxCancel", + "MessageBoxYes", + "MessageBoxNo", + "WindowButtonClose", + "WindowButtonMaximize", + "WindowButtonMinimize", + "WindowButtonRestore", + 0 + }; + + //! Customizable symbols for GUI + enum EGUI_DEFAULT_ICON + { + //! maximize window button + EGDI_WINDOW_MAXIMIZE = 0, + //! restore window button + EGDI_WINDOW_RESTORE, + //! close window button + EGDI_WINDOW_CLOSE, + //! minimize window button + EGDI_WINDOW_MINIMIZE, + //! resize icon for bottom right corner of a window + EGDI_WINDOW_RESIZE, + //! scroll bar up button + EGDI_CURSOR_UP, + //! scroll bar down button + EGDI_CURSOR_DOWN, + //! scroll bar left button + EGDI_CURSOR_LEFT, + //! scroll bar right button + EGDI_CURSOR_RIGHT, + //! icon for menu children + EGDI_MENU_MORE, + //! tick for checkbox + EGDI_CHECK_BOX_CHECKED, + //! down arrow for dropdown menus + EGDI_DROP_DOWN, + //! smaller up arrow + EGDI_SMALL_CURSOR_UP, + //! smaller down arrow + EGDI_SMALL_CURSOR_DOWN, + //! selection dot in a radio button + EGDI_RADIO_BUTTON_CHECKED, + //! << icon indicating there is more content to the left + EGDI_MORE_LEFT, + //! >> icon indicating that there is more content to the right + EGDI_MORE_RIGHT, + //! icon indicating that there is more content above + EGDI_MORE_UP, + //! icon indicating that there is more content below + EGDI_MORE_DOWN, + //! plus icon for trees + EGDI_EXPAND, + + //! minus icon for trees + EGDI_COLLAPSE, + //! file icon for file selection + EGDI_FILE, + //! folder icon for file selection + EGDI_DIRECTORY, + + //! value not used, it only specifies the number of icons + EGDI_COUNT + }; + + const c8* const GUISkinIconNames[EGDI_COUNT+1] = + { + "windowMaximize", + "windowRestore", + "windowClose", + "windowMinimize", + "windowResize", + "cursorUp", + "cursorDown", + "cursorLeft", + "cursorRight", + "menuMore", + "checkBoxChecked", + "dropDown", + "smallCursorUp", + "smallCursorDown", + "radioButtonChecked", + "moreLeft", + "moreRight", + "moreUp", + "moreDown", + "expand", + "collapse", + "file", + "directory", + 0 + }; + + // Customizable fonts + enum EGUI_DEFAULT_FONT + { + //! For static text, edit boxes, lists and most other places + EGDF_DEFAULT=0, + //! Font for buttons + EGDF_BUTTON, + //! Font for window title bars + EGDF_WINDOW, + //! Font for menu items + EGDF_MENU, + //! Font for tooltips + EGDF_TOOLTIP, + //! this value is not used, it only specifies the amount of default fonts + //! available. + EGDF_COUNT + }; + + const c8* const GUISkinFontNames[EGDF_COUNT+1] = + { + "defaultFont", + "buttonFont", + "windowFont", + "menuFont", + "tooltipFont", + 0 + }; + + //! A skin modifies the look of the GUI elements. + class IGUISkin : public virtual io::IAttributeExchangingObject + { + public: + + //! returns default color + virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0; + + //! sets a default color + virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor) = 0; + + //! returns size for the given size type + virtual s32 getSize(EGUI_DEFAULT_SIZE size) const = 0; + + //! Returns a default text. + /** For example for Message box button captions: + "OK", "Cancel", "Yes", "No" and so on. */ + virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const = 0; + + //! Sets a default text. + /** For example for Message box button captions: + "OK", "Cancel", "Yes", "No" and so on. */ + virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText) = 0; + + //! sets a default size + virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size) = 0; + + //! returns the default font + virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const = 0; + + //! sets a default font + virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT) = 0; + + //! returns the sprite bank + virtual IGUISpriteBank* getSpriteBank() const = 0; + + //! sets the sprite bank + virtual void setSpriteBank(IGUISpriteBank* bank) = 0; + + //! Returns a default icon + /** Returns the sprite index within the sprite bank */ + virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const = 0; + + //! Sets a default icon + /** Sets the sprite index used for drawing icons like arrows, + close buttons and ticks in checkboxes + \param icon: Enum specifying which icon to change + \param index: The sprite index used to draw this icon */ + virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index) = 0; + + //! draws a standard 3d button pane + /** Used for drawing for example buttons in normal state. + It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param rect: Defining area where to draw. + \param clip: Clip area. */ + virtual void draw3DButtonPaneStandard(IGUIElement* element, + const core::rect& rect, + const core::rect* clip=0) = 0; + + //! draws a pressed 3d button pane + /** Used for drawing for example buttons in pressed state. + It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param rect: Defining area where to draw. + \param clip: Clip area. */ + virtual void draw3DButtonPanePressed(IGUIElement* element, + const core::rect& rect, + const core::rect* clip=0) = 0; + + //! draws a sunken 3d pane + /** Used for drawing the background of edit, combo or check boxes. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param bgcolor: Background color. + \param flat: Specifies if the sunken pane should be flat or displayed as sunken + deep into the ground. + \param fillBackGround: Specifies if the background should be filled with the background + color or not be drawn at all. + \param rect: Defining area where to draw. + \param clip: Clip area. */ + virtual void draw3DSunkenPane(IGUIElement* element, + video::SColor bgcolor, bool flat, bool fillBackGround, + const core::rect& rect, + const core::rect* clip=0) = 0; + + //! draws a window background + /** Used for drawing the background of dialogs and windows. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param titleBarColor: Title color. + \param drawTitleBar: True to enable title drawing. + \param rect: Defining area where to draw. + \param clip: Clip area. + \param checkClientArea: When set to non-null the function will not draw anything, + but will instead return the clientArea which can be used for drawing by the calling window. + That is the area without borders and without titlebar. + \return Returns rect where it would be good to draw title bar text. This will + work even when checkClientArea is set to a non-null value.*/ + virtual core::rect draw3DWindowBackground(IGUIElement* element, + bool drawTitleBar, video::SColor titleBarColor, + const core::rect& rect, + const core::rect* clip=0, + core::rect* checkClientArea=0) = 0; + + //! draws a standard 3d menu pane + /** Used for drawing for menus and context menus. + It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and + EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param rect: Defining area where to draw. + \param clip: Clip area. */ + virtual void draw3DMenuPane(IGUIElement* element, + const core::rect& rect, + const core::rect* clip=0) = 0; + + //! draws a standard 3d tool bar + /** Used for drawing for toolbars and menus. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param rect: Defining area where to draw. + \param clip: Clip area. */ + virtual void draw3DToolBar(IGUIElement* element, + const core::rect& rect, + const core::rect* clip=0) = 0; + + //! draws a tab button + /** Used for drawing for tab buttons on top of tabs. + \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param active: Specifies if the tab is currently active. + \param rect: Defining area where to draw. + \param clip: Clip area. + \param alignment Alignment of GUI element. */ + virtual void draw3DTabButton(IGUIElement* element, bool active, + const core::rect& rect, const core::rect* clip=0, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) = 0; + + //! draws a tab control body + /** \param element: Pointer to the element which wishes to draw this. This parameter + is usually not used by IGUISkin, but can be used for example by more complex + implementations to find out how to draw the part exactly. + \param border: Specifies if the border should be drawn. + \param background: Specifies if the background should be drawn. + \param rect: Defining area where to draw. + \param clip: Clip area. + \param tabHeight Height of tab. + \param alignment Alignment of GUI element. */ + virtual void draw3DTabBody(IGUIElement* element, bool border, bool background, + const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT ) = 0; + + //! draws an icon, usually from the skin's sprite bank + /** \param element: Pointer to the element which wishes to draw this icon. + This parameter is usually not used by IGUISkin, but can be used for example + by more complex implementations to find out how to draw the part exactly. + \param icon: Specifies the icon to be drawn. + \param position: The position to draw the icon + \param starttime: The time at the start of the animation + \param currenttime: The present time, used to calculate the frame number + \param loop: Whether the animation should loop or not + \param clip: Clip area. */ + virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, + const core::position2di position, u32 starttime=0, u32 currenttime=0, + bool loop=false, const core::rect* clip=0) = 0; + + //! draws a 2d rectangle. + /** \param element: Pointer to the element which wishes to draw this icon. + This parameter is usually not used by IGUISkin, but can be used for example + by more complex implementations to find out how to draw the part exactly. + \param color: Color of the rectangle to draw. The alpha component specifies how + transparent the rectangle will be. + \param pos: Position of the rectangle. + \param clip: Pointer to rectangle against which the rectangle will be clipped. + If the pointer is null, no clipping will be performed. */ + virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color, + const core::rect& pos, const core::rect* clip = 0) = 0; + + //! get the type of this skin + virtual EGUI_SKIN_TYPE getType() const { return EGST_UNKNOWN; } + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUISpinBox.h b/inc/IGUISpinBox.h new file mode 100644 index 0000000..2310161 --- /dev/null +++ b/inc/IGUISpinBox.h @@ -0,0 +1,69 @@ +// Copyright (C) 2006-2012 Michael Zeilfelder +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_SPIN_BOX_H_INCLUDED__ +#define __I_GUI_SPIN_BOX_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace gui +{ + class IGUIEditBox; + + //! Single line edit box + spin buttons + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_SPINBOX_CHANGED + */ + class IGUISpinBox : public IGUIElement + { + public: + + //! constructor + IGUISpinBox(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle) + : IGUIElement(EGUIET_SPIN_BOX, environment, parent, id, rectangle) {} + + //! Access the edit box used in the spin control + virtual IGUIEditBox* getEditBox() const = 0; + + //! set the current value of the spinbox + /** \param val: value to be set in the spinbox */ + virtual void setValue(f32 val) = 0; + + //! Get the current value of the spinbox + virtual f32 getValue() const = 0; + + //! set the range of values which can be used in the spinbox + /** \param min: minimum value + \param max: maximum value */ + virtual void setRange(f32 min, f32 max) = 0; + + //! get the minimum value which can be used in the spinbox + virtual f32 getMin() const = 0; + + //! get the maximum value which can be used in the spinbox + virtual f32 getMax() const = 0; + + //! Step size by which values are changed when pressing the spinbuttons + /** The step size also determines the number of decimal places to display + \param step: stepsize used for value changes when pressing spinbuttons */ + virtual void setStepSize(f32 step=1.f) = 0; + + //! Sets the number of decimal places to display. + //! Note that this also rounds the range to the same number of decimal places. + /** \param places: The number of decimal places to display, use -1 to reset */ + virtual void setDecimalPlaces(s32 places) = 0; + + //! get the current step size + virtual f32 getStepSize() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif // __I_GUI_SPIN_BOX_H_INCLUDED__ + diff --git a/inc/IGUISpriteBank.h b/inc/IGUISpriteBank.h new file mode 100644 index 0000000..872bbca --- /dev/null +++ b/inc/IGUISpriteBank.h @@ -0,0 +1,95 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_SPRITE_BANK_H_INCLUDED__ +#define __I_GUI_SPRITE_BANK_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "SColor.h" +#include "rect.h" + +namespace irr +{ + +namespace video +{ + class ITexture; +} // end namespace video + +namespace gui +{ + +//! A single sprite frame. +struct SGUISpriteFrame +{ + u32 textureNumber; + u32 rectNumber; +}; + +//! A sprite composed of several frames. +struct SGUISprite +{ + SGUISprite() : Frames(), frameTime(0) {} + + core::array Frames; + u32 frameTime; +}; + + +//! Sprite bank interface. +/** See http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=25742&highlight=spritebank +* for more information how to use the spritebank. +*/ +class IGUISpriteBank : public virtual IReferenceCounted +{ +public: + + //! Returns the list of rectangles held by the sprite bank + virtual core::array< core::rect >& getPositions() = 0; + + //! Returns the array of animated sprites within the sprite bank + virtual core::array< SGUISprite >& getSprites() = 0; + + //! Returns the number of textures held by the sprite bank + virtual u32 getTextureCount() const = 0; + + //! Gets the texture with the specified index + virtual video::ITexture* getTexture(u32 index) const = 0; + + //! Adds a texture to the sprite bank + virtual void addTexture(video::ITexture* texture) = 0; + + //! Changes one of the textures in the sprite bank + virtual void setTexture(u32 index, video::ITexture* texture) = 0; + + //! Add the texture and use it for a single non-animated sprite. + //! The texture and the corresponding rectangle and sprite will all be added to the end of each array. + //! returns the index of the sprite or -1 on failure + virtual s32 addTextureAsSprite(video::ITexture* texture) = 0; + + //! clears sprites, rectangles and textures + virtual void clear() = 0; + + //! Draws a sprite in 2d with position and color + virtual void draw2DSprite(u32 index, const core::position2di& pos, + const core::rect* clip=0, + const video::SColor& color= video::SColor(255,255,255,255), + u32 starttime=0, u32 currenttime=0, + bool loop=true, bool center=false) = 0; + + //! Draws a sprite batch in 2d using an array of positions and a color + virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, + const core::rect* clip=0, + const video::SColor& color= video::SColor(255,255,255,255), + u32 starttime=0, u32 currenttime=0, + bool loop=true, bool center=false) = 0; +}; + + +} // end namespace gui +} // end namespace irr + +#endif // __I_GUI_SPRITE_BANK_H_INCLUDED__ + diff --git a/inc/IGUIStaticText.h b/inc/IGUIStaticText.h new file mode 100644 index 0000000..b0594ab --- /dev/null +++ b/inc/IGUIStaticText.h @@ -0,0 +1,135 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_STATIC_TEXT_H_INCLUDED__ +#define __I_GUI_STATIC_TEXT_H_INCLUDED__ + +#include "IGUIElement.h" +#include "SColor.h" + +namespace irr +{ +namespace gui +{ + class IGUIFont; + + //! Multi or single line text label. + class IGUIStaticText : public IGUIElement + { + public: + + //! constructor + IGUIStaticText(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_STATIC_TEXT, environment, parent, id, rectangle) {} + + //! Sets another skin independent font. + /** If this is set to zero, the button uses the font of the skin. + \param font: New font to set. */ + virtual void setOverrideFont(IGUIFont* font=0) = 0; + + //! Gets the override font (if any) + /** \return The override font (may be 0) */ + virtual IGUIFont* getOverrideFont(void) const = 0; + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont* getActiveFont() const = 0; + + //! Sets another color for the text. + /** If set, the static text does not use the EGDC_BUTTON_TEXT color defined + in the skin, but the set color instead. You don't need to call + IGUIStaticText::enableOverrrideColor(true) after this, this is done + by this function. + If you set a color, and you want the text displayed with the color + of the skin again, call IGUIStaticText::enableOverrideColor(false); + \param color: New color of the text. */ + virtual void setOverrideColor(video::SColor color) = 0; + + //! Gets the override color + /** \return: The override color */ + virtual video::SColor getOverrideColor(void) const = 0; + + //! Sets if the static text should use the overide color or the color in the gui skin. + /** \param enable: If set to true, the override color, which can be set + with IGUIStaticText::setOverrideColor is used, otherwise the + EGDC_BUTTON_TEXT color of the skin. */ + virtual void enableOverrideColor(bool enable) = 0; + + //! Checks if an override color is enabled + /** \return true if the override color is enabled, false otherwise */ + virtual bool isOverrideColorEnabled(void) const = 0; + + //! Sets another color for the background. + virtual void setBackgroundColor(video::SColor color) = 0; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw) = 0; + + //! Gets the background color + /** \return: The background color */ + virtual video::SColor getBackgroundColor() const = 0; + + //! Checks if background drawing is enabled + /** \return true if background drawing is enabled, false otherwise */ + virtual bool isDrawBackgroundEnabled() const = 0; + + //! Sets whether to draw the border + virtual void setDrawBorder(bool draw) = 0; + + //! Checks if border drawing is enabled + /** \return true if border drawing is enabled, false otherwise */ + virtual bool isDrawBorderEnabled() const = 0; + + //! Sets text justification mode + /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), + EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. + \param vertical: EGUIA_UPPERLEFT to align with top edge, + EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; + + //! Enables or disables word wrap for using the static text as multiline text control. + /** \param enable: If set to true, words going over one line are + broken on to the next line. */ + virtual void setWordWrap(bool enable) = 0; + + //! Checks if word wrap is enabled + /** \return true if word wrap is enabled, false otherwise */ + virtual bool isWordWrapEnabled(void) const = 0; + + //! Returns the height of the text in pixels when it is drawn. + /** This is useful for adjusting the layout of gui elements based on the height + of the multiline text in this element. + \return Height of text in pixels. */ + virtual s32 getTextHeight() const = 0; + + //! Returns the width of the current text, in the current font + /** If the text is broken, this returns the width of the widest line + \return The width of the text, or the widest broken line. */ + virtual s32 getTextWidth(void) const = 0; + + //! Set whether the text in this label should be clipped if it goes outside bounds + virtual void setTextRestrainedInside(bool restrainedInside) = 0; + + //! Checks if the text in this label should be clipped if it goes outside bounds + virtual bool isTextRestrainedInside() const = 0; + + //! Set whether the string should be interpreted as right-to-left (RTL) text + /** \note This component does not implement the Unicode bidi standard, the + text of the component should be already RTL if you call this. The + main difference when RTL is enabled is that the linebreaks for multiline + elements are performed starting from the end. + */ + virtual void setRightToLeft(bool rtl) = 0; + + //! Checks whether the text in this element should be interpreted as right-to-left + virtual bool isRightToLeft() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUITabControl.h b/inc/IGUITabControl.h new file mode 100644 index 0000000..d9b4d12 --- /dev/null +++ b/inc/IGUITabControl.h @@ -0,0 +1,136 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_TAB_CONTROL_H_INCLUDED__ +#define __I_GUI_TAB_CONTROL_H_INCLUDED__ + +#include "IGUIElement.h" +#include "SColor.h" +#include "IGUISkin.h" + +namespace irr +{ +namespace gui +{ + //! A tab-page, onto which other gui elements could be added. + /** IGUITab refers to the page itself, not to the tab in the tabbar of an IGUITabControl. */ + class IGUITab : public IGUIElement + { + public: + + //! constructor + IGUITab(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_TAB, environment, parent, id, rectangle) {} + + //! Returns zero based index of tab if in tabcontrol. + /** Can be accessed later IGUITabControl::getTab() by this number. + Note that this number can change when other tabs are inserted or removed . + */ + virtual s32 getNumber() const = 0; + + //! sets if the tab should draw its background + virtual void setDrawBackground(bool draw=true) = 0; + + //! sets the color of the background, if it should be drawn. + virtual void setBackgroundColor(video::SColor c) = 0; + + //! returns true if the tab is drawing its background, false if not + virtual bool isDrawingBackground() const = 0; + + //! returns the color of the background + virtual video::SColor getBackgroundColor() const = 0; + + //! sets the color of the text + virtual void setTextColor(video::SColor c) = 0; + + //! gets the color of the text + virtual video::SColor getTextColor() const = 0; + }; + + //! A standard tab control + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_TAB_CHANGED + */ + class IGUITabControl : public IGUIElement + { + public: + + //! constructor + IGUITabControl(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_TAB_CONTROL, environment, parent, id, rectangle) {} + + //! Adds a tab + virtual IGUITab* addTab(const wchar_t* caption, s32 id=-1) = 0; + + //! Insert the tab at the given index + /** \return The tab on success or NULL on failure. */ + virtual IGUITab* insertTab(s32 idx, const wchar_t* caption, s32 id=-1) = 0; + + //! Removes a tab from the tabcontrol + virtual void removeTab(s32 idx) = 0; + + //! Clears the tabcontrol removing all tabs + virtual void clear() = 0; + + //! Returns amount of tabs in the tabcontrol + virtual s32 getTabCount() const = 0; + + //! Returns a tab based on zero based index + /** \param idx: zero based index of tab. Is a value betwenn 0 and getTabcount()-1; + \return Returns pointer to the Tab. Returns 0 if no tab + is corresponding to this tab. */ + virtual IGUITab* getTab(s32 idx) const = 0; + + //! Brings a tab to front. + /** \param idx: number of the tab. + \return Returns true if successful. */ + virtual bool setActiveTab(s32 idx) = 0; + + //! Brings a tab to front. + /** \param tab: pointer to the tab. + \return Returns true if successful. */ + virtual bool setActiveTab(IGUITab *tab) = 0; + + //! Returns which tab is currently active + virtual s32 getActiveTab() const = 0; + + //! get the the id of the tab at the given absolute coordinates + /** \return The id of the tab or -1 when no tab is at those coordinates*/ + virtual s32 getTabAt(s32 xpos, s32 ypos) const = 0; + + //! Set the height of the tabs + virtual void setTabHeight( s32 height ) = 0; + + //! Get the height of the tabs + /** return Returns the height of the tabs */ + virtual s32 getTabHeight() const = 0; + + //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". + virtual void setTabMaxWidth(s32 width ) = 0; + + //! get the maximal width of a tab + virtual s32 getTabMaxWidth() const = 0; + + //! Set the alignment of the tabs + /** Use EGUIA_UPPERLEFT or EGUIA_LOWERRIGHT */ + virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) = 0; + + //! Get the alignment of the tabs + /** return Returns the alignment of the tabs */ + virtual gui::EGUI_ALIGNMENT getTabVerticalAlignment() const = 0; + + //! Set the extra width added to tabs on each side of the text + virtual void setTabExtraWidth( s32 extraWidth ) = 0; + + //! Get the extra width added to tabs on each side of the text + /** return Returns the extra width of the tabs */ + virtual s32 getTabExtraWidth() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUITable.h b/inc/IGUITable.h new file mode 100644 index 0000000..219d28d --- /dev/null +++ b/inc/IGUITable.h @@ -0,0 +1,205 @@ +// Copyright (C) 2003-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_TABLE_H_INCLUDED__ +#define __I_GUI_TABLE_H_INCLUDED__ + +#include "IGUIElement.h" +#include "irrTypes.h" +#include "SColor.h" +#include "IGUISkin.h" + +namespace irr +{ +namespace gui +{ + + //! modes for ordering used when a column header is clicked + enum EGUI_COLUMN_ORDERING + { + //! Do not use ordering + EGCO_NONE, + + //! Send a EGET_TABLE_HEADER_CHANGED message when a column header is clicked. + EGCO_CUSTOM, + + //! Sort it ascending by it's ascii value like: a,b,c,... + EGCO_ASCENDING, + + //! Sort it descending by it's ascii value like: z,x,y,... + EGCO_DESCENDING, + + //! Sort it ascending on first click, descending on next, etc + EGCO_FLIP_ASCENDING_DESCENDING, + + //! Not used as mode, only to get maximum value for this enum + EGCO_COUNT + }; + + //! Names for EGUI_COLUMN_ORDERING types + const c8* const GUIColumnOrderingNames[] = + { + "none", + "custom", + "ascend", + "descend", + "ascend_descend", + 0, + }; + + enum EGUI_ORDERING_MODE + { + //! No element ordering + EGOM_NONE, + + //! Elements are ordered from the smallest to the largest. + EGOM_ASCENDING, + + //! Elements are ordered from the largest to the smallest. + EGOM_DESCENDING, + + //! this value is not used, it only specifies the amount of default ordering types + //! available. + EGOM_COUNT + }; + + const c8* const GUIOrderingModeNames[] = + { + "none", + "ascending", + "descending", + 0 + }; + + enum EGUI_TABLE_DRAW_FLAGS + { + EGTDF_ROWS = 1, + EGTDF_COLUMNS = 2, + EGTDF_ACTIVE_ROW = 4, + EGTDF_COUNT + }; + + //! Default list box GUI element. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_TABLE_CHANGED + \li EGET_TABLE_SELECTED_AGAIN + \li EGET_TABLE_HEADER_CHANGED + */ + class IGUITable : public IGUIElement + { + public: + //! constructor + IGUITable(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_TABLE, environment, parent, id, rectangle) {} + + //! Adds a column + /** If columnIndex is outside the current range, do push new colum at the end */ + virtual void addColumn(const wchar_t* caption, s32 columnIndex=-1) = 0; + + //! remove a column from the table + virtual void removeColumn(u32 columnIndex) = 0; + + //! Returns the number of columns in the table control + virtual s32 getColumnCount() const = 0; + + //! Makes a column active. This will trigger an ordering process. + /** \param idx: The id of the column to make active. + \param doOrder: Do also the ordering which depending on mode for active column + \return True if successful. */ + virtual bool setActiveColumn(s32 idx, bool doOrder=false) = 0; + + //! Returns which header is currently active + virtual s32 getActiveColumn() const = 0; + + //! Returns the ordering used by the currently active column + virtual EGUI_ORDERING_MODE getActiveColumnOrdering() const = 0; + + //! Set the width of a column + virtual void setColumnWidth(u32 columnIndex, u32 width) = 0; + + //! Get the width of a column + virtual u32 getColumnWidth(u32 columnIndex) const = 0; + + //! columns can be resized by drag 'n drop + virtual void setResizableColumns(bool resizable) = 0; + + //! can columns be resized by dran 'n drop? + virtual bool hasResizableColumns() const = 0; + + //! This tells the table control which ordering mode should be used when a column header is clicked. + /** \param columnIndex The index of the column header. + \param mode: One of the modes defined in EGUI_COLUMN_ORDERING */ + virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode) = 0; + + //! Returns which row is currently selected + virtual s32 getSelected() const = 0; + + //! set wich row is currently selected + virtual void setSelected( s32 index ) = 0; + + //! Get amount of rows in the tabcontrol + virtual s32 getRowCount() const = 0; + + //! adds a row to the table + /** \param rowIndex Zero based index of rows. The row will be + inserted at this position, if a row already exist there, it + will be placed after it. If the row is larger than the actual + number of row by more than one, it won't be created. Note that + if you create a row that's not at the end, there might be + performance issues. + \return index of inserted row. */ + virtual u32 addRow(u32 rowIndex) = 0; + + //! Remove a row from the table + virtual void removeRow(u32 rowIndex) = 0; + + //! clears the table rows, but keeps the columns intact + virtual void clearRows() = 0; + + //! Swap two row positions. + virtual void swapRows(u32 rowIndexA, u32 rowIndexB) = 0; + + //! This tells the table to start ordering all the rows. + /** You need to explicitly tell the table to re order the rows + when a new row is added or the cells data is changed. This + makes the system more flexible and doesn't make you pay the + cost of ordering when adding a lot of rows. + \param columnIndex: When set to -1 the active column is used. + \param mode Ordering mode of the rows. */ + virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE) = 0; + + //! Set the text of a cell + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; + + //! Set the text of a cell, and set a color of this cell. + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; + + //! Set the data of a cell + virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data) = 0; + + //! Set the color of a cell text + virtual void setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color) = 0; + + //! Get the text of a cell + virtual const wchar_t* getCellText(u32 rowIndex, u32 columnIndex ) const = 0; + + //! Get the data of a cell + virtual void* getCellData(u32 rowIndex, u32 columnIndex ) const = 0; + + //! clears the table, deletes all items in the table + virtual void clear() = 0; + + //! Set flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout + virtual void setDrawFlags(s32 flags) = 0; + + //! Get the flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout + virtual s32 getDrawFlags() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIToolbar.h b/inc/IGUIToolbar.h new file mode 100644 index 0000000..08519fc --- /dev/null +++ b/inc/IGUIToolbar.h @@ -0,0 +1,40 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_TOOL_BAR_H_INCLUDED__ +#define __I_GUI_TOOL_BAR_H_INCLUDED__ + +#include "IGUIElement.h" + +namespace irr +{ +namespace video +{ + class ITexture; +} // end namespace video +namespace gui +{ + class IGUIButton; + + //! Stays at the top of its parent like the menu bar and contains tool buttons + class IGUIToolBar : public IGUIElement + { + public: + + //! constructor + IGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_TOOL_BAR, environment, parent, id, rectangle) {} + + //! Adds a button to the tool bar + virtual IGUIButton* addButton(s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext=0, + video::ITexture* img=0, video::ITexture* pressedimg=0, + bool isPushButton=false, bool useAlphaChannel=false) = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUITreeView.h b/inc/IGUITreeView.h new file mode 100644 index 0000000..5f21022 --- /dev/null +++ b/inc/IGUITreeView.h @@ -0,0 +1,278 @@ +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_TREE_VIEW_H_INCLUDED__ +#define __I_GUI_TREE_VIEW_H_INCLUDED__ + +#include "IGUIElement.h" +#include "IGUIImageList.h" +#include "irrTypes.h" + +namespace irr +{ +namespace gui +{ + class IGUIFont; + class IGUITreeView; + + + //! Node for gui tree view + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_TREEVIEW_NODE_EXPAND + \li EGET_TREEVIEW_NODE_COLLAPS + \li EGET_TREEVIEW_NODE_DESELECT + \li EGET_TREEVIEW_NODE_SELECT + */ + class IGUITreeViewNode : public IReferenceCounted + { + public: + //! returns the owner (tree view) of this node + virtual IGUITreeView* getOwner() const = 0; + + //! Returns the parent node of this node. + /** For the root node this will return 0. */ + virtual IGUITreeViewNode* getParent() const = 0; + + //! returns the text of the node + virtual const wchar_t* getText() const = 0; + + //! sets the text of the node + virtual void setText( const wchar_t* text ) = 0; + + //! returns the icon text of the node + virtual const wchar_t* getIcon() const = 0; + + //! sets the icon text of the node + virtual void setIcon( const wchar_t* icon ) = 0; + + //! returns the image index of the node + virtual u32 getImageIndex() const = 0; + + //! sets the image index of the node + virtual void setImageIndex( u32 imageIndex ) = 0; + + //! returns the image index of the node + virtual u32 getSelectedImageIndex() const = 0; + + //! sets the image index of the node + virtual void setSelectedImageIndex( u32 imageIndex ) = 0; + + //! returns the user data (void*) of this node + virtual void* getData() const = 0; + + //! sets the user data (void*) of this node + virtual void setData( void* data ) = 0; + + //! returns the user data2 (IReferenceCounted) of this node + virtual IReferenceCounted* getData2() const = 0; + + //! sets the user data2 (IReferenceCounted) of this node + virtual void setData2( IReferenceCounted* data ) = 0; + + //! returns the child item count + virtual u32 getChildCount() const = 0; + + //! removes all children (recursive) from this node + virtual void clearChildren() = 0; + + //! removes all children (recursive) from this node + /** \deprecated Deprecated in 1.8, use clearChildren() instead. + This method may be removed by Irrlicht 1.9 */ + _IRR_DEPRECATED_ void clearChilds() + { + return clearChildren(); + } + + //! returns true if this node has child nodes + virtual bool hasChildren() const = 0; + + //! returns true if this node has child nodes + /** \deprecated Deprecated in 1.8, use hasChildren() instead. + This method may be removed by Irrlicht 1.9 */ + _IRR_DEPRECATED_ bool hasChilds() const + { + return hasChildren(); + } + + //! Adds a new node behind the last child node. + /** \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node + */ + virtual IGUITreeViewNode* addChildBack( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; + + //! Adds a new node before the first child node. + /** \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node + */ + virtual IGUITreeViewNode* addChildFront( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0 ) =0; + + //! Adds a new node behind the other node. + /** The other node has also te be a child node from this node. + \param other Node to insert after + \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node or 0 if other is no child node from this + */ + virtual IGUITreeViewNode* insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; + + //! Adds a new node before the other node. + /** The other node has also te be a child node from this node. + \param other Node to insert before + \param text text of the new node + \param icon icon text of the new node + \param imageIndex index of the image for the new node (-1 = none) + \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + \param data user data (void*) of the new node + \param data2 user data2 (IReferenceCounted*) of the new node + \return The new node or 0 if other is no child node from this + */ + virtual IGUITreeViewNode* insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) = 0; + + //! Return the first child node from this node. + /** \return The first child node or 0 if this node has no children. */ + virtual IGUITreeViewNode* getFirstChild() const = 0; + + //! Return the last child node from this node. + /** \return The last child node or 0 if this node has no children. */ + virtual IGUITreeViewNode* getLastChild() const = 0; + + //! Returns the previous sibling node from this node. + /** \return The previous sibling node from this node or 0 if this is + the first node from the parent node. + */ + virtual IGUITreeViewNode* getPrevSibling() const = 0; + + //! Returns the next sibling node from this node. + /** \return The next sibling node from this node or 0 if this is + the last node from the parent node. + */ + virtual IGUITreeViewNode* getNextSibling() const = 0; + + //! Returns the next visible (expanded, may be out of scrolling) node from this node. + /** \return The next visible node from this node or 0 if this is + the last visible node. */ + virtual IGUITreeViewNode* getNextVisible() const = 0; + + //! Deletes a child node. + /** \return Returns true if the node was found as a child and is deleted. */ + virtual bool deleteChild( IGUITreeViewNode* child ) = 0; + + //! Moves a child node one position up. + /** \return True if the node was found as achild node and was not already the first child. */ + virtual bool moveChildUp( IGUITreeViewNode* child ) = 0; + + //! Moves a child node one position down. + /** \return True if the node was found as achild node and was not already the last child. */ + virtual bool moveChildDown( IGUITreeViewNode* child ) = 0; + + //! Returns true if the node is expanded (children are visible). + virtual bool getExpanded() const = 0; + + //! Sets if the node is expanded. + virtual void setExpanded( bool expanded ) = 0; + + //! Returns true if the node is currently selected. + virtual bool getSelected() const = 0; + + //! Sets this node as selected. + virtual void setSelected( bool selected ) = 0; + + //! Returns true if this node is the root node. + virtual bool isRoot() const = 0; + + //! Returns the level of this node. + /** The root node has level 0. Direct children of the root has level 1 ... */ + virtual s32 getLevel() const = 0; + + //! Returns true if this node is visible (all parents are expanded). + virtual bool isVisible() const = 0; + }; + + + //! Default tree view GUI element. + /** Displays a windows like tree buttons to expand/collaps the child + nodes of an node and optional tree lines. Each node consits of an + text, an icon text and a void pointer for user data. */ + class IGUITreeView : public IGUIElement + { + public: + //! constructor + IGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle) + : IGUIElement( EGUIET_TREE_VIEW, environment, parent, id, rectangle ) {} + + //! returns the root node (not visible) from the tree. + virtual IGUITreeViewNode* getRoot() const = 0; + + //! returns the selected node of the tree or 0 if none is selected + virtual IGUITreeViewNode* getSelected() const = 0; + + //! returns true if the tree lines are visible + virtual bool getLinesVisible() const = 0; + + //! sets if the tree lines are visible + /** \param visible true for visible, false for invisible */ + virtual void setLinesVisible( bool visible ) = 0; + + //! Sets the font which should be used as icon font. + /** This font is set to the Irrlicht engine built-in-font by + default. Icons can be displayed in front of every list item. + An icon is a string, displayed with the icon font. When using + the build-in-font of the Irrlicht engine as icon font, the icon + strings defined in GUIIcons.h can be used. + */ + virtual void setIconFont( IGUIFont* font ) = 0; + + //! Sets the image list which should be used for the image and selected image of every node. + /** The default is 0 (no images). */ + virtual void setImageList( IGUIImageList* imageList ) = 0; + + //! Returns the image list which is used for the nodes. + virtual IGUIImageList* getImageList() const = 0; + + //! Sets if the image is left of the icon. Default is true. + virtual void setImageLeftOfIcon( bool bLeftOf ) = 0; + + //! Returns if the Image is left of the icon. Default is true. + virtual bool getImageLeftOfIcon() const = 0; + + //! Returns the node which is associated to the last event. + /** This pointer is only valid inside the OnEvent call! */ + virtual IGUITreeViewNode* getLastEventNode() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGUIWindow.h b/inc/IGUIWindow.h new file mode 100644 index 0000000..23d45da --- /dev/null +++ b/inc/IGUIWindow.h @@ -0,0 +1,74 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GUI_WINDOW_H_INCLUDED__ +#define __I_GUI_WINDOW_H_INCLUDED__ + +#include "IGUIElement.h" +#include "EMessageBoxFlags.h" + +namespace irr +{ +namespace gui +{ + class IGUIButton; + + //! Default moveable window GUI element with border, caption and close icons. + /** \par This element can create the following events of type EGUI_EVENT_TYPE: + \li EGET_ELEMENT_CLOSED + */ + class IGUIWindow : public IGUIElement + { + public: + + //! constructor + IGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) + : IGUIElement(EGUIET_WINDOW, environment, parent, id, rectangle) {} + + //! Returns pointer to the close button + /** You can hide the button by calling setVisible(false) on the result. */ + virtual IGUIButton* getCloseButton() const = 0; + + //! Returns pointer to the minimize button + /** You can hide the button by calling setVisible(false) on the result. */ + virtual IGUIButton* getMinimizeButton() const = 0; + + //! Returns pointer to the maximize button + /** You can hide the button by calling setVisible(false) on the result. */ + virtual IGUIButton* getMaximizeButton() const = 0; + + //! Returns true if the window can be dragged with the mouse, false if not + virtual bool isDraggable() const = 0; + + //! Sets whether the window can be dragged by the mouse + virtual void setDraggable(bool draggable) = 0; + + //! Set if the window background will be drawn + virtual void setDrawBackground(bool draw) = 0; + + //! Get if the window background will be drawn + virtual bool getDrawBackground() const = 0; + + //! Set if the window titlebar will be drawn + //! Note: If the background is not drawn, then the titlebar is automatically also not drawn + virtual void setDrawTitlebar(bool draw) = 0; + + //! Get if the window titlebar will be drawn + virtual bool getDrawTitlebar() const = 0; + + //! Returns the rectangle of the drawable area (without border and without titlebar) + /** The coordinates are given relative to the top-left position of the gui element.
+ So to get absolute positions you have to add the resulting rectangle to getAbsolutePosition().UpperLeftCorner.
+ To get it relative to the parent element you have to add the resulting rectangle to getRelativePosition().UpperLeftCorner. + Beware that adding a menu will not change the clientRect as menus are own gui elements, so in that case you might want to subtract + the menu area additionally. */ + virtual core::rect getClientRect() const = 0; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/inc/IGeometryCreator.h b/inc/IGeometryCreator.h new file mode 100644 index 0000000..22cd013 --- /dev/null +++ b/inc/IGeometryCreator.h @@ -0,0 +1,177 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_GEOMETRY_CREATOR_H_INCLUDED__ +#define __I_GEOMETRY_CREATOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IMesh.h" +#include "IImage.h" + +namespace irr +{ +namespace video +{ + class IVideoDriver; + class SMaterial; +} + +namespace scene +{ + +//! Helper class for creating geometry on the fly. +/** You can get an instance of this class through ISceneManager::getGeometryCreator() */ +class IGeometryCreator : public IReferenceCounted +{ +public: + + //! Creates a simple cube mesh. + /** + \param size Dimensions of the cube. + \return Generated mesh. + */ + virtual IMesh* createCubeMesh(const core::vector3df& size=core::vector3df(5.f,5.f,5.f)) const =0; + + //! Create a pseudo-random mesh representing a hilly terrain. + /** + \param tileSize The size of each tile. + \param tileCount The number of tiles in each dimension. + \param material The material to apply to the mesh. + \param hillHeight The maximum height of the hills. + \param countHills The number of hills along each dimension. + \param textureRepeatCount The number of times to repeat the material texture along each dimension. + \return Generated mesh. + */ + virtual IMesh* createHillPlaneMesh( + const core::dimension2d& tileSize, + const core::dimension2d& tileCount, + video::SMaterial* material, f32 hillHeight, + const core::dimension2d& countHills, + const core::dimension2d& textureRepeatCount) const =0; + + //! Create a simple rectangular textured plane mesh. + /** + \param tileSize The size of each tile. + \param tileCount The number of tiles in each dimension. + \param material The material to apply to the mesh. + \param textureRepeatCount The number of times to repeat the material texture along each dimension. + \return Generated mesh. + */ + IMesh* createPlaneMesh( + const core::dimension2d& tileSize, + const core::dimension2d& tileCount=core::dimension2du(1,1), + video::SMaterial* material=0, + const core::dimension2df& textureRepeatCount=core::dimension2df(1.f,1.f)) const + { + return createHillPlaneMesh(tileSize, tileCount, material, 0.f, core::dimension2df(), textureRepeatCount); + } + + //! Create a terrain mesh from an image representing a heightfield. + /** + \param texture The texture to apply to the terrain. + \param heightmap An image that will be interpreted as a heightmap. The + brightness (average color) of each pixel is interpreted as a height, + with a 255 brightness pixel producing the maximum height. + \param stretchSize The size that each pixel will produce, i.e. a + 512x512 heightmap + and a stretchSize of (10.f, 20.f) will produce a mesh of size + 5120.f x 10240.f + \param maxHeight The maximum height of the terrain. + \param driver The current video driver. + \param defaultVertexBlockSize (to be documented) + \param debugBorders (to be documented) + \return Generated mesh. + */ + virtual IMesh* createTerrainMesh(video::IImage* texture, + video::IImage* heightmap, + const core::dimension2d& stretchSize, + f32 maxHeight, video::IVideoDriver* driver, + const core::dimension2d& defaultVertexBlockSize, + bool debugBorders=false) const =0; + + //! Create an arrow mesh, composed of a cylinder and a cone. + /** + \param tesselationCylinder Number of quads composing the cylinder. + \param tesselationCone Number of triangles composing the cone's roof. + \param height Total height of the arrow + \param cylinderHeight Total height of the cylinder, should be lesser + than total height + \param widthCylinder Diameter of the cylinder + \param widthCone Diameter of the cone's base, should be not smaller + than the cylinder's diameter + \param colorCylinder color of the cylinder + \param colorCone color of the cone + \return Generated mesh. + */ + virtual IMesh* createArrowMesh(const u32 tesselationCylinder = 4, + const u32 tesselationCone = 8, const f32 height = 1.f, + const f32 cylinderHeight = 0.6f, const f32 widthCylinder = 0.05f, + const f32 widthCone = 0.3f, const video::SColor colorCylinder = 0xFFFFFFFF, + const video::SColor colorCone = 0xFFFFFFFF) const =0; + + + //! Create a sphere mesh. + /** + \param radius Radius of the sphere + \param polyCountX Number of quads used for the horizontal tiling + \param polyCountY Number of quads used for the vertical tiling + \return Generated mesh. + */ + virtual IMesh* createSphereMesh(f32 radius = 5.f, + u32 polyCountX = 16, u32 polyCountY = 16) const =0; + + //! Create a cylinder mesh. + /** + \param radius Radius of the cylinder. + \param length Length of the cylinder. + \param tesselation Number of quads around the circumference of the cylinder. + \param color The color of the cylinder. + \param closeTop If true, close the ends of the cylinder, otherwise leave them open. + \param oblique (to be documented) + \return Generated mesh. + */ + virtual IMesh* createCylinderMesh(f32 radius, f32 length, + u32 tesselation, + const video::SColor& color=video::SColor(0xffffffff), + bool closeTop=true, f32 oblique=0.f) const =0; + + //! Create a cone mesh. + /** + \param radius Radius of the cone. + \param length Length of the cone. + \param tesselation Number of quads around the circumference of the cone. + \param colorTop The color of the top of the cone. + \param colorBottom The color of the bottom of the cone. + \param oblique (to be documented) + \return Generated mesh. + */ + virtual IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& colorTop=video::SColor(0xffffffff), + const video::SColor& colorBottom=video::SColor(0xffffffff), + f32 oblique=0.f) const =0; + + //! Create a volume light mesh. + /** + \param subdivideU Horizontal patch count. + \param subdivideV Vertical patch count. + \param footColor Color at the bottom of the light. + \param tailColor Color at the mid of the light. + \param lpDistance Virtual distance of the light point for normals. + \param lightDim Dimensions of the light. + \return Generated mesh. + */ + virtual IMesh* createVolumeLightMesh( + const u32 subdivideU=32, const u32 subdivideV=32, + const video::SColor footColor = 0xffffffff, + const video::SColor tailColor = 0xffffffff, + const f32 lpDistance = 8.f, + const core::vector3df& lightDim = core::vector3df(1.f,1.2f,1.f)) const =0; +}; + + +} // end namespace scene +} // end namespace irr + +#endif // __I_GEOMETRY_CREATOR_H_INCLUDED__ + diff --git a/inc/IImage.h b/inc/IImage.h new file mode 100644 index 0000000..d484293 --- /dev/null +++ b/inc/IImage.h @@ -0,0 +1,155 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_IMAGE_H_INCLUDED__ +#define __I_IMAGE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "position2d.h" +#include "rect.h" +#include "SColor.h" + +namespace irr +{ +namespace video +{ + +//! Interface for software image data. +/** Image loaders create these images from files. IVideoDrivers convert +these images into their (hardware) textures. +*/ +class IImage : public virtual IReferenceCounted +{ +public: + + //! Lock function. Use this to get a pointer to the image data. + /** After you don't need the pointer anymore, you must call unlock(). + \return Pointer to the image data. What type of data is pointed to + depends on the color format of the image. For example if the color + format is ECF_A8R8G8B8, it is of u32. Be sure to call unlock() after + you don't need the pointer any more. */ + virtual void* lock() = 0; + + //! Unlock function. + /** Should be called after the pointer received by lock() is not + needed anymore. */ + virtual void unlock() = 0; + + //! Returns width and height of image data. + virtual const core::dimension2d& getDimension() const = 0; + + //! Returns bits per pixel. + virtual u32 getBitsPerPixel() const = 0; + + //! Returns bytes per pixel + virtual u32 getBytesPerPixel() const = 0; + + //! Returns image data size in bytes + virtual u32 getImageDataSizeInBytes() const = 0; + + //! Returns image data size in pixels + virtual u32 getImageDataSizeInPixels() const = 0; + + //! Returns a pixel + virtual SColor getPixel(u32 x, u32 y) const = 0; + + //! Sets a pixel + virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0; + + //! Returns the color format + virtual ECOLOR_FORMAT getColorFormat() const = 0; + + //! Returns mask for red value of a pixel + virtual u32 getRedMask() const = 0; + + //! Returns mask for green value of a pixel + virtual u32 getGreenMask() const = 0; + + //! Returns mask for blue value of a pixel + virtual u32 getBlueMask() const = 0; + + //! Returns mask for alpha value of a pixel + virtual u32 getAlphaMask() const = 0; + + //! Returns pitch of image + virtual u32 getPitch() const =0; + + //! Copies the image into the target, scaling the image to fit + virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; + + //! Copies the image into the target, scaling the image to fit + virtual void copyToScaling(IImage* target) =0; + + //! copies this surface into another + virtual void copyTo(IImage* target, const core::position2d& pos=core::position2d(0,0)) =0; + + //! copies this surface into another + virtual void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0) =0; + + //! copies this surface into another, using the alpha mask and cliprect and a color to add with + virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, + const core::rect& sourceRect, const SColor &color, + const core::rect* clipRect = 0) =0; + + //! copies this surface into another, scaling it to fit, appyling a box filter + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; + + //! fills the surface with given color + virtual void fill(const SColor &color) =0; + + //! get the amount of Bits per Pixel of the given color format + static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) + { + switch(format) + { + case ECF_A1R5G5B5: + return 16; + case ECF_R5G6B5: + return 16; + case ECF_R8G8B8: + return 24; + case ECF_A8R8G8B8: + return 32; + case ECF_R16F: + return 16; + case ECF_G16R16F: + return 32; + case ECF_A16B16G16R16F: + return 64; + case ECF_R32F: + return 32; + case ECF_G32R32F: + return 64; + case ECF_A32B32G32R32F: + return 128; + default: + return 0; + } + } + + //! test if the color format is only viable for RenderTarget textures + /** Since we don't have support for e.g. floating point IImage formats + one should test if the color format can be used for arbitrary usage, or + if it is restricted to RTTs. */ + static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) + { + switch(format) + { + case ECF_A1R5G5B5: + case ECF_R5G6B5: + case ECF_R8G8B8: + case ECF_A8R8G8B8: + return false; + default: + return true; + } + } + +}; + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IImageLoader.h b/inc/IImageLoader.h new file mode 100644 index 0000000..77603f5 --- /dev/null +++ b/inc/IImageLoader.h @@ -0,0 +1,53 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SURFACE_LOADER_H_INCLUDED__ +#define __I_SURFACE_LOADER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IImage.h" +#include "path.h" + +namespace irr +{ +namespace io +{ + class IReadFile; +} // end namespace io +namespace video +{ + +//! Class which is able to create a image from a file. +/** If you want the Irrlicht Engine be able to load textures of +currently unsupported file formats (e.g .gif), then implement +this and add your new Surface loader with +IVideoDriver::addExternalImageLoader() to the engine. */ +class IImageLoader : public virtual IReferenceCounted +{ +public: + + //! Check if the file might be loaded by this class + /** Check is based on the file extension (e.g. ".tga") + \param filename Name of file to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const = 0; + + //! Creates a surface from the file + /** \param file File handle to check. + \return Pointer to newly created image, or 0 upon error. */ + virtual IImage* loadImage(io::IReadFile* file) const = 0; +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IImageWriter.h b/inc/IImageWriter.h new file mode 100644 index 0000000..fd00793 --- /dev/null +++ b/inc/IImageWriter.h @@ -0,0 +1,45 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef _I_IMAGE_WRITER_H_INCLUDED__ +#define _I_IMAGE_WRITER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrString.h" +#include "coreutil.h" + +namespace irr +{ +namespace io +{ + class IWriteFile; +} // end namespace io + +namespace video +{ + class IImage; + + +//! Interface for writing software image data. +class IImageWriter : public IReferenceCounted +{ +public: + //! Check if this writer can write a file with the given extension + /** \param filename Name of the file to check. + \return True if file extension specifies a writable type. */ + virtual bool isAWriteableFileExtension(const io::path& filename) const = 0; + + //! Write image to file + /** \param file File handle to write to. + \param image Image to write into file. + \param param Writer specific parameter, influencing e.g. quality. + \return True if image was successfully written. */ + virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param = 0) const = 0; +}; + +} // namespace video +} // namespace irr + +#endif // _I_IMAGE_WRITER_H_INCLUDED__ + diff --git a/inc/IIndexBuffer.h b/inc/IIndexBuffer.h new file mode 100644 index 0000000..ff5738c --- /dev/null +++ b/inc/IIndexBuffer.h @@ -0,0 +1,65 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_INDEX_BUFFER_H_INCLUDED__ +#define __I_INDEX_BUFFER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" + +#include "SVertexIndex.h" + +namespace irr +{ + +namespace video +{ + +} + +namespace scene +{ + + class IIndexBuffer : public virtual IReferenceCounted + { + public: + + virtual void* getData() =0; + + virtual video::E_INDEX_TYPE getType() const =0; + virtual void setType(video::E_INDEX_TYPE IndexType) =0; + + virtual u32 stride() const =0; + + virtual u32 size() const =0; + virtual void push_back (const u32 &element) =0; + virtual u32 operator [](u32 index) const =0; + virtual u32 getLast() =0; + virtual void setValue(u32 index, u32 value) =0; + virtual void set_used(u32 usedNow) =0; + virtual void reallocate(u32 new_size) =0; + virtual u32 allocated_size() const=0; + + virtual void* pointer() =0; + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) =0; + + //! flags the meshbuffer as changed, reloads hardware buffers + virtual void setDirty() = 0; + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID() const = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ILightManager.h b/inc/ILightManager.h new file mode 100644 index 0000000..35fb9cb --- /dev/null +++ b/inc/ILightManager.h @@ -0,0 +1,62 @@ +// Written by Colin MacDonald - all rights assigned to Nikolaus Gebhardt +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_LIGHT_MANAGER_H_INCLUDED__ +#define __I_LIGHT_MANAGER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" + +namespace irr +{ +namespace scene +{ + class ILightSceneNode; + + //! ILightManager provides an interface for user applications to manipulate the list of lights in the scene. + /** The light list can be trimmed or re-ordered before device/ hardware + lights are created, and/or individual lights can be switched on and off + before or after each scene node is rendered. It is assumed that the + ILightManager implementation will store any data that it wishes to + retain, i.e. the ISceneManager to which it is assigned, the lightList, + the current render pass, and the current scene node. */ + class ILightManager : public IReferenceCounted + { + public: + //! Called after the scene's light list has been built, but before rendering has begun. + /** As actual device/hardware lights are not created until the + ESNRP_LIGHT render pass, this provides an opportunity for the + light manager to trim or re-order the light list, before any + device/hardware lights have actually been created. + \param lightList: the Scene Manager's light list, which + the light manager may modify. This reference will remain valid + until OnPostRender(). + */ + virtual void OnPreRender(core::array & lightList) = 0; + + //! Called after the last scene node is rendered. + /** After this call returns, the lightList passed to OnPreRender() becomes invalid. */ + virtual void OnPostRender(void) = 0; + + //! Called before a render pass begins + /** \param renderPass: the render pass that's about to begin */ + virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + + //! Called after the render pass specified in OnRenderPassPreRender() ends + /** \param[in] renderPass: the render pass that has finished */ + virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + + //! Called before the given scene node is rendered + /** \param[in] node: the scene node that's about to be rendered */ + virtual void OnNodePreRender(ISceneNode* node) = 0; + + //! Called after the the node specified in OnNodePreRender() has been rendered + /** \param[in] node: the scene node that has just been rendered */ + virtual void OnNodePostRender(ISceneNode* node) = 0; + }; +} // end namespace scene +} // end namespace irr + +#endif diff --git a/inc/ILightSceneNode.h b/inc/ILightSceneNode.h new file mode 100644 index 0000000..3feb207 --- /dev/null +++ b/inc/ILightSceneNode.h @@ -0,0 +1,86 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_LIGHT_SCENE_NODE_H_INCLUDED__ +#define __I_LIGHT_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" +#include "SLight.h" + +namespace irr +{ +namespace scene +{ + +//! Scene node which is a dynamic light. +/** You can switch the light on and off by making it visible or not. It can be +animated by ordinary scene node animators. If the light type is directional or +spot, the direction of the light source is defined by the rotation of the scene +node (assuming (0,0,1) as the local direction of the light). +*/ +class ILightSceneNode : public ISceneNode +{ +public: + + //! constructor + ILightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0)) + : ISceneNode(parent, mgr, id, position) {} + + //! Sets the light data associated with this ILightSceneNode + /** \param light The new light data. */ + virtual void setLightData(const video::SLight& light) = 0; + + //! Gets the light data associated with this ILightSceneNode + /** \return The light data. */ + virtual const video::SLight& getLightData() const = 0; + + //! Gets the light data associated with this ILightSceneNode + /** \return The light data. */ + virtual video::SLight& getLightData() = 0; + + //! Sets if the node should be visible or not. + /** All children of this node won't be visible either, when set + to true. + \param isVisible If the node shall be visible. */ + virtual void setVisible(bool isVisible) = 0; + + //! Sets the light's radius of influence. + /** Outside this radius the light won't lighten geometry and cast no + shadows. Setting the radius will also influence the attenuation, setting + it to (0,1/radius,0). If you want to override this behavior, set the + attenuation after the radius. + \param radius The new radius. */ + virtual void setRadius(f32 radius) = 0; + + //! Gets the light's radius of influence. + /** \return The current radius. */ + virtual f32 getRadius() const = 0; + + //! Sets the light type. + /** \param type The new type. */ + virtual void setLightType(video::E_LIGHT_TYPE type) = 0; + + //! Gets the light type. + /** \return The current light type. */ + virtual video::E_LIGHT_TYPE getLightType() const = 0; + + //! Sets whether this light casts shadows. + /** Enabling this flag won't automatically cast shadows, the meshes + will still need shadow scene nodes attached. But one can enable or + disable distinct lights for shadow casting for performance reasons. + \param shadow True if this light shall cast shadows. */ + virtual void enableCastShadow(bool shadow=true) = 0; + + //! Check whether this light casts shadows. + /** \return True if light would cast shadows, else false. */ + virtual bool getCastShadow() const = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/ILogger.h b/inc/ILogger.h new file mode 100644 index 0000000..53f6273 --- /dev/null +++ b/inc/ILogger.h @@ -0,0 +1,102 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_LOGGER_H_INCLUDED__ +#define __I_LOGGER_H_INCLUDED__ + +#include "IReferenceCounted.h" + +namespace irr +{ + +//! Possible log levels. +//! When used has filter ELL_DEBUG means => log everything and ELL_NONE means => log (nearly) nothing. +//! When used to print logging information ELL_DEBUG will have lowest priority while ELL_NONE +//! messages are never filtered and always printed. +enum ELOG_LEVEL +{ + //! Used for printing information helpful in debugging + ELL_DEBUG, + + //! Useful information to print. For example hardware infos or something started/stopped. + ELL_INFORMATION, + + //! Warnings that something isn't as expected and can cause oddities + ELL_WARNING, + + //! Something did go wrong. + ELL_ERROR, + + //! Logs with ELL_NONE will never be filtered. + //! And used as filter it will remove all logging except ELL_NONE messages. + ELL_NONE +}; + + +//! Interface for logging messages, warnings and errors +class ILogger : public virtual IReferenceCounted +{ +public: + + //! Destructor + virtual ~ILogger() {} + + //! Returns the current set log level. + virtual ELOG_LEVEL getLogLevel() const = 0; + + //! Sets a new log level. + /** With this value, texts which are sent to the logger are filtered + out. For example setting this value to ELL_WARNING, only warnings and + errors are printed out. Setting it to ELL_INFORMATION, which is the + default setting, warnings, errors and informational texts are printed + out. + \param ll: new log level filter value. */ + virtual void setLogLevel(ELOG_LEVEL ll) = 0; + + //! Prints out a text into the log + /** \param text: Text to print out. + \param ll: Log level of the text. If the text is an error, set + it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it + is just an informational text, set it to ELL_INFORMATION. Texts are + filtered with these levels. If you want to be a text displayed, + independent on what level filter is set, use ELL_NONE. */ + virtual void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + + //! Prints out a text into the log + /** \param text: Text to print out. + \param hint: Additional info. This string is added after a " :" to the + string. + \param ll: Log level of the text. If the text is an error, set + it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it + is just an informational text, set it to ELL_INFORMATION. Texts are + filtered with these levels. If you want to be a text displayed, + independent on what level filter is set, use ELL_NONE. */ + virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + + //! Prints out a text into the log + /** \param text: Text to print out. + \param hint: Additional info. This string is added after a " :" to the + string. + \param ll: Log level of the text. If the text is an error, set + it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it + is just an informational text, set it to ELL_INFORMATION. Texts are + filtered with these levels. If you want to be a text displayed, + independent on what level filter is set, use ELL_NONE. */ + virtual void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + + //! Prints out a text into the log + /** \param text: Text to print out. + \param ll: Log level of the text. If the text is an error, set + it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it + is just an informational text, set it to ELL_INFORMATION. Texts are + filtered with these levels. If you want to be a text displayed, + independent on what level filter is set, use ELL_NONE. */ + virtual void log(const wchar_t* text, ELOG_LEVEL ll=ELL_INFORMATION) = 0; +}; + +} // end namespace + +#endif + diff --git a/inc/IMaterialRenderer.h b/inc/IMaterialRenderer.h new file mode 100644 index 0000000..a4e1d20 --- /dev/null +++ b/inc/IMaterialRenderer.h @@ -0,0 +1,101 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MATERIAL_RENDERER_H_INCLUDED__ +#define __I_MATERIAL_RENDERER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SMaterial.h" +#include "S3DVertex.h" + +namespace irr +{ +namespace video +{ + +class IVideoDriver; +class IMaterialRendererServices; + +//! Interface for material rendering. +/** Can be used to extend the engine with new materials. Refer to +IVideoDriver::addMaterialRenderer() for more informations on how to extend the +engine with new materials. */ +class IMaterialRenderer : public virtual IReferenceCounted +{ +public: + + //! Called by the IVideoDriver implementation the let the renderer set its needed render states. + /** This is called during the IVideoDriver::setMaterial() call. + When overriding this, you can set some renderstates or for example a + vertex or pixel shader if you like. + \param material: The new material parameters to be set. The renderer + may change the material flags in this material. For example if this + material does not accept the zbuffer = true, it can set it to false. + This is useful, because in the next lastMaterial will be just the + material in this call. + \param lastMaterial: The material parameters which have been set before + this material. + \param resetAllRenderstates: True if all renderstates should really be + reset. This is usually true if the last rendering mode was not a usual + 3d rendering mode, but for example a 2d rendering mode. + You should reset really all renderstates if this is true, no matter if + the lastMaterial had some similar settings. This is used because in + most cases, some common renderstates are not changed if they are + already there, for example bilinear filtering, wireframe, + gouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and + fogenable. + \param services: Interface providing some methods for changing + advanced, internal states of a IVideoDriver. */ + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) {} + + //! Called every time before a new bunch of geometry is being drawn using this material with for example drawIndexedTriangleList() call. + /** OnSetMaterial should normally only be called if the renderer decides + that the renderstates should be changed, it won't be called if for + example two drawIndexedTriangleList() will be called with the same + material set. This method will be called every time. This is useful for + example for materials with shaders, which don't only set new + renderstates but also shader constants. + \param service: Pointer to interface providing methos for setting + constants and other things. + \param vtxtype: Vertex type with which the next rendering will be done. + This can be used by the material renderer to set some specific + optimized shaders or if this is an incompatible vertex type for this + renderer, to refuse rendering for example. + \return Returns true if everything is ok, and false if nothing should + be rendered. The material renderer can choose to return false for + example if he doesn't support the specified vertex type. This is + actually done in D3D8 and D3D9 when using a normal mapped material with + a vertex type other than EVT_TANGENTS. */ + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { return true; } + + //! Called by the IVideoDriver to unset this material. + /** Called during the IVideoDriver::setMaterial() call before the new + material will get the OnSetMaterial() call. */ + virtual void OnUnsetMaterial() {} + + //! Returns if the material is transparent. + /** The scene managment needs to know this + for being able to sort the materials by opaque and transparent. */ + virtual bool isTransparent() const { return false; } + + //! Returns the render capability of the material. + /** Because some more complex materials + are implemented in multiple ways and need special hardware capabilities, it is possible + to query how the current material renderer is performing on the current hardware with this + function. + \return Returns 0 if everything is running fine. Any other value is material renderer + specific and means for example that the renderer switched back to a fall back material because + it cannot use the latest shaders. More specific examples: + Fixed function pipeline materials should return 0 in most cases, parallax mapped + material will only return 0 when at least pixel shader 1.4 is available on that machine. */ + virtual s32 getRenderCapability() const { return 0; } +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IMaterialRendererServices.h b/inc/IMaterialRendererServices.h new file mode 100644 index 0000000..dafad09 --- /dev/null +++ b/inc/IMaterialRendererServices.h @@ -0,0 +1,115 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ +#define __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ + +#include "SMaterial.h" +#include "S3DVertex.h" + +namespace irr +{ +namespace video +{ + +class IVideoDriver; + + +//! Interface providing some methods for changing advanced, internal states of a IVideoDriver. +class IMaterialRendererServices +{ +public: + + //! Destructor + virtual ~IMaterialRendererServices() {} + + //! Can be called by an IMaterialRenderer to make its work easier. + /** Sets all basic renderstates if needed. + Basic render states are diffuse, ambient, specular, and emissive color, + specular power, bilinear and trilinear filtering, wireframe mode, + grouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and + fog enabling. + \param material The new material to be used. + \param lastMaterial The material used until now. + \param resetAllRenderstates Set to true if all renderstates should be + set, regardless of their current state. */ + virtual void setBasicRenderStates(const SMaterial& material, + const SMaterial& lastMaterial, + bool resetAllRenderstates) = 0; + + //! Sets a constant for the vertex shader based on a name. + /** This can be used if you used a high level shader language like GLSL + or HLSL to create a shader. Example: If you created a shader which has + variables named 'mWorldViewProj' (containing the WorldViewProjection + matrix) and another one named 'fTime' containing one float, you can set + them in your IShaderConstantSetCallBack derived class like this: + \code + virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) + { + video::IVideoDriver* driver = services->getVideoDriver(); + + f32 time = (f32)os::Timer::getTime()/100000.0f; + services->setVertexShaderConstant("fTime", &time, 1); + + core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); + worldViewProj *= driver->getTransform(video::ETS_VIEW); + worldViewProj *= driver->getTransform(video::ETS_WORLD); + services->setVertexShaderConstant("mWorldViewProj", worldViewProj.M, 16); + } + \endcode + \param name Name of the variable + \param floats Pointer to array of floats + \param count Amount of floats in array. + \return True if successful. + */ + virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count) = 0; + + //! Bool interface for the above. + virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count) = 0; + + //! Int interface for the above. + virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count) = 0; + + //! Sets a vertex shader constant. + /** Can be used if you created a shader using pixel/vertex shader + assembler or ARB_fragment_program or ARB_vertex_program. + \param data: Data to be set in the constants + \param startRegister: First register to be set + \param constantAmount: Amount of registers to be set. One register consists of 4 floats. */ + virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) = 0; + + //! Sets a constant for the pixel shader based on a name. + /** This can be used if you used a high level shader language like GLSL + or HLSL to create a shader. See setVertexShaderConstant() for an + example on how to use this. + \param name Name of the variable + \param floats Pointer to array of floats + \param count Amount of floats in array. + \return True if successful. */ + virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count) = 0; + + //! Bool interface for the above. + virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count) = 0; + + //! Int interface for the above. + virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count) = 0; + + //! Sets a pixel shader constant. + /** Can be used if you created a shader using pixel/vertex shader + assembler or ARB_fragment_program or ARB_vertex_program. + \param data Data to be set in the constants + \param startRegister First register to be set. + \param constantAmount Amount of registers to be set. One register consists of 4 floats. */ + virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) = 0; + + //! Get pointer to the IVideoDriver interface + /** \return Pointer to the IVideoDriver interface */ + virtual IVideoDriver* getVideoDriver() = 0; +}; + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IMesh.h b/inc/IMesh.h new file mode 100644 index 0000000..89f936b --- /dev/null +++ b/inc/IMesh.h @@ -0,0 +1,75 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_H_INCLUDED__ +#define __I_MESH_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SMaterial.h" +#include "EHardwareBufferFlags.h" + +namespace irr +{ +namespace scene +{ + class IMeshBuffer; + + //! Class which holds the geometry of an object. + /** An IMesh is nothing more than a collection of some mesh buffers + (IMeshBuffer). SMesh is a simple implementation of an IMesh. + A mesh is usually added to an IMeshSceneNode in order to be rendered. + */ + class IMesh : public virtual IReferenceCounted + { + public: + + //! Get the amount of mesh buffers. + /** \return Amount of mesh buffers (IMeshBuffer) in this mesh. */ + virtual u32 getMeshBufferCount() const = 0; + + //! Get pointer to a mesh buffer. + /** \param nr: Zero based index of the mesh buffer. The maximum value is + getMeshBufferCount() - 1; + \return Pointer to the mesh buffer or 0 if there is no such + mesh buffer. */ + virtual IMeshBuffer* getMeshBuffer(u32 nr) const = 0; + + //! Get pointer to a mesh buffer which fits a material + /** \param material: material to search for + \return Pointer to the mesh buffer or 0 if there is no such + mesh buffer. */ + virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const = 0; + + //! Get an axis aligned bounding box of the mesh. + /** \return Bounding box of this mesh. */ + virtual const core::aabbox3d& getBoundingBox() const = 0; + + //! Set user-defined axis aligned bounding box + /** \param box New bounding box to use for the mesh. */ + virtual void setBoundingBox( const core::aabbox3df& box) = 0; + + //! Sets a flag of all contained materials to a new value. + /** \param flag: Flag to set in all materials. + \param newvalue: New value to set in all materials. */ + virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) = 0; + + //! Set the hardware mapping hint + /** This methods allows to define optimization hints for the + hardware. This enables, e.g., the use of hardware buffers on + pltforms that support this feature. This can lead to noticeable + performance gains. */ + virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; + + //! Flag the meshbuffer as changed, reloads hardware buffers + /** This method has to be called every time the vertices or + indices have changed. Otherwise, changes won't be updated + on the GPU in the next render cycle. */ + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IMeshBuffer.h b/inc/IMeshBuffer.h new file mode 100644 index 0000000..99a9f48 --- /dev/null +++ b/inc/IMeshBuffer.h @@ -0,0 +1,154 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_BUFFER_H_INCLUDED__ +#define __I_MESH_BUFFER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SMaterial.h" +#include "aabbox3d.h" +#include "S3DVertex.h" +#include "SVertexIndex.h" +#include "EHardwareBufferFlags.h" +#include "EPrimitiveTypes.h" + +namespace irr +{ +namespace scene +{ + //! Struct for holding a mesh with a single material. + /** A part of an IMesh which has the same material on each face of that + group. Logical groups of an IMesh need not be put into separate mesh + buffers, but can be. Separately animated parts of the mesh must be put + into separate mesh buffers. + Some mesh buffer implementations have limitations on the number of + vertices the buffer can hold. In that case, logical grouping can help. + Moreover, the number of vertices should be optimized for the GPU upload, + which often depends on the type of gfx card. Typial figures are + 1000-10000 vertices per buffer. + SMeshBuffer is a simple implementation of a MeshBuffer, which supports + up to 65535 vertices. + + Since meshbuffers are used for drawing, and hence will be exposed + to the driver, chances are high that they are grab()'ed from somewhere. + It's therefore required to dynamically allocate meshbuffers which are + passed to a video driver and only drop the buffer once it's not used in + the current code block anymore. + */ + class IMeshBuffer : public virtual IReferenceCounted + { + public: + + //! Get the material of this meshbuffer + /** \return Material of this buffer. */ + virtual video::SMaterial& getMaterial() = 0; + + //! Get the material of this meshbuffer + /** \return Material of this buffer. */ + virtual const video::SMaterial& getMaterial() const = 0; + + //! Get type of vertex data which is stored in this meshbuffer. + /** \return Vertex type of this buffer. */ + virtual video::E_VERTEX_TYPE getVertexType() const = 0; + + //! Get access to vertex data. The data is an array of vertices. + /** Which vertex type is used can be determined by getVertexType(). + \return Pointer to array of vertices. */ + virtual const void* getVertices() const = 0; + + //! Get access to vertex data. The data is an array of vertices. + /** Which vertex type is used can be determined by getVertexType(). + \return Pointer to array of vertices. */ + virtual void* getVertices() = 0; + + //! Get amount of vertices in meshbuffer. + /** \return Number of vertices in this buffer. */ + virtual u32 getVertexCount() const = 0; + + //! Get type of index data which is stored in this meshbuffer. + /** \return Index type of this buffer. */ + virtual video::E_INDEX_TYPE getIndexType() const =0; + + //! Get access to Indices. + /** \return Pointer to indices array. */ + virtual const u16* getIndices() const = 0; + + //! Get access to Indices. + /** \return Pointer to indices array. */ + virtual u16* getIndices() = 0; + + //! Get amount of indices in this meshbuffer. + /** \return Number of indices in this buffer. */ + virtual u32 getIndexCount() const = 0; + + //! Get the axis aligned bounding box of this meshbuffer. + /** \return Axis aligned bounding box of this buffer. */ + virtual const core::aabbox3df& getBoundingBox() const = 0; + + //! Set axis aligned bounding box + /** \param box User defined axis aligned bounding box to use + for this buffer. */ + virtual void setBoundingBox(const core::aabbox3df& box) = 0; + + //! Recalculates the bounding box. Should be called if the mesh changed. + virtual void recalculateBoundingBox() = 0; + + //! returns position of vertex i + virtual const core::vector3df& getPosition(u32 i) const = 0; + + //! returns position of vertex i + virtual core::vector3df& getPosition(u32 i) = 0; + + //! returns normal of vertex i + virtual const core::vector3df& getNormal(u32 i) const = 0; + + //! returns normal of vertex i + virtual core::vector3df& getNormal(u32 i) = 0; + + //! returns texture coord of vertex i + virtual const core::vector2df& getTCoords(u32 i) const = 0; + + //! returns texture coord of vertex i + virtual core::vector2df& getTCoords(u32 i) = 0; + + //! Append the vertices and indices to the current buffer + /** Only works for compatible vertex types. + \param vertices Pointer to a vertex array. + \param numVertices Number of vertices in the array. + \param indices Pointer to index array. + \param numIndices Number of indices in array. */ + virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) = 0; + + //! Append the meshbuffer to the current buffer + /** Only works for compatible vertex types + \param other Buffer to append to this one. */ + virtual void append(const IMeshBuffer* const other) = 0; + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const = 0; + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const = 0; + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) = 0; + + //! flags the meshbuffer as changed, reloads hardware buffers + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID_Vertex() const = 0; + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID_Index() const = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + + diff --git a/inc/IMeshCache.h b/inc/IMeshCache.h new file mode 100644 index 0000000..2d2bfa0 --- /dev/null +++ b/inc/IMeshCache.h @@ -0,0 +1,177 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_CACHE_H_INCLUDED__ +#define __I_MESH_CACHE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "path.h" + +namespace irr +{ + +namespace scene +{ + class IMesh; + class IAnimatedMesh; + class IAnimatedMeshSceneNode; + class IMeshLoader; + + //! The mesh cache stores already loaded meshes and provides an interface to them. + /** You can access it using ISceneManager::getMeshCache(). All existing + scene managers will return a pointer to the same mesh cache, because it + is shared between them. With this interface, it is possible to manually + add new loaded meshes (if ISceneManager::getMesh() is not sufficient), + to remove them and to iterate through already loaded meshes. */ + class IMeshCache : public virtual IReferenceCounted + { + public: + + //! Destructor + virtual ~IMeshCache() {} + + //! Adds a mesh to the internal list of loaded meshes. + /** Usually, ISceneManager::getMesh() is called to load a mesh + from a file. That method searches the list of loaded meshes if + a mesh has already been loaded and returns a pointer to if it + is in that list and already in memory. Otherwise it loads the + mesh. With IMeshCache::addMesh(), it is possible to pretend + that a mesh already has been loaded. This method can be used + for example by mesh loaders who need to load more than one mesh + with one call. They can add additional meshes with this method + to the scene manager. The COLLADA loader for example uses this + method. + \param name Name of the mesh. When calling + ISceneManager::getMesh() with this name it will return the mesh + set by this method. + \param mesh Pointer to a mesh which will now be referenced by + this name. */ + virtual void addMesh(const io::path& name, IAnimatedMesh* mesh) = 0; + + //! Removes the mesh from the cache. + /** After loading a mesh with getMesh(), the mesh can be + removed from the cache using this method, freeing a lot of + memory. + \param mesh Pointer to the mesh which shall be removed. */ + virtual void removeMesh(const IMesh* const mesh) = 0; + + //! Returns amount of loaded meshes in the cache. + /** You can load new meshes into the cache using getMesh() and + addMesh(). If you ever need to access the internal mesh cache, + you can do this using removeMesh(), getMeshNumber(), + getMeshByIndex() and getMeshName(). + \return Number of meshes in cache. */ + virtual u32 getMeshCount() const = 0; + + //! Returns current index number of the mesh or -1 when not found. + /** \param mesh Pointer to the mesh to search for. + \return Index of the mesh in the cache, or -1 if not found. */ + virtual s32 getMeshIndex(const IMesh* const mesh) const = 0; + + //! Returns a mesh based on its index number. + /** \param index: Index of the mesh, number between 0 and + getMeshCount()-1. + Note that this number is only valid until a new mesh is loaded + or removed. + \return Pointer to the mesh or 0 if there is none with this + number. */ + virtual IAnimatedMesh* getMeshByIndex(u32 index) = 0; + + //! Returns a mesh based on its name (often a filename). + /** \deprecated Use getMeshByName() instead. This method may be removed by + Irrlicht 1.9 */ + _IRR_DEPRECATED_ IAnimatedMesh* getMeshByFilename(const io::path& filename) + { + return getMeshByName(filename); + } + + //! Get the name of a loaded mesh, based on its index. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. This method may be removed by + Irrlicht 1.9 */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(u32 index) const + { + return getMeshName(index).getInternalName(); + } + + //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. This method may be removed by + Irrlicht 1.9 */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(const IMesh* const mesh) const + { + return getMeshName(mesh).getInternalName(); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. This method may be removed by + Irrlicht 1.9 */ + _IRR_DEPRECATED_ bool setMeshFilename(u32 index, const io::path& filename) + { + return renameMesh(index, filename); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. This method may be removed by + Irrlicht 1.9 */ + _IRR_DEPRECATED_ bool setMeshFilename(const IMesh* const mesh, const io::path& filename) + { + return renameMesh(mesh, filename); + } + + //! Returns a mesh based on its name. + /** \param name Name of the mesh. Usually a filename. + \return Pointer to the mesh or 0 if there is none with this number. */ + virtual IAnimatedMesh* getMeshByName(const io::path& name) = 0; + + //! Get the name of a loaded mesh, based on its index. + /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(u32 index) const = 0; + + //! Get the name of the loaded mesh if there is any. + /** \param mesh Pointer to mesh to query. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const = 0; + + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param index The index of the mesh in the cache. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(u32 index, const io::path& name) = 0; + + //! Renames the loaded mesh + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param mesh Mesh to be renamed. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(const IMesh* const mesh, const io::path& name) = 0; + + //! Check if a mesh was already loaded. + /** \param name Name of the mesh. Usually a filename. + \return True if the mesh has been loaded, else false. */ + virtual bool isMeshLoaded(const io::path& name) = 0; + + //! Clears the whole mesh cache, removing all meshes. + /** All meshes will be reloaded completely when using ISceneManager::getMesh() + after calling this method. + Warning: If you have pointers to meshes that were loaded with ISceneManager::getMesh() + and you did not grab them, then they may become invalid. */ + virtual void clear() = 0; + + //! Clears all meshes that are held in the mesh cache but not used anywhere else. + /** Warning: If you have pointers to meshes that were loaded with ISceneManager::getMesh() + and you did not grab them, then they may become invalid. */ + virtual void clearUnusedMeshes() = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IMeshLoader.h b/inc/IMeshLoader.h new file mode 100644 index 0000000..3955fb4 --- /dev/null +++ b/inc/IMeshLoader.h @@ -0,0 +1,53 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_LOADER_H_INCLUDED__ +#define __I_MESH_LOADER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "path.h" + +namespace irr +{ +namespace io +{ + class IReadFile; +} // end namespace io +namespace scene +{ + class IAnimatedMesh; + +//! Class which is able to load an animated mesh from a file. +/** If you want Irrlicht be able to load meshes of +currently unsupported file formats (e.g. .cob), then implement +this and add your new Meshloader with +ISceneManager::addExternalMeshLoader() to the engine. */ +class IMeshLoader : public virtual IReferenceCounted +{ +public: + + //! Destructor + virtual ~IMeshLoader() {} + + //! Returns true if the file might be loaded by this class. + /** This decision should be based on the file extension (e.g. ".cob") + only. + \param filename Name of the file to test. + \return True if the file might be loaded by this class. */ + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; + + //! Creates/loads an animated mesh from the file. + /** \param file File handler to load the file from. + \return Pointer to the created mesh. Returns 0 if loading failed. + If you no longer need the mesh, you should call IAnimatedMesh::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* createMesh(io::IReadFile* file) = 0; +}; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IMeshManipulator.h b/inc/IMeshManipulator.h new file mode 100644 index 0000000..d6ac89f --- /dev/null +++ b/inc/IMeshManipulator.h @@ -0,0 +1,393 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_MANIPULATOR_H_INCLUDED__ +#define __I_MESH_MANIPULATOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "vector3d.h" +#include "aabbox3d.h" +#include "matrix4.h" +#include "IAnimatedMesh.h" +#include "IMeshBuffer.h" +#include "SVertexManipulator.h" + +namespace irr +{ +namespace scene +{ + + struct SMesh; + + //! An interface for easy manipulation of meshes. + /** Scale, set alpha value, flip surfaces, and so on. This exists for + fixing problems with wrong imported or exported meshes quickly after + loading. It is not intended for doing mesh modifications and/or + animations during runtime. + */ + class IMeshManipulator : public virtual IReferenceCounted + { + public: + + //! Flips the direction of surfaces. + /** Changes backfacing triangles to frontfacing + triangles and vice versa. + \param mesh Mesh on which the operation is performed. */ + virtual void flipSurfaces(IMesh* mesh) const = 0; + + //! Sets the alpha vertex color value of the whole mesh to a new value. + /** \param mesh Mesh on which the operation is performed. + \param alpha New alpha value. Must be a value between 0 and 255. */ + void setVertexColorAlpha(IMesh* mesh, s32 alpha) const + { + apply(scene::SVertexColorSetAlphaManipulator(alpha), mesh); + } + + //! Sets the alpha vertex color value of the whole mesh to a new value. + /** \param buffer Meshbuffer on which the operation is performed. + \param alpha New alpha value. Must be a value between 0 and 255. */ + void setVertexColorAlpha(IMeshBuffer* buffer, s32 alpha) const + { + apply(scene::SVertexColorSetAlphaManipulator(alpha), buffer); + } + + //! Sets the colors of all vertices to one color + /** \param mesh Mesh on which the operation is performed. + \param color New color. */ + void setVertexColors(IMesh* mesh, video::SColor color) const + { + apply(scene::SVertexColorSetManipulator(color), mesh); + } + + //! Sets the colors of all vertices to one color + /** \param buffer Meshbuffer on which the operation is performed. + \param color New color. */ + void setVertexColors(IMeshBuffer* buffer, video::SColor color) const + { + apply(scene::SVertexColorSetManipulator(color), buffer); + } + + //! Recalculates all normals of the mesh. + /** \param mesh: Mesh on which the operation is performed. + \param smooth: If the normals shall be smoothed. + \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ + virtual void recalculateNormals(IMesh* mesh, bool smooth = false, + bool angleWeighted = false) const=0; + + //! Recalculates all normals of the mesh buffer. + /** \param buffer: Mesh buffer on which the operation is performed. + \param smooth: If the normals shall be smoothed. + \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ + virtual void recalculateNormals(IMeshBuffer* buffer, + bool smooth = false, bool angleWeighted = false) const=0; + + //! Recalculates tangents, requires a tangent mesh + /** \param mesh Mesh on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMesh* mesh, + bool recalculateNormals=false, bool smooth=false, + bool angleWeighted=false) const=0; + + //! Recalculates tangents, requires a tangent mesh buffer + /** \param buffer Meshbuffer on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMeshBuffer* buffer, + bool recalculateNormals=false, bool smooth=false, + bool angleWeighted=false) const=0; + + //! Scales the actual mesh, not a scene node. + /** \param mesh Mesh on which the operation is performed. + \param factor Scale factor for each axis. */ + void scale(IMesh* mesh, const core::vector3df& factor) const + { + apply(SVertexPositionScaleManipulator(factor), mesh, true); + } + + //! Scales the actual meshbuffer, not a scene node. + /** \param buffer Meshbuffer on which the operation is performed. + \param factor Scale factor for each axis. */ + void scale(IMeshBuffer* buffer, const core::vector3df& factor) const + { + apply(SVertexPositionScaleManipulator(factor), buffer, true); + } + + //! Scales the actual mesh, not a scene node. + /** \deprecated Use scale() instead. This method may be removed by Irrlicht 1.9 + \param mesh Mesh on which the operation is performed. + \param factor Scale factor for each axis. */ + _IRR_DEPRECATED_ void scaleMesh(IMesh* mesh, const core::vector3df& factor) const {return scale(mesh,factor);} + + //! Scale the texture coords of a mesh. + /** \param mesh Mesh on which the operation is performed. + \param factor Vector which defines the scale for each axis. + \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ + void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 level=1) const + { + apply(SVertexTCoordsScaleManipulator(factor, level), mesh); + } + + //! Scale the texture coords of a meshbuffer. + /** \param buffer Meshbuffer on which the operation is performed. + \param factor Vector which defines the scale for each axis. + \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ + void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const + { + apply(SVertexTCoordsScaleManipulator(factor, level), buffer); + } + + //! Applies a transformation to a mesh + /** \param mesh Mesh on which the operation is performed. + \param m transformation matrix. */ + void transform(IMesh* mesh, const core::matrix4& m) const + { + apply(SVertexPositionTransformManipulator(m), mesh, true); + } + + //! Applies a transformation to a meshbuffer + /** \param buffer Meshbuffer on which the operation is performed. + \param m transformation matrix. */ + void transform(IMeshBuffer* buffer, const core::matrix4& m) const + { + apply(SVertexPositionTransformManipulator(m), buffer, true); + } + + //! Applies a transformation to a mesh + /** \deprecated Use transform() instead. This method may be removed by Irrlicht 1.9 + \param mesh Mesh on which the operation is performed. + \param m transformation matrix. */ + _IRR_DEPRECATED_ virtual void transformMesh(IMesh* mesh, const core::matrix4& m) const {return transform(mesh,m);} + + //! Creates a planar texture mapping on the mesh + /** \param mesh: Mesh on which the operation is performed. + \param resolution: resolution of the planar mapping. This is + the value specifying which is the relation between world space + and texture coordinate space. */ + virtual void makePlanarTextureMapping(IMesh* mesh, f32 resolution=0.001f) const=0; + + //! Creates a planar texture mapping on the meshbuffer + /** \param meshbuffer: Buffer on which the operation is performed. + \param resolution: resolution of the planar mapping. This is + the value specifying which is the relation between world space + and texture coordinate space. */ + virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const=0; + + //! Creates a planar texture mapping on the buffer + /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required. + \param mesh Mesh on which the operation is performed. + \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space. + \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space. + \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z). + \param offset Vector added to the vertex positions (in object coordinates). + */ + virtual void makePlanarTextureMapping(scene::IMesh* mesh, + f32 resolutionS, f32 resolutionT, + u8 axis, const core::vector3df& offset) const=0; + + //! Creates a planar texture mapping on the meshbuffer + /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required. + \param buffer Buffer on which the operation is performed. + \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space. + \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space. + \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z). + \param offset Vector added to the vertex positions (in object coordinates). + */ + virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer, + f32 resolutionS, f32 resolutionT, + u8 axis, const core::vector3df& offset) const=0; + + //! Clones a static IMesh into a modifiable SMesh. + /** All meshbuffers in the returned SMesh + are of type SMeshBuffer or SMeshBufferLightMap. + \param mesh Mesh to copy. + \return Cloned mesh. If you no longer need the + cloned mesh, you should call SMesh::drop(). See + IReferenceCounted::drop() for more information. */ + virtual SMesh* createMeshCopy(IMesh* mesh) const = 0; + + //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. + /** This is useful if you want to draw tangent space normal + mapped geometry because it calculates the tangent and binormal + data which is needed there. + \param mesh Input mesh + \param recalculateNormals The normals are recalculated if set, + otherwise the original ones are kept. Note that keeping the + normals may introduce inaccurate tangents if the normals are + very different to those calculated from the faces. + \param smooth The normals/tangents are smoothed across the + meshbuffer's faces if this flag is set. + \param angleWeighted Improved smoothing calculation used + \param recalculateTangents Whether are actually calculated, or just the mesh with proper type is created. + \return Mesh consisting only of S3DVertexTangents vertices. If + you no longer need the cloned mesh, you should call + IMesh::drop(). See IReferenceCounted::drop() for more + information. */ + virtual IMesh* createMeshWithTangents(IMesh* mesh, + bool recalculateNormals=false, bool smooth=false, + bool angleWeighted=false, bool recalculateTangents=true) const=0; + + //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. + /** \param mesh Input mesh + \return Mesh consisting only of S3DVertex2TCoord vertices. If + you no longer need the cloned mesh, you should call + IMesh::drop(). See IReferenceCounted::drop() for more + information. */ + virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0; + + //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. + /** \param mesh Input mesh + \return Mesh consisting only of S3DVertex vertices. If + you no longer need the cloned mesh, you should call + IMesh::drop(). See IReferenceCounted::drop() for more + information. */ + virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; + + //! Creates a copy of a mesh with all vertices unwelded + /** \param mesh Input mesh + \return Mesh consisting only of unique faces. All vertices + which were previously shared are now duplicated. If you no + longer need the cloned mesh, you should call IMesh::drop(). See + IReferenceCounted::drop() for more information. */ + virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0; + + //! Creates a copy of a mesh with vertices welded + /** \param mesh Input mesh + \param tolerance The threshold for vertex comparisons. + \return Mesh without redundant vertices. If you no longer need + the cloned mesh, you should call IMesh::drop(). See + IReferenceCounted::drop() for more information. */ + virtual IMesh* createMeshWelded(IMesh* mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const = 0; + + //! Get amount of polygons in mesh. + /** \param mesh Input mesh + \return Number of polygons in mesh. */ + virtual s32 getPolyCount(IMesh* mesh) const = 0; + + //! Get amount of polygons in mesh. + /** \param mesh Input mesh + \return Number of polygons in mesh. */ + virtual s32 getPolyCount(IAnimatedMesh* mesh) const = 0; + + //! Create a new AnimatedMesh and adds the mesh to it + /** \param mesh Input mesh + \param type The type of the animated mesh to create. + \return Newly created animated mesh with mesh as its only + content. When you don't need the animated mesh anymore, you + should call IAnimatedMesh::drop(). See + IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh, + scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0; + + //! Vertex cache optimization according to the Forsyth paper + /** More information can be found at + http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html + + The function is thread-safe (read: you can optimize several + meshes in different threads). + + \param mesh Source mesh for the operation. + \return A new mesh optimized for the vertex cache. */ + virtual IMesh* createForsythOptimizedMesh(const IMesh *mesh) const = 0; + + //! Apply a manipulator on the Meshbuffer + /** \param func A functor defining the mesh manipulation. + \param buffer The Meshbuffer to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \return True if the functor was successfully applied, else false. */ + template + bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const + { + return apply_(func, buffer, boundingBoxUpdate, func); + } + + + //! Apply a manipulator on the Mesh + /** \param func A functor defining the mesh manipulation. + \param mesh The Mesh to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \return True if the functor was successfully applied, else false. */ + template + bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const + { + if (!mesh) + return true; + bool result = true; + core::aabbox3df bufferbox; + for (u32 i=0; igetMeshBufferCount(); ++i) + { + result &= apply(func, mesh->getMeshBuffer(i), boundingBoxUpdate); + if (boundingBoxUpdate) + { + if (0==i) + bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox()); + else + bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox()); + } + } + if (boundingBoxUpdate) + mesh->setBoundingBox(bufferbox); + return result; + } + +protected: + //! Apply a manipulator based on the type of the functor + /** \param func A functor defining the mesh manipulation. + \param buffer The Meshbuffer to apply the manipulator to. + \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. + \param typeTest Unused parameter, which handles the proper call selection based on the type of the Functor which is passed in two times. + \return True if the functor was successfully applied, else false. */ + template + bool apply_(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate, const IVertexManipulator& typeTest) const + { + if (!buffer) + return true; + + core::aabbox3df bufferbox; + for (u32 i=0; igetVertexCount(); ++i) + { + switch (buffer->getVertexType()) + { + case video::EVT_STANDARD: + { + video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices(); + func(verts[i]); + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices(); + func(verts[i]); + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices(); + func(verts[i]); + } + break; + } + if (boundingBoxUpdate) + { + if (0==i) + bufferbox.reset(buffer->getPosition(0)); + else + bufferbox.addInternalPoint(buffer->getPosition(i)); + } + } + if (boundingBoxUpdate) + buffer->setBoundingBox(bufferbox); + return true; + } +}; + +} // end namespace scene +} // end namespace irr + + +#endif diff --git a/inc/IMeshSceneNode.h b/inc/IMeshSceneNode.h new file mode 100644 index 0000000..4541069 --- /dev/null +++ b/inc/IMeshSceneNode.h @@ -0,0 +1,79 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_MESH_SCENE_NODE_H_INCLUDED__ +#define __I_MESH_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + +class IShadowVolumeSceneNode; +class IMesh; + + +//! A scene node displaying a static mesh +class IMeshSceneNode : public ISceneNode +{ +public: + + //! Constructor + /** Use setMesh() to set the mesh to display. + */ + IMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1,1,1)) + : ISceneNode(parent, mgr, id, position, rotation, scale) {} + + //! Sets a new mesh to display + /** \param mesh Mesh to display. */ + virtual void setMesh(IMesh* mesh) = 0; + + //! Get the currently defined mesh for display. + /** \return Pointer to mesh which is displayed by this node. */ + virtual IMesh* getMesh(void) = 0; + + //! Creates shadow volume scene node as child of this node. + /** The shadow can be rendered using the ZPass or the zfail + method. ZPass is a little bit faster because the shadow volume + creation is easier, but with this method there occur ugly + looking artifacs when the camera is inside the shadow volume. + These error do not occur with the ZFail method. + \param shadowMesh: Optional custom mesh for shadow volume. + \param id: Id of the shadow scene node. This id can be used to + identify the node later. + \param zfailmethod: If set to true, the shadow will use the + zfail method, if not, zpass is used. + \param infinity: Value used by the shadow volume algorithm to + scale the shadow volume (for zfail shadow volume we support only + finite shadows, so camera zfar must be larger than shadow back cap, + which is depend on infinity parameter). + \return Pointer to the created shadow scene node. This pointer + should not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, + s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0; + + //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. + /** In this way it is possible to change the materials of a mesh + causing all mesh scene nodes referencing this mesh to change, too. + \param readonly Flag if the materials shall be read-only. */ + virtual void setReadOnlyMaterials(bool readonly) = 0; + + //! Check if the scene node should not copy the materials of the mesh but use them in a read only style + /** This flag can be set by setReadOnlyMaterials(). + \return Whether the materials are read-only. */ + virtual bool isReadOnlyMaterials() const = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IMeshWriter.h b/inc/IMeshWriter.h new file mode 100644 index 0000000..aef3e28 --- /dev/null +++ b/inc/IMeshWriter.h @@ -0,0 +1,58 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_I_MESH_WRITER_H_INCLUDED__ +#define __IRR_I_MESH_WRITER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "EMeshWriterEnums.h" + +namespace irr +{ +namespace io +{ + class IWriteFile; +} // end namespace io + +namespace scene +{ + class IMesh; + + //! Interface for writing meshes + class IMeshWriter : public virtual IReferenceCounted + { + public: + + //! Destructor + virtual ~IMeshWriter() {} + + //! Get the type of the mesh writer + /** For own implementations, use MAKE_IRR_ID as shown in the + EMESH_WRITER_TYPE enumeration to return your own unique mesh + type id. + \return Type of the mesh writer. */ + virtual EMESH_WRITER_TYPE getType() const = 0; + + //! Write a static mesh. + /** \param file File handle to write the mesh to. + \param mesh Pointer to mesh to be written. + \param flags Optional flags to set properties of the writer. + \return True if sucessful */ + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, + s32 flags=EMWF_NONE) = 0; + + // Writes an animated mesh + // for future use, no writer is able to write animated meshes currently + /* \return Returns true if sucessful */ + //virtual bool writeAnimatedMesh(io::IWriteFile* file, + // scene::IAnimatedMesh* mesh, + // s32 flags=EMWF_NONE) = 0; + }; + + +} // end namespace +} // end namespace + +#endif + diff --git a/inc/IMetaTriangleSelector.h b/inc/IMetaTriangleSelector.h new file mode 100644 index 0000000..366893a --- /dev/null +++ b/inc/IMetaTriangleSelector.h @@ -0,0 +1,43 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_META_TRIANGLE_SELECTOR_H_INCLUDED__ +#define __I_META_TRIANGLE_SELECTOR_H_INCLUDED__ + +#include "ITriangleSelector.h" + +namespace irr +{ +namespace scene +{ + +//! Interface for making multiple triangle selectors work as one big selector. +/** This is nothing more than a collection of one or more triangle selectors +providing together the interface of one triangle selector. In this way, +collision tests can be done with different triangle soups in one pass. +*/ +class IMetaTriangleSelector : public ITriangleSelector +{ +public: + + //! Adds a triangle selector to the collection of triangle selectors. + /** \param toAdd: Pointer to an triangle selector to add to the list. */ + virtual void addTriangleSelector(ITriangleSelector* toAdd) = 0; + + //! Removes a specific triangle selector from the collection. + /** \param toRemove: Pointer to an triangle selector which is in the + list but will be removed. + \return True if successful, false if not. */ + virtual bool removeTriangleSelector(ITriangleSelector* toRemove) = 0; + + //! Removes all triangle selectors from the collection. + virtual void removeAllTriangleSelectors() = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IOSOperator.h b/inc/IOSOperator.h new file mode 100644 index 0000000..b5c6236 --- /dev/null +++ b/inc/IOSOperator.h @@ -0,0 +1,50 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_OS_OPERATOR_H_INCLUDED__ +#define __I_OS_OPERATOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrString.h" + +namespace irr +{ + +//! The Operating system operator provides operation system specific methods and informations. +class IOSOperator : public virtual IReferenceCounted +{ +public: + //! Get the current operation system version as string. + virtual const core::stringc& getOperatingSystemVersion() const = 0; + + //! Get the current operation system version as string. + /** \deprecated Use getOperatingSystemVersion instead. This method will be removed in Irrlicht 1.9. */ + _IRR_DEPRECATED_ const wchar_t* getOperationSystemVersion() const + { + return core::stringw(getOperatingSystemVersion()).c_str(); + } + + //! Copies text to the clipboard + virtual void copyToClipboard(const c8* text) const = 0; + + //! Get text from the clipboard + /** \return Returns 0 if no string is in there. */ + virtual const c8* getTextFromClipboard() const = 0; + + //! Get the processor speed in megahertz + /** \param MHz The integer variable to store the speed in. + \return True if successful, false if not */ + virtual bool getProcessorSpeedMHz(u32* MHz) const = 0; + + //! Get the total and available system RAM + /** \param Total: will contain the total system memory + \param Avail: will contain the available memory + \return True if successful, false if not */ + virtual bool getSystemMemory(u32* Total, u32* Avail) const = 0; + +}; + +} // end namespace + +#endif diff --git a/inc/IParticleAffector.h b/inc/IParticleAffector.h new file mode 100644 index 0000000..f5a18c6 --- /dev/null +++ b/inc/IParticleAffector.h @@ -0,0 +1,72 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_AFFECTOR_H_INCLUDED__ +#define __I_PARTICLE_AFFECTOR_H_INCLUDED__ + +#include "IAttributeExchangingObject.h" +#include "SParticle.h" + +namespace irr +{ +namespace scene +{ + +//! Types of built in particle affectors +enum E_PARTICLE_AFFECTOR_TYPE +{ + EPAT_NONE = 0, + EPAT_ATTRACT, + EPAT_FADE_OUT, + EPAT_GRAVITY, + EPAT_ROTATE, + EPAT_SCALE, + EPAT_COUNT +}; + +//! Names for built in particle affectors +const c8* const ParticleAffectorTypeNames[] = +{ + "None", + "Attract", + "FadeOut", + "Gravity", + "Rotate", + "Scale", + 0 +}; + +//! A particle affector modifies particles. +class IParticleAffector : public virtual io::IAttributeExchangingObject +{ +public: + + //! constructor + IParticleAffector() : Enabled(true) {} + + //! Affects an array of particles. + /** \param now Current time. (Same as ITimer::getTime() would return) + \param particlearray Array of particles. + \param count Amount of particles in array. */ + virtual void affect(u32 now, SParticle* particlearray, u32 count) = 0; + + //! Sets whether or not the affector is currently enabled. + virtual void setEnabled(bool enabled) { Enabled = enabled; } + + //! Gets whether or not the affector is currently enabled. + virtual bool getEnabled() const { return Enabled; } + + //! Get emitter type + virtual E_PARTICLE_AFFECTOR_TYPE getType() const = 0; + +protected: + bool Enabled; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleAnimatedMeshSceneNodeEmitter.h b/inc/IParticleAnimatedMeshSceneNodeEmitter.h new file mode 100644 index 0000000..b64d1d6 --- /dev/null +++ b/inc/IParticleAnimatedMeshSceneNodeEmitter.h @@ -0,0 +1,54 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" +#include "IAnimatedMeshSceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits particles from mesh vertices. +class IParticleAnimatedMeshSceneNodeEmitter : public IParticleEmitter +{ +public: + + //! Set Mesh to emit particles from + virtual void setAnimatedMeshSceneNode( IAnimatedMeshSceneNode* node ) = 0; + + //! Set whether to use vertex normal for direction, or direction specified + virtual void setUseNormalDirection( bool useNormalDirection = true ) = 0; + + //! Set the amount that the normal is divided by for getting a particles direction + virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) = 0; + + //! Sets whether to emit min<->max particles for every vertex or to pick min<->max vertices + virtual void setEveryMeshVertex( bool everyMeshVertex = true ) = 0; + + //! Get mesh we're emitting particles from + virtual const IAnimatedMeshSceneNode* getAnimatedMeshSceneNode() const = 0; + + //! Get whether to use vertex normal for direction, or direction specified + virtual bool isUsingNormalDirection() const = 0; + + //! Get the amount that the normal is divided by for getting a particles direction + virtual f32 getNormalDirectionModifier() const = 0; + + //! Gets whether to emit min<->max particles for every vertex or to pick min<->max vertices + virtual bool getEveryMeshVertex() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_ANIMATED_MESH; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ + diff --git a/inc/IParticleAttractionAffector.h b/inc/IParticleAttractionAffector.h new file mode 100644 index 0000000..7e874e8 --- /dev/null +++ b/inc/IParticleAttractionAffector.h @@ -0,0 +1,59 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ +#define __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ + +#include "IParticleAffector.h" + +namespace irr +{ +namespace scene +{ + +//! A particle affector which attracts or detracts particles. +class IParticleAttractionAffector : public IParticleAffector +{ +public: + + //! Set the point that particles will attract to + virtual void setPoint( const core::vector3df& point ) = 0; + + //! Set whether or not the particles are attracting or detracting + virtual void setAttract( bool attract ) = 0; + + //! Set whether or not this will affect particles in the X direction + virtual void setAffectX( bool affect ) = 0; + + //! Set whether or not this will affect particles in the Y direction + virtual void setAffectY( bool affect ) = 0; + + //! Set whether or not this will affect particles in the Z direction + virtual void setAffectZ( bool affect ) = 0; + + //! Get the point that particles are attracted to + virtual const core::vector3df& getPoint() const = 0; + + //! Get whether or not the particles are attracting or detracting + virtual bool getAttract() const = 0; + + //! Get whether or not the particles X position are affected + virtual bool getAffectX() const = 0; + + //! Get whether or not the particles Y position are affected + virtual bool getAffectY() const = 0; + + //! Get whether or not the particles Z position are affected + virtual bool getAffectZ() const = 0; + + //! Get emitter type + virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_ATTRACT; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ + diff --git a/inc/IParticleBoxEmitter.h b/inc/IParticleBoxEmitter.h new file mode 100644 index 0000000..9ea388a --- /dev/null +++ b/inc/IParticleBoxEmitter.h @@ -0,0 +1,36 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_BOX_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_BOX_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" +#include "aabbox3d.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits particles from a box shaped space +class IParticleBoxEmitter : public IParticleEmitter +{ +public: + + //! Set the box shape + virtual void setBox( const core::aabbox3df& box ) = 0; + + //! Get the box shape set + virtual const core::aabbox3df& getBox() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_BOX; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleCylinderEmitter.h b/inc/IParticleCylinderEmitter.h new file mode 100644 index 0000000..cd063b8 --- /dev/null +++ b/inc/IParticleCylinderEmitter.h @@ -0,0 +1,59 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits from a cylindrically shaped space. +class IParticleCylinderEmitter : public IParticleEmitter +{ +public: + + //! Set the center of the radius for the cylinder, at one end of the cylinder + virtual void setCenter( const core::vector3df& center ) = 0; + + //! Set the normal of the cylinder + virtual void setNormal( const core::vector3df& normal ) = 0; + + //! Set the radius of the cylinder + virtual void setRadius( f32 radius ) = 0; + + //! Set the length of the cylinder + virtual void setLength( f32 length ) = 0; + + //! Set whether or not to draw points inside the cylinder + virtual void setOutlineOnly( bool outlineOnly = true ) = 0; + + //! Get the center of the cylinder + virtual const core::vector3df& getCenter() const = 0; + + //! Get the normal of the cylinder + virtual const core::vector3df& getNormal() const = 0; + + //! Get the radius of the cylinder + virtual f32 getRadius() const = 0; + + //! Get the center of the cylinder + virtual f32 getLength() const = 0; + + //! Get whether or not to draw points inside the cylinder + virtual bool getOutlineOnly() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_CYLINDER; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleEmitter.h b/inc/IParticleEmitter.h new file mode 100644 index 0000000..6fc9a2c --- /dev/null +++ b/inc/IParticleEmitter.h @@ -0,0 +1,129 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_EMITTER_H_INCLUDED__ + +#include "IAttributeExchangingObject.h" +#include "SParticle.h" + +namespace irr +{ +namespace scene +{ + +//! Types of built in particle emitters +enum E_PARTICLE_EMITTER_TYPE +{ + EPET_POINT = 0, + EPET_ANIMATED_MESH, + EPET_BOX, + EPET_CYLINDER, + EPET_MESH, + EPET_RING, + EPET_SPHERE, + EPET_COUNT +}; + +//! Names for built in particle emitters +const c8* const ParticleEmitterTypeNames[] = +{ + "Point", + "AnimatedMesh", + "Box", + "Cylinder", + "Mesh", + "Ring", + "Sphere", + 0 +}; + +//! A particle emitter for using with particle systems. +/** A Particle emitter emitts new particles into a particle system. +*/ +class IParticleEmitter : public virtual io::IAttributeExchangingObject +{ +public: + + //! Prepares an array with new particles to emitt into the system + /** \param now Current time. + \param timeSinceLastCall Time elapsed since last call, in milliseconds. + \param outArray Pointer which will point to the array with the new + particles to add into the system. + \return Amount of new particles in the array. Can be 0. */ + virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) = 0; + + //! Set direction the emitter emits particles + virtual void setDirection( const core::vector3df& newDirection ) = 0; + + //! Set minimum number of particles the emitter emits per second + virtual void setMinParticlesPerSecond( u32 minPPS ) = 0; + + //! Set maximum number of particles the emitter emits per second + virtual void setMaxParticlesPerSecond( u32 maxPPS ) = 0; + + //! Set minimum starting color for particles + virtual void setMinStartColor( const video::SColor& color ) = 0; + + //! Set maximum starting color for particles + virtual void setMaxStartColor( const video::SColor& color ) = 0; + + //! Set the maximum starting size for particles + virtual void setMaxStartSize( const core::dimension2df& size ) = 0; + + //! Set the minimum starting size for particles + virtual void setMinStartSize( const core::dimension2df& size ) = 0; + + //! Set the minimum particle life-time in milliseconds + virtual void setMinLifeTime( u32 lifeTimeMin ) = 0; + + //! Set the maximum particle life-time in milliseconds + virtual void setMaxLifeTime( u32 lifeTimeMax ) = 0; + + //! Set maximal random derivation from the direction + virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) = 0; + + //! Get direction the emitter emits particles + virtual const core::vector3df& getDirection() const = 0; + + //! Get the minimum number of particles the emitter emits per second + virtual u32 getMinParticlesPerSecond() const = 0; + + //! Get the maximum number of particles the emitter emits per second + virtual u32 getMaxParticlesPerSecond() const = 0; + + //! Get the minimum starting color for particles + virtual const video::SColor& getMinStartColor() const = 0; + + //! Get the maximum starting color for particles + virtual const video::SColor& getMaxStartColor() const = 0; + + //! Get the maximum starting size for particles + virtual const core::dimension2df& getMaxStartSize() const = 0; + + //! Get the minimum starting size for particles + virtual const core::dimension2df& getMinStartSize() const = 0; + + //! Get the minimum particle life-time in milliseconds + virtual u32 getMinLifeTime() const = 0; + + //! Get the maximum particle life-time in milliseconds + virtual u32 getMaxLifeTime() const = 0; + + //! Get maximal random derivation from the direction + virtual s32 getMaxAngleDegrees() const = 0; + + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_POINT; } +}; + +typedef IParticleEmitter IParticlePointEmitter; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleFadeOutAffector.h b/inc/IParticleFadeOutAffector.h new file mode 100644 index 0000000..c3ce78b --- /dev/null +++ b/inc/IParticleFadeOutAffector.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ +#define __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ + +#include "IParticleAffector.h" + +namespace irr +{ +namespace scene +{ + +//! A particle affector which fades out the particles. +class IParticleFadeOutAffector : public IParticleAffector +{ +public: + + //! Sets the targetColor, i.e. the color the particles will interpolate to over time. + virtual void setTargetColor( const video::SColor& targetColor ) = 0; + + //! Sets the time in milliseconds it takes for each particle to fade out (minimal 1 ms) + virtual void setFadeOutTime( u32 fadeOutTime ) = 0; + + //! Gets the targetColor, i.e. the color the particles will interpolate to over time. + virtual const video::SColor& getTargetColor() const = 0; + + //! Gets the time in milliseconds it takes for each particle to fade out. + virtual u32 getFadeOutTime() const = 0; + + //! Get emitter type + virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_FADE_OUT; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ + diff --git a/inc/IParticleGravityAffector.h b/inc/IParticleGravityAffector.h new file mode 100644 index 0000000..f0e4f8e --- /dev/null +++ b/inc/IParticleGravityAffector.h @@ -0,0 +1,42 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ +#define __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ + +#include "IParticleAffector.h" + +namespace irr +{ +namespace scene +{ + +//! A particle affector which applies gravity to particles. +class IParticleGravityAffector : public IParticleAffector +{ +public: + + //! Set the time in milliseconds when the gravity force is totally lost + /** At that point the particle does not move any more. */ + virtual void setTimeForceLost( f32 timeForceLost ) = 0; + + //! Set the direction and force of gravity in all 3 dimensions. + virtual void setGravity( const core::vector3df& gravity ) = 0; + + //! Get the time in milliseconds when the gravity force is totally lost + virtual f32 getTimeForceLost() const = 0; + + //! Get the direction and force of gravity. + virtual const core::vector3df& getGravity() const = 0; + + //! Get emitter type + virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_GRAVITY; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ + diff --git a/inc/IParticleMeshEmitter.h b/inc/IParticleMeshEmitter.h new file mode 100644 index 0000000..4d066a1 --- /dev/null +++ b/inc/IParticleMeshEmitter.h @@ -0,0 +1,54 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_MESH_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_MESH_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" +#include "IMesh.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits from vertices of a mesh +class IParticleMeshEmitter : public IParticleEmitter +{ +public: + + //! Set Mesh to emit particles from + virtual void setMesh( IMesh* mesh ) = 0; + + //! Set whether to use vertex normal for direction, or direction specified + virtual void setUseNormalDirection( bool useNormalDirection = true ) = 0; + + //! Set the amount that the normal is divided by for getting a particles direction + virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) = 0; + + //! Sets whether to emit min<->max particles for every vertex or to pick min<->max vertices + virtual void setEveryMeshVertex( bool everyMeshVertex = true ) = 0; + + //! Get Mesh we're emitting particles from + virtual const IMesh* getMesh() const = 0; + + //! Get whether to use vertex normal for direction, or direction specified + virtual bool isUsingNormalDirection() const = 0; + + //! Get the amount that the normal is divided by for getting a particles direction + virtual f32 getNormalDirectionModifier() const = 0; + + //! Gets whether to emit min<->max particles for every vertex or to pick min<->max vertices + virtual bool getEveryMeshVertex() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_MESH; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleRingEmitter.h b/inc/IParticleRingEmitter.h new file mode 100644 index 0000000..4330092 --- /dev/null +++ b/inc/IParticleRingEmitter.h @@ -0,0 +1,47 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_RING_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_RING_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits particles along a ring shaped area. +class IParticleRingEmitter : public IParticleEmitter +{ +public: + + //! Set the center of the ring + virtual void setCenter( const core::vector3df& center ) = 0; + + //! Set the radius of the ring + virtual void setRadius( f32 radius ) = 0; + + //! Set the thickness of the ring + virtual void setRingThickness( f32 ringThickness ) = 0; + + //! Get the center of the ring + virtual const core::vector3df& getCenter() const = 0; + + //! Get the radius of the ring + virtual f32 getRadius() const = 0; + + //! Get the thickness of the ring + virtual f32 getRingThickness() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_RING; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleRotationAffector.h b/inc/IParticleRotationAffector.h new file mode 100644 index 0000000..611fc3b --- /dev/null +++ b/inc/IParticleRotationAffector.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ +#define __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ + +#include "IParticleAffector.h" + +namespace irr +{ +namespace scene +{ + +//! A particle affector which rotates the particle system. +class IParticleRotationAffector : public IParticleAffector +{ +public: + + //! Set the point that particles will rotate around + virtual void setPivotPoint( const core::vector3df& point ) = 0; + + //! Set the speed in degrees per second in all 3 dimensions + virtual void setSpeed( const core::vector3df& speed ) = 0; + + //! Get the point that particles are attracted to + virtual const core::vector3df& getPivotPoint() const = 0; + + //! Get the speed in degrees per second in all 3 dimensions + virtual const core::vector3df& getSpeed() const = 0; + + //! Get emitter type + virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_ROTATE; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ + diff --git a/inc/IParticleSphereEmitter.h b/inc/IParticleSphereEmitter.h new file mode 100644 index 0000000..edde2da --- /dev/null +++ b/inc/IParticleSphereEmitter.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ +#define __I_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ + +#include "IParticleEmitter.h" + +namespace irr +{ +namespace scene +{ + +//! A particle emitter which emits from a spherical space. +class IParticleSphereEmitter : public IParticleEmitter +{ +public: + + //! Set the center of the sphere for particle emissions + virtual void setCenter( const core::vector3df& center ) = 0; + + //! Set the radius of the sphere for particle emissions + virtual void setRadius( f32 radius ) = 0; + + //! Get the center of the sphere for particle emissions + virtual const core::vector3df& getCenter() const = 0; + + //! Get the radius of the sphere for particle emissions + virtual f32 getRadius() const = 0; + + //! Get emitter type + virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_SPHERE; } +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IParticleSystemSceneNode.h b/inc/IParticleSystemSceneNode.h new file mode 100644 index 0000000..56a47c8 --- /dev/null +++ b/inc/IParticleSystemSceneNode.h @@ -0,0 +1,512 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ +#define __I_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" +#include "IParticleAnimatedMeshSceneNodeEmitter.h" +#include "IParticleBoxEmitter.h" +#include "IParticleCylinderEmitter.h" +#include "IParticleMeshEmitter.h" +#include "IParticleRingEmitter.h" +#include "IParticleSphereEmitter.h" +#include "IParticleAttractionAffector.h" +#include "IParticleFadeOutAffector.h" +#include "IParticleGravityAffector.h" +#include "IParticleRotationAffector.h" +#include "dimension2d.h" + +namespace irr +{ +namespace scene +{ + +//! A particle system scene node for creating snow, fire, exlosions, smoke... +/** A scene node controlling a particle System. The behavior of the particles +can be controlled by setting the right particle emitters and affectors. +You can for example easily create a campfire by doing this: + +\code + scene::IParticleSystemSceneNode* p = scenemgr->addParticleSystemSceneNode(); + p->setParticleSize(core::dimension2d(20.0f, 10.0f)); + scene::IParticleEmitter* em = p->createBoxEmitter( + core::aabbox3d(-5,0,-5,5,1,5), + core::vector3df(0.0f,0.03f,0.0f), + 40,80, video::SColor(0,255,255,255),video::SColor(0,255,255,255), 1100,2000); + p->setEmitter(em); + em->drop(); + scene::IParticleAffector* paf = p->createFadeOutParticleAffector(); + p->addAffector(paf); + paf->drop(); +\endcode + +*/ +class IParticleSystemSceneNode : public ISceneNode +{ +public: + + //! Constructor + IParticleSystemSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) + : ISceneNode(parent, mgr, id, position, rotation, scale) {} + + //! Sets the size of all particles. + virtual void setParticleSize( + const core::dimension2d &size = core::dimension2d(5.0f, 5.0f)) = 0; + + //! Sets if the particles should be global. + /** If they are, the particles are affected by the movement of the + particle system scene node too, otherwise they completely ignore it. + Default is true. */ + virtual void setParticlesAreGlobal(bool global=true) = 0; + + //! Remove all currently visible particles + virtual void clearParticles() = 0; + + //! Do manually update the particles. + //! This should only be called when you want to render the node outside the scenegraph, + //! as the node will care about this otherwise automatically. + virtual void doParticleSystem(u32 time) = 0; + + //! Gets the particle emitter, which creates the particles. + /** \return The particle emitter. Can be 0 if none is set. */ + virtual IParticleEmitter* getEmitter() =0; + + //! Sets the particle emitter, which creates the particles. + /** A particle emitter can be created using one of the createEmitter + methods. For example to create and use a simple PointEmitter, call + IParticleEmitter* p = createPointEmitter(); setEmitter(p); p->drop(); + \param emitter: Sets the particle emitter. You can set this to 0 for + removing the current emitter and stopping the particle system emitting + new particles. */ + virtual void setEmitter(IParticleEmitter* emitter) = 0; + + //! Adds new particle effector to the particle system. + /** A particle affector modifies the particles. For example, the FadeOut + affector lets all particles fade out after some time. It is created and + used in this way: + \code + IParticleAffector* p = createFadeOutParticleAffector(); + addAffector(p); + p->drop(); + \endcode + Please note that an affector is not necessary for the particle system to + work. + \param affector: New affector. */ + virtual void addAffector(IParticleAffector* affector) = 0; + + //! Get a list of all particle affectors. + /** \return The list of particle affectors attached to this node. */ + virtual const core::list& getAffectors() const = 0; + + //! Removes all particle affectors in the particle system. + virtual void removeAllAffectors() = 0; + + //! Creates a particle emitter for an animated mesh scene node + /** \param node: Pointer to the animated mesh scene node to emit + particles from + \param useNormalDirection: If true, the direction of each particle + created will be the normal of the vertex that it's emitting from. The + normal is divided by the normalDirectionModifier parameter, which + defaults to 100.0f. + \param direction: Direction and speed of particle emission. + \param normalDirectionModifier: If the emitter is using the normal + direction then the normal of the vertex that is being emitted from is + divided by this number. + \param mbNumber: This allows you to specify a specific meshBuffer for + the IMesh* to emit particles from. The default value is -1, which + means a random meshBuffer picked from all of the meshes meshBuffers + will be selected to pick a random vertex from. If the value is 0 or + greater, it will only pick random vertices from the meshBuffer + specified by this value. + \param everyMeshVertex: If true, the emitter will emit between min/max + particles every second, for every vertex in the mesh, if false, it will + emit between min/max particles from random vertices in the mesh. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleAnimatedMeshSceneNodeEmitter* createAnimatedMeshSceneNodeEmitter( + scene::IAnimatedMeshSceneNode* node, bool useNormalDirection = true, + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, + bool everyMeshVertex = false, + u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, + s32 maxAngleDegrees = 0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a box particle emitter. + /** \param box: The box for the emitter. + \param direction: Direction and speed of particle emission. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleBoxEmitter* createBoxEmitter( + const core::aabbox3df& box = core::aabbox3df(-10,28,-10,10,30,10), + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + u32 minParticlesPerSecond = 5, + u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, + s32 maxAngleDegrees=0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a particle emitter for emitting from a cylinder + /** \param center: The center of the circle at the base of the cylinder + \param radius: The thickness of the cylinder + \param normal: Direction of the length of the cylinder + \param length: The length of the the cylinder + \param outlineOnly: Whether or not to put points inside the cylinder or + on the outline only + \param direction: Direction and speed of particle emission. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleCylinderEmitter* createCylinderEmitter( + const core::vector3df& center, f32 radius, + const core::vector3df& normal, f32 length, + bool outlineOnly = false, + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, + s32 maxAngleDegrees = 0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a mesh particle emitter. + /** \param mesh: Pointer to mesh to emit particles from + \param useNormalDirection: If true, the direction of each particle + created will be the normal of the vertex that it's emitting from. The + normal is divided by the normalDirectionModifier parameter, which + defaults to 100.0f. + \param direction: Direction and speed of particle emission. + \param normalDirectionModifier: If the emitter is using the normal + direction then the normal of the vertex that is being emitted from is + divided by this number. + \param mbNumber: This allows you to specify a specific meshBuffer for + the IMesh* to emit particles from. The default value is -1, which + means a random meshBuffer picked from all of the meshes meshBuffers + will be selected to pick a random vertex from. If the value is 0 or + greater, it will only pick random vertices from the meshBuffer + specified by this value. + \param everyMeshVertex: If true, the emitter will emit between min/max + particles every second, for every vertex in the mesh, if false, it will + emit between min/max particles from random vertices in the mesh. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleMeshEmitter* createMeshEmitter( + scene::IMesh* mesh, bool useNormalDirection = true, + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, + bool everyMeshVertex = false, + u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, + s32 maxAngleDegrees = 0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a point particle emitter. + /** \param direction: Direction and speed of particle emission. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticlePointEmitter* createPointEmitter( + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + u32 minParticlesPerSecond = 5, + u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, + s32 maxAngleDegrees=0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a ring particle emitter. + /** \param center: Center of ring + \param radius: Distance of points from center, points will be rotated + around the Y axis at a random 360 degrees and will then be shifted by + the provided ringThickness values in each axis. + \param ringThickness : thickness of the ring or how wide the ring is + \param direction: Direction and speed of particle emission. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleRingEmitter* createRingEmitter( + const core::vector3df& center, f32 radius, f32 ringThickness, + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + u32 minParticlesPerSecond = 5, + u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, + s32 maxAngleDegrees=0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a sphere particle emitter. + /** \param center: Center of sphere + \param radius: Radius of sphere + \param direction: Direction and speed of particle emission. + \param minParticlesPerSecond: Minimal amount of particles emitted per + second. + \param maxParticlesPerSecond: Maximal amount of particles emitted per + second. + \param minStartColor: Minimal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param maxStartColor: Maximal initial start color of a particle. The + real color of every particle is calculated as random interpolation + between minStartColor and maxStartColor. + \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. + \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. + \param maxAngleDegrees: Maximal angle in degrees, the emitting + direction of the particle will differ from the original direction. + \param minStartSize: Minimal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \param maxStartSize: Maximal initial start size of a particle. The + real size of every particle is calculated as random interpolation + between minStartSize and maxStartSize. + \return Pointer to the created particle emitter. To set this emitter + as new emitter of this particle system, just call setEmitter(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleSphereEmitter* createSphereEmitter( + const core::vector3df& center, f32 radius, + const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), + u32 minParticlesPerSecond = 5, + u32 maxParticlesPerSecond = 10, + const video::SColor& minStartColor = video::SColor(255,0,0,0), + const video::SColor& maxStartColor = video::SColor(255,255,255,255), + u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, + s32 maxAngleDegrees=0, + const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), + const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; + + //! Creates a point attraction affector. + /** This affector modifies the positions of the particles and attracts + them to a specified point at a specified speed per second. + \param point: Point to attract particles to. + \param speed: Speed in units per second, to attract to the specified + point. + \param attract: Whether the particles attract or detract from this + point. + \param affectX: Whether or not this will affect the X position of the + particle. + \param affectY: Whether or not this will affect the Y position of the + particle. + \param affectZ: Whether or not this will affect the Z position of the + particle. + \return Pointer to the created particle affector. To add this affector + as new affector of this particle system, just call addAffector(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleAttractionAffector* createAttractionAffector( + const core::vector3df& point, f32 speed = 1.0f, bool attract = true, + bool affectX = true, bool affectY = true, bool affectZ = true) = 0; + + //! Creates a scale particle affector. + /** This affector scales the particle to the a multiple of its size defined + by the scaleTo variable. + \param scaleTo: multiple of the size which the particle will be scaled to until deletion + \return Pointer to the created particle affector. + To add this affector as new affector of this particle system, + just call addAffector(). Note that you'll have to drop() the + returned pointer, after you don't need it any more, see + IReferenceCounted::drop() for more information. */ + virtual IParticleAffector* createScaleParticleAffector(const core::dimension2df& scaleTo = core::dimension2df(1.0f, 1.0f)) = 0; + + //! Creates a fade out particle affector. + /** This affector modifies the color of every particle and and reaches + the final color when the particle dies. This affector looks really + good, if the EMT_TRANSPARENT_ADD_COLOR material is used and the + targetColor is video::SColor(0,0,0,0): Particles are fading out into + void with this setting. + \param targetColor: Color whereto the color of the particle is changed. + \param timeNeededToFadeOut: How much time in milli seconds should the + affector need to change the color to the targetColor. + \return Pointer to the created particle affector. To add this affector + as new affector of this particle system, just call addAffector(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleFadeOutAffector* createFadeOutParticleAffector( + const video::SColor& targetColor = video::SColor(0,0,0,0), + u32 timeNeededToFadeOut = 1000) = 0; + + //! Creates a gravity affector. + /** This affector modifies the direction of the particle. It assumes + that the particle is fired out of the emitter with huge force, but is + loosing this after some time and is catched by the gravity then. This + affector is ideal for creating things like fountains. + \param gravity: Direction and force of gravity. + \param timeForceLost: Time in milli seconds when the force of the + emitter is totally lost and the particle does not move any more. This + is the time where gravity fully affects the particle. + \return Pointer to the created particle affector. To add this affector + as new affector of this particle system, just call addAffector(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleGravityAffector* createGravityAffector( + const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), + u32 timeForceLost = 1000) = 0; + + //! Creates a rotation affector. + /** This affector modifies the positions of the particles and attracts + them to a specified point at a specified speed per second. + \param speed: Rotation in degrees per second + \param pivotPoint: Point to rotate the particles around + \return Pointer to the created particle affector. To add this affector + as new affector of this particle system, just call addAffector(). Note + that you'll have to drop() the returned pointer, after you don't need + it any more, see IReferenceCounted::drop() for more informations. */ + virtual IParticleRotationAffector* createRotationAffector( + const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f), + const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/IQ3LevelMesh.h b/inc/IQ3LevelMesh.h new file mode 100644 index 0000000..f8ff03f --- /dev/null +++ b/inc/IQ3LevelMesh.h @@ -0,0 +1,46 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_Q3_LEVEL_MESH_H_INCLUDED__ +#define __I_Q3_LEVEL_MESH_H_INCLUDED__ + +#include "IAnimatedMesh.h" +#include "IQ3Shader.h" + +namespace irr +{ +namespace scene +{ + //! Interface for a Mesh which can be loaded directly from a Quake3 .bsp-file. + /** The Mesh tries to load all textures of the map.*/ + class IQ3LevelMesh : public IAnimatedMesh + { + public: + + //! loads the shader definition from file + /** \param filename Name of the shaderfile, defaults to /scripts if fileNameIsValid is false. + \param fileNameIsValid Specifies whether the filename is valid in the current situation. */ + virtual const quake3::IShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; + + //! returns a already loaded Shader + virtual const quake3::IShader* getShader(u32 index) const = 0; + + //! get's an interface to the entities + virtual quake3::tQ3EntityList& getEntityList() = 0; + + //! returns the requested brush entity + /** \param num The number from the model key of the entity. + + Use this interface if you parse the entities yourself.*/ + virtual IMesh* getBrushEntityMesh(s32 num) const = 0; + + //! returns the requested brush entity + virtual IMesh* getBrushEntityMesh(quake3::IEntity &ent) const = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IQ3Shader.h b/inc/IQ3Shader.h new file mode 100644 index 0000000..735fdf8 --- /dev/null +++ b/inc/IQ3Shader.h @@ -0,0 +1,885 @@ +// Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__ +#define __I_Q3_LEVEL_SHADER_H_INCLUDED__ + +#include "irrArray.h" +#include "fast_atof.h" +#include "IFileSystem.h" +#include "IVideoDriver.h" +#include "coreutil.h" + +namespace irr +{ +namespace scene +{ +namespace quake3 +{ + + static core::stringc irrEmptyStringc(""); + + //! Hold the different Mesh Types used for getMesh + enum eQ3MeshIndex + { + E_Q3_MESH_GEOMETRY = 0, + E_Q3_MESH_ITEMS, + E_Q3_MESH_BILLBOARD, + E_Q3_MESH_FOG, + E_Q3_MESH_UNRESOLVED, + E_Q3_MESH_SIZE + }; + + /*! used to customize Quake3 BSP Loader + */ + + struct Q3LevelLoadParameter + { + Q3LevelLoadParameter () + :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ), + defaultModulate ( video::EMFN_MODULATE_4X ), + defaultFilter ( video::EMF_BILINEAR_FILTER ), + patchTesselation ( 8 ), + verbose ( 0 ), + startTime ( 0 ), endTime ( 0 ), + mergeShaderBuffer ( 1 ), + cleanUnResolvedMeshes ( 1 ), + loadAllShaders ( 0 ), + loadSkyShader ( 0 ), + alpharef ( 1 ), + swapLump ( 0 ), + #ifdef __BIG_ENDIAN__ + swapHeader ( 1 ) + #else + swapHeader ( 0 ) + #endif + { + memcpy ( scriptDir, "scripts\x0", 8 ); + } + + video::E_MATERIAL_TYPE defaultLightMapMaterial; + video::E_MODULATE_FUNC defaultModulate; + video::E_MATERIAL_FLAG defaultFilter; + s32 patchTesselation; + s32 verbose; + u32 startTime; + u32 endTime; + s32 mergeShaderBuffer; + s32 cleanUnResolvedMeshes; + s32 loadAllShaders; + s32 loadSkyShader; + s32 alpharef; + s32 swapLump; + s32 swapHeader; + c8 scriptDir [ 64 ]; + }; + + // some useful typedefs + typedef core::array< core::stringc > tStringList; + typedef core::array< video::ITexture* > tTexArray; + + // string helper.. TODO: move to generic files + inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize ) + { + const char * in = string.c_str () + pos; + + for ( u16 i = 0; i != listSize; ++i ) + { + if (string.size() < pos) + return -2; + u32 len = (u32) strlen ( list[i] ); + if (string.size() < pos+len) + continue; + if ( in [len] != 0 && in [len] != ' ' ) + continue; + if ( strncmp ( in, list[i], len ) ) + continue; + + pos += len + 1; + return (s16) i; + } + return -2; + } + + inline f32 getAsFloat ( const core::stringc &string, u32 &pos ) + { + const char * in = string.c_str () + pos; + + f32 value = 0.f; + pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1; + return value; + } + + //! get a quake3 vector translated to irrlicht position (x,-z,y ) + inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos ) + { + core::vector3df v; + + v.X = getAsFloat ( string, pos ); + v.Z = getAsFloat ( string, pos ); + v.Y = getAsFloat ( string, pos ); + + return v; + } + + + /* + extract substrings + */ + inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos ) + { + list.clear (); + + s32 finish = 0; + s32 endPos; + do + { + endPos = string.findNext ( ' ', startPos ); + if ( endPos == -1 ) + { + finish = 1; + endPos = string.size(); + } + + list.push_back ( string.subString ( startPos, endPos - startPos ) ); + startPos = endPos + 1; + + if ( list.size() >= (u32) max ) + finish = 1; + + } while ( !finish ); + + } + + //! A blend function for a q3 shader. + struct SBlendFunc + { + SBlendFunc ( video::E_MODULATE_FUNC mod ) + : type ( video::EMT_SOLID ), modulate ( mod ), + param0( 0.f ), + isTransparent ( 0 ) {} + + video::E_MATERIAL_TYPE type; + video::E_MODULATE_FUNC modulate; + + f32 param0; + u32 isTransparent; + }; + + // parses the content of Variable cull + inline bool getCullingFunction ( const core::stringc &cull ) + { + if ( cull.size() == 0 ) + return true; + + bool ret = true; + static const c8 * funclist[] = { "none", "disable", "twosided" }; + + u32 pos = 0; + switch ( isEqual ( cull, pos, funclist, 3 ) ) + { + case 0: + case 1: + case 2: + ret = false; + break; + } + return ret; + } + + // parses the content of Variable depthfunc + // return a z-test + inline u8 getDepthFunction ( const core::stringc &string ) + { + u8 ret = video::ECFN_LESSEQUAL; + + if ( string.size() == 0 ) + return ret; + + static const c8 * funclist[] = { "lequal","equal" }; + + u32 pos = 0; + switch ( isEqual ( string, pos, funclist, 2 ) ) + { + case 0: + ret = video::ECFN_LESSEQUAL; + break; + case 1: + ret = video::ECFN_EQUAL; + break; + } + return ret; + } + + + /*! + parses the content of Variable blendfunc,alphafunc + it also make a hint for rendering as transparent or solid node. + + we assume a typical quake scene would look like this.. + 1) Big Static Mesh ( solid ) + 2) static scene item ( may use transparency ) but rendered in the solid pass + 3) additional transparency item in the transparent pass + + it's not 100% accurate! it just empirical.. + */ + inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) + { + if ( string.size() == 0 ) + return; + + // maps to E_BLEND_FACTOR + static const c8 * funclist[] = + { + "gl_zero", + "gl_one", + "gl_dst_color", + "gl_one_minus_dst_color", + "gl_src_color", + "gl_one_minus_src_color", + "gl_src_alpha", + "gl_one_minus_src_alpha", + "gl_dst_alpha", + "gl_one_minus_dst_alpha", + "gl_src_alpha_sat", + + "add", + "filter", + "blend", + + "ge128", + "gt0", + }; + + + u32 pos = 0; + s32 srcFact = isEqual ( string, pos, funclist, 16 ); + + if ( srcFact < 0 ) + return; + + u32 resolved = 0; + s32 dstFact = isEqual ( string, pos, funclist, 16 ); + + switch ( srcFact ) + { + case video::EBF_ZERO: + switch ( dstFact ) + { + // gl_zero gl_src_color == gl_dst_color gl_zero + case video::EBF_SRC_COLOR: + blendfunc.type = video::EMT_ONETEXTURE_BLEND; + blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); + blendfunc.isTransparent = 1; + resolved = 1; + break; + } break; + + case video::EBF_ONE: + switch ( dstFact ) + { + // gl_one gl_zero + case video::EBF_ZERO: + blendfunc.type = video::EMT_SOLID; + blendfunc.isTransparent = 0; + resolved = 1; + break; + + // gl_one gl_one + case video::EBF_ONE: + blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; + blendfunc.isTransparent = 1; + resolved = 1; + break; + } break; + + case video::EBF_SRC_ALPHA: + switch ( dstFact ) + { + // gl_src_alpha gl_one_minus_src_alpha + case video::EBF_ONE_MINUS_SRC_ALPHA: + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 1.f/255.f; + blendfunc.isTransparent = 1; + resolved = 1; + break; + } break; + + case 11: + // add + blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; + blendfunc.isTransparent = 1; + resolved = 1; + break; + case 12: + // filter = gl_dst_color gl_zero or gl_zero gl_src_color + blendfunc.type = video::EMT_ONETEXTURE_BLEND; + blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); + blendfunc.isTransparent = 1; + resolved = 1; + break; + case 13: + // blend = gl_src_alpha gl_one_minus_src_alpha + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 1.f/255.f; + blendfunc.isTransparent = 1; + resolved = 1; + break; + case 14: + // alphafunc ge128 + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 0.5f; + blendfunc.isTransparent = 1; + resolved = 1; + break; + case 15: + // alphafunc gt0 + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 1.f / 255.f; + blendfunc.isTransparent = 1; + resolved = 1; + break; + + } + + // use the generic blender + if ( 0 == resolved ) + { + blendfunc.type = video::EMT_ONETEXTURE_BLEND; + blendfunc.param0 = video::pack_textureBlendFunc ( + (video::E_BLEND_FACTOR) srcFact, + (video::E_BLEND_FACTOR) dstFact, + blendfunc.modulate); + + blendfunc.isTransparent = 1; + } + } + + // random noise [-1;1] + struct Noiser + { + static f32 get () + { + static u32 RandomSeed = 0x69666966; + RandomSeed = (RandomSeed * 3631 + 1); + + f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; + return value; + } + }; + + enum eQ3ModifierFunction + { + TCMOD = 0, + DEFORMVERTEXES = 1, + RGBGEN = 2, + TCGEN = 3, + MAP = 4, + ALPHAGEN = 5, + + FUNCTION2 = 0x10, + SCROLL = FUNCTION2 + 1, + SCALE = FUNCTION2 + 2, + ROTATE = FUNCTION2 + 3, + STRETCH = FUNCTION2 + 4, + TURBULENCE = FUNCTION2 + 5, + WAVE = FUNCTION2 + 6, + + IDENTITY = FUNCTION2 + 7, + VERTEX = FUNCTION2 + 8, + TEXTURE = FUNCTION2 + 9, + LIGHTMAP = FUNCTION2 + 10, + ENVIRONMENT = FUNCTION2 + 11, + DOLLAR_LIGHTMAP = FUNCTION2 + 12, + BULGE = FUNCTION2 + 13, + AUTOSPRITE = FUNCTION2 + 14, + AUTOSPRITE2 = FUNCTION2 + 15, + TRANSFORM = FUNCTION2 + 16, + EXACTVERTEX = FUNCTION2 + 17, + CONSTANT = FUNCTION2 + 18, + LIGHTINGSPECULAR = FUNCTION2 + 19, + MOVE = FUNCTION2 + 20, + NORMAL = FUNCTION2 + 21, + IDENTITYLIGHTING = FUNCTION2 + 22, + + WAVE_MODIFIER_FUNCTION = 0x30, + SINUS = WAVE_MODIFIER_FUNCTION + 1, + COSINUS = WAVE_MODIFIER_FUNCTION + 2, + SQUARE = WAVE_MODIFIER_FUNCTION + 3, + TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, + SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, + SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, + NOISE = WAVE_MODIFIER_FUNCTION + 7, + + + UNKNOWN = -2 + + }; + + struct SModifierFunction + { + SModifierFunction () + : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), + tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), + base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), + wave ( 1 ), + x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} + + // "tcmod","deformvertexes","rgbgen", "tcgen" + eQ3ModifierFunction masterfunc0; + // depends + eQ3ModifierFunction masterfunc1; + // depends + eQ3ModifierFunction func; + + eQ3ModifierFunction tcgen; + eQ3ModifierFunction rgbgen; + eQ3ModifierFunction alphagen; + + union + { + f32 base; + f32 bulgewidth; + }; + + union + { + f32 amp; + f32 bulgeheight; + }; + + f32 phase; + + union + { + f32 frequency; + f32 bulgespeed; + }; + + union + { + f32 wave; + f32 div; + }; + + f32 x; + f32 y; + f32 z; + u32 count; + + f32 evaluate ( f32 dt ) const + { + // phase in 0 and 1.. + f32 x = core::fract( (dt + phase ) * frequency ); + f32 y = 0.f; + + switch ( func ) + { + case SINUS: + y = sinf ( x * core::PI * 2.f ); + break; + case COSINUS: + y = cosf ( x * core::PI * 2.f ); + break; + case SQUARE: + y = x < 0.5f ? 1.f : -1.f; + break; + case TRIANGLE: + y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; + break; + case SAWTOOTH: + y = x; + break; + case SAWTOOTH_INVERSE: + y = 1.f - x; + break; + case NOISE: + y = Noiser::get(); + break; + default: + break; + } + + return base + ( y * amp ); + } + + + }; + + inline core::vector3df getMD3Normal ( u32 i, u32 j ) + { + const f32 lng = i * 2.0f * core::PI / 255.0f; + const f32 lat = j * 2.0f * core::PI / 255.0f; + return core::vector3df(cosf ( lat ) * sinf ( lng ), + sinf ( lat ) * sinf ( lng ), + cosf ( lng )); + } + + // + inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) + { + if ( string.size() == 0 ) + return; + + static const c8 * funclist[] = + { + "sin","cos","square", + "triangle", "sawtooth","inversesawtooth", "noise" + }; + + fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); + fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); + + fill.base = getAsFloat ( string, pos ); + fill.amp = getAsFloat ( string, pos ); + fill.phase = getAsFloat ( string, pos ); + fill.frequency = getAsFloat ( string, pos ); + } + + + // name = "a b c .." + struct SVariable + { + core::stringc name; + core::stringc content; + + SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} + virtual ~SVariable () {} + + void clear () + { + name = ""; + content = ""; + } + + s32 isValid () const + { + return name.size(); + } + + bool operator == ( const SVariable &other ) const + { + return 0 == strcmp ( name.c_str(), other.name.c_str () ); + } + + bool operator < ( const SVariable &other ) const + { + return 0 > strcmp ( name.c_str(), other.name.c_str () ); + } + + }; + + + // string database. "a" = "Hello", "b" = "1234.6" + struct SVarGroup + { + SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } + virtual ~SVarGroup () {} + + u32 isDefined ( const c8 * name, const c8 * content = 0 ) const + { + for ( u32 i = 0; i != Variable.size (); ++i ) + { + if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && + ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) + ) + { + return i + 1; + } + } + return 0; + } + + // searches for Variable name and returns is content + // if Variable is not found a reference to an Empty String is returned + const core::stringc &get( const c8 * name ) const + { + SVariable search ( name ); + s32 index = Variable.linear_search ( search ); + if ( index < 0 ) + return irrEmptyStringc; + + return Variable [ index ].content; + } + + // set the Variable name + void set ( const c8 * name, const c8 * content = 0 ) + { + u32 index = isDefined ( name, 0 ); + if ( 0 == index ) + { + Variable.push_back ( SVariable ( name, content ) ); + } + else + { + Variable [ index ].content = content; + } + } + + + core::array < SVariable > Variable; + }; + + //! holding a group a variable + struct SVarGroupList: public IReferenceCounted + { + SVarGroupList () + { + VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } + virtual ~SVarGroupList () {} + + core::array < SVarGroup > VariableGroup; + }; + + + //! A Parsed Shader Holding Variables ordered in Groups + struct IShader + { + IShader () + : ID ( 0 ), VarGroup ( 0 ) {} + virtual ~IShader () {} + + void operator = (const IShader &other ) + { + ID = other.ID; + VarGroup = other.VarGroup; + name = other.name; + } + + bool operator == (const IShader &other ) const + { + return 0 == strcmp ( name.c_str(), other.name.c_str () ); + //return name == other.name; + } + + bool operator < (const IShader &other ) const + { + return strcmp ( name.c_str(), other.name.c_str () ) < 0; + //return name < other.name; + } + + u32 getGroupSize () const + { + if ( 0 == VarGroup ) + return 0; + return VarGroup->VariableGroup.size (); + } + + const SVarGroup * getGroup ( u32 stage ) const + { + if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) + return 0; + + return &VarGroup->VariableGroup [ stage ]; + } + + // id + s32 ID; + SVarGroupList *VarGroup; // reference + + // Shader: shader name ( also first variable in first Vargroup ) + // Entity: classname ( variable in Group(1) ) + core::stringc name; + }; + + typedef IShader IEntity; + + typedef core::array < IEntity > tQ3EntityList; + + /* + dump shader like original layout, regardless of internal data holding + no recursive folding.. + */ + inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack ) + { + core::stringc buf; + s32 i; + + + if ( stack > 0 ) + { + buf = ""; + for ( i = 0; i < stack - 1; ++i ) + buf += '\t'; + + buf += "{\n"; + dest.append ( buf ); + } + + for ( u32 g = 0; g != group->Variable.size(); ++g ) + { + buf = ""; + for ( i = 0; i < stack; ++i ) + buf += '\t'; + + buf += group->Variable[g].name; + buf += " "; + buf += group->Variable[g].content; + buf += "\n"; + dest.append ( buf ); + } + + if ( stack > 1 ) + { + buf = ""; + for ( i = 0; i < stack - 1; ++i ) + buf += '\t'; + + buf += "}\n"; + dest.append ( buf ); + } + + } + + /*! + dump a Shader or an Entity + */ + inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) + { + if ( 0 == shader ) + return dest; + + const SVarGroup * group; + + const u32 size = shader->VarGroup->VariableGroup.size (); + for ( u32 i = 0; i != size; ++i ) + { + group = &shader->VarGroup->VariableGroup[ i ]; + dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); + } + + if ( !entity ) + { + if ( size <= 1 ) + { + dest.append ( "{\n" ); + } + dest.append ( "}\n" ); + } + return dest; + } + + + /* + quake3 doesn't care much about tga & jpg + load one or multiple files stored in name started at startPos to the texture array textures + if texture is not loaded 0 will be added ( to find missing textures easier) + */ + inline void getTextures(tTexArray &textures, + const core::stringc &name, u32 &startPos, + io::IFileSystem *fileSystem, + video::IVideoDriver* driver) + { + static const char* extension[] = + { + ".jpg", + ".jpeg", + ".png", + ".dds", + ".tga", + ".bmp", + ".pcx" + }; + + tStringList stringList; + getAsStringList(stringList, -1, name, startPos); + + textures.clear(); + + io::path loadFile; + for ( u32 i = 0; i!= stringList.size (); ++i ) + { + video::ITexture* texture = 0; + for (u32 g = 0; g != 7 ; ++g) + { + core::cutFilenameExtension ( loadFile, stringList[i] ); + + if ( loadFile == "$whiteimage" ) + { + texture = driver->getTexture( "$whiteimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$whiteimage", w ); + w->drop (); + } + + } + else + if ( loadFile == "$redimage" ) + { + texture = driver->getTexture( "$redimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$redimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$blueimage" ) + { + texture = driver->getTexture( "$blueimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$blueimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$checkerimage" ) + { + texture = driver->getTexture( "$checkerimage" ); + if ( 0 == texture ) + { + core::dimension2du s ( 2, 2 ); + u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; + video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); + texture = driver->addTexture( "$checkerimage", w ); + w->drop (); + } + } + else + if ( loadFile == "$lightmap" ) + { + texture = 0; + } + else + { + loadFile.append ( extension[g] ); + } + + if ( fileSystem->existFile ( loadFile ) ) + { + texture = driver->getTexture( loadFile ); + if ( texture ) + break; + texture = 0; + } + } + // take 0 Texture + textures.push_back(texture); + } + } + + + //! Manages various Quake3 Shader Styles + class IShaderManager : public IReferenceCounted + { + }; + +} // end namespace quake3 +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IRandomizer.h b/inc/IRandomizer.h new file mode 100644 index 0000000..2d7d1d8 --- /dev/null +++ b/inc/IRandomizer.h @@ -0,0 +1,33 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_RANDOMIZER_H_INCLUDED__ +#define __I_RANDOMIZER_H_INCLUDED__ + +#include "IReferenceCounted.h" + +namespace irr +{ + +//! Interface for generating random numbers +class IRandomizer : public virtual IReferenceCounted +{ +public: + //! resets the randomizer + /** \param value Initialization value (seed) */ + virtual void reset(s32 value=0x0f0f0f0f) =0; + + //! generates a pseudo random number in the range 0..randMax() + virtual s32 rand() const =0; + + //! generates a pseudo random number in the range 0..1 + virtual f32 frand() const =0; + + //! get maxmimum number generated by rand() + virtual s32 randMax() const =0; +}; + +} // end namespace irr + +#endif diff --git a/inc/IReadFile.h b/inc/IReadFile.h new file mode 100644 index 0000000..eb4f0bd --- /dev/null +++ b/inc/IReadFile.h @@ -0,0 +1,58 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_READ_FILE_H_INCLUDED__ +#define __I_READ_FILE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "coreutil.h" + +namespace irr +{ +namespace io +{ + + //! Interface providing read acess to a file. + class IReadFile : public virtual IReferenceCounted + { + public: + //! Reads an amount of bytes from the file. + /** \param buffer Pointer to buffer where read bytes are written to. + \param sizeToRead Amount of bytes to read from the file. + \return How many bytes were read. */ + virtual s32 read(void* buffer, u32 sizeToRead) = 0; + + //! Changes position in file + /** \param finalPos Destination position in the file. + \param relativeMovement If set to true, the position in the file is + changed relative to current position. Otherwise the position is changed + from beginning of file. + \return True if successful, otherwise false. */ + virtual bool seek(long finalPos, bool relativeMovement = false) = 0; + + //! Get size of file. + /** \return Size of the file in bytes. */ + virtual long getSize() const = 0; + + //! Get the current position in the file. + /** \return Current position in the file in bytes. */ + virtual long getPos() const = 0; + + //! Get name of file. + /** \return File name as zero terminated character string. */ + virtual const io::path& getFileName() const = 0; + }; + + //! Internal function, please do not use. + IReadFile* createReadFile(const io::path& fileName); + //! Internal function, please do not use. + IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); + //! Internal function, please do not use. + IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped); + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IReferenceCounted.h b/inc/IReferenceCounted.h new file mode 100644 index 0000000..0eb23a5 --- /dev/null +++ b/inc/IReferenceCounted.h @@ -0,0 +1,170 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_IREFERENCE_COUNTED_H_INCLUDED__ +#define __I_IREFERENCE_COUNTED_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ + + //! Base class of most objects of the Irrlicht Engine. + /** This class provides reference counting through the methods grab() and drop(). + It also is able to store a debug string for every instance of an object. + Most objects of the Irrlicht + Engine are derived from IReferenceCounted, and so they are reference counted. + + When you create an object in the Irrlicht engine, calling a method + which starts with 'create', an object is created, and you get a pointer + to the new object. If you no longer need the object, you have + to call drop(). This will destroy the object, if grab() was not called + in another part of you program, because this part still needs the object. + Note, that you only need to call drop() to the object, if you created it, + and the method had a 'create' in it. + + A simple example: + + If you want to create a texture, you may want to call an imaginable method + IDriver::createTexture. You call + ITexture* texture = driver->createTexture(dimension2d(128, 128)); + If you no longer need the texture, call texture->drop(). + + If you want to load a texture, you may want to call imaginable method + IDriver::loadTexture. You do this like + ITexture* texture = driver->loadTexture("example.jpg"); + You will not have to drop the pointer to the loaded texture, because + the name of the method does not start with 'create'. The texture + is stored somewhere by the driver. + */ + class IReferenceCounted + { + public: + + //! Constructor. + IReferenceCounted() + : DebugName(0), ReferenceCounter(1) + { + } + + //! Destructor. + virtual ~IReferenceCounted() + { + } + + //! Grabs the object. Increments the reference counter by one. + /** Someone who calls grab() to an object, should later also + call drop() to it. If an object never gets as much drop() as + grab() calls, it will never be destroyed. The + IReferenceCounted class provides a basic reference counting + mechanism with its methods grab() and drop(). Most objects of + the Irrlicht Engine are derived from IReferenceCounted, and so + they are reference counted. + + When you create an object in the Irrlicht engine, calling a + method which starts with 'create', an object is created, and + you get a pointer to the new object. If you no longer need the + object, you have to call drop(). This will destroy the object, + if grab() was not called in another part of you program, + because this part still needs the object. Note, that you only + need to call drop() to the object, if you created it, and the + method had a 'create' in it. + + A simple example: + + If you want to create a texture, you may want to call an + imaginable method IDriver::createTexture. You call + ITexture* texture = driver->createTexture(dimension2d(128, 128)); + If you no longer need the texture, call texture->drop(). + If you want to load a texture, you may want to call imaginable + method IDriver::loadTexture. You do this like + ITexture* texture = driver->loadTexture("example.jpg"); + You will not have to drop the pointer to the loaded texture, + because the name of the method does not start with 'create'. + The texture is stored somewhere by the driver. */ + void grab() const { ++ReferenceCounter; } + + //! Drops the object. Decrements the reference counter by one. + /** The IReferenceCounted class provides a basic reference + counting mechanism with its methods grab() and drop(). Most + objects of the Irrlicht Engine are derived from + IReferenceCounted, and so they are reference counted. + + When you create an object in the Irrlicht engine, calling a + method which starts with 'create', an object is created, and + you get a pointer to the new object. If you no longer need the + object, you have to call drop(). This will destroy the object, + if grab() was not called in another part of you program, + because this part still needs the object. Note, that you only + need to call drop() to the object, if you created it, and the + method had a 'create' in it. + + A simple example: + + If you want to create a texture, you may want to call an + imaginable method IDriver::createTexture. You call + ITexture* texture = driver->createTexture(dimension2d(128, 128)); + If you no longer need the texture, call texture->drop(). + If you want to load a texture, you may want to call imaginable + method IDriver::loadTexture. You do this like + ITexture* texture = driver->loadTexture("example.jpg"); + You will not have to drop the pointer to the loaded texture, + because the name of the method does not start with 'create'. + The texture is stored somewhere by the driver. + \return True, if the object was deleted. */ + bool drop() const + { + // someone is doing bad reference counting. + _IRR_DEBUG_BREAK_IF(ReferenceCounter <= 0) + + --ReferenceCounter; + if (!ReferenceCounter) + { + delete this; + return true; + } + + return false; + } + + //! Get the reference count. + /** \return Current value of the reference counter. */ + s32 getReferenceCount() const + { + return ReferenceCounter; + } + + //! Returns the debug name of the object. + /** The Debugname may only be set and changed by the object + itself. This method should only be used in Debug mode. + \return Returns a string, previously set by setDebugName(); */ + const c8* getDebugName() const + { + return DebugName; + } + + protected: + + //! Sets the debug name of the object. + /** The Debugname may only be set and changed by the object + itself. This method should only be used in Debug mode. + \param newName: New debug name to set. */ + void setDebugName(const c8* newName) + { + DebugName = newName; + } + + private: + + //! The debug name. + const c8* DebugName; + + //! The reference counter. Mutable to do reference counting on const objects. + mutable s32 ReferenceCounter; + }; + +} // end namespace irr + +#endif + diff --git a/inc/ISceneCollisionManager.h b/inc/ISceneCollisionManager.h new file mode 100644 index 0000000..726936a --- /dev/null +++ b/inc/ISceneCollisionManager.h @@ -0,0 +1,205 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_COLLISION_MANAGER_H_INCLUDED__ +#define __I_SCENE_COLLISION_MANAGER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "vector3d.h" +#include "triangle3d.h" +#include "position2d.h" +#include "line3d.h" + +namespace irr +{ + +namespace scene +{ + class ISceneNode; + class ICameraSceneNode; + class ITriangleSelector; + + //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. + class ISceneCollisionManager : public virtual IReferenceCounted + { + public: + + //! Finds the nearest collision point of a line and lots of triangles, if there is one. + /** \param ray: Line with which collisions are tested. + \param selector: TriangleSelector containing the triangles. It + can be created for example using + ISceneManager::createTriangleSelector() or + ISceneManager::createTriangleOctreeSelector(). + \param outCollisionPoint: If a collision is detected, this will + contain the position of the nearest collision to the line-start. + \param outTriangle: If a collision is detected, this will + contain the triangle with which the ray collided. + \param outNode: If a collision is detected, this will contain + the scene node associated with the triangle that was hit. + \return True if a collision was detected and false if not. */ + virtual bool getCollisionPoint(const core::line3d& ray, + ITriangleSelector* selector, core::vector3df& outCollisionPoint, + core::triangle3df& outTriangle, ISceneNode*& outNode) =0; + + //! Collides a moving ellipsoid with a 3d world with gravity and returns the resulting new position of the ellipsoid. + /** This can be used for moving a character in a 3d world: The + character will slide at walls and is able to walk up stairs. + The method used how to calculate the collision result position + is based on the paper "Improved Collision detection and + Response" by Kasper Fauerby. + \param selector: TriangleSelector containing the triangles of + the world. It can be created for example using + ISceneManager::createTriangleSelector() or + ISceneManager::createTriangleOctreeSelector(). + \param ellipsoidPosition: Position of the ellipsoid. + \param ellipsoidRadius: Radius of the ellipsoid. + \param ellipsoidDirectionAndSpeed: Direction and speed of the + movement of the ellipsoid. + \param triout: Optional parameter where the last triangle + causing a collision is stored, if there is a collision. + \param hitPosition: Return value for the position of the collision + \param outFalling: Is set to true if the ellipsoid is falling + down, caused by gravity. + \param outNode: the node with which the ellipoid collided (if any) + \param slidingSpeed: DOCUMENTATION NEEDED. + \param gravityDirectionAndSpeed: Direction and force of gravity. + \return New position of the ellipsoid. */ + virtual core::vector3df getCollisionResultPosition( + ITriangleSelector* selector, + const core::vector3df &ellipsoidPosition, + const core::vector3df& ellipsoidRadius, + const core::vector3df& ellipsoidDirectionAndSpeed, + core::triangle3df& triout, + core::vector3df& hitPosition, + bool& outFalling, + ISceneNode*& outNode, + f32 slidingSpeed = 0.0005f, + const core::vector3df& gravityDirectionAndSpeed + = core::vector3df(0.0f, 0.0f, 0.0f)) = 0; + + //! Returns a 3d ray which would go through the 2d screen coodinates. + /** \param pos: Screen coordinates in pixels. + \param camera: Camera from which the ray starts. If null, the + active camera is used. + \return Ray starting from the position of the camera and ending + at a length of the far value of the camera at a position which + would be behind the 2d screen coodinates. */ + virtual core::line3d getRayFromScreenCoordinates( + const core::position2d& pos, ICameraSceneNode* camera = 0) = 0; + + //! Calculates 2d screen position from a 3d position. + /** \param pos: 3D position in world space to be transformed + into 2d. + \param camera: Camera to be used. If null, the currently active + camera is used. + \param useViewPort: Calculate screen coordinates relative to + the current view port. Please note that unless the driver does + not take care of the view port, it is usually best to get the + result in absolute screen coordinates (flag=false). + \return 2d screen coordinates which a object in the 3d world + would have if it would be rendered to the screen. If the 3d + position is behind the camera, it is set to (-1000,-1000). In + most cases you can ignore this fact, because if you use this + method for drawing a decorator over a 3d object, it will be + clipped by the screen borders. */ + virtual core::position2d getScreenCoordinatesFrom3DPosition( + const core::vector3df& pos, ICameraSceneNode* camera=0, bool useViewPort=false) = 0; + + //! Gets the scene node, which is currently visible under the given screencoordinates, viewed from the currently active camera. + /** The collision tests are done using a bounding box for each + scene node. You can limit the recursive search so just all children of the specified root are tested. + \param pos: Position in pixel screen coordinates, under which + the returned scene node will be. + \param idBitMask: Only scene nodes with an id with bits set + like in this mask will be tested. If the BitMask is 0, this + feature is disabled. + Please note that the default node id of -1 will match with + every bitmask != 0 + \param bNoDebugObjects: Doesn't take debug objects into account + when true. These are scene nodes with IsDebugObject() = true. + \param root If different from 0, the search is limited to the children of this node. + \return Visible scene node under screen coordinates with + matching bits in its id. If there is no scene node under this + position, 0 is returned. */ + virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; + + //! Returns the nearest scene node which collides with a 3d ray and whose id matches a bitmask. + /** The collision tests are done using a bounding box for each + scene node. The recursive search can be limited be specifying a scene node. + \param ray Line with which collisions are tested. + \param idBitMask Only scene nodes with an id which matches at + least one of the bits contained in this mask will be tested. + However, if this parameter is 0, then all nodes are checked. + \param bNoDebugObjects: Doesn't take debug objects into account when true. These + are scene nodes with IsDebugObject() = true. + \param root If different from 0, the search is limited to the children of this node. + \return Scene node nearest to ray.start, which collides with + the ray and matches the idBitMask, if the mask is not null. If + no scene node is found, 0 is returned. */ + virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; + + //! Get the scene node, which the given camera is looking at and whose id matches the bitmask. + /** A ray is simply casted from the position of the camera to + the view target position, and all scene nodes are tested + against this ray. The collision tests are done using a bounding + box for each scene node. + \param camera: Camera from which the ray is casted. + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then + all nodes are checked. + feature is disabled. + Please note that the default node id of -1 will match with + every bitmask != 0 + \param bNoDebugObjects: Doesn't take debug objects into account + when true. These are scene nodes with IsDebugObject() = true. + \return Scene node nearest to the camera, which collides with + the ray and matches the idBitMask, if the mask is not null. If + no scene node is found, 0 is returned. */ + virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, + s32 idBitMask=0, bool bNoDebugObjects = false) = 0; + + //! Perform a ray/box and ray/triangle collision check on a heirarchy of scene nodes. + /** This checks all scene nodes under the specified one, first by ray/bounding + box, and then by accurate ray/triangle collision, finding the nearest collision, + and the scene node containg it. It returns the node hit, and (via output + parameters) the position of the collision, and the triangle that was hit. + + All scene nodes in the hierarchy tree under the specified node are checked. Only + nodes that are visible, with an ID that matches at least one bit in the supplied + bitmask, and which have a triangle selector are considered as candidates for being hit. + You do not have to build a meta triangle selector; the individual triangle selectors + of each candidate scene node are used automatically. + + \param ray: Line with which collisions are tested. + \param outCollisionPoint: If a collision is detected, this will contain the + position of the nearest collision. + \param outTriangle: If a collision is detected, this will contain the triangle + with which the ray collided. + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then + all nodes are checked. + \param collisionRootNode: the scene node at which to begin checking. Only this + node and its children will be checked. If you want to check the entire scene, + pass 0, and the root scene node will be used (this is the default). + \param noDebugObjects: when true, debug objects are not considered viable targets. + Debug objects are scene nodes with IsDebugObject() = true. + \return Returns the scene node containing the hit triangle nearest to ray.start. + If no collision is detected, then 0 is returned. */ + virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( + core::line3df ray, + core::vector3df & outCollisionPoint, + core::triangle3df & outTriangle, + s32 idBitMask = 0, + ISceneNode * collisionRootNode = 0, + bool noDebugObjects = false) = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneLoader.h b/inc/ISceneLoader.h new file mode 100644 index 0000000..45a80f3 --- /dev/null +++ b/inc/ISceneLoader.h @@ -0,0 +1,62 @@ +// Copyright (C) 2010-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_LOADER_H_INCLUDED__ +#define __I_SCENE_LOADER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "path.h" + +namespace irr +{ +namespace io +{ + class IReadFile; +} // end namespace io +namespace scene +{ + class ISceneNode; + class ISceneUserDataSerializer; + +//! Class which can load a scene into the scene manager. +/** If you want Irrlicht to be able to load currently unsupported +scene file formats (e.g. .vrml), then implement this and add your +new Sceneloader to the engine with ISceneManager::addExternalSceneLoader(). */ +class ISceneLoader : public virtual IReferenceCounted +{ +public: + + //! Returns true if the class might be able to load this file. + /** This decision should be based on the file extension (e.g. ".vrml") + only. + \param filename Name of the file to test. + \return True if the extension is a recognised type. */ + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; + + //! Returns true if the class might be able to load this file. + /** This decision will be based on a quick look at the contents of the file. + \param file The file to test. + \return True if the extension is a recognised type. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const = 0; + + //! Loads the scene into the scene manager. + /** \param file File which contains the scene. + \param userDataSerializer: If you want to load user data which may be attached + to some some scene nodes in the file, implement the ISceneUserDataSerializer + interface and provide it as parameter here. Otherwise, simply specify 0 as this + parameter. + \param rootNode The node to load the scene into, if none is provided then the + scene will be loaded into the root node. + \return Returns true on success, false on failure. Returns 0 if loading failed. */ + virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, + ISceneNode* rootNode=0) = 0; + +}; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneManager.h b/inc/ISceneManager.h new file mode 100644 index 0000000..8041348 --- /dev/null +++ b/inc/ISceneManager.h @@ -0,0 +1,1663 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_MANAGER_H_INCLUDED__ +#define __I_SCENE_MANAGER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "irrString.h" +#include "path.h" +#include "vector3d.h" +#include "dimension2d.h" +#include "SColor.h" +#include "ETerrainElements.h" +#include "ESceneNodeTypes.h" +#include "ESceneNodeAnimatorTypes.h" +#include "EMeshWriterEnums.h" +#include "SceneParameters.h" +#include "IGeometryCreator.h" +#include "ISkinnedMesh.h" + +namespace irr +{ + struct SKeyMap; + struct SEvent; + +namespace io +{ + class IReadFile; + class IAttributes; + class IWriteFile; + class IFileSystem; +} // end namespace io + +namespace gui +{ + class IGUIFont; + class IGUIEnvironment; +} // end namespace gui + +namespace video +{ + class IVideoDriver; + class SMaterial; + class IImage; + class ITexture; +} // end namespace video + +namespace scene +{ + //! Enumeration for render passes. + /** A parameter passed to the registerNodeForRendering() method of the ISceneManager, + specifying when the node wants to be drawn in relation to the other nodes. */ + enum E_SCENE_NODE_RENDER_PASS + { + //! No pass currently active + ESNRP_NONE =0, + + //! Camera pass. The active view is set up here. The very first pass. + ESNRP_CAMERA =1, + + //! In this pass, lights are transformed into camera space and added to the driver + ESNRP_LIGHT =2, + + //! This is used for sky boxes. + ESNRP_SKY_BOX =4, + + //! All normal objects can use this for registering themselves. + /** This value will never be returned by + ISceneManager::getSceneNodeRenderPass(). The scene manager + will determine by itself if an object is transparent or solid + and register the object as SNRT_TRANSPARENT or SNRT_SOLD + automatically if you call registerNodeForRendering with this + value (which is default). Note that it will register the node + only as ONE type. If your scene node has both solid and + transparent material types register it twice (one time as + SNRT_SOLID, the other time as SNRT_TRANSPARENT) and in the + render() method call getSceneNodeRenderPass() to find out the + current render pass and render only the corresponding parts of + the node. */ + ESNRP_AUTOMATIC =24, + + //! Solid scene nodes or special scene nodes without materials. + ESNRP_SOLID =8, + + //! Transparent scene nodes, drawn after solid nodes. They are sorted from back to front and drawn in that order. + ESNRP_TRANSPARENT =16, + + //! Transparent effect scene nodes, drawn after Transparent nodes. They are sorted from back to front and drawn in that order. + ESNRP_TRANSPARENT_EFFECT =32, + + //! Drawn after the solid nodes, before the transparent nodes, the time for drawing shadow volumes + ESNRP_SHADOW =64 + }; + + class IAnimatedMesh; + class IAnimatedMeshSceneNode; + class IBillboardSceneNode; + class IBillboardTextSceneNode; + class ICameraSceneNode; + class IDummyTransformationSceneNode; + class ILightManager; + class ILightSceneNode; + class IMesh; + class IMeshBuffer; + class IMeshCache; + class IMeshLoader; + class IMeshManipulator; + class IMeshSceneNode; + class IMeshWriter; + class IMetaTriangleSelector; + class IParticleSystemSceneNode; + class ISceneCollisionManager; + class ISceneLoader; + class ISceneNode; + class ISceneNodeAnimator; + class ISceneNodeAnimatorCollisionResponse; + class ISceneNodeAnimatorFactory; + class ISceneNodeFactory; + class ISceneUserDataSerializer; + class ITerrainSceneNode; + class ITextSceneNode; + class ITriangleSelector; + class IVolumeLightSceneNode; + + namespace quake3 + { + struct IShader; + } // end namespace quake3 + + //! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. + /** All Scene nodes can be created only here. There is a always growing + list of scene nodes for lots of purposes: Indoor rendering scene nodes + like the Octree (addOctreeSceneNode()) or the terrain renderer + (addTerrainSceneNode()), different Camera scene nodes + (addCameraSceneNode(), addCameraSceneNodeMaya()), scene nodes for Light + (addLightSceneNode()), Billboards (addBillboardSceneNode()) and so on. + A scene node is a node in the hierachical scene graph. Every scene node + may have children, which are other scene nodes. Children move relative + the their parents position. If the parent of a node is not visible, its + children won't be visible, too. In this way, it is for example easily + possible to attach a light to a moving car or to place a walking + character on a moving platform on a moving ship. + The SceneManager is also able to load 3d mesh files of different + formats. Take a look at getMesh() to find out what formats are + supported. If these formats are not enough, use + addExternalMeshLoader() to add new formats to the engine. + */ + class ISceneManager : public virtual IReferenceCounted + { + public: + + //! Get pointer to an animateable mesh. Loads the file if not loaded already. + /** + * If you want to remove a loaded mesh from the cache again, use removeMesh(). + * Currently there are the following mesh formats supported: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FormatDescription
3D Studio (.3ds)Loader for 3D-Studio files which lots of 3D packages + * are able to export. Only static meshes are currently + * supported by this importer.
3D World Studio (.smf)Loader for Leadwerks SMF mesh files, a simple mesh format + * containing static geometry for games. The proprietary .STF texture format + * is not supported yet. This loader was originally written by Joseph Ellis.
Bliz Basic B3D (.b3d)Loader for blitz basic files, developed by Mark + * Sibly. This is the ideal animated mesh format for game + * characters as it is both rigidly defined and widely + * supported by modeling and animation software. + * As this format supports skeletal animations, an + * ISkinnedMesh will be returned by this importer.
Cartography shop 4 (.csm)Cartography Shop is a modeling program for creating + * architecture and calculating lighting. Irrlicht can + * directly import .csm files thanks to the IrrCSM library + * created by Saurav Mohapatra which is now integrated + * directly in Irrlicht. If you are using this loader, + * please note that you'll have to set the path of the + * textures before loading .csm files. You can do this + * using + * SceneManager->getParameters()->setAttribute(scene::CSM_TEXTURE_PATH, + * "path/to/your/textures");
COLLADA (.dae, .xml)COLLADA is an open Digital Asset Exchange Schema for + * the interactive 3D industry. There are exporters and + * importers for this format available for most of the + * big 3d packagesat http://collada.org. Irrlicht can + * import COLLADA files by using the + * ISceneManager::getMesh() method. COLLADA files need + * not contain only one single mesh but multiple meshes + * and a whole scene setup with lights, cameras and mesh + * instances, this loader can set up a scene as + * described by the COLLADA file instead of loading and + * returning one single mesh. By default, this loader + * behaves like the other loaders and does not create + * instances, but it can be switched into this mode by + * using + * SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, true); + * Created scene nodes will be named as the names of the + * nodes in the COLLADA file. The returned mesh is just + * a dummy object in this mode. Meshes included in the + * scene will be added into the scene manager with the + * following naming scheme: + * "path/to/file/file.dea#meshname". The loading of such + * meshes is logged. Currently, this loader is able to + + + * create meshes (made of only polygons), lights, and + * cameras. Materials and animations are currently not + * supported but this will change with future releases. + *
Delgine DeleD (.dmf)DeleD (delgine.com) is a 3D editor and level-editor + * combined into one and is specifically designed for 3D + * game-development. With this loader, it is possible to + * directly load all geometry is as well as textures and + * lightmaps from .dmf files. To set texture and + * material paths, see scene::DMF_USE_MATERIALS_DIRS and + * scene::DMF_TEXTURE_PATH. It is also possible to flip + * the alpha texture by setting + * scene::DMF_FLIP_ALPHA_TEXTURES to true and to set the + * material transparent reference value by setting + * scene::DMF_ALPHA_CHANNEL_REF to a float between 0 and + * 1. The loader is based on Salvatore Russo's .dmf + * loader, I just changed some parts of it. Thanks to + * Salvatore for his work and for allowing me to use his + * code in Irrlicht and put it under Irrlicht's license. + * For newer and more enchanced versions of the loader, + * take a look at delgine.com. + *
DirectX (.x)Platform independent importer (so not D3D-only) for + * .x files. Most 3D packages can export these natively + * and there are several tools for them available, e.g. + * the Maya exporter included in the DX SDK. + * .x files can include skeletal animations and Irrlicht + * is able to play and display them, users can manipulate + * the joints via the ISkinnedMesh interface. Currently, + * Irrlicht only supports uncompressed .x files.
Half-Life model (.mdl)This loader opens Half-life 1 models, it was contributed + * by Fabio Concas and adapted by Thomas Alten.
Irrlicht Mesh (.irrMesh)This is a static mesh format written in XML, native + * to Irrlicht and written by the irr mesh writer. + * This format is exported by the CopperCube engine's + * lightmapper.
LightWave (.lwo)Native to NewTek's LightWave 3D, the LWO format is well + * known and supported by many exporters. This loader will + * import LWO2 models including lightmaps, bumpmaps and + * reflection textures.
Maya (.obj)Most 3D software can create .obj files which contain + * static geometry without material data. The material + * files .mtl are also supported. This importer for + * Irrlicht can load them directly.
Milkshape (.ms3d).MS3D files contain models and sometimes skeletal + * animations from the Milkshape 3D modeling and animation + * software. Like the other skeletal mesh loaders, oints + * are exposed via the ISkinnedMesh animated mesh type.
My3D (.my3d).my3D is a flexible 3D file format. The My3DTools + * contains plug-ins to export .my3D files from several + * 3D packages. With this built-in importer, Irrlicht + * can read and display those files directly. This + * loader was written by Zhuck Dimitry who also created + * the whole My3DTools package. If you are using this + * loader, please note that you can set the path of the + * textures before loading .my3d files. You can do this + * using + * SceneManager->getParameters()->setAttribute(scene::MY3D_TEXTURE_PATH, + * "path/to/your/textures"); + *
OCT (.oct)The oct file format contains 3D geometry and + * lightmaps and can be loaded directly by Irrlicht. OCT + * files
can be created by FSRad, Paul Nette's + * radiosity processor or exported from Blender using + * OCTTools which can be found in the exporters/OCTTools + * directory of the SDK. Thanks to Murphy McCauley for + * creating all this.
OGRE Meshes (.mesh)Ogre .mesh files contain 3D data for the OGRE 3D + * engine. Irrlicht can read and display them directly + * with this importer. To define materials for the mesh, + * copy a .material file named like the corresponding + * .mesh file where the .mesh file is. (For example + * ogrehead.material for ogrehead.mesh). Thanks to + * Christian Stehno who wrote and contributed this + * loader.
Pulsar LMTools (.lmts)LMTools is a set of tools (Windows & Linux) for + * creating lightmaps. Irrlicht can directly read .lmts + * files thanks to
the importer created by Jonas + * Petersen. If you are using this loader, please note + * that you can set the path of the textures before + * loading .lmts files. You can do this using + * SceneManager->getParameters()->setAttribute(scene::LMTS_TEXTURE_PATH, + * "path/to/your/textures"); + * Notes for
this version of the loader:
+ * - It does not recognise/support user data in the + * *.lmts files.
+ * - The TGAs generated by LMTools don't work in + * Irrlicht for some reason (the textures are upside + * down). Opening and resaving them in a graphics app + * will solve the problem.
Quake 3 levels (.bsp)Quake 3 is a popular game by IDSoftware, and .pk3 + * files contain .bsp files and textures/lightmaps + * describing huge prelighted levels. Irrlicht can read + * .pk3 and .bsp files directly and thus render Quake 3 + * levels directly. Written by Nikolaus Gebhardt + * enhanced by Dean P. Macri with the curved surfaces + * feature.
Quake 2 models (.md2)Quake 2 models are characters with morph target + * animation. Irrlicht can read, display and animate + * them directly with this importer.
Quake 3 models (.md3)Quake 3 models are characters with morph target + * animation, they contain mount points for weapons and body + * parts and are typically made of several sections which are + * manually joined together.
Stanford Triangle (.ply)Invented by Stanford University and known as the native + * format of the infamous "Stanford Bunny" model, this is a + * popular static mesh format used by 3D scanning hardware + * and software. This loader supports extremely large models + * in both ASCII and binary format, but only has rudimentary + * material support in the form of vertex colors and texture + * coordinates.
Stereolithography (.stl)The STL format is used for rapid prototyping and + * computer-aided manufacturing, thus has no support for + * materials.
+ * + * To load and display a mesh quickly, just do this: + * \code + * SceneManager->addAnimatedMeshSceneNode( + * SceneManager->getMesh("yourmesh.3ds")); + * \endcode + * If you would like to implement and add your own file format loader to Irrlicht, + * see addExternalMeshLoader(). + * \param filename: Filename of the mesh to load. + * \return Null if failed, otherwise pointer to the mesh. + * This pointer should not be dropped. See IReferenceCounted::drop() for more information. + **/ + virtual IAnimatedMesh* getMesh(const io::path& filename) = 0; + + //! Get pointer to an animateable mesh. Loads the file if not loaded already. + /** Works just as getMesh(const char* filename). If you want to + remove a loaded mesh from the cache again, use removeMesh(). + \param file File handle of the mesh to load. + \return NULL if failed and pointer to the mesh if successful. + This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0; + + //! Get interface to the mesh cache which is shared beween all existing scene managers. + /** With this interface, it is possible to manually add new loaded + meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate + through already loaded meshes. */ + virtual IMeshCache* getMeshCache() = 0; + + //! Get the video driver. + /** \return Pointer to the video Driver. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual video::IVideoDriver* getVideoDriver() = 0; + + //! Get the active GUIEnvironment + /** \return Pointer to the GUIEnvironment + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; + + //! Get the active FileSystem + /** \return Pointer to the FileSystem + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual io::IFileSystem* getFileSystem() = 0; + + //! adds Volume Lighting Scene Node. + /** Example Usage: + scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, + 32, 32, //Subdivide U/V + video::SColor(0, 180, 180, 180), //foot color + video::SColor(0, 0, 0, 0) //tail color + ); + if (n) + { + n->setScale(core::vector3df(46.0f, 45.0f, 46.0f)); + n->getMaterial(0).setTexture(0, smgr->getVideoDriver()->getTexture("lightFalloff.png")); + } + \return Pointer to the volumeLight if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IVolumeLightSceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, + const u32 subdivU = 32, const u32 subdivV = 32, + const video::SColor foot = video::SColor(51, 0, 230, 180), + const video::SColor tail = video::SColor(0, 0, 0, 0), + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a cube scene node + /** \param size: Size of the cube, uniformly in each dimension. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent + where the scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Pointer to the created test scene node. This + pointer should not be dropped. See IReferenceCounted::drop() + for more information. */ + virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a sphere scene node of the given radius and detail + /** \param radius: Radius of the sphere. + \param polyCount: The number of vertices in horizontal and + vertical direction. The total polyCount of the sphere is + polyCount*polyCount. This parameter must be less than 256 to + stay within the 16-bit limit of the indices of a meshbuffer. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent + where the scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Pointer to the created test scene node. This + pointer should not be dropped. See IReferenceCounted::drop() + for more information. */ + virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a scene node for rendering an animated mesh model. + /** \param mesh: Pointer to the loaded animated mesh to be displayed. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), + bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering a static mesh. + /** \param mesh: Pointer to the loaded static mesh to be displayed. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), + bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering a animated water surface mesh. + /** Looks really good when the Material type EMT_TRANSPARENT_REFLECTION + is used. + \param waveHeight: Height of the water waves. + \param waveSpeed: Speed of the water waves. + \param waveLength: Lenght of a water wave. + \param mesh: Pointer to the loaded static mesh to be displayed with water waves on it. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, + f32 waveHeight=2.0f, f32 waveSpeed=300.0f, f32 waveLength=10.0f, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + + //! Adds a scene node for rendering using a octree to the scene graph. + /** This a good method for rendering + scenes with lots of geometry. The Octree is built on the fly from the mesh. + \param mesh: The mesh containing all geometry from which the octree will be build. + If this animated mesh has more than one frames in it, the first frame is taken. + \param parent: Parent node of the octree node. + \param id: id of the node. This id can be used to identify the node. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys than this value it will not be split into + smaller nodes. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Pointer to the Octree if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. This method may be removed by Irrlicht 1.9. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + + //! Adds a scene node for rendering using a octree to the scene graph. + /** This a good method for rendering scenes with lots of + geometry. The Octree is built on the fly from the mesh, much + faster then a bsp tree. + \param mesh: The mesh containing all geometry from which the octree will be build. + \param parent: Parent node of the octree node. + \param id: id of the node. This id can be used to identify the node. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys than this value it will not be split into + smaller nodes. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Pointer to the octree if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. This method may be removed by Irrlicht 1.9. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + + //! Adds a camera scene node to the scene graph and sets it as active camera. + /** This camera does not react on user input like for example the one created with + addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the + ISceneNode::setPosition(), ICameraSceneNode::setTarget() etc methods. + By default, a camera's look at position (set with setTarget()) and its scene node + rotation (set with setRotation()) are independent. If you want to be able to + control the direction that the camera looks by using setRotation() then call + ICameraSceneNode::bindTargetAndRotation(true) on it. + \param position: Position of the space relative to its parent where the camera will be placed. + \param lookat: Position where the camera will look at. Also known as target. + \param parent: Parent scene node of the camera. Can be null. If the parent moves, + the camera will move too. + \param id: id of the camera. This id can be used to identify the camera. + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active camera. + \return Pointer to interface to camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& lookat = core::vector3df(0,0,100), + s32 id=-1, bool makeActive=true) = 0; + + //! Adds a maya style user controlled camera scene node to the scene graph. + /** This is a standard camera with an animator that provides mouse control similar + to camera in the 3D Software Maya by Alias Wavefront. + The camera does not react on setPosition anymore after applying this animator. Instead + use setTarget, to fix the target the camera the camera hovers around. And setDistance + to set the current distance from that target, i.e. the radius of the orbit the camera + hovers on. + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Rotation speed of the camera. + \param zoomSpeed: Zoom speed of the camera. + \param translationSpeed: TranslationSpeed of the camera. + \param id: id of the camera. This id can be used to identify the camera. + \param distance Initial distance of the camera from the object + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active camera. + \return Returns a pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent=0, + f32 rotateSpeed=-1500.f, f32 zoomSpeed=200.f, + f32 translationSpeed=1500.f, s32 id=-1, f32 distance=70.f, + bool makeActive=true) =0; + + //! Adds a camera scene node with an animator which provides mouse and keyboard control appropriate for first person shooters (FPS). + /** This FPS camera is intended to provide a demonstration of a + camera that behaves like a typical First Person Shooter. It is + useful for simple demos and prototyping but is not intended to + provide a full solution for a production quality game. It binds + the camera scene node rotation to the look-at target; @see + ICameraSceneNode::bindTargetAndRotation(). With this camera, + you look with the mouse, and move with cursor keys. If you want + to change the key layout, you can specify your own keymap. For + example to make the camera be controlled by the cursor keys AND + the keys W,A,S, and D, do something like this: + \code + SKeyMap keyMap[8]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; + + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; + + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; + + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; + + camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); + \endcode + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Speed in degress with which the camera is + rotated. This can be done only with the mouse. + \param moveSpeed: Speed in units per millisecond with which + the camera is moved. Movement is done with the cursor keys. + \param id: id of the camera. This id can be used to identify + the camera. + \param keyMapArray: Optional pointer to an array of a keymap, + specifying what keys should be used to move the camera. If this + is null, the default keymap is used. You can define actions + more then one time in the array, to bind multiple keys to the + same action. + \param keyMapSize: Amount of items in the keymap array. + \param noVerticalMovement: Setting this to true makes the + camera only move within a horizontal plane, and disables + vertical movement as known from most ego shooters. Default is + 'false', with which it is possible to fly around in space, if + no gravity is there. + \param jumpSpeed: Speed with which the camera is moved when + jumping. + \param invertMouse: Setting this to true makes the camera look + up when the mouse is moved down and down when the mouse is + moved up, the default is 'false' which means it will follow the + movement of the mouse cursor. + \param makeActive Flag whether this camera should become the active one. + Make sure you always have one active camera. + \return Pointer to the interface of the camera if successful, + otherwise 0. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, + f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, + SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, + f32 jumpSpeed = 0.f, bool invertMouse=false, + bool makeActive=true) = 0; + + //! Adds a dynamic light scene node to the scene graph. + /** The light will cast dynamic light on all + other scene nodes in the scene, which have the material flag video::MTF_LIGHTING + turned on. (This is the default setting in most scene nodes). + \param parent: Parent scene node of the light. Can be null. If the parent moves, + the light will move too. + \param position: Position of the space relative to its parent where the light will be placed. + \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with + the ILightSceneNode::getLightData() method. + \param radius: Radius of the light. + \param id: id of the node. This id can be used to identify the node. + \return Pointer to the interface of the light if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, + const core::vector3df& position = core::vector3df(0,0,0), + video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), + f32 radius=100.0f, s32 id=-1) = 0; + + //! Adds a billboard scene node to the scene graph. + /** A billboard is like a 3d sprite: A 2d element, + which always looks to the camera. It is usually used for things + like explosions, fire, lensflares and things like that. + \param parent Parent scene node of the billboard. Can be null. + If the parent moves, the billboard will move too. + \param size Size of the billboard. This size is 2 dimensional + because a billboard only has width and height. + \param position Position of the space relative to its parent + where the billboard will be placed. + \param id An id of the node. This id can be used to identify + the node. + \param colorTop The color of the vertices at the top of the + billboard (default: white). + \param colorBottom The color of the vertices at the bottom of + the billboard (default: white). + \return Pointer to the billboard if successful, otherwise NULL. + This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, + const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), + const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, + video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF) = 0; + + //! Adds a skybox scene node to the scene graph. + /** A skybox is a big cube with 6 textures on it and + is drawn around the camera position. + \param top: Texture for the top plane of the box. + \param bottom: Texture for the bottom plane of the box. + \param left: Texture for the left plane of the box. + \param right: Texture for the right plane of the box. + \param front: Texture for the front plane of the box. + \param back: Texture for the back plane of the box. + \param parent: Parent scene node of the skybox. A skybox usually has no parent, + so this should be null. Note: If a parent is set to the skybox, the box will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return Pointer to the sky box if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, + video::ITexture* left, video::ITexture* right, video::ITexture* front, + video::ITexture* back, ISceneNode* parent = 0, s32 id=-1) = 0; + + //! Adds a skydome scene node to the scene graph. + /** A skydome is a large (half-) sphere with a panoramic texture + on the inside and is drawn around the camera position. + \param texture: Texture for the dome. + \param horiRes: Number of vertices of a horizontal layer of the sphere. + \param vertRes: Number of vertices of a vertical layer of the sphere. + \param texturePercentage: How much of the height of the + texture is used. Should be between 0 and 1. + \param spherePercentage: How much of the sphere is drawn. + Value should be between 0 and 2, where 1 is an exact + half-sphere and 2 is a full sphere. + \param radius The Radius of the sphere + \param parent: Parent scene node of the dome. A dome usually has no parent, + so this should be null. Note: If a parent is set, the dome will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return Pointer to the sky dome if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, + u32 horiRes=16, u32 vertRes=8, + f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, + ISceneNode* parent=0, s32 id=-1) = 0; + + //! Adds a particle system scene node to the scene graph. + /** \param withDefaultEmitter: Creates a default working point emitter + which emitts some particles. Set this to true to see a particle system + in action. If set to false, you'll have to set the emitter you want by + calling IParticleSystemSceneNode::setEmitter(). + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IParticleSystemSceneNode* addParticleSystemSceneNode( + bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a terrain scene node to the scene graph. + /** This node implements is a simple terrain renderer which uses + a technique known as geo mip mapping + for reducing the detail of triangle blocks which are far away. + The code for the TerrainSceneNode is based on the terrain + renderer by Soconne and the GeoMipMapSceneNode developed by + Spintz. They made their code available for Irrlicht and allowed + it to be distributed under this licence. I only modified some + parts. A lot of thanks go to them. + + This scene node is capable of loading terrains and updating + the indices at runtime to enable viewing very large terrains + very quickly. It uses a CLOD (Continuous Level of Detail) + algorithm which updates the indices for each patch based on + a LOD (Level of Detail) which is determined based on a patch's + distance from the camera. + + The patch size of the terrain must always be a size of 2^N+1, + i.e. 8+1(9), 16+1(17), etc. + The MaxLOD available is directly dependent on the patch size + of the terrain. LOD 0 contains all of the indices to draw all + the triangles at the max detail for a patch. As each LOD goes + up by 1 the step taken, in generating indices increases by + -2^LOD, so for LOD 1, the step taken is 2, for LOD 2, the step + taken is 4, LOD 3 - 8, etc. The step can be no larger than + the size of the patch, so having a LOD of 8, with a patch size + of 17, is asking the algoritm to generate indices every 2^8 ( + 256 ) vertices, which is not possible with a patch size of 17. + The maximum LOD for a patch size of 17 is 2^4 ( 16 ). So, + with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( + every 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every + 8 vertices ) and LOD 4 ( every 16 vertices ). + \param heightMapFileName: The name of the file on disk, to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're + using a heightmap of size 129x129 and would like your terrain + to be 12900x12900 in game units, then use a scale factor of ( + core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y + scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behavior. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behavior. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Pointer to the created scene node. Can be null + if the terrain could not be created, for example because the + heightmap could not be loaded. The returned pointer should + not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual ITerrainSceneNode* addTerrainSceneNode( + const io::path& heightMapFileName, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), + video::SColor vertexColor = video::SColor(255,255,255,255), + s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, + bool addAlsoIfHeightmapEmpty = false) = 0; + + //! Adds a terrain scene node to the scene graph. + /** Just like the other addTerrainSceneNode() method, but takes an IReadFile + pointer as parameter for the heightmap. For more informations take a look + at the other function. + \param heightMapFile: The file handle to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're + using a heightmap of size 129x129 and would like your terrain + to be 12900x12900 in game units, then use a scale factor of ( + core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y + scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behavior. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behavior. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Pointer to the created scene node. Can be null + if the terrain could not be created, for example because the + heightmap could not be loaded. The returned pointer should + not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual ITerrainSceneNode* addTerrainSceneNode( + io::IReadFile* heightMapFile, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), + video::SColor vertexColor = video::SColor(255,255,255,255), + s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, + bool addAlsoIfHeightmapEmpty = false) = 0; + + //! Adds a quake3 scene node to the scene graph. + /** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style ) + \return Pointer to the quake3 scene node if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, + ISceneNode* parent=0, s32 id=-1 + ) = 0; + + + //! Adds an empty scene node to the scene graph. + /** Can be used for doing advanced transformations + or structuring the scene graph. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addEmptySceneNode(ISceneNode* parent=0, s32 id=-1) = 0; + + //! Adds a dummy transformation scene node to the scene graph. + /** This scene node does not render itself, and does not respond to set/getPosition, + set/getRotation and set/getScale. Its just a simple scene node that takes a + matrix as relative transformation, making it possible to insert any transformation + anywhere into the scene graph. + \return Pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( + ISceneNode* parent=0, s32 id=-1) = 0; + + //! Adds a text scene node, which is able to display 2d text at a position in three dimensional space + virtual ITextSceneNode* addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, + video::SColor color=video::SColor(100,255,255,255), + ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), + s32 id=-1) = 0; + + //! Adds a text scene node, which uses billboards. The node, and the text on it, will scale with distance. + /** + \param font The font to use on the billboard. Pass 0 to use the GUI environment's default font. + \param text The text to display on the billboard. + \param parent The billboard's parent. Pass 0 to use the root scene node. + \param size The billboard's width and height. + \param position The billboards position relative to its parent. + \param id: An id of the node. This id can be used to identify the node. + \param colorTop: The color of the vertices at the top of the billboard (default: white). + \param colorBottom: The color of the vertices at the bottom of the billboard (default: white). + \return Pointer to the billboard if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IBillboardTextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, + ISceneNode* parent = 0, + const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), + const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, + video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF) = 0; + + //! Adds a Hill Plane mesh to the mesh pool. + /** The mesh is generated on the fly + and looks like a plane with some hills on it. It is uses mostly for quick + tests of the engine only. You can specify how many hills there should be + on the plane and how high they should be. Also you must specify a name for + the mesh, because the mesh is added to the mesh pool, and can be retrieved + again using ISceneManager::getMesh() with the name as parameter. + \param name: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a + good value to start, for example. + \param tileCount: Specifies how much tiles there will be. If you specifiy + for example that a tile has the size (10.0f, 10.0f) and the tileCount is + (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. + \param material: Material of the hill mesh. + \param hillHeight: Height of the hills. If you specify a negative value + you will get holes instead of hills. If the height is 0, no hills will be + created. + \param countHills: Amount of hills on the plane. There will be countHills.X + hills along the X axis and countHills.Y along the Y axis. So in total there + will be countHills.X * countHills.Y hills. + \param textureRepeatCount: Defines how often the texture will be repeated in + x and y direction. + return Null if the creation failed. The reason could be that you + specified some invalid parameters or that a mesh with that name already + exists. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, + const core::dimension2d& tileSize, const core::dimension2d& tileCount, + video::SMaterial* material = 0, f32 hillHeight = 0.0f, + const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), + const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; + + //! Adds a static terrain mesh to the mesh pool. + /** The mesh is generated on the fly + from a texture file and a height map file. Both files may be huge + (8000x8000 pixels would be no problem) because the generator splits the + files into smaller textures if necessary. + You must specify a name for the mesh, because the mesh is added to the mesh pool, + and can be retrieved again using ISceneManager::getMesh() with the name as parameter. + \param meshname: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param texture: Texture for the terrain. Please note that this is not a + hardware texture as usual (ITexture), but an IImage software texture. + You can load this texture with IVideoDriver::createImageFromFile(). + \param heightmap: A grayscaled heightmap image. Like the texture, + it can be created with IVideoDriver::createImageFromFile(). The amount + of triangles created depends on the size of this texture, so use a small + heightmap to increase rendering speed. + \param stretchSize: Parameter defining how big a is pixel on the heightmap. + \param maxHeight: Defines how high a white pixel on the heighmap is. + \param defaultVertexBlockSize: Defines the initial dimension between vertices. + \return Null if the creation failed. The reason could be that you + specified some invalid parameters, that a mesh with that name already + exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, + video::IImage* texture, video::IImage* heightmap, + const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), + f32 maxHeight=200.0f, + const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; + + //! add a static arrow mesh to the meshpool + /** \param name Name of the mesh + \param vtxColorCylinder color of the cylinder + \param vtxColorCone color of the cone + \param tesselationCylinder Number of quads the cylinder side consists of + \param tesselationCone Number of triangles the cone's roof consits of + \param height Total height of the arrow + \param cylinderHeight Total height of the cylinder, should be lesser than total height + \param widthCylinder Diameter of the cylinder + \param widthCone Diameter of the cone's base, should be not smaller than the cylinder's diameter + \return Pointer to the arrow mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addArrowMesh(const io::path& name, + video::SColor vtxColorCylinder=0xFFFFFFFF, + video::SColor vtxColorCone=0xFFFFFFFF, + u32 tesselationCylinder=4, u32 tesselationCone=8, + f32 height=1.f, f32 cylinderHeight=0.6f, + f32 widthCylinder=0.05f, f32 widthCone=0.3f) = 0; + + //! add a static sphere mesh to the meshpool + /** \param name Name of the mesh + \param radius Radius of the sphere + \param polyCountX Number of quads used for the horizontal tiling + \param polyCountY Number of quads used for the vertical tiling + \return Pointer to the sphere mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addSphereMesh(const io::path& name, + f32 radius=5.f, u32 polyCountX = 16, + u32 polyCountY = 16) = 0; + + //! Add a volume light mesh to the meshpool + /** \param name Name of the mesh + \param SubdivideU Horizontal subdivision count + \param SubdivideV Vertical subdivision count + \param FootColor Color of the bottom of the light + \param TailColor Color of the top of the light + \return Pointer to the volume light mesh if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. + */ + virtual IAnimatedMesh* addVolumeLightMesh(const io::path& name, + const u32 SubdivideU = 32, const u32 SubdivideV = 32, + const video::SColor FootColor = video::SColor(51, 0, 230, 180), + const video::SColor TailColor = video::SColor(0, 0, 0, 0)) = 0; + + //! Gets the root scene node. + /** This is the scene node which is parent + of all scene nodes. The root scene node is a special scene node which + only exists to manage all scene nodes. It will not be rendered and cannot + be removed from the scene. + \return Pointer to the root scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* getRootSceneNode() = 0; + + //! Get the first scene node with the specified id. + /** \param id: The id to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this id, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0) = 0; + + //! Get the first scene node with the specified name. + /** \param name: The name to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this id, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0) = 0; + + //! Get the first scene node with the specified type. + /** \param type: The type to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Pointer to the first scene node with this type, + and null if no scene node could be found. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0) = 0; + + //! Get scene nodes by type. + /** \param type: Type of scene node to find (ESNT_ANY will return all child nodes). + \param outNodes: array to be filled with results. + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. */ + virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, + core::array& outNodes, + ISceneNode* start=0) = 0; + + //! Get the current active camera. + /** \return The active camera is returned. Note that this can + be NULL, if there was no camera created yet. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* getActiveCamera() const =0; + + //! Sets the currently active camera. + /** The previous active camera will be deactivated. + \param camera: The new camera which should be active. */ + virtual void setActiveCamera(ICameraSceneNode* camera) = 0; + + //! Sets the color of stencil buffers shadows drawn by the scene manager. + virtual void setShadowColor(video::SColor color = video::SColor(150,0,0,0)) = 0; + + //! Get the current color of shadows. + virtual video::SColor getShadowColor() const = 0; + + //! Registers a node for rendering it at a specific time. + /** This method should only be used by SceneNodes when they get a + ISceneNode::OnRegisterSceneNode() call. + \param node: Node to register for drawing. Usually scene nodes would set 'this' + as parameter here because they want to be drawn. + \param pass: Specifies when the node wants to be drawn in relation to the other nodes. + For example, if the node is a shadow, it usually wants to be drawn after all other nodes + and will use ESNRP_SHADOW for this. See scene::E_SCENE_NODE_RENDER_PASS for details. + \return scene will be rendered ( passed culling ) */ + virtual u32 registerNodeForRendering(ISceneNode* node, + E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; + + //! Draws all the scene nodes. + /** This can only be invoked between + IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that + the scene is not only drawn when calling this, but also animated + by existing scene node animators, culling of scene nodes is done, etc. */ + virtual void drawAll() = 0; + + //! Creates a rotation animator, which rotates the attached scene node around itself. + /** \param rotationSpeed Specifies the speed of the animation in degree per 10 milliseconds. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationSpeed) = 0; + + //! Creates a fly circle animator, which lets the attached scene node fly around a center. + /** \param center: Center of the circle. + \param radius: Radius of the circle. + \param speed: The orbital speed, in radians per millisecond. + \param direction: Specifies the upvector used for alignment of the mesh. + \param startPosition: The position on the circle where the animator will + begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) + \param radiusEllipsoid: if radiusEllipsoid != 0 then radius2 froms a ellipsoid + begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createFlyCircleAnimator( + const core::vector3df& center=core::vector3df(0.f,0.f,0.f), + f32 radius=100.f, f32 speed=0.001f, + const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), + f32 startPosition = 0.f, + f32 radiusEllipsoid = 0.f) = 0; + + //! Creates a fly straight animator, which lets the attached scene node fly or move along a line between two points. + /** \param startPoint: Start point of the line. + \param endPoint: End point of the line. + \param timeForWay: Time in milli seconds how long the node should need to + move from the start point to the end point. + \param loop: If set to false, the node stops when the end point is reached. + If loop is true, the node begins again at the start. + \param pingpong Flag to set whether the animator should fly + back from end to start again. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, + const core::vector3df& endPoint, u32 timeForWay, bool loop=false, bool pingpong = false) = 0; + + //! Creates a texture animator, which switches the textures of the target scene node based on a list of textures. + /** \param textures: List of textures to use. + \param timePerFrame: Time in milliseconds, how long any texture in the list + should be visible. + \param loop: If set to to false, the last texture remains set, and the animation + stops. If set to true, the animation restarts with the first texture. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, + s32 timePerFrame, bool loop=true) = 0; + + //! Creates a scene node animator, which deletes the scene node after some time automatically. + /** \param timeMs: Time in milliseconds, after when the node will be deleted. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMs) = 0; + + //! Creates a special scene node animator for doing automatic collision detection and response. + /** See ISceneNodeAnimatorCollisionResponse for details. + \param world: Triangle selector holding all triangles of the world with which + the scene node may collide. You can create a triangle selector with + ISceneManager::createTriangleSelector(); + \param sceneNode: SceneNode which should be manipulated. After you added this animator + to the scene node, the scene node will not be able to move through walls and is + affected by gravity. If you need to teleport the scene node to a new position without + it being effected by the collision geometry, then call sceneNode->setPosition(); then + animator->setTargetNode(sceneNode); + \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and + response is done. If you have got a scene node, and you are unsure about + how big the radius should be, you could use the following code to determine + it: + \code + const core::aabbox3d& box = yourSceneNode->getBoundingBox(); + core::vector3df radius = box.MaxEdge - box.getCenter(); + \endcode + \param gravityPerSecond: Sets the gravity of the environment, as an acceleration in + units per second per second. If your units are equivalent to metres, then + core::vector3df(0,-10.0f,0) would give an approximately realistic gravity. + You can disable gravity by setting it to core::vector3df(0,0,0). + \param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around + the center of the scene node, which means that the ellipsoid surrounds + it completely. If this is not what you want, you may specify a translation + for the ellipsoid. + \param slidingValue: DOCUMENTATION NEEDED. + \return The animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will cause it to do collision detection and response. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( + ITriangleSelector* world, ISceneNode* sceneNode, + const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), + const core::vector3df& gravityPerSecond = core::vector3df(0,-10.0f,0), + const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), + f32 slidingValue = 0.0005f) = 0; + + //! Creates a follow spline animator. + /** The animator modifies the position of + the attached scene node to make it follow a hermite spline. + It uses a subset of hermite splines: either cardinal splines + (tightness != 0.5) or catmull-rom-splines (tightness == 0.5). + The animator moves from one control point to the next in + 1/speed seconds. This code was sent in by Matthias Gall. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, + const core::array< core::vector3df >& points, + f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false) = 0; + + //! Creates a simple ITriangleSelector, based on a mesh. + /** Triangle selectors + can be used for doing collision detection. Don't use this selector + for a huge amount of triangles like in Quake3 maps. + Instead, use for example ISceneManager::createOctreeTriangleSelector(). + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, + yourSceneNode); + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0; + + //! Creates a simple ITriangleSelector, based on an animated mesh scene node. + /** Details of the mesh associated with the node will be extracted internally. + Call ITriangleSelector::update() to have the triangle selector updated based + on the current frame of the animated mesh scene node. + \param node The animated mesh scene node from which to build the selector + */ + virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0; + + + //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. + /** Triangle selectors + can be used for doing collision detection. Every time when triangles are + queried, the triangle selector gets the bounding box of the scene node, + an creates new triangles. In this way, it works good with animated scene nodes. + \param node: Scene node of which the bounding box, visibility and transformation is used. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; + + //! Creates a Triangle Selector, optimized by an octree. + /** Triangle selectors + can be used for doing collision detection. This triangle selector is + optimized for huge amounts of triangle, it organizes them in an octree. + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh, + yourSceneNode); + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + For more informations and examples on this, take a look at the collision + tutorial in the SDK. + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys the this value, it will not be splitted into + smaller nodes. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, + ISceneNode* node, s32 minimalPolysPerNode=32) = 0; + + //! //! Creates a Triangle Selector, optimized by an octree. + /** \deprecated Use createOctreeTriangleSelector instead. This method may be removed by Irrlicht 1.9. */ + _IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + ISceneNode* node, s32 minimalPolysPerNode=32) + { + return createOctreeTriangleSelector(mesh, node, minimalPolysPerNode); + } + + //! Creates a meta triangle selector. + /** A meta triangle selector is nothing more than a + collection of one or more triangle selectors providing together + the interface of one triangle selector. In this way, + collision tests can be done with different triangle soups in one pass. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IMetaTriangleSelector* createMetaTriangleSelector() = 0; + + //! Creates a triangle selector which can select triangles from a terrain scene node. + /** \param node: Pointer to the created terrain scene node + \param LOD: Level of detail, 0 for highest detail. + \return The selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createTerrainTriangleSelector( + ITerrainSceneNode* node, s32 LOD=0) = 0; + + //! Adds an external mesh loader for extending the engine with new file formats. + /** If you want the engine to be extended with + file formats it currently is not able to load (e.g. .cob), just implement + the IMeshLoader interface in your loading class and add it with this method. + Using this method it is also possible to override built-in mesh loaders with + newer or updated versions without the need to recompile the engine. + \param externalLoader: Implementation of a new mesh loader. */ + virtual void addExternalMeshLoader(IMeshLoader* externalLoader) = 0; + + //! Returns the number of mesh loaders supported by Irrlicht at this time + virtual u32 getMeshLoaderCount() const = 0; + + //! Retrieve the given mesh loader + /** \param index The index of the loader to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified loader, 0 if the index is incorrect. */ + virtual IMeshLoader* getMeshLoader(u32 index) const = 0; + + //! Adds an external scene loader for extending the engine with new file formats. + /** If you want the engine to be extended with + file formats it currently is not able to load (e.g. .vrml), just implement + the ISceneLoader interface in your loading class and add it with this method. + Using this method it is also possible to override the built-in scene loaders + with newer or updated versions without the need to recompile the engine. + \param externalLoader: Implementation of a new mesh loader. */ + virtual void addExternalSceneLoader(ISceneLoader* externalLoader) = 0; + + //! Returns the number of scene loaders supported by Irrlicht at this time + virtual u32 getSceneLoaderCount() const = 0; + + //! Retrieve the given scene loader + /** \param index The index of the loader to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified loader, 0 if the index is incorrect. */ + virtual ISceneLoader* getSceneLoader(u32 index) const = 0; + + //! Get pointer to the scene collision manager. + /** \return Pointer to the collision manager + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneCollisionManager* getSceneCollisionManager() = 0; + + //! Get pointer to the mesh manipulator. + /** \return Pointer to the mesh manipulator + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshManipulator* getMeshManipulator() = 0; + + //! Adds a scene node to the deletion queue. + /** The scene node is immediatly + deleted when it's secure. Which means when the scene node does not + execute animators and things like that. This method is for example + used for deleting scene nodes by their scene node animators. In + most other cases, a ISceneNode::remove() call is enough, using this + deletion queue is not necessary. + See ISceneManager::createDeleteAnimator() for details. + \param node: Node to detete. */ + virtual void addToDeletionQueue(ISceneNode* node) = 0; + + //! Posts an input event to the environment. + /** Usually you do not have to + use this method, it is used by the internal engine. */ + virtual bool postEventFromUser(const SEvent& event) = 0; + + //! Clears the whole scene. + /** All scene nodes are removed. */ + virtual void clear() = 0; + + //! Get interface to the parameters set in this scene. + /** String parameters can be used by plugins and mesh loaders. + For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' + and 'LMTS_TexturePath' set to the path were attached textures can be found. See + CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, + COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ + virtual io::IAttributes* getParameters() = 0; + + //! Get current render pass. + /** All scene nodes are being rendered in a specific order. + First lights, cameras, sky boxes, solid geometry, and then transparent + stuff. During the rendering process, scene nodes may want to know what the scene + manager is rendering currently, because for example they registered for rendering + twice, once for transparent geometry and once for solid. When knowing what rendering + pass currently is active they can render the correct part of their geometry. */ + virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; + + //! Get the default scene node factory which can create all built in scene nodes + /** \return Pointer to the default scene node factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeFactory* getDefaultSceneNodeFactory() = 0; + + //! Adds a scene node factory to the scene manager. + /** Use this to extend the scene manager with new scene node types which it should be + able to create automaticly, for example when loading data from xml files. */ + virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) = 0; + + //! Get amount of registered scene node factories. + virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; + + //! Get a scene node factory by index + /** \return Pointer to the requested scene node factory, or 0 if it does not exist. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; + + //! Get the default scene node animator factory which can create all built-in scene node animators + /** \return Pointer to the default scene node animator factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory() = 0; + + //! Adds a scene node animator factory to the scene manager. + /** Use this to extend the scene manager with new scene node animator types which it should be + able to create automaticly, for example when loading data from xml files. */ + virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) = 0; + + //! Get amount of registered scene node animator factories. + virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; + + //! Get scene node animator factory by index + /** \return Pointer to the requested scene node animator factory, or 0 if it does not exist. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; + + //! Get typename from a scene node type or null if not found + virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type) = 0; + + //! Returns a typename from a scene node animator type or null if not found + virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) = 0; + + //! Adds a scene node to the scene by name + /** \return Pointer to the scene node added by a factory + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent=0) = 0; + + //! creates a scene node animator based on its type name + /** \param typeName: Type of the scene node animator to add. + \param target: Target scene node of the new animator. + \return Returns pointer to the new scene node animator or null if not successful. You need to + drop this pointer after calling this, see IReferenceCounted::drop() for details. */ + virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target=0) = 0; + + //! Creates a new scene manager. + /** This can be used to easily draw and/or store two + independent scenes at the same time. The mesh cache will be + shared between all existing scene managers, which means if you + load a mesh in the original scene manager using for example + getMesh(), the mesh will be available in all other scene + managers too, without loading. + The original/main scene manager will still be there and + accessible via IrrlichtDevice::getSceneManager(). If you need + input event in this new scene manager, for example for FPS + cameras, you'll need to forward input to this manually: Just + implement an IEventReceiver and call + yourNewSceneManager->postEventFromUser(), and return true so + that the original scene manager doesn't get the event. + Otherwise, all input will go to the main scene manager + automatically. + If you no longer need the new scene manager, you should call + ISceneManager::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneManager* createNewSceneManager(bool cloneContent=false) = 0; + + //! Saves the current scene into a file. + /** Scene nodes with the option isDebugObject set to true are + not being saved. The scene is usually written to an .irr file, + an xml based format. .irr files can Be edited with the Irrlicht + Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To + load .irr files again, see ISceneManager::loadScene(). + \param filename Name of the file. + \param userDataSerializer If you want to save some user data + for every scene node into the file, implement the + ISceneUserDataSerializer interface and provide it as parameter + here. Otherwise, simply specify 0 as this parameter. + \param node Node which is taken as the top node of the scene. + This node and all of its descendants are saved into the scene + file. Pass 0 or the scene manager to save the full scene (which + is also the default). + \return True if successful. */ + virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; + + //! Saves the current scene into a file. + /** Scene nodes with the option isDebugObject set to true are + not being saved. The scene is usually written to an .irr file, + an xml based format. .irr files can Be edited with the Irrlicht + Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To + load .irr files again, see ISceneManager::loadScene(). + \param file File where the scene is saved into. + \param userDataSerializer If you want to save some user data + for every scene node into the file, implement the + ISceneUserDataSerializer interface and provide it as parameter + here. Otherwise, simply specify 0 as this parameter. + \param node Node which is taken as the top node of the scene. + This node and all of its descendants are saved into the scene + file. Pass 0 or the scene manager to save the full scene (which + is also the default). + \return True if successful. */ + virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; + + //! Saves the current scene into a file. + /** Scene nodes with the option isDebugObject set to true are + not being saved. The scene is usually written to an .irr file, + an xml based format. .irr files can Be edited with the Irrlicht + Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To + load .irr files again, see ISceneManager::loadScene(). + \param writer XMLWriter with which the scene is saved. + \param currentPath Path which is used for relative file names. + Usually the directory of the file written into. + \param userDataSerializer If you want to save some user data + for every scene node into the file, implement the + ISceneUserDataSerializer interface and provide it as parameter + here. Otherwise, simply specify 0 as this parameter. + \param node Node which is taken as the top node of the scene. + This node and all of its descendants are saved into the scene + file. Pass 0 or the scene manager to save the full scene (which + is also the default). + \return True if successful. */ + virtual bool saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; + + //! Loads a scene. Note that the current scene is not cleared before. + /** The scene is usually loaded from an .irr file, an xml based + format, but other scene formats can be added to the engine via + ISceneManager::addExternalSceneLoader. .irr files can Be edited + with the Irrlicht Engine Editor, irrEdit + (http://www.ambiera.com/irredit/) or saved directly by the engine + using ISceneManager::saveScene(). + \param filename Name of the file to load from. + \param userDataSerializer If you want to load user data + possibily saved in that file for some scene nodes in the file, + implement the ISceneUserDataSerializer interface and provide it + as parameter here. Otherwise, simply specify 0 as this + parameter. + \param rootNode Node which is taken as the root node of the + scene. Pass 0 to add the scene directly to the scene manager + (which is also the default). + \return True if successful. */ + virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) = 0; + + //! Loads a scene. Note that the current scene is not cleared before. + /** The scene is usually loaded from an .irr file, an xml based + format, but other scene formats can be added to the engine via + ISceneManager::addExternalSceneLoader. .irr files can Be edited + with the Irrlicht Engine Editor, irrEdit + (http://www.ambiera.com/irredit/) or saved directly by the engine + using ISceneManager::saveScene(). + \param file File where the scene is loaded from. + \param userDataSerializer If you want to load user data + possibily saved in that file for some scene nodes in the file, + implement the ISceneUserDataSerializer interface and provide it + as parameter here. Otherwise, simply specify 0 as this + parameter. + \param rootNode Node which is taken as the root node of the + scene. Pass 0 to add the scene directly to the scene manager + (which is also the default). + \return True if successful. */ + virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) = 0; + + //! Get a mesh writer implementation if available + /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() + for details. */ + virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; + + //! Get a skinned mesh, which is not available as header-only code + /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() + for details. */ + virtual ISkinnedMesh* createSkinnedMesh() = 0; + + //! Sets ambient color of the scene + virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; + + //! Get ambient color of the scene + virtual const video::SColorf& getAmbientLight() const = 0; + + //! Register a custom callbacks manager which gets callbacks during scene rendering. + /** \param[in] lightManager: the new callbacks manager. You may pass 0 to remove the + current callbacks manager and restore the default behavior. */ + virtual void setLightManager(ILightManager* lightManager) = 0; + + //! Get an instance of a geometry creator. + /** The geometry creator provides some helper methods to create various types of + basic geometry. This can be useful for custom scene nodes. */ + virtual const IGeometryCreator* getGeometryCreator(void) const = 0; + + //! Check if node is culled in current view frustum + /** Please note that depending on the used culling method this + check can be rather coarse, or slow. A positive result is + correct, though, i.e. if this method returns true the node is + positively not visible. The node might still be invisible even + if this method returns false. + \param node The scene node which is checked for culling. + \return True if node is not visible in the current scene, else + false. */ + virtual bool isCulled(const ISceneNode* node) const =0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNode.h b/inc/ISceneNode.h new file mode 100644 index 0000000..63d74f0 --- /dev/null +++ b/inc/ISceneNode.h @@ -0,0 +1,858 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_H_INCLUDED__ +#define __I_SCENE_NODE_H_INCLUDED__ + +#include "IAttributeExchangingObject.h" +#include "ESceneNodeTypes.h" +#include "ECullingTypes.h" +#include "EDebugSceneTypes.h" +#include "ISceneNodeAnimator.h" +#include "ITriangleSelector.h" +#include "SMaterial.h" +#include "irrString.h" +#include "aabbox3d.h" +#include "matrix4.h" +#include "irrList.h" +#include "IAttributes.h" + +namespace irr +{ +namespace scene +{ + class ISceneManager; + + //! Typedef for list of scene nodes + typedef core::list ISceneNodeList; + //! Typedef for list of scene node animators + typedef core::list ISceneNodeAnimatorList; + + //! Scene node interface. + /** A scene node is a node in the hierarchical scene graph. Every scene + node may have children, which are also scene nodes. Children move + relative to their parent's position. If the parent of a node is not + visible, its children won't be visible either. In this way, it is for + example easily possible to attach a light to a moving car, or to place + a walking character on a moving platform on a moving ship. + */ + class ISceneNode : virtual public io::IAttributeExchangingObject + { + public: + + //! Constructor + ISceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) + : RelativeTranslation(position), RelativeRotation(rotation), RelativeScale(scale), + Parent(0), SceneManager(mgr), TriangleSelector(0), ID(id), + AutomaticCullingState(EAC_BOX), DebugDataVisible(EDS_OFF), + IsVisible(true), IsDebugObject(false) + { + if (parent) + parent->addChild(this); + + updateAbsolutePosition(); + } + + + //! Destructor + virtual ~ISceneNode() + { + // delete all children + removeAll(); + + // delete all animators + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); + for (; ait != Animators.end(); ++ait) + (*ait)->drop(); + + if (TriangleSelector) + TriangleSelector->drop(); + } + + + //! This method is called just before the rendering process of the whole scene. + /** Nodes may register themselves in the render pipeline during this call, + precalculate the geometry which should be renderered, and prevent their + children from being able to register themselves if they are clipped by simply + not calling their OnRegisterSceneNode method. + If you are implementing your own scene node, you should overwrite this method + with an implementation code looking like this: + \code + if (IsVisible) + SceneManager->registerNodeForRendering(this); + + ISceneNode::OnRegisterSceneNode(); + \endcode + */ + virtual void OnRegisterSceneNode() + { + if (IsVisible) + { + ISceneNodeList::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnRegisterSceneNode(); + } + } + + + //! OnAnimate() is called just before rendering the whole scene. + /** Nodes may calculate or store animations here, and may do other useful things, + depending on what they are. Also, OnAnimate() should be called for all + child scene nodes here. This method will be called once per frame, independent + of whether the scene node is visible or not. + \param timeMs Current time in milliseconds. */ + virtual void OnAnimate(u32 timeMs) + { + if (IsVisible) + { + // animate this node with all animators + + ISceneNodeAnimatorList::Iterator ait = Animators.begin(); + while (ait != Animators.end()) + { + // continue to the next node before calling animateNode() + // so that the animator may remove itself from the scene + // node without the iterator becoming invalid + ISceneNodeAnimator* anim = *ait; + ++ait; + anim->animateNode(this, timeMs); + } + + // update absolute position + updateAbsolutePosition(); + + // perform the post render process on all children + + ISceneNodeList::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnAnimate(timeMs); + } + } + + + //! Renders the node. + virtual void render() = 0; + + + //! Returns the name of the node. + /** \return Name as character string. */ + virtual const c8* getName() const + { + return Name.c_str(); + } + + + //! Sets the name of the node. + /** \param name New name of the scene node. */ + virtual void setName(const c8* name) + { + Name = name; + } + + + //! Sets the name of the node. + /** \param name New name of the scene node. */ + virtual void setName(const core::stringc& name) + { + Name = name; + } + + + //! Get the axis aligned, not transformed bounding box of this node. + /** This means that if this node is an animated 3d character, + moving in a room, the bounding box will always be around the + origin. To get the box in real world coordinates, just + transform it with the matrix you receive with + getAbsoluteTransformation() or simply use + getTransformedBoundingBox(), which does the same. + \return The non-transformed bounding box. */ + virtual const core::aabbox3d& getBoundingBox() const = 0; + + + //! Get the axis aligned, transformed and animated absolute bounding box of this node. + /** \return The transformed bounding box. */ + virtual const core::aabbox3d getTransformedBoundingBox() const + { + core::aabbox3d box = getBoundingBox(); + AbsoluteTransformation.transformBoxEx(box); + return box; + } + + + //! Get the absolute transformation of the node. Is recalculated every OnAnimate()-call. + /** NOTE: For speed reasons the absolute transformation is not + automatically recalculated on each change of the relative + transformation or by a transformation change of an parent. Instead the + update usually happens once per frame in OnAnimate. You can enforce + an update with updateAbsolutePosition(). + \return The absolute transformation matrix. */ + virtual const core::matrix4& getAbsoluteTransformation() const + { + return AbsoluteTransformation; + } + + + //! Returns the relative transformation of the scene node. + /** The relative transformation is stored internally as 3 + vectors: translation, rotation and scale. To get the relative + transformation matrix, it is calculated from these values. + \return The relative transformation matrix. */ + virtual core::matrix4 getRelativeTransformation() const + { + core::matrix4 mat; + mat.setRotationDegrees(RelativeRotation); + mat.setTranslation(RelativeTranslation); + + if (RelativeScale != core::vector3df(1.f,1.f,1.f)) + { + core::matrix4 smat; + smat.setScale(RelativeScale); + mat *= smat; + } + + return mat; + } + + + //! Returns whether the node should be visible (if all of its parents are visible). + /** This is only an option set by the user, but has nothing to + do with geometry culling + \return The requested visibility of the node, true means + visible (if all parents are also visible). */ + virtual bool isVisible() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsVisible; + } + + //! Check whether the node is truly visible, taking into accounts its parents' visibility + /** \return true if the node and all its parents are visible, + false if this or any parent node is invisible. */ + virtual bool isTrulyVisible() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + if(!IsVisible) + return false; + + if(!Parent) + return true; + + return Parent->isTrulyVisible(); + } + + //! Sets if the node should be visible or not. + /** All children of this node won't be visible either, when set + to false. Invisible nodes are not valid candidates for selection by + collision manager bounding box methods. + \param isVisible If the node shall be visible. */ + virtual void setVisible(bool isVisible) + { + IsVisible = isVisible; + } + + + //! Get the id of the scene node. + /** This id can be used to identify the node. + \return The id. */ + virtual s32 getID() const + { + return ID; + } + + + //! Sets the id of the scene node. + /** This id can be used to identify the node. + \param id The new id. */ + virtual void setID(s32 id) + { + ID = id; + } + + + //! Adds a child to this scene node. + /** If the scene node already has a parent it is first removed + from the other parent. + \param child A pointer to the new child. */ + virtual void addChild(ISceneNode* child) + { + if (child && (child != this)) + { + // Change scene manager? + if (SceneManager != child->SceneManager) + child->setSceneManager(SceneManager); + + child->grab(); + child->remove(); // remove from old parent + Children.push_back(child); + child->Parent = this; + } + } + + + //! Removes a child from this scene node. + /** If found in the children list, the child pointer is also + dropped and might be deleted if no other grab exists. + \param child A pointer to the child which shall be removed. + \return True if the child was removed, and false if not, + e.g. because it couldn't be found in the children list. */ + virtual bool removeChild(ISceneNode* child) + { + ISceneNodeList::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + if ((*it) == child) + { + (*it)->Parent = 0; + (*it)->drop(); + Children.erase(it); + return true; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + + //! Removes all children of this scene node + /** The scene nodes found in the children list are also dropped + and might be deleted if no other grab exists on them. + */ + virtual void removeAll() + { + ISceneNodeList::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->Parent = 0; + (*it)->drop(); + } + + Children.clear(); + } + + + //! Removes this scene node from the scene + /** If no other grab exists for this node, it will be deleted. + */ + virtual void remove() + { + if (Parent) + Parent->removeChild(this); + } + + + //! Adds an animator which should animate this node. + /** \param animator A pointer to the new animator. */ + virtual void addAnimator(ISceneNodeAnimator* animator) + { + if (animator) + { + Animators.push_back(animator); + animator->grab(); + } + } + + + //! Get a list of all scene node animators. + /** \return The list of animators attached to this node. */ + const core::list& getAnimators() const + { + return Animators; + } + + + //! Removes an animator from this scene node. + /** If the animator is found, it is also dropped and might be + deleted if not other grab exists for it. + \param animator A pointer to the animator to be deleted. */ + virtual void removeAnimator(ISceneNodeAnimator* animator) + { + ISceneNodeAnimatorList::Iterator it = Animators.begin(); + for (; it != Animators.end(); ++it) + { + if ((*it) == animator) + { + (*it)->drop(); + Animators.erase(it); + return; + } + } + } + + + //! Removes all animators from this scene node. + /** The animators might also be deleted if no other grab exists + for them. */ + virtual void removeAnimators() + { + ISceneNodeAnimatorList::Iterator it = Animators.begin(); + for (; it != Animators.end(); ++it) + (*it)->drop(); + + Animators.clear(); + } + + + //! Returns the material based on the zero based index i. + /** To get the amount of materials used by this scene node, use + getMaterialCount(). This function is needed for inserting the + node into the scene hierarchy at an optimal position for + minimizing renderstate changes, but can also be used to + directly modify the material of a scene node. + \param num Zero based index. The maximal value is getMaterialCount() - 1. + \return The material at that index. */ + virtual video::SMaterial& getMaterial(u32 num) + { + return video::IdentityMaterial; + } + + + //! Get amount of materials used by this scene node. + /** \return Current amount of materials of this scene node. */ + virtual u32 getMaterialCount() const + { + return 0; + } + + + //! Sets all material flags at once to a new value. + /** Useful, for example, if you want the whole mesh to be + affected by light. + \param flag Which flag of all materials to be set. + \param newvalue New value of that flag. */ + void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) + { + for (u32 i=0; i= video::MATERIAL_MAX_TEXTURES) + return; + + for (u32 i=0; i& getChildren() const + { + return Children; + } + + + //! Changes the parent of the scene node. + /** \param newParent The new parent to be used. */ + virtual void setParent(ISceneNode* newParent) + { + grab(); + remove(); + + Parent = newParent; + + if (Parent) + Parent->addChild(this); + + drop(); + } + + + //! Returns the triangle selector attached to this scene node. + /** The Selector can be used by the engine for doing collision + detection. You can create a TriangleSelector with + ISceneManager::createTriangleSelector() or + ISceneManager::createOctreeTriangleSelector and set it with + ISceneNode::setTriangleSelector(). If a scene node got no triangle + selector, but collision tests should be done with it, a triangle + selector is created using the bounding box of the scene node. + \return A pointer to the TriangleSelector or 0, if there + is none. */ + virtual ITriangleSelector* getTriangleSelector() const + { + return TriangleSelector; + } + + + //! Sets the triangle selector of the scene node. + /** The Selector can be used by the engine for doing collision + detection. You can create a TriangleSelector with + ISceneManager::createTriangleSelector() or + ISceneManager::createOctreeTriangleSelector(). Some nodes may + create their own selector by default, so it would be good to + check if there is already a selector in this node by calling + ISceneNode::getTriangleSelector(). + \param selector New triangle selector for this scene node. */ + virtual void setTriangleSelector(ITriangleSelector* selector) + { + if (TriangleSelector != selector) + { + if (TriangleSelector) + TriangleSelector->drop(); + + TriangleSelector = selector; + if (TriangleSelector) + TriangleSelector->grab(); + } + } + + + //! Updates the absolute position based on the relative and the parents position + /** Note: This does not recursively update the parents absolute positions, so if you have a deeper + hierarchy you might want to update the parents first.*/ + virtual void updateAbsolutePosition() + { + if (Parent) + { + AbsoluteTransformation = + Parent->getAbsoluteTransformation() * getRelativeTransformation(); + } + else + AbsoluteTransformation = getRelativeTransformation(); + } + + + //! Returns the parent of this scene node + /** \return A pointer to the parent. */ + scene::ISceneNode* getParent() const + { + return Parent; + } + + + //! Returns type of the scene node + /** \return The type of this node. */ + virtual ESCENE_NODE_TYPE getType() const + { + return ESNT_UNKNOWN; + } + + + //! Writes attributes of the scene node. + /** Implement this to expose the attributes of your scene node + for scripting languages, editors, debuggers or xml + serialization purposes. + \param out The attribute container to write into. + \param options Additional options which might influence the + serialization. */ + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const + { + if (!out) + return; + out->addString ("Name", Name.c_str()); + out->addInt ("Id", ID ); + + out->addVector3d("Position", getPosition() ); + out->addVector3d("Rotation", getRotation() ); + out->addVector3d("Scale", getScale() ); + + out->addBool ("Visible", IsVisible ); + out->addInt ("AutomaticCulling", AutomaticCullingState); + out->addInt ("DebugDataVisible", DebugDataVisible ); + out->addBool ("IsDebugObject", IsDebugObject ); + } + + + //! Reads attributes of the scene node. + /** Implement this to set the attributes of your scene node for + scripting languages, editors, debuggers or xml deserialization + purposes. + \param in The attribute container to read from. + \param options Additional options which might influence the + deserialization. */ + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) + { + if (!in) + return; + Name = in->getAttributeAsString("Name"); + ID = in->getAttributeAsInt("Id"); + + setPosition(in->getAttributeAsVector3d("Position")); + setRotation(in->getAttributeAsVector3d("Rotation")); + setScale(in->getAttributeAsVector3d("Scale")); + + IsVisible = in->getAttributeAsBool("Visible"); + s32 tmpState = in->getAttributeAsEnumeration("AutomaticCulling", + scene::AutomaticCullingNames); + if (tmpState != -1) + AutomaticCullingState = (u32)tmpState; + else + AutomaticCullingState = in->getAttributeAsInt("AutomaticCulling"); + + DebugDataVisible = in->getAttributeAsInt("DebugDataVisible"); + IsDebugObject = in->getAttributeAsBool("IsDebugObject"); + + updateAbsolutePosition(); + } + + //! Creates a clone of this scene node and its children. + /** \param newParent An optional new parent. + \param newManager An optional new scene manager. + \return The newly created clone of this node. */ + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) + { + return 0; // to be implemented by derived classes + } + + //! Retrieve the scene manager for this node. + /** \return The node's scene manager. */ + virtual ISceneManager* getSceneManager(void) const { return SceneManager; } + + protected: + + //! A clone function for the ISceneNode members. + /** This method can be used by clone() implementations of + derived classes + \param toCopyFrom The node from which the values are copied + \param newManager The new scene manager. */ + void cloneMembers(ISceneNode* toCopyFrom, ISceneManager* newManager) + { + Name = toCopyFrom->Name; + AbsoluteTransformation = toCopyFrom->AbsoluteTransformation; + RelativeTranslation = toCopyFrom->RelativeTranslation; + RelativeRotation = toCopyFrom->RelativeRotation; + RelativeScale = toCopyFrom->RelativeScale; + ID = toCopyFrom->ID; + setTriangleSelector(toCopyFrom->TriangleSelector); + AutomaticCullingState = toCopyFrom->AutomaticCullingState; + DebugDataVisible = toCopyFrom->DebugDataVisible; + IsVisible = toCopyFrom->IsVisible; + IsDebugObject = toCopyFrom->IsDebugObject; + + if (newManager) + SceneManager = newManager; + else + SceneManager = toCopyFrom->SceneManager; + + // clone children + + ISceneNodeList::Iterator it = toCopyFrom->Children.begin(); + for (; it != toCopyFrom->Children.end(); ++it) + (*it)->clone(this, newManager); + + // clone animators + + ISceneNodeAnimatorList::Iterator ait = toCopyFrom->Animators.begin(); + for (; ait != toCopyFrom->Animators.end(); ++ait) + { + ISceneNodeAnimator* anim = (*ait)->createClone(this, SceneManager); + if (anim) + { + addAnimator(anim); + anim->drop(); + } + } + } + + //! Sets the new scene manager for this node and all children. + //! Called by addChild when moving nodes between scene managers + void setSceneManager(ISceneManager* newManager) + { + SceneManager = newManager; + + ISceneNodeList::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->setSceneManager(newManager); + } + + //! Name of the scene node. + core::stringc Name; + + //! Absolute transformation of the node. + core::matrix4 AbsoluteTransformation; + + //! Relative translation of the scene node. + core::vector3df RelativeTranslation; + + //! Relative rotation of the scene node. + core::vector3df RelativeRotation; + + //! Relative scale of the scene node. + core::vector3df RelativeScale; + + //! Pointer to the parent + ISceneNode* Parent; + + //! List of all children of this node + core::list Children; + + //! List of all animator nodes + core::list Animators; + + //! Pointer to the scene manager + ISceneManager* SceneManager; + + //! Pointer to the triangle selector + ITriangleSelector* TriangleSelector; + + //! ID of the node. + s32 ID; + + //! Automatic culling state + u32 AutomaticCullingState; + + //! Flag if debug data should be drawn, such as Bounding Boxes. + u32 DebugDataVisible; + + //! Is the node visible? + bool IsVisible; + + //! Is debug object? + bool IsDebugObject; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeAnimator.h b/inc/ISceneNodeAnimator.h new file mode 100644 index 0000000..c69474b --- /dev/null +++ b/inc/ISceneNodeAnimator.h @@ -0,0 +1,78 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "vector3d.h" +#include "ESceneNodeAnimatorTypes.h" +#include "IAttributeExchangingObject.h" +#include "IEventReceiver.h" + +namespace irr +{ +namespace io +{ + class IAttributes; +} // end namespace io +namespace scene +{ + class ISceneNode; + class ISceneManager; + + //! Animates a scene node. Can animate position, rotation, material, and so on. + /** A scene node animator is able to animate a scene node in a very simple way. It may + change its position, rotation, scale and/or material. There are lots of animators + to choose from. You can create scene node animators with the ISceneManager interface. + */ + class ISceneNodeAnimator : public io::IAttributeExchangingObject, public IEventReceiver + { + public: + //! Animates a scene node. + /** \param node Node to animate. + \param timeMs Current time in milli seconds. */ + virtual void animateNode(ISceneNode* node, u32 timeMs) =0; + + //! Creates a clone of this animator. + /** Please note that you will have to drop + (IReferenceCounted::drop()) the returned pointer after calling this. */ + virtual ISceneNodeAnimator* createClone(ISceneNode* node, + ISceneManager* newManager=0) =0; + + //! Returns true if this animator receives events. + /** When attached to an active camera, this animator will be + able to respond to events such as mouse and keyboard events. */ + virtual bool isEventReceiverEnabled() const + { + return false; + } + + //! Event receiver, override this function for camera controlling animators + virtual bool OnEvent(const SEvent& event) + { + return false; + } + + //! Returns type of the scene node animator + virtual ESCENE_NODE_ANIMATOR_TYPE getType() const + { + return ESNAT_UNKNOWN; + } + + //! Returns if the animator has finished. + /** This is only valid for non-looping animators with a discrete end state. + \return true if the animator has finished, false if it is still running. */ + virtual bool hasFinished(void) const + { + return false; + } + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeAnimatorCameraFPS.h b/inc/ISceneNodeAnimatorCameraFPS.h new file mode 100644 index 0000000..adfe9e9 --- /dev/null +++ b/inc/ISceneNodeAnimatorCameraFPS.h @@ -0,0 +1,69 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ + +#include "ISceneNodeAnimator.h" +#include "IEventReceiver.h" +#include "irrArray.h" + +namespace irr +{ + struct SKeyMap; + +namespace scene +{ + + //! Special scene node animator for FPS cameras + /** This scene node animator can be attached to a camera to make it act + like a first person shooter + */ + class ISceneNodeAnimatorCameraFPS : public ISceneNodeAnimator + { + public: + + //! Returns the speed of movement in units per millisecond + virtual f32 getMoveSpeed() const = 0; + + //! Sets the speed of movement in units per millisecond + virtual void setMoveSpeed(f32 moveSpeed) = 0; + + //! Returns the rotation speed in degrees + /** The degrees are equivalent to a half screen movement of the mouse, + i.e. if the mouse cursor had been moved to the border of the screen since + the last animation. */ + virtual f32 getRotateSpeed() const = 0; + + //! Set the rotation speed in degrees + virtual void setRotateSpeed(f32 rotateSpeed) = 0; + + //! Sets the keyboard mapping for this animator (old style) + /** \param map Array of keyboard mappings, see irr::SKeyMap + \param count Size of the keyboard map array. */ + virtual void setKeyMap(SKeyMap *map, u32 count) = 0; + + //! Sets the keyboard mapping for this animator + //! \param keymap The new keymap array + virtual void setKeyMap(const core::array& keymap) = 0; + + //! Gets the keyboard mapping for this animator + virtual const core::array& getKeyMap() const = 0; + + //! Sets whether vertical movement should be allowed. + /** If vertical movement is enabled then the camera may fight with + gravity causing camera shake. Disable this if the camera has + a collision animator with gravity enabled. */ + virtual void setVerticalMovement(bool allow) = 0; + + //! Sets whether the Y axis of the mouse should be inverted. + /** If enabled then moving the mouse down will cause + the camera to look up. It is disabled by default. */ + virtual void setInvertMouse(bool invert) = 0; + }; +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeAnimatorCameraMaya.h b/inc/ISceneNodeAnimatorCameraMaya.h new file mode 100644 index 0000000..ebee950 --- /dev/null +++ b/inc/ISceneNodeAnimatorCameraMaya.h @@ -0,0 +1,58 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ + +#include "ISceneNodeAnimator.h" + +namespace irr +{ + +namespace scene +{ + + //! Special scene node animator for Maya-style cameras + /** This scene node animator can be attached to a camera to make it act like a 3d + modelling tool. + The camera is moving relative to the target with the mouse, by pressing either + of the three buttons. + In order to move the camera, set a new target for the camera. The distance defines + the current orbit radius the camera moves on. Distance can be changed via the setter + or by mouse events. + */ + class ISceneNodeAnimatorCameraMaya : public ISceneNodeAnimator + { + public: + + //! Returns the speed of movement + virtual f32 getMoveSpeed() const = 0; + + //! Sets the speed of movement + virtual void setMoveSpeed(f32 moveSpeed) = 0; + + //! Returns the rotation speed + virtual f32 getRotateSpeed() const = 0; + + //! Set the rotation speed + virtual void setRotateSpeed(f32 rotateSpeed) = 0; + + //! Returns the zoom speed + virtual f32 getZoomSpeed() const = 0; + + //! Set the zoom speed + virtual void setZoomSpeed(f32 zoomSpeed) = 0; + + //! Returns the current distance, i.e. orbit radius + virtual f32 getDistance() const = 0; + + //! Set the distance + virtual void setDistance(f32 distance) = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeAnimatorCollisionResponse.h b/inc/ISceneNodeAnimatorCollisionResponse.h new file mode 100644 index 0000000..e2bba8a --- /dev/null +++ b/inc/ISceneNodeAnimatorCollisionResponse.h @@ -0,0 +1,171 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + + class ISceneNodeAnimatorCollisionResponse; + + //! Callback interface for catching events of collisions. + /** Implement this interface and use + ISceneNodeAnimatorCollisionResponse::setCollisionCallback to be able to + be notified if a collision has occurred. + **/ + class ICollisionCallback : public virtual IReferenceCounted + { + public: + + //! Will be called when a collision occurrs. + /** See ISceneNodeAnimatorCollisionResponse::setCollisionCallback for more information. + \param animator: Collision response animator in which the collision occurred. You can call + this animator's methods to find the node, collisionPoint and/or collision triangle. + \retval true if the collision was handled in the animator. The animator's target + node will *not* be stopped at the collision point, but will instead move fully + to the location that triggered the collision check. + \retval false if the collision was not handled in the animator. The animator's + target node will be moved to the collision position. + */ + virtual bool onCollision(const ISceneNodeAnimatorCollisionResponse& animator) = 0; + }; + + //! Special scene node animator for doing automatic collision detection and response. + /** This scene node animator can be attached to any single scene node + and will then prevent it from moving through specified collision geometry + (e.g. walls and floors of the) world, as well as having it fall under gravity. + This animator provides a simple implementation of first person shooter cameras. + Attach it to a camera, and the camera will behave as the player control in a + first person shooter game: The camera stops and slides at walls, walks up stairs, + falls down if there is no floor under it, and so on. + + The animator will treat any change in the position of its target scene + node as movement, including a setPosition(), as movement. If you want to + teleport the target scene node manually to a location without it being effected + by collision geometry, then call setTargetNode(node) after calling node->setPosition(). + */ + class ISceneNodeAnimatorCollisionResponse : public ISceneNodeAnimator + { + public: + + //! Destructor + virtual ~ISceneNodeAnimatorCollisionResponse() {} + + //! Check if the attached scene node is falling. + /** Falling means that there is no blocking wall from the scene + node in the direction of the gravity. The implementation of + this method is very fast, no collision detection is done when + invoking it. + \return True if the scene node is falling, false if not. */ + virtual bool isFalling() const = 0; + + //! Sets the radius of the ellipsoid for collision detection and response. + /** If you have a scene node, and you are unsure about how big + the radius should be, you could use the following code to + determine it: + \code + core::aabbox box = yourSceneNode->getBoundingBox(); + core::vector3df radius = box.MaxEdge - box.getCenter(); + \endcode + \param radius: New radius of the ellipsoid. */ + virtual void setEllipsoidRadius(const core::vector3df& radius) = 0; + + //! Returns the radius of the ellipsoid for collision detection and response. + /** \return Radius of the ellipsoid. */ + virtual core::vector3df getEllipsoidRadius() const = 0; + + //! Sets the gravity of the environment. + /** A good example value would be core::vector3df(0,-100.0f,0) + for letting gravity affect all object to fall down. For bigger + gravity, make increase the length of the vector. You can + disable gravity by setting it to core::vector3df(0,0,0); + \param gravity: New gravity vector. */ + virtual void setGravity(const core::vector3df& gravity) = 0; + + //! Get current vector of gravity. + //! \return Gravity vector. */ + virtual core::vector3df getGravity() const = 0; + + //! 'Jump' the animator, by adding a jump speed opposite to its gravity + /** \param jumpSpeed The initial speed of the jump; the velocity will be opposite + to this animator's gravity vector. */ + virtual void jump(f32 jumpSpeed) = 0; + + //! Should the Target react on collision ( default = true ) + virtual void setAnimateTarget ( bool enable ) = 0; + virtual bool getAnimateTarget () const = 0; + + //! Set translation of the collision ellipsoid. + /** By default, the ellipsoid for collision detection is + created around the center of the scene node, which means that + the ellipsoid surrounds it completely. If this is not what you + want, you may specify a translation for the ellipsoid. + \param translation: Translation of the ellipsoid relative + to the position of the scene node. */ + virtual void setEllipsoidTranslation(const core::vector3df &translation) = 0; + + //! Get the translation of the ellipsoid for collision detection. + /** See + ISceneNodeAnimatorCollisionResponse::setEllipsoidTranslation() + for more details. + \return Translation of the ellipsoid relative to the position + of the scene node. */ + virtual core::vector3df getEllipsoidTranslation() const = 0; + + //! Sets a triangle selector holding all triangles of the world with which the scene node may collide. + /** \param newWorld: New triangle selector containing triangles + to let the scene node collide with. */ + virtual void setWorld(ITriangleSelector* newWorld) = 0; + + //! Get the current triangle selector containing all triangles for collision detection. + virtual ITriangleSelector* getWorld() const = 0; + + //! Set the single node that this animator will act on. + /** \param node The new target node. Setting this will force the animator to update + its last target position for the node, allowing setPosition() to teleport + the node through collision geometry. */ + virtual void setTargetNode(ISceneNode * node) = 0; + + //! Gets the single node that this animator is acting on. + /** \return The node that this animator is acting on. */ + virtual ISceneNode* getTargetNode(void) const = 0; + + //! Returns true if a collision occurred during the last animateNode() + virtual bool collisionOccurred() const = 0; + + //! Returns the last point of collision. + virtual const core::vector3df & getCollisionPoint() const = 0; + + //! Returns the last triangle that caused a collision + virtual const core::triangle3df & getCollisionTriangle() const = 0; + + //! Returns the position that the target node will be moved to, unless the collision is consumed in a callback. + /** + If you have a collision callback registered, and it consumes the collision, then the + node will ignore the collision and will not stop at this position. Instead, it will + move fully to the position that caused the collision to occur. */ + virtual const core::vector3df & getCollisionResultPosition(void) const = 0; + + //! Returns the node that was collided with. + virtual ISceneNode* getCollisionNode(void) const = 0; + + //! Sets a callback interface which will be called if a collision occurs. + /** \param callback: collision callback handler that will be called when a collision + occurs. Set this to 0 to disable the callback. + */ + virtual void setCollisionCallback(ICollisionCallback* callback) = 0; + + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeAnimatorFactory.h b/inc/ISceneNodeAnimatorFactory.h new file mode 100644 index 0000000..8afe3ef --- /dev/null +++ b/inc/ISceneNodeAnimatorFactory.h @@ -0,0 +1,69 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__ +#define __I_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "ESceneNodeAnimatorTypes.h" + +namespace irr +{ +namespace scene +{ + class ISceneNode; + class ISceneNodeAnimator; + + //! Interface for dynamic creation of scene node animators + /** To be able to add custom scene node animators to Irrlicht and to make it possible for the + scene manager to save and load those external animators, simply implement this + interface and register it in you scene manager via ISceneManager::registerSceneNodeAnimatorFactory. + Note: When implementing your own scene node factory, don't call ISceneNodeManager::grab() to + increase the reference counter of the scene node manager. This is not necessary because the + scene node manager will grab() the factory anyway, and otherwise cyclic references will + be created and the scene manager and all its nodes won't get deallocated. + */ + class ISceneNodeAnimatorFactory : public virtual IReferenceCounted + { + public: + + //! creates a scene node animator based on its type id + /** \param type: Type of the scene node animator to add. + \param target: Target scene node of the new animator. + \return Returns pointer to the new scene node animator or null if not successful. You need to + drop this pointer after calling this, see IReferenceCounted::drop() for details. */ + virtual ISceneNodeAnimator* createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target) = 0; + + //! creates a scene node animator based on its type name + /** \param typeName: Type of the scene node animator to add. + \param target: Target scene node of the new animator. + \return Returns pointer to the new scene node animator or null if not successful. You need to + drop this pointer after calling this, see IReferenceCounted::drop() for details. */ + virtual ISceneNodeAnimator* createSceneNodeAnimator(const c8* typeName, ISceneNode* target) = 0; + + //! returns amount of scene node animator types this factory is able to create + virtual u32 getCreatableSceneNodeAnimatorTypeCount() const = 0; + + //! returns type of a createable scene node animator type + /** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and + getCreatableSceneNodeTypeCount() */ + virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const = 0; + + //! returns type name of a createable scene node animator type + /** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and + getCreatableSceneNodeAnimatorTypeCount() */ + virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const = 0; + + //! returns type name of a createable scene node animator type + /** \param type: Type of scene node animator. + \return: Returns name of scene node animator type if this factory can create the type, otherwise 0. */ + virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneNodeFactory.h b/inc/ISceneNodeFactory.h new file mode 100644 index 0000000..247b47b --- /dev/null +++ b/inc/ISceneNodeFactory.h @@ -0,0 +1,68 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_NODE_FACTORY_H_INCLUDED__ +#define __I_SCENE_NODE_FACTORY_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "ESceneNodeTypes.h" + +namespace irr +{ + +namespace scene +{ + class ISceneNode; + + //! Interface for dynamic creation of scene nodes + /** To be able to add custom scene nodes to Irrlicht and to make it possible for the + scene manager to save and load those external scene nodes, simply implement this + interface and register it in you scene manager via ISceneManager::registerSceneNodeFactory. + Note: When implementing your own scene node factory, don't call ISceneNodeManager::grab() to + increase the reference counter of the scene node manager. This is not necessary because the + scene node manager will grab() the factory anyway, and otherwise cyclic references will + be created and the scene manager and all its nodes won't get deallocated. + */ + class ISceneNodeFactory : public virtual IReferenceCounted + { + public: + //! adds a scene node to the scene graph based on its type id + /** \param type: Type of the scene node to add. + \param parent: Parent scene node of the new node, can be null to add the scene node to the root. + \return Returns pointer to the new scene node or null if not successful. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0) = 0; + + //! adds a scene node to the scene graph based on its type name + /** \param typeName: Type name of the scene node to add. + \param parent: Parent scene node of the new node, can be null to add the scene node to the root. + \return Returns pointer to the new scene node or null if not successful. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0) = 0; + + //! returns amount of scene node types this factory is able to create + virtual u32 getCreatableSceneNodeTypeCount() const = 0; + + //! returns type of a createable scene node type + /** \param idx: Index of scene node type in this factory. Must be a value between 0 and + getCreatableSceneNodeTypeCount() */ + virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const = 0; + + //! returns type name of a createable scene node type by index + /** \param idx: Index of scene node type in this factory. Must be a value between 0 and + getCreatableSceneNodeTypeCount() */ + virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const = 0; + + //! returns type name of a createable scene node type + /** \param type: Type of scene node. + \return: Returns name of scene node type if this factory can create the type, otherwise 0. */ + virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISceneUserDataSerializer.h b/inc/ISceneUserDataSerializer.h new file mode 100644 index 0000000..0e63440 --- /dev/null +++ b/inc/ISceneUserDataSerializer.h @@ -0,0 +1,51 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_USER_DATA_SERIALIZER_H_INCLUDED__ +#define __I_SCENE_USER_DATA_SERIALIZER_H_INCLUDED__ + +#include "IReferenceCounted.h" + +namespace irr +{ +namespace io +{ + class IAttributes; +} // end namespace io +namespace scene +{ + class ISceneNode; + +//! Interface to read and write user data to and from .irr files. +/** This interface is to be implemented by the user, to make it possible to read +and write user data when reading or writing .irr files via ISceneManager. +To be used with ISceneManager::loadScene() and ISceneManager::saveScene() */ +class ISceneUserDataSerializer +{ +public: + + virtual ~ISceneUserDataSerializer() {} + + //! Called when the scene manager create a scene node while loading a file. + virtual void OnCreateNode(ISceneNode* node) = 0; + + //! Called when the scene manager read a scene node while loading a file. + /** The userData pointer contains a list of attributes with userData which + were attached to the scene node in the read scene file.*/ + virtual void OnReadUserData(ISceneNode* forSceneNode, io::IAttributes* userData) = 0; + + //! Called when the scene manager is writing a scene node to an xml file for example. + /** Implement this method and return a list of attributes containing the user data + you want to be saved together with the scene node. Return 0 if no user data should + be added. Please note that the scene manager will call drop() to the returned pointer + after it no longer needs it, so if you didn't create a new object for the return value + and returning a longer existing IAttributes object, simply call grab() before returning it. */ + virtual io::IAttributes* createUserData(ISceneNode* forSceneNode) = 0; +}; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IShaderConstantSetCallBack.h b/inc/IShaderConstantSetCallBack.h new file mode 100644 index 0000000..f88393f --- /dev/null +++ b/inc/IShaderConstantSetCallBack.h @@ -0,0 +1,85 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SHADER_CONSTANT_SET_CALLBACT_H_INCLUDED__ +#define __I_SHADER_CONSTANT_SET_CALLBACT_H_INCLUDED__ + +#include "IReferenceCounted.h" + +namespace irr +{ +namespace video +{ + class IMaterialRendererServices; + class SMaterial; + +//! Interface making it possible to set constants for gpu programs every frame. +/** Implement this interface in an own class and pass a pointer to it to one of +the methods in IGPUProgrammingServices when creating a shader. The +OnSetConstants method will be called every frame now. */ +class IShaderConstantSetCallBack : public virtual IReferenceCounted +{ +public: + + //! Called to let the callBack know the used material (optional method) + /** + \code + class MyCallBack : public IShaderConstantSetCallBack + { + const video::SMaterial *UsedMaterial; + + OnSetMaterial(const video::SMaterial& material) + { + UsedMaterial=&material; + } + + OnSetConstants(IMaterialRendererServices* services, s32 userData) + { + services->setVertexShaderConstant("myColor", reinterpret_cast(&UsedMaterial->color), 4); + } + } + \endcode + */ + virtual void OnSetMaterial(const SMaterial& material) { } + + //! Called by the engine when the vertex and/or pixel shader constants for an material renderer should be set. + /** + Implement the IShaderConstantSetCallBack in an own class and implement your own + OnSetConstants method using the given IMaterialRendererServices interface. + Pass a pointer to this class to one of the methods in IGPUProgrammingServices + when creating a shader. The OnSetConstants method will now be called every time + before geometry is being drawn using your shader material. A sample implementation + would look like this: + \code + virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) + { + video::IVideoDriver* driver = services->getVideoDriver(); + + // set clip matrix at register 4 + core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); + worldViewProj *= driver->getTransform(video::ETS_VIEW); + worldViewProj *= driver->getTransform(video::ETS_WORLD); + services->setVertexShaderConstant(&worldViewProj.M[0], 4, 4); + // for high level shading languages, this would be another solution: + //services->setVertexShaderConstant("mWorldViewProj", worldViewProj.M, 16); + + // set some light color at register 9 + video::SColorf col(0.0f,1.0f,1.0f,0.0f); + services->setVertexShaderConstant(reinterpret_cast(&col), 9, 1); + // for high level shading languages, this would be another solution: + //services->setVertexShaderConstant("myColor", reinterpret_cast(&col), 4); + } + \endcode + \param services: Pointer to an interface providing methods to set the constants for the shader. + \param userData: Userdata int which can be specified when creating the shader. + */ + virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData) = 0; +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/IShadowVolumeSceneNode.h b/inc/IShadowVolumeSceneNode.h new file mode 100644 index 0000000..40781a9 --- /dev/null +++ b/inc/IShadowVolumeSceneNode.h @@ -0,0 +1,38 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__ +#define __I_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + class IMesh; + + //! Scene node for rendering a shadow volume into a stencil buffer. + class IShadowVolumeSceneNode : public ISceneNode + { + public: + + //! constructor + IShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) + : ISceneNode(parent, mgr, id) {} + + //! Sets the mesh from which the shadow volume should be generated. + /** To optimize shadow rendering, use a simpler mesh for shadows. + */ + virtual void setShadowMesh(const IMesh* mesh) = 0; + + //! Updates the shadow volumes for current light positions. + virtual void updateShadowVolumes() = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ISkinnedMesh.h b/inc/ISkinnedMesh.h new file mode 100644 index 0000000..5f0f9cb --- /dev/null +++ b/inc/ISkinnedMesh.h @@ -0,0 +1,219 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SKINNED_MESH_H_INCLUDED__ +#define __I_SKINNED_MESH_H_INCLUDED__ + +#include "irrArray.h" +#include "IBoneSceneNode.h" +#include "IAnimatedMesh.h" +#include "SSkinMeshBuffer.h" + +namespace irr +{ +namespace scene +{ + + enum E_INTERPOLATION_MODE + { + // constant does use the current key-values without interpolation + EIM_CONSTANT = 0, + + // linear interpolation + EIM_LINEAR, + + //! count of all available interpolation modes + EIM_COUNT + }; + + + //! Interface for using some special functions of Skinned meshes + class ISkinnedMesh : public IAnimatedMesh + { + public: + + //! Gets joint count. + /** \return Amount of joints in the skeletal animated mesh. */ + virtual u32 getJointCount() const = 0; + + //! Gets the name of a joint. + /** \param number: Zero based index of joint. The last joint + has the number getJointCount()-1; + \return Name of joint and null if an error happened. */ + virtual const c8* getJointName(u32 number) const = 0; + + //! Gets a joint number from its name + /** \param name: Name of the joint. + \return Number of the joint or -1 if not found. */ + virtual s32 getJointNumber(const c8* name) const = 0; + + //! Use animation from another mesh + /** The animation is linked (not copied) based on joint names + so make sure they are unique. + \return True if all joints in this mesh were + matched up (empty names will not be matched, and it's case + sensitive). Unmatched joints will not be animated. */ + virtual bool useAnimationFrom(const ISkinnedMesh *mesh) = 0; + + //! Update Normals when Animating + /** \param on If false don't animate, which is faster. + Else update normals, which allows for proper lighting of + animated meshes. */ + virtual void updateNormalsWhenAnimating(bool on) = 0; + + //! Sets Interpolation Mode + virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) = 0; + + //! Animates this mesh's joints based on frame input + virtual void animateMesh(f32 frame, f32 blend)=0; + + //! Preforms a software skin on this mesh based of joint positions + virtual void skinMesh() = 0; + + //! converts the vertex type of all meshbuffers to tangents. + /** E.g. used for bump mapping. */ + virtual void convertMeshToTangents() = 0; + + //! Allows to enable hardware skinning. + /* This feature is not implementated in Irrlicht yet */ + virtual bool setHardwareSkinning(bool on) = 0; + + //! A vertex weight + struct SWeight + { + //! Index of the mesh buffer + u16 buffer_id; //I doubt 32bits is needed + + //! Index of the vertex + u32 vertex_id; //Store global ID here + + //! Weight Strength/Percentage (0-1) + f32 strength; + + private: + //! Internal members used by CSkinnedMesh + friend class CSkinnedMesh; + bool *Moved; + core::vector3df StaticPos; + core::vector3df StaticNormal; + }; + + + //! Animation keyframe which describes a new position + struct SPositionKey + { + f32 frame; + core::vector3df position; + }; + + //! Animation keyframe which describes a new scale + struct SScaleKey + { + f32 frame; + core::vector3df scale; + }; + + //! Animation keyframe which describes a new rotation + struct SRotationKey + { + f32 frame; + core::quaternion rotation; + }; + + //! Joints + struct SJoint + { + SJoint() : UseAnimationFrom(0), GlobalSkinningSpace(false), + positionHint(-1),scaleHint(-1),rotationHint(-1) + { + } + + //! The name of this joint + core::stringc Name; + + //! Local matrix of this joint + core::matrix4 LocalMatrix; + + //! List of child joints + core::array Children; + + //! List of attached meshes + core::array AttachedMeshes; + + //! Animation keys causing translation change + core::array PositionKeys; + + //! Animation keys causing scale change + core::array ScaleKeys; + + //! Animation keys causing rotation change + core::array RotationKeys; + + //! Skin weights + core::array Weights; + + //! Unnecessary for loaders, will be overwritten on finalize + core::matrix4 GlobalMatrix; + core::matrix4 GlobalAnimatedMatrix; + core::matrix4 LocalAnimatedMatrix; + core::vector3df Animatedposition; + core::vector3df Animatedscale; + core::quaternion Animatedrotation; + + core::matrix4 GlobalInversedMatrix; //the x format pre-calculates this + + private: + //! Internal members used by CSkinnedMesh + friend class CSkinnedMesh; + + SJoint *UseAnimationFrom; + bool GlobalSkinningSpace; + + s32 positionHint; + s32 scaleHint; + s32 rotationHint; + }; + + + //Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_ + + //these functions will use the needed arrays, set values, etc to help the loaders + + //! exposed for loaders: to add mesh buffers + virtual core::array& getMeshBuffers() = 0; + + //! exposed for loaders: joints list + virtual core::array& getAllJoints() = 0; + + //! exposed for loaders: joints list + virtual const core::array& getAllJoints() const = 0; + + //! loaders should call this after populating the mesh + virtual void finalize() = 0; + + //! Adds a new meshbuffer to the mesh, access it as last one + virtual SSkinMeshBuffer* addMeshBuffer() = 0; + + //! Adds a new joint to the mesh, access it as last one + virtual SJoint* addJoint(SJoint *parent=0) = 0; + + //! Adds a new weight to the mesh, access it as last one + virtual SWeight* addWeight(SJoint *joint) = 0; + + //! Adds a new position key to the mesh, access it as last one + virtual SPositionKey* addPositionKey(SJoint *joint) = 0; + //! Adds a new scale key to the mesh, access it as last one + virtual SScaleKey* addScaleKey(SJoint *joint) = 0; + //! Adds a new rotation key to the mesh, access it as last one + virtual SRotationKey* addRotationKey(SJoint *joint) = 0; + + //! Check if the mesh is non-animated + virtual bool isStatic()=0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/ITerrainSceneNode.h b/inc/ITerrainSceneNode.h new file mode 100644 index 0000000..4802710 --- /dev/null +++ b/inc/ITerrainSceneNode.h @@ -0,0 +1,182 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// The code for the TerrainSceneNode is based on the terrain renderer by +// Soconne and the GeoMipMapSceneNode developed by Spintz. They made their +// code available for Irrlicht and allowed it to be distributed under this +// licence. I only modified some parts. A lot of thanks go to them. + +#ifndef __I_TERRAIN_SCENE_NODE_H__ +#define __I_TERRAIN_SCENE_NODE_H__ + +#include "ETerrainElements.h" +#include "ISceneNode.h" +#include "IDynamicMeshBuffer.h" +#include "irrArray.h" + +namespace irr +{ +namespace io +{ + class IReadFile; +} // end namespace io +namespace scene +{ + class IMesh; + + //! A scene node for displaying terrain using the geo mip map algorithm. + /** The code for the TerrainSceneNode is based on the Terrain renderer by Soconne and + * the GeoMipMapSceneNode developed by Spintz. They made their code available for Irrlicht + * and allowed it to be distributed under this licence. I only modified some parts. + * A lot of thanks go to them. + * + * This scene node is capable of very quickly loading + * terrains and updating the indices at runtime to enable viewing very large terrains. It uses a + * CLOD (Continuous Level of Detail) algorithm which updates the indices for each patch based on + * a LOD (Level of Detail) which is determined based on a patch's distance from the camera. + * + * The Patch Size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ). + * The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all + * of the indices to draw all the triangles at the max detail for a patch. As each LOD goes up by 1 + * the step taken, in generating indices increases by - 2^LOD, so for LOD 1, the step taken is 2, for + * LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than the size of the patch, + * so having a LOD of 8, with a patch size of 17, is asking the algoritm to generate indices every + * 2^8 ( 256 ) vertices, which is not possible with a patch size of 17. The maximum LOD for a patch + * size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( every + * 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices ) and LOD 4 ( every 16 vertices ). + **/ + class ITerrainSceneNode : public ISceneNode + { + public: + //! Constructor + ITerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0.0f, 0.0f, 0.0f), + const core::vector3df& rotation = core::vector3df(0.0f, 0.0f, 0.0f), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f) ) + : ISceneNode (parent, mgr, id, position, rotation, scale) {} + + //! Get the bounding box of the terrain. + /** \return The bounding box of the entire terrain. */ + virtual const core::aabbox3d& getBoundingBox() const =0; + + //! Get the bounding box of a patch + /** \return The bounding box of the chosen patch. */ + virtual const core::aabbox3d& getBoundingBox(s32 patchX, s32 patchZ) const =0; + + //! Get the number of indices currently in the meshbuffer + /** \return The index count. */ + virtual u32 getIndexCount() const =0; + + //! Get pointer to the mesh + /** \return Pointer to the mesh. */ + virtual IMesh* getMesh() =0; + + //! Get pointer to the buffer used by the terrain (most users will not need this) + virtual IMeshBuffer* getRenderBuffer() =0; + + + //! Gets the meshbuffer data based on a specified level of detail. + /** \param mb A reference to an IDynamicMeshBuffer object + \param LOD The level of detail you want the indices from. */ + virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const =0; + + //! Gets the indices for a specified patch at a specified Level of Detail. + /** \param indices A reference to an array of u32 indices. + \param patchX Patch x coordinate. + \param patchZ Patch z coordinate. + \param LOD The level of detail to get for that patch. If -1, + then get the CurrentLOD. If the CurrentLOD is set to -1, + meaning it's not shown, then it will retrieve the triangles at + the highest LOD (0). + \return Number of indices put into the buffer. */ + virtual s32 getIndicesForPatch(core::array& indices, + s32 patchX, s32 patchZ, s32 LOD=0) =0; + + //! Populates an array with the CurrentLOD of each patch. + /** \param LODs A reference to a core::array to hold the + values + \return Number of elements in the array */ + virtual s32 getCurrentLODOfPatches(core::array& LODs) const =0; + + //! Manually sets the LOD of a patch + /** \param patchX Patch x coordinate. + \param patchZ Patch z coordinate. + \param LOD The level of detail to set the patch to. */ + virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; + + //! Get center of terrain. + virtual const core::vector3df& getTerrainCenter() const =0; + + //! Get height of a point of the terrain. + virtual f32 getHeight(f32 x, f32 y) const =0; + + //! Sets the movement camera threshold. + /** It is used to determine when to recalculate + indices for the scene node. The default value is 10.0f. */ + virtual void setCameraMovementDelta(f32 delta) =0; + + //! Sets the rotation camera threshold. + /** It is used to determine when to recalculate + indices for the scene node. The default value is 1.0f. */ + virtual void setCameraRotationDelta(f32 delta) =0; + + //! Sets whether or not the node should dynamically update its associated selector when the geomipmap data changes. + /** \param bVal: Boolean value representing whether or not to update selector dynamically. */ + virtual void setDynamicSelectorUpdate(bool bVal) =0; + + //! Override the default generation of distance thresholds. + /** For determining the LOD a patch is rendered at. If any LOD + is overridden, then the scene node will no longer apply scaling + factors to these values. If you override these distances, and + then apply a scale to the scene node, it is your responsibility + to update the new distances to work best with your new terrain + size. */ + virtual bool overrideLODDistance(s32 LOD, f64 newDistance) =0; + + //! Scales the base texture, similar to makePlanarTextureMapping. + /** \param scale The scaling amount. Values above 1.0 + increase the number of time the texture is drawn on the + terrain. Values below 0 will decrease the number of times the + texture is drawn on the terrain. Using negative values will + flip the texture, as well as still scaling it. + \param scale2 If set to 0 (default value), this will set the + second texture coordinate set to the same values as in the + first set. If this is another value than zero, it will scale + the second texture coordinate set by this value. */ + virtual void scaleTexture(f32 scale = 1.0f, f32 scale2=0.0f) =0; + + //! Initializes the terrain data. Loads the vertices from the heightMapFile. + /** The file must contain a loadable image of the heightmap. The heightmap + must be square. + \param file The file to read the image from. File is not rewinded. + \param vertexColor Color of all vertices. + \param smoothFactor Number of smoothing passes. */ + virtual bool loadHeightMap(io::IReadFile* file, + video::SColor vertexColor=video::SColor(255,255,255,255), + s32 smoothFactor=0) =0; + + //! Initializes the terrain data. Loads the vertices from the heightMapFile. + /** The data is interpreted as (signed) integers of the given bit size or + floats (with 32bits, signed). Allowed bitsizes for integers are + 8, 16, and 32. The heightmap must be square. + \param file The file to read the RAW data from. File is not rewinded. + \param bitsPerPixel Size of data if integers used, for floats always use 32. + \param signedData Whether we use signed or unsigned ints, ignored for floats. + \param floatVals Whether the data is float or int. + \param width Width (and also Height, as it must be square) of the heightmap. Use 0 for autocalculating from the filesize. + \param vertexColor Color of all vertices. + \param smoothFactor Number of smoothing passes. */ + virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel=16, + bool signedData=false, bool floatVals=false, s32 width=0, + video::SColor vertexColor=video::SColor(255,255,255,255), + s32 smoothFactor=0) =0; + + }; + +} // end namespace scene +} // end namespace irr + + +#endif // __I_TERRAIN_SCENE_NODE_H__ + diff --git a/inc/ITextSceneNode.h b/inc/ITextSceneNode.h new file mode 100644 index 0000000..e715a46 --- /dev/null +++ b/inc/ITextSceneNode.h @@ -0,0 +1,37 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_TEXT_SCENE_NODE_H_INCLUDED__ +#define __I_TEXT_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! A scene node for displaying 2d text at a position in three dimensional space +class ITextSceneNode : public ISceneNode +{ +public: + + //! constructor + ITextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0)) + : ISceneNode(parent, mgr, id, position) {} + + //! sets the text string + virtual void setText(const wchar_t* text) = 0; + + //! sets the color of the text + virtual void setTextColor(video::SColor color) = 0; +}; + +} // end namespace scene +} // end namespace irr + + +#endif + diff --git a/inc/ITexture.h b/inc/ITexture.h new file mode 100644 index 0000000..66f039d --- /dev/null +++ b/inc/ITexture.h @@ -0,0 +1,219 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_TEXTURE_H_INCLUDED__ +#define __I_TEXTURE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IImage.h" +#include "dimension2d.h" +#include "EDriverTypes.h" +#include "path.h" +#include "matrix4.h" + +namespace irr +{ +namespace video +{ + + +//! Enumeration flags telling the video driver in which format textures should be created. +enum E_TEXTURE_CREATION_FLAG +{ + /** Forces the driver to create 16 bit textures always, independent of + which format the file on disk has. When choosing this you may lose + some color detail, but gain much speed and memory. 16 bit textures can + be transferred twice as fast as 32 bit textures and only use half of + the space in memory. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_32_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or + ETCF_OPTIMIZED_FOR_SPEED at the same time. */ + ETCF_ALWAYS_16_BIT = 0x00000001, + + /** Forces the driver to create 32 bit textures always, independent of + which format the file on disk has. Please note that some drivers (like + the software device) will ignore this, because they are only able to + create and use 16 bit textures. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or + ETCF_OPTIMIZED_FOR_SPEED at the same time. */ + ETCF_ALWAYS_32_BIT = 0x00000002, + + /** Lets the driver decide in which format the textures are created and + tries to make the textures look as good as possible. Usually it simply + chooses the format in which the texture was stored on disk. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_SPEED at + the same time. */ + ETCF_OPTIMIZED_FOR_QUALITY = 0x00000004, + + /** Lets the driver decide in which format the textures are created and + tries to create them maximizing render speed. + When using this flag, it does not make sense to use the flags + ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_QUALITY, + at the same time. */ + ETCF_OPTIMIZED_FOR_SPEED = 0x00000008, + + /** Automatically creates mip map levels for the textures. */ + ETCF_CREATE_MIP_MAPS = 0x00000010, + + /** Discard any alpha layer and use non-alpha color format. */ + ETCF_NO_ALPHA_CHANNEL = 0x00000020, + + //! Allow the Driver to use Non-Power-2-Textures + /** BurningVideo can handle Non-Power-2 Textures in 2D (GUI), but not in 3D. */ + ETCF_ALLOW_NON_POWER_2 = 0x00000040, + + /** This flag is never used, it only forces the compiler to compile + these enumeration values to 32 bit. */ + ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff +}; + +//! Enum for the mode for texture locking. Read-Only, write-only or read/write. +enum E_TEXTURE_LOCK_MODE +{ + //! The default mode. Texture can be read and written to. + ETLM_READ_WRITE = 0, + + //! Read only. The texture is downloaded, but not uploaded again. + /** Often used to read back shader generated textures. */ + ETLM_READ_ONLY, + + //! Write only. The texture is not downloaded and might be uninitialised. + /** The updated texture is uploaded to the GPU. + Used for initialising the shader from the CPU. */ + ETLM_WRITE_ONLY +}; + +//! Interface of a Video Driver dependent Texture. +/** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture +or IVideoDriver::getTexture. After that, the texture may only be used by this +VideoDriver. As you can imagine, textures of the DirectX and the OpenGL device +will, e.g., not be compatible. An exception is the Software device and the +NULL device, their textures are compatible. If you try to use a texture +created by one device with an other device, the device will refuse to do that +and write a warning or an error message to the output buffer. +*/ +class ITexture : public virtual IReferenceCounted +{ +public: + + //! constructor + ITexture(const io::path& name) : NamedPath(name) + { + } + + //! Lock function. + /** Locks the Texture and returns a pointer to access the + pixels. After lock() has been called and all operations on the pixels + are done, you must call unlock(). + Locks are not accumulating, hence one unlock will do for an arbitrary + number of previous locks. You should avoid locking different levels without + unlocking inbetween, though, because only the last level locked will be + unlocked. + The size of the i-th mipmap level is defined as max(getSize().Width>>i,1) + and max(getSize().Height>>i,1) + \param mode Specifies what kind of changes to the locked texture are + allowed. Unspecified behavior will arise if texture is written in read + only mode or read from in write only mode. + Support for this feature depends on the driver, so don't rely on the + texture being write-protected when locking with read-only, etc. + \param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture. + Non-existing levels will silently fail and return 0. + \return Returns a pointer to the pixel data. The format of the pixel can + be determined by using getColorFormat(). 0 is returned, if + the texture cannot be locked. */ + virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) = 0; + + //! Unlock function. Must be called after a lock() to the texture. + /** One should avoid to call unlock more than once before another lock. + The last locked mip level will be unlocked. */ + virtual void unlock() = 0; + + //! Get original size of the texture. + /** The texture is usually scaled, if it was created with an unoptimal + size. For example if the size was not a power of two. This method + returns the size of the texture it had before it was scaled. Can be + useful when drawing 2d images on the screen, which should have the + exact size of the original texture. Use ITexture::getSize() if you want + to know the real size it has now stored in the system. + \return The original size of the texture. */ + virtual const core::dimension2d& getOriginalSize() const = 0; + + //! Get dimension (=size) of the texture. + /** \return The size of the texture. */ + virtual const core::dimension2d& getSize() const = 0; + + //! Get driver type of texture. + /** This is the driver, which created the texture. This method is used + internally by the video devices, to check, if they may use a texture + because textures may be incompatible between different devices. + \return Driver type of texture. */ + virtual E_DRIVER_TYPE getDriverType() const = 0; + + //! Get the color format of texture. + /** \return The color format of texture. */ + virtual ECOLOR_FORMAT getColorFormat() const = 0; + + //! Get pitch of the main texture (in bytes). + /** The pitch is the amount of bytes used for a row of pixels in a + texture. + \return Pitch of texture in bytes. */ + virtual u32 getPitch() const = 0; + + //! Check whether the texture has MipMaps + /** \return True if texture has MipMaps, else false. */ + virtual bool hasMipMaps() const { return false; } + + //! Returns if the texture has an alpha channel + virtual bool hasAlpha() const { + return getColorFormat () == video::ECF_A8R8G8B8 || getColorFormat () == video::ECF_A1R5G5B5; + } + + //! Regenerates the mip map levels of the texture. + /** Required after modifying the texture, usually after calling unlock(). + \param mipmapData Optional parameter to pass in image data which will be + used instead of the previously stored or automatically generated mipmap + data. The data has to be a continuous pixel data for all mipmaps until + 1x1 pixel. Each mipmap has to be half the width and height of the previous + level. At least one pixel will be always kept.*/ + virtual void regenerateMipMapLevels(void* mipmapData=0) = 0; + + //! Check whether the texture is a render target + /** Render targets can be set as such in the video driver, in order to + render a scene into the texture. Once unbound as render target, they can + be used just as usual textures again. + \return True if this is a render target, otherwise false. */ + virtual bool isRenderTarget() const { return false; } + + //! Get name of texture (in most cases this is the filename) + const io::SNamedPath& getName() const { return NamedPath; } + +protected: + + //! Helper function, helps to get the desired texture creation format from the flags. + /** \return Either ETCF_ALWAYS_32_BIT, ETCF_ALWAYS_16_BIT, + ETCF_OPTIMIZED_FOR_QUALITY, or ETCF_OPTIMIZED_FOR_SPEED. */ + inline E_TEXTURE_CREATION_FLAG getTextureFormatFromFlags(u32 flags) + { + if (flags & ETCF_OPTIMIZED_FOR_SPEED) + return ETCF_OPTIMIZED_FOR_SPEED; + if (flags & ETCF_ALWAYS_16_BIT) + return ETCF_ALWAYS_16_BIT; + if (flags & ETCF_ALWAYS_32_BIT) + return ETCF_ALWAYS_32_BIT; + if (flags & ETCF_OPTIMIZED_FOR_QUALITY) + return ETCF_OPTIMIZED_FOR_QUALITY; + return ETCF_OPTIMIZED_FOR_SPEED; + } + + io::SNamedPath NamedPath; +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/ITimer.h b/inc/ITimer.h new file mode 100644 index 0000000..610d6fa --- /dev/null +++ b/inc/ITimer.h @@ -0,0 +1,103 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_TIMER_H_INCLUDED__ +#define __I_TIMER_H_INCLUDED__ + +#include "IReferenceCounted.h" + +namespace irr +{ + +//! Interface for getting and manipulating the virtual time +class ITimer : public virtual IReferenceCounted +{ +public: + //! Returns current real time in milliseconds of the system. + /** This value does not start with 0 when the application starts. + For example in one implementation the value returned could be the + amount of milliseconds which have elapsed since the system was started. + */ + virtual u32 getRealTime() const = 0; + + enum EWeekday + { + EWD_SUNDAY=0, + EWD_MONDAY, + EWD_TUESDAY, + EWD_WEDNESDAY, + EWD_THURSDAY, + EWD_FRIDAY, + EWD_SATURDAY + }; + + struct RealTimeDate + { + // Hour of the day, from 0 to 23 + u32 Hour; + // Minute of the hour, from 0 to 59 + u32 Minute; + // Second of the minute, due to extra seconds from 0 to 61 + u32 Second; + // Year of the gregorian calender + s32 Year; + // Month of the year, from 1 to 12 + u32 Month; + // Day of the month, from 1 to 31 + u32 Day; + // Weekday for the current day + EWeekday Weekday; + // Day of the year, from 1 to 366 + u32 Yearday; + // Whether daylight saving is on + bool IsDST; + }; + + virtual RealTimeDate getRealTimeAndDate() const = 0; + + //! Returns current virtual time in milliseconds. + /** This value starts with 0 and can be manipulated using setTime(), + stopTimer(), startTimer(), etc. This value depends on the set speed of + the timer if the timer is stopped, etc. If you need the system time, + use getRealTime() */ + virtual u32 getTime() const = 0; + + //! sets current virtual time + virtual void setTime(u32 time) = 0; + + //! Stops the virtual timer. + /** The timer is reference counted, which means everything which calls + stop() will also have to call start(), otherwise the timer may not + start/stop correctly again. */ + virtual void stop() = 0; + + //! Starts the virtual timer. + /** The timer is reference counted, which means everything which calls + stop() will also have to call start(), otherwise the timer may not + start/stop correctly again. */ + virtual void start() = 0; + + //! Sets the speed of the timer + /** The speed is the factor with which the time is running faster or + slower then the real system time. */ + virtual void setSpeed(f32 speed = 1.0f) = 0; + + //! Returns current speed of the timer + /** The speed is the factor with which the time is running faster or + slower then the real system time. */ + virtual f32 getSpeed() const = 0; + + //! Returns if the virtual timer is currently stopped + virtual bool isStopped() const = 0; + + //! Advances the virtual time + /** Makes the virtual timer update the time value based on the real + time. This is called automatically when calling IrrlichtDevice::run(), + but you can call it manually if you don't use this method. */ + virtual void tick() = 0; +}; + +} // end namespace irr + +#endif diff --git a/inc/ITriangleSelector.h b/inc/ITriangleSelector.h new file mode 100644 index 0000000..9d038df --- /dev/null +++ b/inc/ITriangleSelector.h @@ -0,0 +1,131 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_TRIANGLE_SELECTOR_H_INCLUDED__ +#define __I_TRIANGLE_SELECTOR_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "triangle3d.h" +#include "aabbox3d.h" +#include "matrix4.h" +#include "line3d.h" + +namespace irr +{ +namespace scene +{ + +class ISceneNode; + +//! Interface to return triangles with specific properties. +/** Every ISceneNode may have a triangle selector, available with +ISceneNode::getTriangleScelector() or ISceneManager::createTriangleSelector. +This is used for doing collision detection: For example if you know, that a +collision may have happened in the area between (1,1,1) and (10,10,10), you +can get all triangles of the scene node in this area with the +ITriangleSelector easily and check every triangle if it collided. */ +class ITriangleSelector : public virtual IReferenceCounted +{ +public: + + //! Get amount of all available triangles in this selector + virtual s32 getTriangleCount() const = 0; + + //! Gets the triangles for one associated node. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + \param triangles Array where the resulting triangles will be + written to. + \param arraySize Size of the target array. + \param outTriangleCount: Amount of triangles which have been written + into the array. + \param transform Pointer to matrix for transforming the triangles + before they are returned. Useful for example to scale all triangles + down into an ellipsoid space. If this pointer is null, no + transformation will be done. */ + virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, + s32& outTriangleCount, const core::matrix4* transform=0) const = 0; + + //! Gets the triangles for one associated node which may lie within a specific bounding box. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + + This method will return at least the triangles that intersect the box, + but may return other triangles as well. + \param triangles Array where the resulting triangles will be written + to. + \param arraySize Size of the target array. + \param outTriangleCount Amount of triangles which have been written + into the array. + \param box Only triangles which are in this axis aligned bounding box + will be written into the array. + \param transform Pointer to matrix for transforming the triangles + before they are returned. Useful for example to scale all triangles + down into an ellipsoid space. If this pointer is null, no + transformation will be done. */ + virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, + s32& outTriangleCount, const core::aabbox3d& box, + const core::matrix4* transform=0) const = 0; + + //! Gets the triangles for one associated node which have or may have contact with a 3d line. + /** + This returns all triangles for one scene node associated with this + selector. If there is more than one scene node associated (e.g. for + an IMetaTriangleSelector) this this function may be called multiple + times to retrieve all triangles. + + Please note that unoptimized triangle selectors also may return + triangles which are not in contact at all with the 3d line. + \param triangles Array where the resulting triangles will be written + to. + \param arraySize Size of the target array. + \param outTriangleCount Amount of triangles which have been written + into the array. + \param line Only triangles which may be in contact with this 3d line + will be written into the array. + \param transform Pointer to matrix for transforming the triangles + before they are returned. Useful for example to scale all triangles + down into an ellipsoid space. If this pointer is null, no + transformation will be done. */ + virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, + s32& outTriangleCount, const core::line3d& line, + const core::matrix4* transform=0) const = 0; + + //! Get scene node associated with a given triangle. + /** + This allows to find which scene node (potentially of several) is + associated with a specific triangle. + + \param triangleIndex: the index of the triangle for which you want to find + the associated scene node. + \return The scene node associated with that triangle. + */ + virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0; + + //! Get number of TriangleSelectors that are part of this one + /** Only useful for MetaTriangleSelector, others return 1 + */ + virtual u32 getSelectorCount() const = 0; + + //! Get TriangleSelector based on index based on getSelectorCount + /** Only useful for MetaTriangleSelector, others return 'this' or 0 + */ + virtual ITriangleSelector* getSelector(u32 index) = 0; + + //! Get TriangleSelector based on index based on getSelectorCount + /** Only useful for MetaTriangleSelector, others return 'this' or 0 + */ + virtual const ITriangleSelector* getSelector(u32 index) const = 0; +}; + +} // end namespace scene +} // end namespace irr + +#endif diff --git a/inc/IVertexBuffer.h b/inc/IVertexBuffer.h new file mode 100644 index 0000000..04606b2 --- /dev/null +++ b/inc/IVertexBuffer.h @@ -0,0 +1,52 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_VERTEX_BUFFER_H_INCLUDED__ +#define __I_VERTEX_BUFFER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "S3DVertex.h" + +namespace irr +{ +namespace scene +{ + + class IVertexBuffer : public virtual IReferenceCounted + { + public: + virtual void* getData() =0; + virtual video::E_VERTEX_TYPE getType() const =0; + virtual void setType(video::E_VERTEX_TYPE vertexType) =0; + virtual u32 stride() const =0; + virtual u32 size() const =0; + virtual void push_back(const video::S3DVertex &element) =0; + virtual video::S3DVertex& operator [](const u32 index) const =0; + virtual video::S3DVertex& getLast() =0; + virtual void set_used(u32 usedNow) =0; + virtual void reallocate(u32 new_size) =0; + virtual u32 allocated_size() const =0; + virtual video::S3DVertex* pointer() =0; + + //! get the current hardware mapping hint + virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) =0; + + //! flags the meshbuffer as changed, reloads hardware buffers + virtual void setDirty() =0; + + //! Get the currently used ID for identification of changes. + /** This shouldn't be used for anything outside the VideoDriver. */ + virtual u32 getChangedID() const = 0; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/IVideoDriver.h b/inc/IVideoDriver.h new file mode 100644 index 0000000..b3af407 --- /dev/null +++ b/inc/IVideoDriver.h @@ -0,0 +1,1471 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_I_VIDEO_DRIVER_H_INCLUDED__ +#define __IRR_I_VIDEO_DRIVER_H_INCLUDED__ + +#include "rect.h" +#include "SColor.h" +#include "ITexture.h" +#include "irrArray.h" +#include "matrix4.h" +#include "plane3d.h" +#include "dimension2d.h" +#include "position2d.h" +#include "SMaterial.h" +#include "IMeshBuffer.h" +#include "triangle3d.h" +#include "EDriverTypes.h" +#include "EDriverFeatures.h" +#include "SExposedVideoData.h" + +namespace irr +{ +namespace io +{ + class IAttributes; + struct SAttributeReadWriteOptions; + class IReadFile; + class IWriteFile; +} // end namespace io +namespace scene +{ + class IMeshBuffer; + class IMesh; + class IMeshManipulator; + class ISceneNode; +} // end namespace scene + +namespace video +{ + struct S3DVertex; + struct S3DVertex2TCoords; + struct S3DVertexTangents; + struct SLight; + class IImageLoader; + class IImageWriter; + class IMaterialRenderer; + class IGPUProgrammingServices; + + //! enumeration for geometry transformation states + enum E_TRANSFORMATION_STATE + { + //! View transformation + ETS_VIEW = 0, + //! World transformation + ETS_WORLD, + //! Projection transformation + ETS_PROJECTION, + //! Texture transformation + ETS_TEXTURE_0, + //! Texture transformation + ETS_TEXTURE_1, + //! Texture transformation + ETS_TEXTURE_2, + //! Texture transformation + ETS_TEXTURE_3, +#if _IRR_MATERIAL_MAX_TEXTURES_>4 + //! Texture transformation + ETS_TEXTURE_4, +#if _IRR_MATERIAL_MAX_TEXTURES_>5 + //! Texture transformation + ETS_TEXTURE_5, +#if _IRR_MATERIAL_MAX_TEXTURES_>6 + //! Texture transformation + ETS_TEXTURE_6, +#if _IRR_MATERIAL_MAX_TEXTURES_>7 + //! Texture transformation + ETS_TEXTURE_7, +#endif +#endif +#endif +#endif + //! Not used + ETS_COUNT + }; + + //! enumeration for signaling resources which were lost after the last render cycle + /** These values can be signaled by the driver, telling the app that some resources + were lost and need to be recreated. Irrlicht will sometimes recreate the actual objects, + but the content needs to be recreated by the application. */ + enum E_LOST_RESOURCE + { + //! The whole device/driver is lost + ELR_DEVICE = 1, + //! All texture are lost, rare problem + ELR_TEXTURES = 2, + //! The Render Target Textures are lost, typical problem for D3D + ELR_RTTS = 4, + //! The HW buffers are lost, will be recreated automatically, but might require some more time this frame + ELR_HW_BUFFERS = 8 + }; + + //! Special render targets, which usually map to dedicated hardware + /** These render targets (besides 0 and 1) need not be supported by gfx cards */ + enum E_RENDER_TARGET + { + //! Render target is the main color frame buffer + ERT_FRAME_BUFFER=0, + //! Render target is a render texture + ERT_RENDER_TEXTURE, + //! Multi-Render target textures + ERT_MULTI_RENDER_TEXTURES, + //! Render target is the main color frame buffer + ERT_STEREO_LEFT_BUFFER, + //! Render target is the right color buffer (left is the main buffer) + ERT_STEREO_RIGHT_BUFFER, + //! Render to both stereo buffers at once + ERT_STEREO_BOTH_BUFFERS, + //! Auxiliary buffer 0 + ERT_AUX_BUFFER0, + //! Auxiliary buffer 1 + ERT_AUX_BUFFER1, + //! Auxiliary buffer 2 + ERT_AUX_BUFFER2, + //! Auxiliary buffer 3 + ERT_AUX_BUFFER3, + //! Auxiliary buffer 4 + ERT_AUX_BUFFER4 + }; + + //! Enum for the types of fog distributions to choose from + enum E_FOG_TYPE + { + EFT_FOG_EXP=0, + EFT_FOG_LINEAR, + EFT_FOG_EXP2 + }; + + const c8* const FogTypeNames[] = + { + "FogExp", + "FogLinear", + "FogExp2", + 0 + }; + + struct SOverrideMaterial + { + //! The Material values + SMaterial Material; + //! Which values are taken for override + /** OR'ed values from E_MATERIAL_FLAGS. */ + u32 EnableFlags; + //! Set in which render passes the material override is active. + /** OR'ed values from E_SCENE_NODE_RENDER_PASS. */ + u16 EnablePasses; + //! Global enable flag, overwritten by the SceneManager in each pass + /** The Scenemanager uses the EnablePass array and sets Enabled to + true if the Override material is enabled in the current pass. */ + bool Enabled; + + //! Default constructor + SOverrideMaterial() : EnableFlags(0), EnablePasses(0), Enabled(false) {} + + //! Apply the enabled overrides + void apply(SMaterial& material) + { + if (Enabled) + { + for (u32 i=0; i<32; ++i) + { + const u32 num=(1<* sourceRect=0) =0; + + //! Presents the rendered image to the screen. + /** Applications must call this method after performing any + rendering. + \return False if failed and true if succeeded. */ + virtual bool endScene() =0; + + //! Queries the features of the driver. + /** Returns true if a feature is available + \param feature Feature to query. + \return True if the feature is available, false if not. */ + virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const =0; + + //! Disable a feature of the driver. + /** Can also be used to enable the features again. It is not + possible to enable unsupported features this way, though. + \param feature Feature to disable. + \param flag When true the feature is disabled, otherwise it is enabled. */ + virtual void disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag=true) =0; + + //! Get attributes of the actual video driver + /** The following names can be queried for the given types: + MaxTextures (int) The maximum number of simultaneous textures supported by the driver. This can be less than the supported number of textures of the driver. Use _IRR_MATERIAL_MAX_TEXTURES_ to adapt the number. + MaxSupportedTextures (int) The maximum number of simultaneous textures supported by the fixed function pipeline of the (hw) driver. The actual supported number of textures supported by the engine can be lower. + MaxLights (int) Number of hardware lights supported in the fixed function pipieline of the driver, typically 6-8. Use light manager or deferred shading for more. + MaxAnisotropy (int) Number of anisotropy levels supported for filtering. At least 1, max is typically at 16 or 32. + MaxUserClipPlanes (int) Number of additional clip planes, which can be set by the user via dedicated driver methods. + MaxAuxBuffers (int) Special render buffers, which are currently not really usable inside Irrlicht. Only supported by OpenGL + MaxMultipleRenderTargets (int) Number of render targets which can be bound simultaneously. Rendering to MRTs is done via shaders. + MaxIndices (int) Number of indices which can be used in one render call (i.e. one mesh buffer). + MaxTextureSize (int) Dimension that a texture may have, both in width and height. + MaxGeometryVerticesOut (int) Number of vertices the geometry shader can output in one pass. Only OpenGL so far. + MaxTextureLODBias (float) Maximum value for LOD bias. Is usually at around 16, but can be lower on some systems. + Version (int) Version of the driver. Should be Major*100+Minor + ShaderLanguageVersion (int) Version of the high level shader language. Should be Major*100+Minor. + AntiAlias (int) Number of Samples the driver uses for each pixel. 0 and 1 means anti aliasing is off, typical values are 2,4,8,16,32 + */ + virtual const io::IAttributes& getDriverAttributes() const=0; + + //! Check if the driver was recently reset. + /** For d3d devices you will need to recreate the RTTs if the + driver was reset. Should be queried right after beginScene(). + */ + virtual bool checkDriverReset() =0; + + //! Sets transformation matrices. + /** \param state Transformation type to be set, e.g. view, + world, or projection. + \param mat Matrix describing the transformation. */ + virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) =0; + + //! Returns the transformation set by setTransform + /** \param state Transformation type to query + \return Matrix describing the transformation. */ + virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const =0; + + //! Retrieve the number of image loaders + /** \return Number of image loaders */ + virtual u32 getImageLoaderCount() const = 0; + + //! Retrieve the given image loader + /** \param n The index of the loader to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified loader, 0 if the index is incorrect. */ + virtual IImageLoader* getImageLoader(u32 n) = 0; + + //! Retrieve the number of image writers + /** \return Number of image writers */ + virtual u32 getImageWriterCount() const = 0; + + //! Retrieve the given image writer + /** \param n The index of the writer to retrieve. This parameter is an 0-based + array index. + \return A pointer to the specified writer, 0 if the index is incorrect. */ + virtual IImageWriter* getImageWriter(u32 n) = 0; + + //! Sets a material. + /** All 3d drawing functions will draw geometry using this material thereafter. + \param material: Material to be used from now on. */ + virtual void setMaterial(const SMaterial& material) =0; + + //! Get access to a named texture. + /** Loads the texture from disk if it is not + already loaded and generates mipmap levels if desired. + Texture loading can be influenced using the + setTextureCreationFlag() method. The texture can be in several + imageformats, such as BMP, JPG, TGA, PCX, PNG, and PSD. + \param filename Filename of the texture to be loaded. + \return Pointer to the texture, or 0 if the texture + could not be loaded. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual ITexture* getTexture(const io::path& filename) = 0; + + //! Get access to a named texture. + /** Loads the texture from disk if it is not + already loaded and generates mipmap levels if desired. + Texture loading can be influenced using the + setTextureCreationFlag() method. The texture can be in several + imageformats, such as BMP, JPG, TGA, PCX, PNG, and PSD. + \param file Pointer to an already opened file. + \return Pointer to the texture, or 0 if the texture + could not be loaded. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual ITexture* getTexture(io::IReadFile* file) =0; + + //! Returns a texture by index + /** \param index: Index of the texture, must be smaller than + getTextureCount() Please note that this index might change when + adding or removing textures + \return Pointer to the texture, or 0 if the texture was not + set or index is out of bounds. This pointer should not be + dropped. See IReferenceCounted::drop() for more information. */ + virtual ITexture* getTextureByIndex(u32 index) =0; + + //! Returns amount of textures currently loaded + /** \return Amount of textures currently loaded */ + virtual u32 getTextureCount() const = 0; + + //! Renames a texture + /** \param texture Pointer to the texture to rename. + \param newName New name for the texture. This should be a unique name. */ + virtual void renameTexture(ITexture* texture, const io::path& newName) = 0; + + //! Creates an empty texture of specified size. + /** \param size: Size of the texture. + \param name A name for the texture. Later calls to + getTexture() with this name will return this texture + \param format Desired color format of the texture. Please note + that the driver may choose to create the texture in another + color format. + \return Pointer to the newly created texture. This pointer + should not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual ITexture* addTexture(const core::dimension2d& size, + const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; + + //! Creates a texture from an IImage. + /** \param name A name for the texture. Later calls of + getTexture() with this name will return this texture + \param image Image the texture is created from. + \param mipmapData Optional pointer to a set of images which + build up the whole mipmap set. Must be images of the same color + type as image. If this parameter is not given, the mipmaps are + derived from image. + \return Pointer to the newly created texture. This pointer + should not be dropped. See IReferenceCounted::drop() for more + information. */ + virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0) = 0; + + //! Adds a new render target texture to the texture cache. + /** \param size Size of the texture, in pixels. Width and + height should be a power of two (e.g. 64, 128, 256, 512, ...) + and it should not be bigger than the backbuffer, because it + shares the zbuffer with the screen buffer. + \param name An optional name for the RTT. + \param format The color format of the render target. Floating point formats are supported. + \return Pointer to the created texture or 0 if the texture + could not be created. This pointer should not be dropped. See + IReferenceCounted::drop() for more information. */ + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN) =0; + + //! Removes a texture from the texture cache and deletes it. + /** This method can free a lot of memory! + Please note that after calling this, the pointer to the + ITexture may no longer be valid, if it was not grabbed before + by other parts of the engine for storing it longer. So it is a + good idea to set all materials which are using this texture to + 0 or another texture first. + \param texture Texture to delete from the engine cache. */ + virtual void removeTexture(ITexture* texture) =0; + + //! Removes all textures from the texture cache and deletes them. + /** This method can free a lot of memory! + Please note that after calling this, the pointer to the + ITexture may no longer be valid, if it was not grabbed before + by other parts of the engine for storing it longer. So it is a + good idea to set all materials which are using this texture to + 0 or another texture first. */ + virtual void removeAllTextures() =0; + + //! Remove hardware buffer + virtual void removeHardwareBuffer(const scene::IMeshBuffer* mb) =0; + + //! Remove all hardware buffers + virtual void removeAllHardwareBuffers() =0; + + //! Create occlusion query. + /** Use node for identification and mesh for occlusion test. */ + virtual void addOcclusionQuery(scene::ISceneNode* node, + const scene::IMesh* mesh=0) =0; + + //! Remove occlusion query. + virtual void removeOcclusionQuery(scene::ISceneNode* node) =0; + + //! Remove all occlusion queries. + virtual void removeAllOcclusionQueries() =0; + + //! Run occlusion query. Draws mesh stored in query. + /** If the mesh shall not be rendered visible, use + overrideMaterial to disable the color and depth buffer. */ + virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false) =0; + + //! Run all occlusion queries. Draws all meshes stored in queries. + /** If the meshes shall not be rendered visible, use + overrideMaterial to disable the color and depth buffer. */ + virtual void runAllOcclusionQueries(bool visible=false) =0; + + //! Update occlusion query. Retrieves results from GPU. + /** If the query shall not block, set the flag to false. + Update might not occur in this case, though */ + virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true) =0; + + //! Update all occlusion queries. Retrieves results from GPU. + /** If the query shall not block, set the flag to false. + Update might not occur in this case, though */ + virtual void updateAllOcclusionQueries(bool block=true) =0; + + //! Return query result. + /** Return value is the number of visible pixels/fragments. + The value is a safe approximation, i.e. can be larger than the + actual value of pixels. */ + virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const =0; + + //! Sets a boolean alpha channel on the texture based on a color key. + /** This makes the texture fully transparent at the texels where + this color key can be found when using for example draw2DImage + with useAlphachannel==true. The alpha of other texels is not modified. + \param texture Texture whose alpha channel is modified. + \param color Color key color. Every texel with this color will + become fully transparent as described above. Please note that the + colors of a texture may be converted when loading it, so the + color values may not be exactly the same in the engine and for + example in picture edit programs. To avoid this problem, you + could use the makeColorKeyTexture method, which takes the + position of a pixel instead a color value. + \param zeroTexels \deprecated If set to true, then any texels that match + the color key will have their color, as well as their alpha, set to zero + (i.e. black). This behavior matches the legacy (buggy) behavior prior + to release 1.5 and is provided for backwards compatibility only. + This parameter may be removed by Irrlicht 1.9. */ + virtual void makeColorKeyTexture(video::ITexture* texture, + video::SColor color, + bool zeroTexels = false) const =0; + + //! Sets a boolean alpha channel on the texture based on the color at a position. + /** This makes the texture fully transparent at the texels where + the color key can be found when using for example draw2DImage + with useAlphachannel==true. The alpha of other texels is not modified. + \param texture Texture whose alpha channel is modified. + \param colorKeyPixelPos Position of a pixel with the color key + color. Every texel with this color will become fully transparent as + described above. + \param zeroTexels \deprecated If set to true, then any texels that match + the color key will have their color, as well as their alpha, set to zero + (i.e. black). This behavior matches the legacy (buggy) behavior prior + to release 1.5 and is provided for backwards compatibility only. + This parameter may be removed by Irrlicht 1.9. */ + virtual void makeColorKeyTexture(video::ITexture* texture, + core::position2d colorKeyPixelPos, + bool zeroTexels = false) const =0; + + //! Creates a normal map from a height map texture. + /** If the target texture has 32 bit, the height value is + stored in the alpha component of the texture as addition. This + value is used by the video::EMT_PARALLAX_MAP_SOLID material and + similar materials. + \param texture Texture whose alpha channel is modified. + \param amplitude Constant value by which the height + information is multiplied.*/ + virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0; + + //! Sets a new render target. + /** This will only work if the driver supports the + EVDF_RENDER_TO_TARGET feature, which can be queried with + queryFeature(). Usually, rendering to textures is done in this + way: + \code + // create render target + ITexture* target = driver->addRenderTargetTexture(core::dimension2d(128,128), "rtt1"); + + // ... + + driver->setRenderTarget(target); // set render target + // .. draw stuff here + driver->setRenderTarget(0); // set previous render target + \endcode + Please note that you cannot render 3D or 2D geometry with a + render target as texture on it when you are rendering the scene + into this render target at the same time. It is usually only + possible to render into a texture between the + IVideoDriver::beginScene() and endScene() method calls. + \param texture New render target. Must be a texture created with + IVideoDriver::addRenderTargetTexture(). If set to 0, it sets + the previous render target which was set before the last + setRenderTarget() call. + \param clearBackBuffer Clears the backbuffer of the render + target with the color parameter + \param clearZBuffer Clears the zBuffer of the rendertarget. + Note that because the frame buffer may share the zbuffer with + the rendertarget, its zbuffer might be partially cleared too + by this. + \param color The background color for the render target. + \return True if sucessful and false if not. */ + virtual bool setRenderTarget(video::ITexture* texture, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) =0; + + //! set or reset special render targets + /** This method enables access to special color buffers such as + stereoscopic buffers or auxiliary buffers. + \param target Enum value for the render target + \param clearTarget Clears the target buffer with the color + parameter + \param clearZBuffer Clears the zBuffer of the rendertarget. + Note that because the main frame buffer may share the zbuffer with + the rendertarget, its zbuffer might be partially cleared too + by this. + \param color The background color for the render target. + \return True if sucessful and false if not. */ + virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget=true, + bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) =0; + + //! Sets new multiple render targets. + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) =0; + + //! Sets a new viewport. + /** Every rendering operation is done into this new area. + \param area: Rectangle defining the new area of rendering + operations. */ + virtual void setViewPort(const core::rect& area) =0; + + //! Gets the area of the current viewport. + /** \return Rectangle of the current viewport. */ + virtual const core::rect& getViewPort() const =0; + + //! Draws a vertex primitive list + /** Note that, depending on the index type, some vertices might be not + accessible through the index list. The limit is at 65535 vertices for 16bit + indices. Please note that currently not all primitives are available for + all drivers, and some might be emulated via triangle renders. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. These define the vertices used + for each primitive. Depending on the pType, indices are interpreted as single + objects (for point like primitives), pairs (for lines), triplets (for + triangles), or quads. + \param primCount Amount of Primitives + \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. + \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. + \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ + virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primCount, + E_VERTEX_TYPE vType=EVT_STANDARD, + scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, + E_INDEX_TYPE iType=EIT_16BIT) =0; + + //! Draws a vertex primitive list in 2d + /** Compared to the general (3d) version of this method, this + one sets up a 2d render mode, and uses only x and y of vectors. + Note that, depending on the index type, some vertices might be + not accessible through the index list. The limit is at 65535 + vertices for 16bit indices. Please note that currently not all + primitives are available for all drivers, and some might be + emulated via triangle renders. This function is not available + for the sw drivers. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. These define the + vertices used for each primitive. Depending on the pType, + indices are interpreted as single objects (for point like + primitives), pairs (for lines), triplets (for triangles), or + quads. + \param primCount Amount of Primitives + \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. + \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. + \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primCount, + E_VERTEX_TYPE vType=EVT_STANDARD, + scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, + E_INDEX_TYPE iType=EIT_16BIT) =0; + + //! Draws an indexed triangle list. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ + void drawIndexedTriangleList(const S3DVertex* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + } + + //! Draws an indexed triangle list. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ + void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLES, EIT_16BIT); + } + + //! Draws an indexed triangle list. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ + void drawIndexedTriangleList(const S3DVertexTangents* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLES, EIT_16BIT); + } + + //! Draws an indexed triangle fan. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ + void drawIndexedTriangleFan(const S3DVertex* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } + + //! Draws an indexed triangle fan. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ + void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } + + //! Draws an indexed triangle fan. + /** Note that there may be at maximum 65536 vertices, because + the index list is an array of 16 bit values each with a maximum + value of 65536. If there are more than 65536 vertices in the + list, results of this operation are not defined. + \param vertices Pointer to array of vertices. + \param vertexCount Amount of vertices in the array. + \param indexList Pointer to array of indices. + \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ + void drawIndexedTriangleFan(const S3DVertexTangents* vertices, + u32 vertexCount, const u16* indexList, u32 triangleCount) + { + drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); + } + + //! Draws a 3d line. + /** For some implementations, this method simply calls + drawVertexPrimitiveList for some triangles. + Note that the line is drawn using the current transformation + matrix and material. So if you need to draw the 3D line + independently of the current transformation, use + \code + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + \endcode + for some properly set up material before drawing the line. + Some drivers support line thickness set in the material. + \param start Start of the 3d line. + \param end End of the 3d line. + \param color Color of the line. */ + virtual void draw3DLine(const core::vector3df& start, + const core::vector3df& end, SColor color = SColor(255,255,255,255)) =0; + + //! Draws a 3d triangle. + /** This method calls drawVertexPrimitiveList for some triangles. + This method works with all drivers because it simply calls + drawVertexPrimitiveList, but it is hence not very fast. + Note that the triangle is drawn using the current + transformation matrix and material. So if you need to draw it + independently of the current transformation, use + \code + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + \endcode + for some properly set up material before drawing the triangle. + \param triangle The triangle to draw. + \param color Color of the line. */ + virtual void draw3DTriangle(const core::triangle3df& triangle, + SColor color = SColor(255,255,255,255)) =0; + + //! Draws a 3d axis aligned box. + /** This method simply calls draw3DLine for the edges of the + box. Note that the box is drawn using the current transformation + matrix and material. So if you need to draw it independently of + the current transformation, use + \code + driver->setMaterial(someMaterial); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + \endcode + for some properly set up material before drawing the box. + \param box The axis aligned box to draw + \param color Color to use while drawing the box. */ + virtual void draw3DBox(const core::aabbox3d& box, + SColor color = SColor(255,255,255,255)) =0; + + //! Draws a 2d image without any special effects + /** \param texture Pointer to texture to use. + \param destPos Upper left 2d destination position where the + image will be drawn. */ + virtual void draw2DImage(const video::ITexture* texture, + const core::position2d& destPos) =0; + + //! Draws a 2d image using a color + /** (if color is other than + Color(255,255,255,255)) and the alpha channel of the texture. + \param texture Texture to be drawn. + \param destPos Upper left 2d destination position where the + image will be drawn. + \param sourceRect Source rectangle in the image. + \param clipRect Pointer to rectangle on the screen where the + image is clipped to. + If this pointer is NULL the image is not clipped. + \param color Color with which the image is drawn. If the color + equals Color(255,255,255,255) it is ignored. Note that the + alpha component is used: If alpha is other than 255, the image + will be transparent. + \param useAlphaChannelOfTexture: If true, the alpha channel of + the texture is used to draw the image.*/ + virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, + const core::rect& sourceRect, const core::rect* clipRect =0, + SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; + + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + /** The images are drawn beginning at pos and concatenated in + one line. All drawings are clipped against clipRect (if != 0). + The subtextures are defined by the array of sourceRects and are + chosen by the indices given. + \param texture Texture to be drawn. + \param pos Upper left 2d destination position where the image + will be drawn. + \param sourceRects Source rectangles of the image. + \param indices List of indices which choose the actual + rectangle used each time. + \param kerningWidth Offset to Position on X + \param clipRect Pointer to rectangle on the screen where the + image is clipped to. + If this pointer is 0 then the image is not clipped. + \param color Color with which the image is drawn. + Note that the alpha component is used. If alpha is other than + 255, the image will be transparent. + \param useAlphaChannelOfTexture: If true, the alpha channel of + the texture is used to draw the image. */ + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::position2d& pos, + const core::array >& sourceRects, + const core::array& indices, + s32 kerningWidth=0, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false) =0; + + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + /** All drawings are clipped against clipRect (if != 0). + The subtextures are defined by the array of sourceRects and are + positioned using the array of positions. + \param texture Texture to be drawn. + \param positions Array of upper left 2d destinations where the + images will be drawn. + \param sourceRects Source rectangles of the image. + \param clipRect Pointer to rectangle on the screen where the + images are clipped to. + If this pointer is 0 then the image is not clipped. + \param color Color with which the image is drawn. + Note that the alpha component is used. If alpha is other than + 255, the image will be transparent. + \param useAlphaChannelOfTexture: If true, the alpha channel of + the texture is used to draw the image. */ + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false) =0; + + //! Draws a part of the texture into the rectangle. Note that colors must be an array of 4 colors if used. + /** Suggested and first implemented by zola. + \param texture The texture to draw from + \param destRect The rectangle to draw into + \param sourceRect The rectangle denoting a part of the texture + \param clipRect Clips the destination rectangle (may be 0) + \param colors Array of 4 colors denoting the color values of + the corners of the destRect + \param useAlphaChannelOfTexture True if alpha channel will be + blended. */ + virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, + const core::rect& sourceRect, const core::rect* clipRect =0, + const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false) =0; + + //! Draws a 2d rectangle. + /** \param color Color of the rectangle to draw. The alpha + component will not be ignored and specifies how transparent the + rectangle will be. + \param pos Position of the rectangle. + \param clip Pointer to rectangle against which the rectangle + will be clipped. If the pointer is null, no clipping will be + performed. */ + virtual void draw2DRectangle(SColor color, const core::rect& pos, + const core::rect* clip =0) =0; + + //! Draws a 2d rectangle with a gradient. + /** \param colorLeftUp Color of the upper left corner to draw. + The alpha component will not be ignored and specifies how + transparent the rectangle will be. + \param colorRightUp Color of the upper right corner to draw. + The alpha component will not be ignored and specifies how + transparent the rectangle will be. + \param colorLeftDown Color of the lower left corner to draw. + The alpha component will not be ignored and specifies how + transparent the rectangle will be. + \param colorRightDown Color of the lower right corner to draw. + The alpha component will not be ignored and specifies how + transparent the rectangle will be. + \param pos Position of the rectangle. + \param clip Pointer to rectangle against which the rectangle + will be clipped. If the pointer is null, no clipping will be + performed. */ + virtual void draw2DRectangle(const core::rect& pos, + SColor colorLeftUp, SColor colorRightUp, + SColor colorLeftDown, SColor colorRightDown, + const core::rect* clip =0) =0; + + //! Draws the outline of a 2D rectangle. + /** \param pos Position of the rectangle. + \param color Color of the rectangle to draw. The alpha component + specifies how transparent the rectangle outline will be. */ + virtual void draw2DRectangleOutline(const core::recti& pos, + SColor color=SColor(255,255,255,255)) =0; + + //! Draws a 2d line. Both start and end will be included in coloring. + /** \param start Screen coordinates of the start of the line + in pixels. + \param end Screen coordinates of the start of the line in + pixels. + \param color Color of the line to draw. */ + virtual void draw2DLine(const core::position2d& start, + const core::position2d& end, + SColor color=SColor(255,255,255,255)) =0; + + //! Draws a pixel. + /** \param x The x-position of the pixel. + \param y The y-position of the pixel. + \param color Color of the pixel to draw. */ + virtual void drawPixel(u32 x, u32 y, const SColor& color) =0; + + //! Draws a non filled concyclic regular 2d polygon. + /** This method can be used to draw circles, but also + triangles, tetragons, pentagons, hexagons, heptagons, octagons, + enneagons, decagons, hendecagons, dodecagon, triskaidecagons, + etc. I think you'll got it now. And all this by simply + specifying the vertex count. Welcome to the wonders of + geometry. + \param center Position of center of circle (pixels). + \param radius Radius of circle in pixels. + \param color Color of the circle. + \param vertexCount Amount of vertices of the polygon. Specify 2 + to draw a line, 3 to draw a triangle, 4 for tetragons and a lot + (>10) for nearly a circle. */ + virtual void draw2DPolygon(core::position2d center, + f32 radius, + video::SColor color=SColor(100,255,255,255), + s32 vertexCount=10) =0; + + //! Draws a shadow volume into the stencil buffer. + /** To draw a stencil shadow, do this: First, draw all geometry. + Then use this method, to draw the shadow volume. Then, use + IVideoDriver::drawStencilShadow() to visualize the shadow. + Please note that the code for the opengl version of the method + is based on free code sent in by Philipp Dortmann, lots of + thanks go to him! + \param triangles Array of 3d vectors, specifying the shadow + volume. + \param zfail If set to true, zfail method is used, otherwise + zpass. + \param debugDataVisible The debug data that is enabled for this + shadow node + */ + virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0) =0; + + //! Fills the stencil shadow with color. + /** After the shadow volume has been drawn into the stencil + buffer using IVideoDriver::drawStencilShadowVolume(), use this + to draw the color of the shadow. + Please note that the code for the opengl version of the method + is based on free code sent in by Philipp Dortmann, lots of + thanks go to him! + \param clearStencilBuffer Set this to false, if you want to + draw every shadow with the same color, and only want to call + drawStencilShadow() once after all shadow volumes have been + drawn. Set this to true, if you want to paint every shadow with + its own color. + \param leftUpEdge Color of the shadow in the upper left corner + of screen. + \param rightUpEdge Color of the shadow in the upper right + corner of screen. + \param leftDownEdge Color of the shadow in the lower left + corner of screen. + \param rightDownEdge Color of the shadow in the lower right + corner of screen. */ + virtual void drawStencilShadow(bool clearStencilBuffer=false, + video::SColor leftUpEdge = video::SColor(255,0,0,0), + video::SColor rightUpEdge = video::SColor(255,0,0,0), + video::SColor leftDownEdge = video::SColor(255,0,0,0), + video::SColor rightDownEdge = video::SColor(255,0,0,0)) =0; + + //! Draws a mesh buffer + /** \param mb Buffer to draw */ + virtual void drawMeshBuffer(const scene::IMeshBuffer* mb) =0; + + //! Draws normals of a mesh buffer + /** \param mb Buffer to draw the normals of + \param length length scale factor of the normals + \param color Color the normals are rendered with + */ + virtual void drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length=10.f, SColor color=0xffffffff) =0; + + //! Sets the fog mode. + /** These are global values attached to each 3d object rendered, + which has the fog flag enabled in its material. + \param color Color of the fog + \param fogType Type of fog used + \param start Only used in linear fog mode (linearFog=true). + Specifies where fog starts. + \param end Only used in linear fog mode (linearFog=true). + Specifies where fog ends. + \param density Only used in exponential fog mode + (linearFog=false). Must be a value between 0 and 1. + \param pixelFog Set this to false for vertex fog, and true if + you want per-pixel fog. + \param rangeFog Set this to true to enable range-based vertex + fog. The distance from the viewer is used to compute the fog, + not the z-coordinate. This is better, but slower. This might not + be available with all drivers and fog settings. */ + virtual void setFog(SColor color=SColor(0,255,255,255), + E_FOG_TYPE fogType=EFT_FOG_LINEAR, + f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, + bool pixelFog=false, bool rangeFog=false) =0; + + //! Gets the fog mode. + virtual void getFog(SColor& color, E_FOG_TYPE& fogType, + f32& start, f32& end, f32& density, + bool& pixelFog, bool& rangeFog) = 0; + + //! Get the current color format of the color buffer + /** \return Color format of the color buffer. */ + virtual ECOLOR_FORMAT getColorFormat() const =0; + + //! Get the size of the screen or render window. + /** \return Size of screen or render window. */ + virtual const core::dimension2d& getScreenSize() const =0; + + //! Get the size of the current render target + /** This method will return the screen size if the driver + doesn't support render to texture, or if the current render + target is the screen. + \return Size of render target or screen/window */ + virtual const core::dimension2d& getCurrentRenderTargetSize() const =0; + + //! Returns current frames per second value. + /** This value is updated approximately every 1.5 seconds and + is only intended to provide a rough guide to the average frame + rate. It is not suitable for use in performing timing + calculations or framerate independent movement. + \return Approximate amount of frames per second drawn. */ + virtual s32 getFPS() const =0; + + //! Returns amount of primitives (mostly triangles) which were drawn in the last frame. + /** Together with getFPS() very useful method for statistics. + \param mode Defines if the primitives drawn are accumulated or + counted per frame. + \return Amount of primitives drawn in the last frame. */ + virtual u32 getPrimitiveCountDrawn( u32 mode =0 ) const =0; + + //! Deletes all dynamic lights which were previously added with addDynamicLight(). + virtual void deleteAllDynamicLights() =0; + + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light) =0; + + //! Returns the maximal amount of dynamic lights the device can handle + /** \return Maximal amount of dynamic lights. */ + virtual u32 getMaximalDynamicLightAmount() const =0; + + //! Returns amount of dynamic lights currently set + /** \return Amount of dynamic lights currently set */ + virtual u32 getDynamicLightCount() const =0; + + //! Returns light data which was previously set by IVideoDriver::addDynamicLight(). + /** \param idx Zero based index of the light. Must be 0 or + greater and smaller than IVideoDriver::getDynamicLightCount. + \return Light data. */ + virtual const SLight& getDynamicLight(u32 idx) const =0; + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn) =0; + + //! Gets name of this video driver. + /** \return Returns the name of the video driver, e.g. in case + of the Direct3D8 driver, it would return "Direct3D 8.1". */ + virtual const wchar_t* getName() const =0; + + //! Adds an external image loader to the engine. + /** This is useful if the Irrlicht Engine should be able to load + textures of currently unsupported file formats (e.g. gif). The + IImageLoader only needs to be implemented for loading this file + format. A pointer to the implementation can be passed to the + engine using this method. + \param loader Pointer to the external loader created. */ + virtual void addExternalImageLoader(IImageLoader* loader) =0; + + //! Adds an external image writer to the engine. + /** This is useful if the Irrlicht Engine should be able to + write textures of currently unsupported file formats (e.g + .gif). The IImageWriter only needs to be implemented for + writing this file format. A pointer to the implementation can + be passed to the engine using this method. + \param writer: Pointer to the external writer created. */ + virtual void addExternalImageWriter(IImageWriter* writer) =0; + + //! Returns the maximum amount of primitives + /** (mostly vertices) which the device is able to render with + one drawVertexPrimitiveList call. + \return Maximum amount of primitives. */ + virtual u32 getMaximalPrimitiveCount() const =0; + + //! Enables or disables a texture creation flag. + /** These flags define how textures should be created. By + changing this value, you can influence for example the speed of + rendering a lot. But please note that the video drivers take + this value only as recommendation. It could happen that you + enable the ETCF_ALWAYS_16_BIT mode, but the driver still creates + 32 bit textures. + \param flag Texture creation flag. + \param enabled Specifies if the given flag should be enabled or + disabled. */ + virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled=true) =0; + + //! Returns if a texture creation flag is enabled or disabled. + /** You can change this value using setTextureCreationFlag(). + \param flag Texture creation flag. + \return The current texture creation flag enabled mode. */ + virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const =0; + + //! Creates a software image from a file. + /** No hardware texture will be created for this image. This + method is useful for example if you want to read a heightmap + for a terrain renderer. + \param filename Name of the file from which the image is + created. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImageFromFile(const io::path& filename) = 0; + + //! Creates a software image from a file. + /** No hardware texture will be created for this image. This + method is useful for example if you want to read a heightmap + for a terrain renderer. + \param file File from which the image is created. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImageFromFile(io::IReadFile* file) =0; + + //! Writes the provided image to a file. + /** Requires that there is a suitable image writer registered + for writing the image. + \param image Image to write. + \param filename Name of the file to write. + \param param Control parameter for the backend (e.g. compression + level). + \return True on successful write. */ + virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0) = 0; + + //! Writes the provided image to a file. + /** Requires that there is a suitable image writer registered + for writing the image. + \param image Image to write. + \param file An already open io::IWriteFile object. The name + will be used to determine the appropriate image writer to use. + \param param Control parameter for the backend (e.g. compression + level). + \return True on successful write. */ + virtual bool writeImageToFile(IImage* image, io::IWriteFile* file, u32 param =0) =0; + + //! Creates a software image from a byte array. + /** No hardware texture will be created for this image. This + method is useful for example if you want to read a heightmap + for a terrain renderer. + \param format Desired color format of the texture + \param size Desired size of the image + \param data A byte array with pixel color information + \param ownForeignMemory If true, the image will use the data + pointer directly and own it afterwards. If false, the memory + will by copied internally. + \param deleteMemory Whether the memory is deallocated upon + destruction. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImageFromData(ECOLOR_FORMAT format, + const core::dimension2d& size, void *data, + bool ownForeignMemory=false, + bool deleteMemory = true) =0; + + //! Creates an empty software image. + /** + \param format Desired color format of the image. + \param size Size of the image to create. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; + + //! Creates a software image by converting it to given format from another image. + /** \deprecated Create an empty image and use copyTo(). This method may be removed by Irrlicht 1.9. + \param format Desired color format of the image. + \param imageToCopy Image to copy to the new image. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + _IRR_DEPRECATED_ virtual IImage* createImage(ECOLOR_FORMAT format, IImage *imageToCopy) =0; + + //! Creates a software image from a part of another image. + /** \deprecated Create an empty image and use copyTo(). This method may be removed by Irrlicht 1.9. + \param imageToCopy Image to copy to the new image in part. + \param pos Position of rectangle to copy. + \param size Extents of rectangle to copy. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + _IRR_DEPRECATED_ virtual IImage* createImage(IImage* imageToCopy, + const core::position2d& pos, + const core::dimension2d& size) =0; + + //! Creates a software image from a part of a texture. + /** + \param texture Texture to copy to the new image in part. + \param pos Position of rectangle to copy. + \param size Extents of rectangle to copy. + \return The created image. + If you no longer need the image, you should call IImage::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IImage* createImage(ITexture* texture, + const core::position2d& pos, + const core::dimension2d& size) =0; + + //! Event handler for resize events. Only used by the engine internally. + /** Used to notify the driver that the window was resized. + Usually, there is no need to call this method. */ + virtual void OnResize(const core::dimension2d& size) =0; + + //! Adds a new material renderer to the video device. + /** Use this method to extend the VideoDriver with new material + types. To extend the engine using this method do the following: + Derive a class from IMaterialRenderer and override the methods + you need. For setting the right renderstates, you can try to + get a pointer to the real rendering device using + IVideoDriver::getExposedVideoData(). Add your class with + IVideoDriver::addMaterialRenderer(). To use an object being + displayed with your new material, set the MaterialType member of + the SMaterial struct to the value returned by this method. + If you simply want to create a new material using vertex and/or + pixel shaders it would be easier to use the + video::IGPUProgrammingServices interface which you can get + using the getGPUProgrammingServices() method. + \param renderer A pointer to the new renderer. + \param name Optional name for the material renderer entry. + \return The number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if + an error occured. For example if you tried to add an material + renderer to the software renderer or the null device, which do + not accept material renderers. */ + virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, const c8* name =0) =0; + + //! Get access to a material renderer by index. + /** \param idx Id of the material renderer. Can be a value of + the E_MATERIAL_TYPE enum or a value which was returned by + addMaterialRenderer(). + \return Pointer to material renderer or null if not existing. */ + virtual IMaterialRenderer* getMaterialRenderer(u32 idx) =0; + + //! Get amount of currently available material renderers. + /** \return Amount of currently available material renderers. */ + virtual u32 getMaterialRendererCount() const =0; + + //! Get name of a material renderer + /** This string can, e.g., be used to test if a specific + renderer already has been registered/created, or use this + string to store data about materials: This returned name will + be also used when serializing materials. + \param idx Id of the material renderer. Can be a value of the + E_MATERIAL_TYPE enum or a value which was returned by + addMaterialRenderer(). + \return String with the name of the renderer, or 0 if not + exisiting */ + virtual const c8* getMaterialRendererName(u32 idx) const =0; + + //! Sets the name of a material renderer. + /** Will have no effect on built-in material renderers. + \param idx: Id of the material renderer. Can be a value of the + E_MATERIAL_TYPE enum or a value which was returned by + addMaterialRenderer(). + \param name: New name of the material renderer. */ + virtual void setMaterialRendererName(s32 idx, const c8* name) =0; + + //! Creates material attributes list from a material + /** This method is useful for serialization and more. + Please note that the video driver will use the material + renderer names from getMaterialRendererName() to write out the + material type name, so they should be set before. + \param material The material to serialize. + \param options Additional options which might influence the + serialization. + \return The io::IAttributes container holding the material + properties. */ + virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material, + io::SAttributeReadWriteOptions* options=0) =0; + + //! Fills an SMaterial structure from attributes. + /** Please note that for setting material types of the + material, the video driver will need to query the material + renderers for their names, so all non built-in materials must + have been created before calling this method. + \param outMaterial The material to set the properties for. + \param attributes The attributes to read from. */ + virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes) =0; + + //! Returns driver and operating system specific data about the IVideoDriver. + /** This method should only be used if the engine should be + extended without having to modify the source of the engine. + \return Collection of device dependent pointers. */ + virtual const SExposedVideoData& getExposedVideoData() =0; + + //! Get type of video driver + /** \return Type of driver. */ + virtual E_DRIVER_TYPE getDriverType() const =0; + + //! Gets the IGPUProgrammingServices interface. + /** \return Pointer to the IGPUProgrammingServices. Returns 0 + if the video driver does not support this. For example the + Software driver and the Null driver will always return 0. */ + virtual IGPUProgrammingServices* getGPUProgrammingServices() =0; + + //! Returns a pointer to the mesh manipulator. + virtual scene::IMeshManipulator* getMeshManipulator() =0; + + //! Clears the ZBuffer. + /** Note that you usually need not to call this method, as it + is automatically done in IVideoDriver::beginScene() or + IVideoDriver::setRenderTarget() if you enable zBuffer. But if + you have to render some special things, you can clear the + zbuffer during the rendering process with this method any time. + */ + virtual void clearZBuffer() =0; + + //! Make a screenshot of the last rendered frame. + /** \return An image created from the last rendered frame. */ + virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) =0; + + //! Check if the image is already loaded. + /** Works similar to getTexture(), but does not load the texture + if it is not currently loaded. + \param filename Name of the texture. + \return Pointer to loaded texture, or 0 if not found. */ + virtual video::ITexture* findTexture(const io::path& filename) = 0; + + //! Set or unset a clipping plane. + /** There are at least 6 clipping planes available for the user + to set at will. + \param index The plane index. Must be between 0 and + MaxUserClipPlanes. + \param plane The plane itself. + \param enable If true, enable the clipping plane else disable + it. + \return True if the clipping plane is usable. */ + virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) =0; + + //! Enable or disable a clipping plane. + /** There are at least 6 clipping planes available for the user + to set at will. + \param index The plane index. Must be between 0 and + MaxUserClipPlanes. + \param enable If true, enable the clipping plane else disable + it. */ + virtual void enableClipPlane(u32 index, bool enable) =0; + + //! Set the minimum number of vertices for which a hw buffer will be created + /** \param count Number of vertices to set as minimum. */ + virtual void setMinHardwareBufferVertexCount(u32 count) =0; + + //! Get the global Material, which might override local materials. + /** Depending on the enable flags, values from this Material + are used to override those of local materials of some + meshbuffer being rendered. + \return Reference to the Override Material. */ + virtual SOverrideMaterial& getOverrideMaterial() =0; + + //! Get the 2d override material for altering its values + /** The 2d override materual allows to alter certain render + states of the 2d methods. Not all members of SMaterial are + honored, especially not MaterialType and Textures. Moreover, + the zbuffer is always ignored, and lighting is always off. All + other flags can be changed, though some might have to effect + in most cases. + Please note that you have to enable/disable this effect with + enableInitMaterial2D(). This effect is costly, as it increases + the number of state changes considerably. Always reset the + values when done. + \return Material reference which should be altered to reflect + the new settings. + */ + virtual SMaterial& getMaterial2D() =0; + + //! Enable the 2d override material + /** \param enable Flag which tells whether the material shall be + enabled or disabled. */ + virtual void enableMaterial2D(bool enable=true) =0; + + //! Get the graphics card vendor name. + virtual core::stringc getVendorInfo() =0; + + //! Only used by the engine internally. + /** The ambient color is set in the scene manager, see + scene::ISceneManager::setAmbientLight(). + \param color New color of the ambient light. */ + virtual void setAmbientLight(const SColorf& color) =0; + + //! Only used by the engine internally. + /** Passes the global material flag AllowZWriteOnTransparent. + Use the SceneManager attribute to set this value from your app. + \param flag Default behavior is to disable ZWrite, i.e. false. */ + virtual void setAllowZWriteOnTransparent(bool flag) =0; + + //! Get the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const =0; + + //! Color conversion convenience function + /** Convert an image (as array of pixels) from source to destination + array, thereby converting the color format. The pixel size is + determined by the color formats. + \param sP Pointer to source + \param sF Color format of source + \param sN Number of pixels to convert, both array must be large enough + \param dP Pointer to destination + \param dF Color format of destination + */ + virtual void convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, + void* dP, ECOLOR_FORMAT dF) const =0; + }; + +} // end namespace video +} // end namespace irr + + +#endif diff --git a/inc/IVideoModeList.h b/inc/IVideoModeList.h new file mode 100644 index 0000000..aef0f5a --- /dev/null +++ b/inc/IVideoModeList.h @@ -0,0 +1,62 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_I_VIDEO_MODE_LIST_H_INCLUDED__ +#define __IRR_I_VIDEO_MODE_LIST_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "dimension2d.h" + +namespace irr +{ +namespace video +{ + + //! A list of all available video modes. + /** You can get a list via IrrlichtDevice::getVideoModeList(). If you are confused + now, because you think you have to create an Irrlicht Device with a video + mode before being able to get the video mode list, let me tell you that + there is no need to start up an Irrlicht Device with EDT_DIRECT3D8, EDT_OPENGL or + EDT_SOFTWARE: For this (and for lots of other reasons) the null device, + EDT_NULL exists.*/ + class IVideoModeList : public virtual IReferenceCounted + { + public: + + //! Gets amount of video modes in the list. + /** \return Returns amount of video modes. */ + virtual s32 getVideoModeCount() const = 0; + + //! Get the screen size of a video mode in pixels. + /** \param modeNumber: zero based index of the video mode. + \return Size of screen in pixels of the specified video mode. */ + virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; + + //! Get a supported screen size with certain constraints. + /** \param minSize: Minimum dimensions required. + \param maxSize: Maximum dimensions allowed. + \return Size of screen in pixels which matches the requirements. + as good as possible. */ + virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; + + //! Get the pixel depth of a video mode in bits. + /** \param modeNumber: zero based index of the video mode. + \return Size of each pixel of the specified video mode in bits. */ + virtual s32 getVideoModeDepth(s32 modeNumber) const = 0; + + //! Get current desktop screen resolution. + /** \return Size of screen in pixels of the current desktop video mode. */ + virtual const core::dimension2d& getDesktopResolution() const = 0; + + //! Get the pixel depth of a video mode in bits. + /** \return Size of each pixel of the current desktop video mode in bits. */ + virtual s32 getDesktopDepth() const = 0; + }; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/inc/IVolumeLightSceneNode.h b/inc/IVolumeLightSceneNode.h new file mode 100644 index 0000000..8ae2d17 --- /dev/null +++ b/inc/IVolumeLightSceneNode.h @@ -0,0 +1,60 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// +// created by Dean Wadsworth aka Varmint Dec 31 2007 + +#ifndef __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ +#define __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + class IMeshBuffer; + + class IVolumeLightSceneNode : public ISceneNode + { + public: + + //! constructor + IVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position, + const core::vector3df& rotation, + const core::vector3df& scale) + : ISceneNode(parent, mgr, id, position, rotation, scale) {}; + + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_VOLUME_LIGHT; } + + //! Sets the number of segments across the U axis + virtual void setSubDivideU(const u32 inU) =0; + + //! Sets the number of segments across the V axis + virtual void setSubDivideV(const u32 inV) =0; + + //! Returns the number of segments across the U axis + virtual u32 getSubDivideU() const =0; + + //! Returns the number of segments across the V axis + virtual u32 getSubDivideV() const =0; + + //! Sets the color of the base of the light + virtual void setFootColor(const video::SColor inColor) =0; + + //! Sets the color of the tip of the light + virtual void setTailColor(const video::SColor inColor) =0; + + //! Returns the color of the base of the light + virtual video::SColor getFootColor() const =0; + + //! Returns the color of the tip of the light + virtual video::SColor getTailColor() const =0; + }; + +} // end namespace scene +} // end namespace irr + +#endif diff --git a/inc/IWriteFile.h b/inc/IWriteFile.h new file mode 100644 index 0000000..7bc9f20 --- /dev/null +++ b/inc/IWriteFile.h @@ -0,0 +1,50 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_WRITE_FILE_H_INCLUDED__ +#define __I_WRITE_FILE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "path.h" + +namespace irr +{ +namespace io +{ + + //! Interface providing write access to a file. + class IWriteFile : public virtual IReferenceCounted + { + public: + //! Writes an amount of bytes to the file. + /** \param buffer Pointer to buffer of bytes to write. + \param sizeToWrite Amount of bytes to write to the file. + \return How much bytes were written. */ + virtual s32 write(const void* buffer, u32 sizeToWrite) = 0; + + //! Changes position in file + /** \param finalPos Destination position in the file. + \param relativeMovement If set to true, the position in the file is + changed relative to current position. Otherwise the position is changed + from begin of file. + \return True if successful, otherwise false. */ + virtual bool seek(long finalPos, bool relativeMovement = false) = 0; + + //! Get the current position in the file. + /** \return Current position in the file in bytes. */ + virtual long getPos() const = 0; + + //! Get name of file. + /** \return File name as zero terminated character string. */ + virtual const path& getFileName() const = 0; + }; + + //! Internal function, please do not use. + IWriteFile* createWriteFile(const io::path& fileName, bool append); + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IXMLReader.h b/inc/IXMLReader.h new file mode 100644 index 0000000..ec47c00 --- /dev/null +++ b/inc/IXMLReader.h @@ -0,0 +1,31 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_XML_READER_H_INCLUDED__ +#define __I_XML_READER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrXML.h" + +namespace irr +{ +namespace io +{ + //! An xml reader for wide characters, derived from IReferenceCounted. + /** This XML Parser can read any type of text files from any source + Irrlicht can read. Just call IFileSystem::createXMLReader(). For more + informations on how to use the parser, see IIrrXMLReader */ + typedef IIrrXMLReader IXMLReader; + + //! An xml reader for ASCII or UTF-8 characters, derived from IReferenceCounted. + /** This XML Parser can read any type of text files from any source + Irrlicht can read. Just call IFileSystem::createXMLReaderUTF8(). For + more informations on how to use the parser, see IIrrXMLReader */ + typedef IIrrXMLReader IXMLReaderUTF8; + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IXMLWriter.h b/inc/IXMLWriter.h new file mode 100644 index 0000000..8b43bc9 --- /dev/null +++ b/inc/IXMLWriter.h @@ -0,0 +1,77 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_XML_WRITER_H_INCLUDED__ +#define __I_XML_WRITER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "irrString.h" + +namespace irr +{ +namespace io +{ + + //! Interface providing methods for making it easier to write XML files. + /** This XML Writer writes xml files using in the platform dependent + wchar_t format and sets the xml-encoding correspondingly. */ + class IXMLWriter : public virtual IReferenceCounted + { + public: + //! Writes an xml 1.0 header. + /** Looks like <?xml version="1.0"?>. This should always + be called before writing anything other, because also the text + file header for unicode texts is written out with this method. */ + virtual void writeXMLHeader() = 0; + + //! Writes an xml element with maximal 5 attributes like "" or + //! <foo optAttr="value" />. + /** The element can be empty or not. + \param name: Name of the element + \param empty: Specifies if the element should be empty. Like + "". If You set this to false, something like this is + written instead: "". + \param attr1Name: 1st attributes name + \param attr1Value: 1st attributes value + \param attr2Name: 2nd attributes name + \param attr2Value: 2nd attributes value + \param attr3Name: 3rd attributes name + \param attr3Value: 3rd attributes value + \param attr4Name: 4th attributes name + \param attr4Value: 4th attributes value + \param attr5Name: 5th attributes name + \param attr5Value: 5th attributes value */ + virtual void writeElement(const wchar_t* name, bool empty=false, + const wchar_t* attr1Name = 0, const wchar_t* attr1Value = 0, + const wchar_t* attr2Name = 0, const wchar_t* attr2Value = 0, + const wchar_t* attr3Name = 0, const wchar_t* attr3Value = 0, + const wchar_t* attr4Name = 0, const wchar_t* attr4Value = 0, + const wchar_t* attr5Name = 0, const wchar_t* attr5Value = 0) = 0; + + //! Writes an xml element with any number of attributes + virtual void writeElement(const wchar_t* name, bool empty, + core::array &names, core::array &values) = 0; + + //! Writes a comment into the xml file + virtual void writeComment(const wchar_t* comment) = 0; + + //! Writes the closing tag for an element. Like "" + virtual void writeClosingTag(const wchar_t* name) = 0; + + //! Writes a text into the file. + /** All occurrences of special characters such as + & (&), < (<), > (>), and " (") are automaticly + replaced. */ + virtual void writeText(const wchar_t* text) = 0; + + //! Writes a line break + virtual void writeLineBreak() = 0; + }; + +} // end namespace io +} // end namespace irr + +#endif + diff --git a/inc/IrrCompileConfig.h b/inc/IrrCompileConfig.h new file mode 100644 index 0000000..c2c5d12 --- /dev/null +++ b/inc/IrrCompileConfig.h @@ -0,0 +1,832 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_COMPILE_CONFIG_H_INCLUDED__ +#define __IRR_COMPILE_CONFIG_H_INCLUDED__ + +//! Irrlicht SDK Version +#define IRRLICHT_VERSION_MAJOR 1 +#define IRRLICHT_VERSION_MINOR 8 +#define IRRLICHT_VERSION_REVISION 4 +// This flag will be defined only in SVN, the official release code will have +// it undefined +//#define IRRLICHT_VERSION_SVN -alpha +#define IRRLICHT_SDK_VERSION "1.8.4" + +#include // TODO: Although included elsewhere this is required at least for mingw + +//! The defines for different operating system are: +//! _IRR_XBOX_PLATFORM_ for XBox +//! _IRR_WINDOWS_ for all irrlicht supported Windows versions +//! _IRR_WINDOWS_CE_PLATFORM_ for Windows CE +//! _IRR_WINDOWS_API_ for Windows or XBox +//! _IRR_LINUX_PLATFORM_ for Linux (it is defined here if no other os is defined) +//! _IRR_SOLARIS_PLATFORM_ for Solaris +//! _IRR_OSX_PLATFORM_ for Apple systems running OSX +//! _IRR_POSIX_API_ for Posix compatible systems +//! Note: PLATFORM defines the OS specific layer, API can group several platforms + +//! DEVICE is the windowing system used, several PLATFORMs support more than one DEVICE +//! Irrlicht can be compiled with more than one device +//! _IRR_COMPILE_WITH_WINDOWS_DEVICE_ for Windows API based device +//! _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ for Windows CE API based device +//! _IRR_COMPILE_WITH_OSX_DEVICE_ for Cocoa native windowing on OSX +//! _IRR_COMPILE_WITH_X11_DEVICE_ for Linux X11 based device +//! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework +//! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback +//! _IRR_COMPILE_WITH_FB_DEVICE_ for framebuffer systems + +//! Passing defines to the compiler which have NO in front of the _IRR definename is an alternative +//! way which can be used to disable defines (instead of outcommenting them in this header). +//! So defines can be controlled from Makefiles or Projectfiles which allows building +//! different library versions without having to change the sources. +//! Example: NO_IRR_COMPILE_WITH_X11_ would disable X11 + + +//! Uncomment this line to compile with the SDL device +//#define _IRR_COMPILE_WITH_SDL_DEVICE_ +#ifdef NO_IRR_COMPILE_WITH_SDL_DEVICE_ +#undef _IRR_COMPILE_WITH_SDL_DEVICE_ +#endif + +//! Comment this line to compile without the fallback console device. +#define _IRR_COMPILE_WITH_CONSOLE_DEVICE_ +#ifdef NO_IRR_COMPILE_WITH_CONSOLE_DEVICE_ +#undef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ +#endif + +//! WIN32 for Windows32 +//! WIN64 for Windows64 +// The windows platform and API support SDL and WINDOW device +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) +#define _IRR_WINDOWS_ +#define _IRR_WINDOWS_API_ +#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ +#endif + +//! WINCE is a very restricted environment for mobile devices +#if defined(_WIN32_WCE) +#define _IRR_WINDOWS_ +#define _IRR_WINDOWS_API_ +#define _IRR_WINDOWS_CE_PLATFORM_ +#define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1300) +# error "Only Microsoft Visual Studio 7.0 and later are supported." +#endif + +// XBox only suppots the native Window stuff +#if defined(_XBOX) + #undef _IRR_WINDOWS_ + #define _IRR_XBOX_PLATFORM_ + #define _IRR_WINDOWS_API_ + //#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + //#define _IRR_COMPILE_WITH_SDL_DEVICE_ + + #include +#endif + +#if defined(__APPLE__) || defined(MACOSX) +#if !defined(MACOSX) +#define MACOSX // legacy support +#endif +#define _IRR_OSX_PLATFORM_ +#define _IRR_COMPILE_WITH_OSX_DEVICE_ +#endif + +#if !defined(_IRR_WINDOWS_API_) && !defined(_IRR_OSX_PLATFORM_) +#ifndef _IRR_SOLARIS_PLATFORM_ +#define _IRR_LINUX_PLATFORM_ +#endif +#define _IRR_POSIX_API_ +#define _IRR_COMPILE_WITH_X11_DEVICE_ +#endif + + +//! Define _IRR_COMPILE_WITH_JOYSTICK_SUPPORT_ if you want joystick events. +#define _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ +#ifdef NO_IRR_COMPILE_WITH_JOYSTICK_EVENTS_ +#undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ +#endif + + +//! Maximum number of texture an SMaterial can have, up to 8 are supported by Irrlicht. +#define _IRR_MATERIAL_MAX_TEXTURES_ 4 + +//! Define _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_ to +//! compile the Irrlicht engine with Direct3D8 and/or DIRECT3D9. +/** If you only want to use the software device or opengl you can disable those defines. +This switch is mostly disabled because people do not get the g++ compiler compile +directX header files, and directX is only available on Windows platforms. If you +are using Dev-Cpp, and want to compile this using a DX dev pack, you can define +_IRR_COMPILE_WITH_DX9_DEV_PACK_. So you simply need to add something like this +to the compiler settings: -DIRR_COMPILE_WITH_DX9_DEV_PACK +and this to the linker settings: -ld3dx9 -ld3dx8 + +Microsoft have chosen to remove D3D8 headers from their recent DXSDKs, and +so D3D8 support is now disabled by default. If you really want to build +with D3D8 support, then you will have to source a DXSDK with the appropriate +headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one. +*/ +#if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) + +//! Define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if you want to use DirectInput for joystick handling. +/** This only applies to Windows devices, currently only supported under Win32 device. +If not defined, Windows Multimedia library is used, which offers also broad support for joystick devices. */ +#define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ +#ifdef NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ +#undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ +#endif +// can't get this to compile currently under borland, can be removed if someone has a better solution +#if defined(__BORLANDC__) +#undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ +#endif + +//! Only define _IRR_COMPILE_WITH_DIRECT3D_8_ if you have an appropriate DXSDK, e.g. Summer 2004 +// #define _IRR_COMPILE_WITH_DIRECT3D_8_ +#define _IRR_COMPILE_WITH_DIRECT3D_9_ + +#ifdef NO_IRR_COMPILE_WITH_DIRECT3D_8_ +#undef _IRR_COMPILE_WITH_DIRECT3D_8_ +#endif +#ifdef NO_IRR_COMPILE_WITH_DIRECT3D_9_ +#undef _IRR_COMPILE_WITH_DIRECT3D_9_ +#endif + +#endif + +//! Define _IRR_COMPILE_WITH_OPENGL_ to compile the Irrlicht engine with OpenGL. +/** If you do not wish the engine to be compiled with OpenGL, comment this +define out. */ +#define _IRR_COMPILE_WITH_OPENGL_ +#ifdef NO_IRR_COMPILE_WITH_OPENGL_ +#undef _IRR_COMPILE_WITH_OPENGL_ +#endif + +//! Define _IRR_COMPILE_WITH_SOFTWARE_ to compile the Irrlicht engine with software driver +/** If you do not need the software driver, or want to use Burning's Video instead, +comment this define out */ +#define _IRR_COMPILE_WITH_SOFTWARE_ +#ifdef NO_IRR_COMPILE_WITH_SOFTWARE_ +#undef _IRR_COMPILE_WITH_SOFTWARE_ +#endif + +//! Define _IRR_COMPILE_WITH_BURNINGSVIDEO_ to compile the Irrlicht engine with Burning's video driver +/** If you do not need this software driver, you can comment this define out. */ +#define _IRR_COMPILE_WITH_BURNINGSVIDEO_ +#ifdef NO_IRR_COMPILE_WITH_BURNINGSVIDEO_ +#undef _IRR_COMPILE_WITH_BURNINGSVIDEO_ +#endif + +//! Define _IRR_COMPILE_WITH_X11_ to compile the Irrlicht engine with X11 support. +/** If you do not wish the engine to be compiled with X11, comment this +define out. */ +// Only used in LinuxDevice. +#define _IRR_COMPILE_WITH_X11_ +#ifdef NO_IRR_COMPILE_WITH_X11_ +#undef _IRR_COMPILE_WITH_X11_ +#endif + +//! Define _IRR_OPENGL_USE_EXTPOINTER_ if the OpenGL renderer should use OpenGL extensions via function pointers. +/** On some systems there is no support for the dynamic extension of OpenGL + via function pointers such that this has to be undef'ed. */ +#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) +#define _IRR_OPENGL_USE_EXTPOINTER_ +#endif + +//! On some Linux systems the XF86 vidmode extension or X11 RandR are missing. Use these flags +//! to remove the dependencies such that Irrlicht will compile on those systems, too. +//! If you don't need colored cursors you can also disable the Xcursor extension +#if defined(_IRR_LINUX_PLATFORM_) && defined(_IRR_COMPILE_WITH_X11_) +#define _IRR_LINUX_X11_VIDMODE_ +//#define _IRR_LINUX_X11_RANDR_ +#ifdef NO_IRR_LINUX_X11_VIDMODE_ +#undef _IRR_LINUX_X11_VIDMODE_ +#endif +#ifdef NO_IRR_LINUX_X11_RANDR_ +#undef _IRR_LINUX_X11_RANDR_ +#endif + +//! X11 has by default only monochrome cursors, but using the Xcursor library we can also get color cursor support. +//! If you have the need for custom color cursors on X11 then enable this and make sure you also link +//! to the Xcursor library in your Makefile/Projectfile. +//#define _IRR_LINUX_XCURSOR_ +#ifdef NO_IRR_LINUX_XCURSOR_ +#undef _IRR_LINUX_XCURSOR_ +#endif + +#endif + +//! Define _IRR_COMPILE_WITH_GUI_ to compile the engine with the built-in GUI +/** Disable this if you are using an external library to draw the GUI. If you disable this then +you will not be able to use anything provided by the GUI Environment, including loading fonts. */ +#define _IRR_COMPILE_WITH_GUI_ +#ifdef NO_IRR_COMPILE_WITH_GUI_ +#undef _IRR_COMPILE_WITH_GUI_ +#endif + +//! Define _IRR_WCHAR_FILESYSTEM to enable unicode filesystem support for the engine. +/** This enables the engine to read/write from unicode filesystem. If you +disable this feature, the engine behave as before (ansi). This is currently only supported +for Windows based systems. You also have to set #define UNICODE for this to compile. +*/ +//#define _IRR_WCHAR_FILESYSTEM +#ifdef NO_IRR_WCHAR_FILESYSTEM +#undef _IRR_WCHAR_FILESYSTEM +#endif + +//! Define _IRR_COMPILE_WITH_JPEGLIB_ to enable compiling the engine using libjpeg. +/** This enables the engine to read jpeg images. If you comment this out, +the engine will no longer read .jpeg images. */ +#define _IRR_COMPILE_WITH_LIBJPEG_ +#ifdef NO_IRR_COMPILE_WITH_LIBJPEG_ +#undef _IRR_COMPILE_WITH_LIBJPEG_ +#endif + +//! Define _IRR_USE_NON_SYSTEM_JPEG_LIB_ to let irrlicht use the jpeglib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the jpeg lib installed in the system. + This is only used when _IRR_COMPILE_WITH_LIBJPEG_ is defined. */ +#define _IRR_USE_NON_SYSTEM_JPEG_LIB_ +#ifdef NO_IRR_USE_NON_SYSTEM_JPEG_LIB_ +#undef _IRR_USE_NON_SYSTEM_JPEG_LIB_ +#endif + +//! Define _IRR_COMPILE_WITH_LIBPNG_ to enable compiling the engine using libpng. +/** This enables the engine to read png images. If you comment this out, +the engine will no longer read .png images. */ +#define _IRR_COMPILE_WITH_LIBPNG_ +#ifdef NO_IRR_COMPILE_WITH_LIBPNG_ +#undef _IRR_COMPILE_WITH_LIBPNG_ +#endif + +//! Define _IRR_USE_NON_SYSTEM_LIBPNG_ to let irrlicht use the libpng which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the libpng installed in the system. + This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */ +#define _IRR_USE_NON_SYSTEM_LIB_PNG_ +#ifdef NO_IRR_USE_NON_SYSTEM_LIB_PNG_ +#undef _IRR_USE_NON_SYSTEM_LIB_PNG_ +#endif + +//! Define _IRR_D3D_NO_SHADER_DEBUGGING to disable shader debugging in D3D9 +/** If _IRR_D3D_NO_SHADER_DEBUGGING is undefined in IrrCompileConfig.h, +it is possible to debug all D3D9 shaders in VisualStudio. All shaders +(which have been generated in memory or read from archives for example) will be emitted +into a temporary file at runtime for this purpose. To debug your shaders, choose +Debug->Direct3D->StartWithDirect3DDebugging in Visual Studio, and for every shader a +file named 'irr_dbg_shader_%%.vsh' or 'irr_dbg_shader_%%.psh' will be created. Drag'n'drop +the file you want to debug into visual studio. That's it. You can now set breakpoints and +watch registers, variables etc. This works with ASM, HLSL, and both with pixel and vertex shaders. +Note that the engine will run in D3D REF for this, which is a lot slower than HAL. */ +#define _IRR_D3D_NO_SHADER_DEBUGGING +#ifdef NO_IRR_D3D_NO_SHADER_DEBUGGING +#undef _IRR_D3D_NO_SHADER_DEBUGGING +#endif + +//! Define _IRR_D3D_USE_LEGACY_HLSL_COMPILER to enable the old HLSL compiler in recent DX SDKs +/** This enables support for ps_1_x shaders for recent DX SDKs. Otherwise, support +for this shader model is not available anymore in SDKs after Oct2006. You need to +distribute the OCT2006_d3dx9_31_x86.cab or OCT2006_d3dx9_31_x64.cab though, in order +to provide the user with the proper DLL. That's why it's disabled by default. */ +//#define _IRR_D3D_USE_LEGACY_HLSL_COMPILER +#ifdef NO_IRR_D3D_USE_LEGACY_HLSL_COMPILER +#undef _IRR_D3D_USE_LEGACY_HLSL_COMPILER +#endif + +//! Define _IRR_COMPILE_WITH_CG_ to enable Cg Shading Language support +//#define _IRR_COMPILE_WITH_CG_ +#ifdef NO_IRR_COMPILE_WITH_CG_ +#undef _IRR_COMPILE_WITH_CG_ +#endif +#if !defined(_IRR_COMPILE_WITH_OPENGL_) && !defined(_IRR_COMPILE_WITH_DIRECT3D_9_) +#undef _IRR_COMPILE_WITH_CG_ +#endif + +//! Define _IRR_USE_NVIDIA_PERFHUD_ to opt-in to using the nVidia PerHUD tool +/** Enable, by opting-in, to use the nVidia PerfHUD performance analysis driver +tool . */ +#undef _IRR_USE_NVIDIA_PERFHUD_ + +//! Define one of the three setting for Burning's Video Software Rasterizer +/** So if we were marketing guys we could say Irrlicht has 4 Software-Rasterizers. + In a Nutshell: + All Burnings Rasterizers use 32 Bit Backbuffer, 32Bit Texture & 32 Bit Z or WBuffer, + 16 Bit/32 Bit can be adjusted on a global flag. + + BURNINGVIDEO_RENDERER_BEAUTIFUL + 32 Bit + Vertexcolor + Lighting + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + + Bilinear Texturefiltering + WBuffer + + BURNINGVIDEO_RENDERER_FAST + 32 Bit + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + WBuffer + + Bilinear Dithering TextureFiltering + WBuffer + + BURNINGVIDEO_RENDERER_ULTRA_FAST + 16Bit + SubPixel/SubTexel Correct + ZBuffer +*/ + +#define BURNINGVIDEO_RENDERER_BEAUTIFUL +//#define BURNINGVIDEO_RENDERER_FAST +//#define BURNINGVIDEO_RENDERER_ULTRA_FAST +//#define BURNINGVIDEO_RENDERER_CE + +//! Uncomment the following line if you want to ignore the deprecated warnings +//#define IGNORE_DEPRECATED_WARNING + +//! Define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ if you want to be able to load +/** .irr scenes using ISceneManager::loadScene */ +#define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_IRR_SCENE_LOADER_ +#undef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ +#endif + +//! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based +/** animated meshes. If you compile without this, you will be unable to load +B3D, MS3D or X meshes */ +#define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ +#ifdef NO_IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ +#undef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ +#endif + +#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ +//! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to use Blitz3D files +#define _IRR_COMPILE_WITH_B3D_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_B3D_LOADER_ +#undef _IRR_COMPILE_WITH_B3D_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_MS3D_LOADER_ if you want to Milkshape files +#define _IRR_COMPILE_WITH_MS3D_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_MS3D_LOADER_ +#undef _IRR_COMPILE_WITH_MS3D_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_X_LOADER_ if you want to use Microsoft X files +#define _IRR_COMPILE_WITH_X_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_X_LOADER_ +#undef _IRR_COMPILE_WITH_X_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_OGRE_LOADER_ if you want to load Ogre 3D files +#define _IRR_COMPILE_WITH_OGRE_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_OGRE_LOADER_ +#undef _IRR_COMPILE_WITH_OGRE_LOADER_ +#endif +#endif // _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ + +//! Define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ if you want to load Irrlicht Engine .irrmesh files +#define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_IRR_MESH_LOADER_ +#undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_HALFLIFE_LOADER_ if you want to load Halflife animated files +#define _IRR_COMPILE_WITH_HALFLIFE_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_HALFLIFE_LOADER_ +#undef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_MD2_LOADER_ if you want to load Quake 2 animated files +#define _IRR_COMPILE_WITH_MD2_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_MD2_LOADER_ +#undef _IRR_COMPILE_WITH_MD2_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_MD3_LOADER_ if you want to load Quake 3 animated files +#define _IRR_COMPILE_WITH_MD3_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_MD3_LOADER_ +#undef _IRR_COMPILE_WITH_MD3_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_3DS_LOADER_ if you want to load 3D Studio Max files +#define _IRR_COMPILE_WITH_3DS_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_3DS_LOADER_ +#undef _IRR_COMPILE_WITH_3DS_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_COLLADA_LOADER_ if you want to load Collada files +#define _IRR_COMPILE_WITH_COLLADA_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_COLLADA_LOADER_ +#undef _IRR_COMPILE_WITH_COLLADA_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_CSM_LOADER_ if you want to load Cartography Shop files +#define _IRR_COMPILE_WITH_CSM_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_CSM_LOADER_ +#undef _IRR_COMPILE_WITH_CSM_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_BSP_LOADER_ if you want to load Quake 3 BSP files +#define _IRR_COMPILE_WITH_BSP_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_BSP_LOADER_ +#undef _IRR_COMPILE_WITH_BSP_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_DMF_LOADER_ if you want to load DeleD files +#define _IRR_COMPILE_WITH_DMF_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_DMF_LOADER_ +#undef _IRR_COMPILE_WITH_DMF_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_LMTS_LOADER_ if you want to load LMTools files +#define _IRR_COMPILE_WITH_LMTS_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_LMTS_LOADER_ +#undef _IRR_COMPILE_WITH_LMTS_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_MY3D_LOADER_ if you want to load MY3D files +#define _IRR_COMPILE_WITH_MY3D_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_MY3D_LOADER_ +#undef _IRR_COMPILE_WITH_MY3D_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_OBJ_LOADER_ if you want to load Wavefront OBJ files +#define _IRR_COMPILE_WITH_OBJ_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_OBJ_LOADER_ +#undef _IRR_COMPILE_WITH_OBJ_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_OCT_LOADER_ if you want to load FSRad OCT files +#define _IRR_COMPILE_WITH_OCT_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_OCT_LOADER_ +#undef _IRR_COMPILE_WITH_OCT_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_LWO_LOADER_ if you want to load Lightwave3D files +#define _IRR_COMPILE_WITH_LWO_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_LWO_LOADER_ +#undef _IRR_COMPILE_WITH_LWO_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load stereolithography files +#define _IRR_COMPILE_WITH_STL_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_STL_LOADER_ +#undef _IRR_COMPILE_WITH_STL_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_PLY_LOADER_ if you want to load Polygon (Stanford Triangle) files +#define _IRR_COMPILE_WITH_PLY_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_PLY_LOADER_ +#undef _IRR_COMPILE_WITH_PLY_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_SMF_LOADER_ if you want to load 3D World Studio mesh files +#define _IRR_COMPILE_WITH_SMF_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_SMF_LOADER_ +#undef _IRR_COMPILE_WITH_SMF_LOADER_ +#endif + +//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irrMesh files +#define _IRR_COMPILE_WITH_IRR_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_IRR_WRITER_ +#undef _IRR_COMPILE_WITH_IRR_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_COLLADA_WRITER_ if you want to write Collada files +#define _IRR_COMPILE_WITH_COLLADA_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_COLLADA_WRITER_ +#undef _IRR_COMPILE_WITH_COLLADA_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_STL_WRITER_ if you want to write .stl files +#define _IRR_COMPILE_WITH_STL_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_STL_WRITER_ +#undef _IRR_COMPILE_WITH_STL_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_OBJ_WRITER_ if you want to write .obj files +#define _IRR_COMPILE_WITH_OBJ_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_OBJ_WRITER_ +#undef _IRR_COMPILE_WITH_OBJ_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_PLY_WRITER_ if you want to write .ply files +#define _IRR_COMPILE_WITH_PLY_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_PLY_WRITER_ +#undef _IRR_COMPILE_WITH_PLY_WRITER_ +#endif + +//! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files +//! Disabling this loader will also disable the built-in font +#define _IRR_COMPILE_WITH_BMP_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_BMP_LOADER_ +#undef _IRR_COMPILE_WITH_BMP_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_JPG_LOADER_ if you want to load .jpg files +#define _IRR_COMPILE_WITH_JPG_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_JPG_LOADER_ +#undef _IRR_COMPILE_WITH_JPG_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_PCX_LOADER_ if you want to load .pcx files +#define _IRR_COMPILE_WITH_PCX_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_PCX_LOADER_ +#undef _IRR_COMPILE_WITH_PCX_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_PNG_LOADER_ if you want to load .png files +#define _IRR_COMPILE_WITH_PNG_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_PNG_LOADER_ +#undef _IRR_COMPILE_WITH_PNG_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_PPM_LOADER_ if you want to load .ppm/.pgm/.pbm files +#define _IRR_COMPILE_WITH_PPM_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_PPM_LOADER_ +#undef _IRR_COMPILE_WITH_PPM_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_PSD_LOADER_ if you want to load .psd files +#define _IRR_COMPILE_WITH_PSD_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_PSD_LOADER_ +#undef _IRR_COMPILE_WITH_PSD_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load .dds files +// Outcommented because +// a) it doesn't compile on 64-bit currently +// b) anyone enabling it should be aware that S3TC compression algorithm which might be used in that loader +// is patented in the US by S3 and they do collect license fees when it's used in applications. +// So if you are unfortunate enough to develop applications for US market and their broken patent system be careful. +// #define _IRR_COMPILE_WITH_DDS_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_DDS_LOADER_ +#undef _IRR_COMPILE_WITH_DDS_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files +#define _IRR_COMPILE_WITH_TGA_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_TGA_LOADER_ +#undef _IRR_COMPILE_WITH_TGA_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files +#define _IRR_COMPILE_WITH_WAL_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_WAL_LOADER_ +#undef _IRR_COMPILE_WITH_WAL_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_LMP_LOADER_ if you want to load .lmp files +#define _IRR_COMPILE_WITH_LMP_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_LMP_LOADER_ +#undef _IRR_COMPILE_WITH_LMP_LOADER_ +#endif +//! Define _IRR_COMPILE_WITH_RGB_LOADER_ if you want to load Silicon Graphics .rgb/.rgba/.sgi/.int/.inta/.bw files +#define _IRR_COMPILE_WITH_RGB_LOADER_ +#ifdef NO_IRR_COMPILE_WITH_RGB_LOADER_ +#undef _IRR_COMPILE_WITH_RGB_LOADER_ +#endif + +//! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files +#define _IRR_COMPILE_WITH_BMP_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_BMP_WRITER_ +#undef _IRR_COMPILE_WITH_BMP_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_JPG_WRITER_ if you want to write .jpg files +#define _IRR_COMPILE_WITH_JPG_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_JPG_WRITER_ +#undef _IRR_COMPILE_WITH_JPG_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_PCX_WRITER_ if you want to write .pcx files +#define _IRR_COMPILE_WITH_PCX_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_PCX_WRITER_ +#undef _IRR_COMPILE_WITH_PCX_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_PNG_WRITER_ if you want to write .png files +#define _IRR_COMPILE_WITH_PNG_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_PNG_WRITER_ +#undef _IRR_COMPILE_WITH_PNG_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_PPM_WRITER_ if you want to write .ppm files +#define _IRR_COMPILE_WITH_PPM_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_PPM_WRITER_ +#undef _IRR_COMPILE_WITH_PPM_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_PSD_WRITER_ if you want to write .psd files +#define _IRR_COMPILE_WITH_PSD_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_PSD_WRITER_ +#undef _IRR_COMPILE_WITH_PSD_WRITER_ +#endif +//! Define _IRR_COMPILE_WITH_TGA_WRITER_ if you want to write .tga files +#define _IRR_COMPILE_WITH_TGA_WRITER_ +#ifdef NO_IRR_COMPILE_WITH_TGA_WRITER_ +#undef _IRR_COMPILE_WITH_TGA_WRITER_ +#endif + +//! Define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ if you want to open ZIP and GZIP archives +/** ZIP reading has several more options below to configure. */ +#define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#endif +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. +/** This enables the engine to read from compressed .zip archives. If you +disable this feature, the engine can still read archives, but only uncompressed +ones. */ +#define _IRR_COMPILE_WITH_ZLIB_ +#ifdef NO_IRR_COMPILE_WITH_ZLIB_ +#undef _IRR_COMPILE_WITH_ZLIB_ +#endif +//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the zlib +installed on the system. This is only used when _IRR_COMPILE_WITH_ZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_ZLIB_ +#ifdef NO_IRR_USE_NON_SYSTEM_ZLIB_ +#undef _IRR_USE_NON_SYSTEM_ZLIB_ +#endif +//! Define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if you want to read AES-encrypted ZIP archives +#define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ +#ifdef NO_IRR_COMPILE_WITH_ZIP_ENCRYPTION_ +#undef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ +#endif +//! Define _IRR_COMPILE_WITH_BZIP2_ if you want to support bzip2 compressed zip archives +/** bzip2 is superior to the original zip file compression modes, but requires +a certain amount of memory for decompression and adds several files to the +library. */ +#define _IRR_COMPILE_WITH_BZIP2_ +#ifdef NO_IRR_COMPILE_WITH_BZIP2_ +#undef _IRR_COMPILE_WITH_BZIP2_ +#endif +//! Define _IRR_USE_NON_SYSTEM_BZLIB_ to let irrlicht use the bzlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the bzlib +installed on the system. This is only used when _IRR_COMPILE_WITH_BZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_BZLIB_ +#ifdef NO_IRR_USE_NON_SYSTEM_BZLIB_ +#undef _IRR_USE_NON_SYSTEM_BZLIB_ +#endif +//! Define _IRR_COMPILE_WITH_LZMA_ if you want to use LZMA compressed zip files. +/** LZMA is a very efficient compression code, known from 7zip. Irrlicht +currently only supports zip archives, though. */ +#define _IRR_COMPILE_WITH_LZMA_ +#ifdef NO_IRR_COMPILE_WITH_LZMA_ +#undef _IRR_COMPILE_WITH_LZMA_ +#endif +#endif + +//! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives +#define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ +#endif +//! Define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ if you want to open ID software PAK archives +#define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ +#endif +//! Define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ if you want to open Nebula Device NPK archives +#define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ +#endif +//! Define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ if you want to open TAR archives +#define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ +#endif +//! Define __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ if you want to open WAD archives +#define __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ +#ifdef NO__IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ +#undef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ +#endif + +//! Set FPU settings +/** Irrlicht should use approximate float and integer fpu techniques +precision will be lower but speed higher. currently X86 only +*/ +#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) + //#define IRRLICHT_FAST_MATH + #ifdef NO_IRRLICHT_FAST_MATH + #undef IRRLICHT_FAST_MATH + #endif +#endif + +// Some cleanup and standard stuff + +#ifdef _IRR_WINDOWS_API_ + +// To build Irrlicht as a static library, you must define _IRR_STATIC_LIB_ in both the +// Irrlicht build, *and* in the user application, before #including +#ifndef _IRR_STATIC_LIB_ +#ifdef IRRLICHT_EXPORTS +#define IRRLICHT_API __declspec(dllexport) +#else +#define IRRLICHT_API __declspec(dllimport) +#endif // IRRLICHT_EXPORT +#else +#define IRRLICHT_API +#endif // _IRR_STATIC_LIB_ + +// Declare the calling convention. +#if defined(_STDCALL_SUPPORTED) +#define IRRCALLCONV __stdcall +#else +#define IRRCALLCONV __cdecl +#endif // STDCALL_SUPPORTED + +#else // _IRR_WINDOWS_API_ + +// Force symbol export in shared libraries built with gcc. +#if (__GNUC__ >= 4) && !defined(_IRR_STATIC_LIB_) && defined(IRRLICHT_EXPORTS) +#define IRRLICHT_API __attribute__ ((visibility("default"))) +#else +#define IRRLICHT_API +#endif + +#define IRRCALLCONV + +#endif // _IRR_WINDOWS_API_ + +// We need to disable DIRECT3D9 support for Visual Studio 6.0 because +// those $%&$!! disabled support for it since Dec. 2004 and users are complaining +// about linker errors. Comment this out only if you are knowing what you are +// doing. (Which means you have an old DX9 SDK and VisualStudio6). +#ifdef _MSC_VER +#if (_MSC_VER < 1300 && !defined(__GNUC__)) +#undef _IRR_COMPILE_WITH_DIRECT3D_9_ +#pragma message("Compiling Irrlicht with Visual Studio 6.0, support for DX9 is disabled.") +#endif +#endif + +// XBox does not have OpenGL or DirectX9 +#if defined(_IRR_XBOX_PLATFORM_) + #undef _IRR_COMPILE_WITH_OPENGL_ + #undef _IRR_COMPILE_WITH_DIRECT3D_9_ +#endif + +//! WinCE does not have OpenGL or DirectX9. use minimal loaders +#if defined(_WIN32_WCE) + #undef _IRR_COMPILE_WITH_OPENGL_ + #undef _IRR_COMPILE_WITH_DIRECT3D_8_ + #undef _IRR_COMPILE_WITH_DIRECT3D_9_ + + #undef BURNINGVIDEO_RENDERER_BEAUTIFUL + #undef BURNINGVIDEO_RENDERER_FAST + #undef BURNINGVIDEO_RENDERER_ULTRA_FAST + #define BURNINGVIDEO_RENDERER_CE + + #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + #define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ + //#define _IRR_WCHAR_FILESYSTEM + + #undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ + //#undef _IRR_COMPILE_WITH_MD2_LOADER_ + #undef _IRR_COMPILE_WITH_MD3_LOADER_ + #undef _IRR_COMPILE_WITH_3DS_LOADER_ + #undef _IRR_COMPILE_WITH_COLLADA_LOADER_ + #undef _IRR_COMPILE_WITH_CSM_LOADER_ + #undef _IRR_COMPILE_WITH_BSP_LOADER_ + #undef _IRR_COMPILE_WITH_DMF_LOADER_ + #undef _IRR_COMPILE_WITH_LMTS_LOADER_ + #undef _IRR_COMPILE_WITH_MY3D_LOADER_ + #undef _IRR_COMPILE_WITH_OBJ_LOADER_ + #undef _IRR_COMPILE_WITH_OCT_LOADER_ + #undef _IRR_COMPILE_WITH_OGRE_LOADER_ + #undef _IRR_COMPILE_WITH_LWO_LOADER_ + #undef _IRR_COMPILE_WITH_STL_LOADER_ + #undef _IRR_COMPILE_WITH_IRR_WRITER_ + #undef _IRR_COMPILE_WITH_COLLADA_WRITER_ + #undef _IRR_COMPILE_WITH_STL_WRITER_ + #undef _IRR_COMPILE_WITH_OBJ_WRITER_ + //#undef _IRR_COMPILE_WITH_BMP_LOADER_ + //#undef _IRR_COMPILE_WITH_JPG_LOADER_ + #undef _IRR_COMPILE_WITH_PCX_LOADER_ + //#undef _IRR_COMPILE_WITH_PNG_LOADER_ + #undef _IRR_COMPILE_WITH_PPM_LOADER_ + #undef _IRR_COMPILE_WITH_PSD_LOADER_ + //#undef _IRR_COMPILE_WITH_TGA_LOADER_ + #undef _IRR_COMPILE_WITH_WAL_LOADER_ + #undef _IRR_COMPILE_WITH_BMP_WRITER_ + #undef _IRR_COMPILE_WITH_JPG_WRITER_ + #undef _IRR_COMPILE_WITH_PCX_WRITER_ + #undef _IRR_COMPILE_WITH_PNG_WRITER_ + #undef _IRR_COMPILE_WITH_PPM_WRITER_ + #undef _IRR_COMPILE_WITH_PSD_WRITER_ + #undef _IRR_COMPILE_WITH_TGA_WRITER_ + +#endif + +#ifndef _IRR_WINDOWS_API_ + #undef _IRR_WCHAR_FILESYSTEM +#endif + +#if defined(__sparc__) || defined(__sun__) +#define __BIG_ENDIAN__ +#endif + +#if defined(_IRR_SOLARIS_PLATFORM_) + #undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ +#endif + +//! Define __IRR_HAS_S64 if the irr::s64 type should be enable (needs long long, available on most platforms, but not part of ISO C++ 98) +#define __IRR_HAS_S64 +#ifdef NO__IRR_HAS_S64 +#undef __IRR_HAS_S64 +#endif + +#if defined(__BORLANDC__) + #include + + // Borland 5.5.1 does not have _strcmpi defined + #if __BORLANDC__ == 0x551 + // #define _strcmpi strcmpi + #undef _tfinddata_t + #undef _tfindfirst + #undef _tfindnext + + #define _tfinddata_t __tfinddata_t + #define _tfindfirst __tfindfirst + #define _tfindnext __tfindnext + typedef long intptr_t; + #endif + +#endif + +#ifdef _DEBUG + //! A few attributes are written in CSceneManager when _IRR_SCENEMANAGER_DEBUG is enabled + // NOTE: Those attributes were used always until 1.8.0 and became a global define for 1.8.1 + // which is only enabled in debug because it had a large (sometimes >5%) impact on speed. + // A better solution in the long run is to break the interface and remove _all_ attribute + // access in functions like CSceneManager::drawAll and instead put that information in some + // own struct/class or in CSceneManager. + // See http://irrlicht.sourceforge.net/forum/viewtopic.php?f=2&t=48211 for the discussion. + #define _IRR_SCENEMANAGER_DEBUG + #ifdef NO_IRR_SCENEMANAGER_DEBUG + #undef _IRR_SCENEMANAGER_DEBUG + #endif +#endif + +#endif // __IRR_COMPILE_CONFIG_H_INCLUDED__ + diff --git a/inc/IrrlichtDevice.h b/inc/IrrlichtDevice.h new file mode 100644 index 0000000..536e10b --- /dev/null +++ b/inc/IrrlichtDevice.h @@ -0,0 +1,322 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_IRRLICHT_DEVICE_H_INCLUDED__ +#define __I_IRRLICHT_DEVICE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "dimension2d.h" +#include "IVideoDriver.h" +#include "EDriverTypes.h" +#include "EDeviceTypes.h" +#include "IEventReceiver.h" +#include "ICursorControl.h" +#include "IVideoModeList.h" +#include "ITimer.h" +#include "IOSOperator.h" + +namespace irr +{ + class ILogger; + class IEventReceiver; + class IRandomizer; + + namespace io { + class IFileSystem; + } // end namespace io + + namespace gui { + class IGUIEnvironment; + } // end namespace gui + + namespace scene { + class ISceneManager; + } // end namespace scene + + //! The Irrlicht device. You can create it with createDevice() or createDeviceEx(). + /** This is the most important class of the Irrlicht Engine. You can + access everything in the engine if you have a pointer to an instance of + this class. There should be only one instance of this class at any + time. + */ + class IrrlichtDevice : public virtual IReferenceCounted + { + public: + + //! Runs the device. + /** Also increments the virtual timer by calling + ITimer::tick();. You can prevent this + by calling ITimer::stop(); before and ITimer::start() after + calling IrrlichtDevice::run(). Returns false if device wants + to be deleted. Use it in this way: + \code + while(device->run()) + { + // draw everything here + } + \endcode + If you want the device to do nothing if the window is inactive + (recommended), use the slightly enhanced code shown at isWindowActive(). + + Note if you are running Irrlicht inside an external, custom + created window: Calling Device->run() will cause Irrlicht to + dispatch windows messages internally. + If you are running Irrlicht in your own custom window, you can + also simply use your own message loop using GetMessage, + DispatchMessage and whatever and simply don't use this method. + But note that Irrlicht will not be able to fetch user input + then. See irr::SIrrlichtCreationParameters::WindowId for more + informations and example code. + */ + virtual bool run() = 0; + + //! Cause the device to temporarily pause execution and let other processes run. + /** This should bring down processor usage without major + performance loss for Irrlicht */ + virtual void yield() = 0; + + //! Pause execution and let other processes to run for a specified amount of time. + /** It may not wait the full given time, as sleep may be interrupted + \param timeMs: Time to sleep for in milisecs. + \param pauseTimer: If true, pauses the device timer while sleeping + */ + virtual void sleep(u32 timeMs, bool pauseTimer=false) = 0; + + //! Provides access to the video driver for drawing 3d and 2d geometry. + /** \return Pointer the video driver. */ + virtual video::IVideoDriver* getVideoDriver() = 0; + + //! Provides access to the virtual file system. + /** \return Pointer to the file system. */ + virtual io::IFileSystem* getFileSystem() = 0; + + //! Provides access to the 2d user interface environment. + /** \return Pointer to the gui environment. */ + virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; + + //! Provides access to the scene manager. + /** \return Pointer to the scene manager. */ + virtual scene::ISceneManager* getSceneManager() = 0; + + //! Provides access to the cursor control. + /** \return Pointer to the mouse cursor control interface. */ + virtual gui::ICursorControl* getCursorControl() = 0; + + //! Provides access to the message logger. + /** \return Pointer to the logger. */ + virtual ILogger* getLogger() = 0; + + //! Gets a list with all video modes available. + /** If you are confused now, because you think you have to + create an Irrlicht Device with a video mode before being able + to get the video mode list, let me tell you that there is no + need to start up an Irrlicht Device with EDT_DIRECT3D8, + EDT_OPENGL or EDT_SOFTWARE: For this (and for lots of other + reasons) the null driver, EDT_NULL exists. + \return Pointer to a list with all video modes supported + by the gfx adapter. */ + virtual video::IVideoModeList* getVideoModeList() = 0; + + //! Provides access to the operation system operator object. + /** The OS operator provides methods for + getting system specific informations and doing system + specific operations, such as exchanging data with the clipboard + or reading the operation system version. + \return Pointer to the OS operator. */ + virtual IOSOperator* getOSOperator() = 0; + + //! Provides access to the engine's timer. + /** The system time can be retrieved by it as + well as the virtual time, which also can be manipulated. + \return Pointer to the ITimer object. */ + virtual ITimer* getTimer() = 0; + + //! Provides access to the engine's currently set randomizer. + /** \return Pointer to the IRandomizer object. */ + virtual IRandomizer* getRandomizer() const =0; + + //! Sets a new randomizer. + /** \param r Pointer to the new IRandomizer object. This object is + grab()'ed by the engine and will be released upon the next setRandomizer + call or upon device destruction. */ + virtual void setRandomizer(IRandomizer* r) =0; + + //! Creates a new default randomizer. + /** The default randomizer provides the random sequence known from previous + Irrlicht versions and is the initial randomizer set on device creation. + \return Pointer to the default IRandomizer object. */ + virtual IRandomizer* createDefaultRandomizer() const =0; + + //! Sets the caption of the window. + /** \param text: New text of the window caption. */ + virtual void setWindowCaption(const wchar_t* text) = 0; + + //! Returns if the window is active. + /** If the window is inactive, + nothing needs to be drawn. So if you don't want to draw anything + when the window is inactive, create your drawing loop this way: + \code + while(device->run()) + { + if (device->isWindowActive()) + { + // draw everything here + } + else + device->yield(); + } + \endcode + \return True if window is active. */ + virtual bool isWindowActive() const = 0; + + //! Checks if the Irrlicht window has focus + /** \return True if window has focus. */ + virtual bool isWindowFocused() const = 0; + + //! Checks if the Irrlicht window is minimized + /** \return True if window is minimized. */ + virtual bool isWindowMinimized() const = 0; + + //! Checks if the Irrlicht window is running in fullscreen mode + /** \return True if window is fullscreen. */ + virtual bool isFullscreen() const = 0; + + //! Get the current color format of the window + /** \return Color format of the window. */ + virtual video::ECOLOR_FORMAT getColorFormat() const = 0; + + //! Notifies the device that it should close itself. + /** IrrlichtDevice::run() will always return false after closeDevice() was called. */ + virtual void closeDevice() = 0; + + //! Get the version of the engine. + /** The returned string + will look like this: "1.2.3" or this: "1.2". + \return String which contains the version. */ + virtual const c8* getVersion() const = 0; + + //! Sets a new user event receiver which will receive events from the engine. + /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along + the chain of event receivers. The path that an event takes through the system depends + on its type. See irr::EEVENT_TYPE for details. + \param receiver New receiver to be used. */ + virtual void setEventReceiver(IEventReceiver* receiver) = 0; + + //! Provides access to the current event receiver. + /** \return Pointer to the current event receiver. Returns 0 if there is none. */ + virtual IEventReceiver* getEventReceiver() = 0; + + //! Sends a user created event to the engine. + /** Is is usually not necessary to use this. However, if you + are using an own input library for example for doing joystick + input, you can use this to post key or mouse input events to + the engine. Internally, this method only delegates the events + further to the scene manager and the GUI environment. */ + virtual bool postEventFromUser(const SEvent& event) = 0; + + //! Sets the input receiving scene manager. + /** If set to null, the main scene manager (returned by + GetSceneManager()) will receive the input + \param sceneManager New scene manager to be used. */ + virtual void setInputReceivingSceneManager(scene::ISceneManager* sceneManager) = 0; + + //! Sets if the window should be resizable in windowed mode. + /** The default is false. This method only works in windowed + mode. + \param resize Flag whether the window should be resizable. */ + virtual void setResizable(bool resize=false) = 0; + + //! Minimizes the window if possible. + virtual void minimizeWindow() =0; + + //! Maximizes the window if possible. + virtual void maximizeWindow() =0; + + //! Restore the window to normal size if possible. + virtual void restoreWindow() =0; + + //! Activate any joysticks, and generate events for them. + /** Irrlicht contains support for joysticks, but does not generate joystick events by default, + as this would consume joystick info that 3rd party libraries might rely on. Call this method to + activate joystick support in Irrlicht and to receive irr::SJoystickEvent events. + \param joystickInfo On return, this will contain an array of each joystick that was found and activated. + \return true if joysticks are supported on this device and _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ + is defined, false if joysticks are not supported or support is compiled out. + */ + virtual bool activateJoysticks(core::array& joystickInfo) =0; + + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp(f32 red, f32 green, f32 blue, + f32 relativebrightness, f32 relativecontrast) =0; + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, + f32 &brightness, f32 &contrast) =0; + + //! Remove messages pending in the system message loop + /** This function is usually used after messages have been buffered for a longer time, for example + when loading a large scene. Clearing the message loop prevents that mouse- or buttonclicks which users + have pressed in the meantime will now trigger unexpected actions in the gui.
+ So far the following messages are cleared:
+ Win32: All keyboard and mouse messages
+ Linux: All keyboard and mouse messages
+ All other devices are not yet supported here.
+ The function is still somewhat experimental, as the kind of messages we clear is based on just a few use-cases. + If you think further messages should be cleared, or some messages should not be cleared here, then please tell us. */ + virtual void clearSystemMessages() = 0; + + //! Get the type of the device. + /** This allows the user to check which windowing system is currently being + used. */ + virtual E_DEVICE_TYPE getType() const = 0; + + //! Check if a driver type is supported by the engine. + /** Even if true is returned the driver may not be available + for a configuration requested when creating the device. */ + static bool isDriverSupported(video::E_DRIVER_TYPE driver) + { + switch (driver) + { + case video::EDT_NULL: + return true; + case video::EDT_SOFTWARE: +#ifdef _IRR_COMPILE_WITH_SOFTWARE_ + return true; +#else + return false; +#endif + case video::EDT_BURNINGSVIDEO: +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + return true; +#else + return false; +#endif + case video::EDT_DIRECT3D8: +#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ + return true; +#else + return false; +#endif + case video::EDT_DIRECT3D9: +#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ + return true; +#else + return false; +#endif + case video::EDT_OPENGL: +#ifdef _IRR_COMPILE_WITH_OPENGL_ + return true; +#else + return false; +#endif + default: + return false; + } + } + }; + +} // end namespace irr + +#endif + diff --git a/inc/Keycodes.h b/inc/Keycodes.h new file mode 100644 index 0000000..e56eca1 --- /dev/null +++ b/inc/Keycodes.h @@ -0,0 +1,173 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_KEY_CODES_H_INCLUDED__ +#define __IRR_KEY_CODES_H_INCLUDED__ + +namespace irr +{ + + enum EKEY_CODE + { + KEY_LBUTTON = 0x01, // Left mouse button + KEY_RBUTTON = 0x02, // Right mouse button + KEY_CANCEL = 0x03, // Control-break processing + KEY_MBUTTON = 0x04, // Middle mouse button (three-button mouse) + KEY_XBUTTON1 = 0x05, // Windows 2000/XP: X1 mouse button + KEY_XBUTTON2 = 0x06, // Windows 2000/XP: X2 mouse button + KEY_BACK = 0x08, // BACKSPACE key + KEY_TAB = 0x09, // TAB key + KEY_CLEAR = 0x0C, // CLEAR key + KEY_RETURN = 0x0D, // ENTER key + KEY_SHIFT = 0x10, // SHIFT key + KEY_CONTROL = 0x11, // CTRL key + KEY_MENU = 0x12, // ALT key + KEY_PAUSE = 0x13, // PAUSE key + KEY_CAPITAL = 0x14, // CAPS LOCK key + KEY_KANA = 0x15, // IME Kana mode + KEY_HANGUEL = 0x15, // IME Hanguel mode (maintained for compatibility use KEY_HANGUL) + KEY_HANGUL = 0x15, // IME Hangul mode + KEY_JUNJA = 0x17, // IME Junja mode + KEY_FINAL = 0x18, // IME final mode + KEY_HANJA = 0x19, // IME Hanja mode + KEY_KANJI = 0x19, // IME Kanji mode + KEY_ESCAPE = 0x1B, // ESC key + KEY_CONVERT = 0x1C, // IME convert + KEY_NONCONVERT = 0x1D, // IME nonconvert + KEY_ACCEPT = 0x1E, // IME accept + KEY_MODECHANGE = 0x1F, // IME mode change request + KEY_SPACE = 0x20, // SPACEBAR + KEY_PRIOR = 0x21, // PAGE UP key + KEY_NEXT = 0x22, // PAGE DOWN key + KEY_END = 0x23, // END key + KEY_HOME = 0x24, // HOME key + KEY_LEFT = 0x25, // LEFT ARROW key + KEY_UP = 0x26, // UP ARROW key + KEY_RIGHT = 0x27, // RIGHT ARROW key + KEY_DOWN = 0x28, // DOWN ARROW key + KEY_SELECT = 0x29, // SELECT key + KEY_PRINT = 0x2A, // PRINT key + KEY_EXECUT = 0x2B, // EXECUTE key + KEY_SNAPSHOT = 0x2C, // PRINT SCREEN key + KEY_INSERT = 0x2D, // INS key + KEY_DELETE = 0x2E, // DEL key + KEY_HELP = 0x2F, // HELP key + KEY_KEY_0 = 0x30, // 0 key + KEY_KEY_1 = 0x31, // 1 key + KEY_KEY_2 = 0x32, // 2 key + KEY_KEY_3 = 0x33, // 3 key + KEY_KEY_4 = 0x34, // 4 key + KEY_KEY_5 = 0x35, // 5 key + KEY_KEY_6 = 0x36, // 6 key + KEY_KEY_7 = 0x37, // 7 key + KEY_KEY_8 = 0x38, // 8 key + KEY_KEY_9 = 0x39, // 9 key + KEY_KEY_A = 0x41, // A key + KEY_KEY_B = 0x42, // B key + KEY_KEY_C = 0x43, // C key + KEY_KEY_D = 0x44, // D key + KEY_KEY_E = 0x45, // E key + KEY_KEY_F = 0x46, // F key + KEY_KEY_G = 0x47, // G key + KEY_KEY_H = 0x48, // H key + KEY_KEY_I = 0x49, // I key + KEY_KEY_J = 0x4A, // J key + KEY_KEY_K = 0x4B, // K key + KEY_KEY_L = 0x4C, // L key + KEY_KEY_M = 0x4D, // M key + KEY_KEY_N = 0x4E, // N key + KEY_KEY_O = 0x4F, // O key + KEY_KEY_P = 0x50, // P key + KEY_KEY_Q = 0x51, // Q key + KEY_KEY_R = 0x52, // R key + KEY_KEY_S = 0x53, // S key + KEY_KEY_T = 0x54, // T key + KEY_KEY_U = 0x55, // U key + KEY_KEY_V = 0x56, // V key + KEY_KEY_W = 0x57, // W key + KEY_KEY_X = 0x58, // X key + KEY_KEY_Y = 0x59, // Y key + KEY_KEY_Z = 0x5A, // Z key + KEY_LWIN = 0x5B, // Left Windows key (Microsoft® Natural® keyboard) + KEY_RWIN = 0x5C, // Right Windows key (Natural keyboard) + KEY_APPS = 0x5D, // Applications key (Natural keyboard) + KEY_SLEEP = 0x5F, // Computer Sleep key + KEY_NUMPAD0 = 0x60, // Numeric keypad 0 key + KEY_NUMPAD1 = 0x61, // Numeric keypad 1 key + KEY_NUMPAD2 = 0x62, // Numeric keypad 2 key + KEY_NUMPAD3 = 0x63, // Numeric keypad 3 key + KEY_NUMPAD4 = 0x64, // Numeric keypad 4 key + KEY_NUMPAD5 = 0x65, // Numeric keypad 5 key + KEY_NUMPAD6 = 0x66, // Numeric keypad 6 key + KEY_NUMPAD7 = 0x67, // Numeric keypad 7 key + KEY_NUMPAD8 = 0x68, // Numeric keypad 8 key + KEY_NUMPAD9 = 0x69, // Numeric keypad 9 key + KEY_MULTIPLY = 0x6A, // Multiply key + KEY_ADD = 0x6B, // Add key + KEY_SEPARATOR = 0x6C, // Separator key + KEY_SUBTRACT = 0x6D, // Subtract key + KEY_DECIMAL = 0x6E, // Decimal key + KEY_DIVIDE = 0x6F, // Divide key + KEY_F1 = 0x70, // F1 key + KEY_F2 = 0x71, // F2 key + KEY_F3 = 0x72, // F3 key + KEY_F4 = 0x73, // F4 key + KEY_F5 = 0x74, // F5 key + KEY_F6 = 0x75, // F6 key + KEY_F7 = 0x76, // F7 key + KEY_F8 = 0x77, // F8 key + KEY_F9 = 0x78, // F9 key + KEY_F10 = 0x79, // F10 key + KEY_F11 = 0x7A, // F11 key + KEY_F12 = 0x7B, // F12 key + KEY_F13 = 0x7C, // F13 key + KEY_F14 = 0x7D, // F14 key + KEY_F15 = 0x7E, // F15 key + KEY_F16 = 0x7F, // F16 key + KEY_F17 = 0x80, // F17 key + KEY_F18 = 0x81, // F18 key + KEY_F19 = 0x82, // F19 key + KEY_F20 = 0x83, // F20 key + KEY_F21 = 0x84, // F21 key + KEY_F22 = 0x85, // F22 key + KEY_F23 = 0x86, // F23 key + KEY_F24 = 0x87, // F24 key + KEY_NUMLOCK = 0x90, // NUM LOCK key + KEY_SCROLL = 0x91, // SCROLL LOCK key + KEY_LSHIFT = 0xA0, // Left SHIFT key + KEY_RSHIFT = 0xA1, // Right SHIFT key + KEY_LCONTROL = 0xA2, // Left CONTROL key + KEY_RCONTROL = 0xA3, // Right CONTROL key + KEY_LMENU = 0xA4, // Left MENU key + KEY_RMENU = 0xA5, // Right MENU key + KEY_OEM_1 = 0xBA, // for US ";:" + KEY_PLUS = 0xBB, // Plus Key "+" + KEY_COMMA = 0xBC, // Comma Key "," + KEY_MINUS = 0xBD, // Minus Key "-" + KEY_PERIOD = 0xBE, // Period Key "." + KEY_OEM_2 = 0xBF, // for US "/?" + KEY_OEM_3 = 0xC0, // for US "`~" + KEY_OEM_4 = 0xDB, // for US "[{" + KEY_OEM_5 = 0xDC, // for US "\|" + KEY_OEM_6 = 0xDD, // for US "]}" + KEY_OEM_7 = 0xDE, // for US "'"" + KEY_OEM_8 = 0xDF, // None + KEY_OEM_AX = 0xE1, // for Japan "AX" + KEY_OEM_102 = 0xE2, // "<>" or "\|" + KEY_ATTN = 0xF6, // Attn key + KEY_CRSEL = 0xF7, // CrSel key + KEY_EXSEL = 0xF8, // ExSel key + KEY_EREOF = 0xF9, // Erase EOF key + KEY_PLAY = 0xFA, // Play key + KEY_ZOOM = 0xFB, // Zoom key + KEY_PA1 = 0xFD, // PA1 key + KEY_OEM_CLEAR = 0xFE, // Clear key + + KEY_KEY_CODES_COUNT = 0xFF // this is not a key, but the amount of keycodes there are. + }; + +} // end namespace irr + +#endif + diff --git a/inc/S3DVertex.h b/inc/S3DVertex.h new file mode 100644 index 0000000..706cf4b --- /dev/null +++ b/inc/S3DVertex.h @@ -0,0 +1,274 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_3D_VERTEX_H_INCLUDED__ +#define __S_3D_VERTEX_H_INCLUDED__ + +#include "vector3d.h" +#include "vector2d.h" +#include "SColor.h" + +namespace irr +{ +namespace video +{ + +//! Enumeration for all vertex types there are. +enum E_VERTEX_TYPE +{ + //! Standard vertex type used by the Irrlicht engine, video::S3DVertex. + EVT_STANDARD = 0, + + //! Vertex with two texture coordinates, video::S3DVertex2TCoords. + /** Usually used for geometry with lightmaps or other special materials. */ + EVT_2TCOORDS, + + //! Vertex with a tangent and binormal vector, video::S3DVertexTangents. + /** Usually used for tangent space normal mapping. */ + EVT_TANGENTS +}; + +//! Array holding the built in vertex type names +const char* const sBuiltInVertexTypeNames[] = +{ + "standard", + "2tcoords", + "tangents", + 0 +}; + +//! standard vertex used by the Irrlicht engine. +struct S3DVertex +{ + //! default constructor + S3DVertex() {} + + //! constructor + S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) + : Pos(x,y,z), Normal(nx,ny,nz), Color(c), TCoords(tu,tv) {} + + //! constructor + S3DVertex(const core::vector3df& pos, const core::vector3df& normal, + SColor color, const core::vector2d& tcoords) + : Pos(pos), Normal(normal), Color(color), TCoords(tcoords) {} + + //! Position + core::vector3df Pos; + + //! Normal vector + core::vector3df Normal; + + //! Color + SColor Color; + + //! Texture coordinates + core::vector2d TCoords; + + bool operator==(const S3DVertex& other) const + { + return ((Pos == other.Pos) && (Normal == other.Normal) && + (Color == other.Color) && (TCoords == other.TCoords)); + } + + bool operator!=(const S3DVertex& other) const + { + return ((Pos != other.Pos) || (Normal != other.Normal) || + (Color != other.Color) || (TCoords != other.TCoords)); + } + + bool operator<(const S3DVertex& other) const + { + return ((Pos < other.Pos) || + ((Pos == other.Pos) && (Normal < other.Normal)) || + ((Pos == other.Pos) && (Normal == other.Normal) && (Color < other.Color)) || + ((Pos == other.Pos) && (Normal == other.Normal) && (Color == other.Color) && (TCoords < other.TCoords))); + } + + E_VERTEX_TYPE getType() const + { + return EVT_STANDARD; + } + + S3DVertex getInterpolated(const S3DVertex& other, f32 d) + { + d = core::clamp(d, 0.0f, 1.0f); + return S3DVertex(Pos.getInterpolated(other.Pos, d), + Normal.getInterpolated(other.Normal, d), + Color.getInterpolated(other.Color, d), + TCoords.getInterpolated(other.TCoords, d)); + } +}; + + +//! Vertex with two texture coordinates. +/** Usually used for geometry with lightmaps +or other special materials. +*/ +struct S3DVertex2TCoords : public S3DVertex +{ + //! default constructor + S3DVertex2TCoords() : S3DVertex() {} + + //! constructor with two different texture coords, but no normal + S3DVertex2TCoords(f32 x, f32 y, f32 z, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2) + : S3DVertex(x,y,z, 0.0f, 0.0f, 0.0f, c, tu,tv), TCoords2(tu2,tv2) {} + + //! constructor with two different texture coords, but no normal + S3DVertex2TCoords(const core::vector3df& pos, SColor color, + const core::vector2d& tcoords, const core::vector2d& tcoords2) + : S3DVertex(pos, core::vector3df(), color, tcoords), TCoords2(tcoords2) {} + + //! constructor with all values + S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, const SColor& color, + const core::vector2d& tcoords, const core::vector2d& tcoords2) + : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords2) {} + + //! constructor with all values + S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2) + : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu2,tv2) {} + + //! constructor with the same texture coords and normal + S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) + : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu,tv) {} + + //! constructor with the same texture coords and normal + S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, + SColor color, const core::vector2d& tcoords) + : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {} + + //! constructor from S3DVertex + S3DVertex2TCoords(S3DVertex& o) : S3DVertex(o) {} + + //! Second set of texture coordinates + core::vector2d TCoords2; + + //! Equality operator + bool operator==(const S3DVertex2TCoords& other) const + { + return ((static_cast(*this)==other) && + (TCoords2 == other.TCoords2)); + } + + //! Inequality operator + bool operator!=(const S3DVertex2TCoords& other) const + { + return ((static_cast(*this)!=other) || + (TCoords2 != other.TCoords2)); + } + + bool operator<(const S3DVertex2TCoords& other) const + { + return ((static_cast(*this) < other) || + ((static_cast(*this) == other) && (TCoords2 < other.TCoords2))); + } + + E_VERTEX_TYPE getType() const + { + return EVT_2TCOORDS; + } + + S3DVertex2TCoords getInterpolated(const S3DVertex2TCoords& other, f32 d) + { + d = core::clamp(d, 0.0f, 1.0f); + return S3DVertex2TCoords(Pos.getInterpolated(other.Pos, d), + Normal.getInterpolated(other.Normal, d), + Color.getInterpolated(other.Color, d), + TCoords.getInterpolated(other.TCoords, d), + TCoords2.getInterpolated(other.TCoords2, d)); + } +}; + + +//! Vertex with a tangent and binormal vector. +/** Usually used for tangent space normal mapping. */ +struct S3DVertexTangents : public S3DVertex +{ + //! default constructor + S3DVertexTangents() : S3DVertex() { } + + //! constructor + S3DVertexTangents(f32 x, f32 y, f32 z, f32 nx=0.0f, f32 ny=0.0f, f32 nz=0.0f, + SColor c = 0xFFFFFFFF, f32 tu=0.0f, f32 tv=0.0f, + f32 tanx=0.0f, f32 tany=0.0f, f32 tanz=0.0f, + f32 bx=0.0f, f32 by=0.0f, f32 bz=0.0f) + : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), Tangent(tanx,tany,tanz), Binormal(bx,by,bz) { } + + //! constructor + S3DVertexTangents(const core::vector3df& pos, SColor c, + const core::vector2df& tcoords) + : S3DVertex(pos, core::vector3df(), c, tcoords) { } + + //! constructor + S3DVertexTangents(const core::vector3df& pos, + const core::vector3df& normal, SColor c, + const core::vector2df& tcoords, + const core::vector3df& tangent=core::vector3df(), + const core::vector3df& binormal=core::vector3df()) + : S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { } + + //! Tangent vector along the x-axis of the texture + core::vector3df Tangent; + + //! Binormal vector (tangent x normal) + core::vector3df Binormal; + + bool operator==(const S3DVertexTangents& other) const + { + return ((static_cast(*this)==other) && + (Tangent == other.Tangent) && + (Binormal == other.Binormal)); + } + + bool operator!=(const S3DVertexTangents& other) const + { + return ((static_cast(*this)!=other) || + (Tangent != other.Tangent) || + (Binormal != other.Binormal)); + } + + bool operator<(const S3DVertexTangents& other) const + { + return ((static_cast(*this) < other) || + ((static_cast(*this) == other) && (Tangent < other.Tangent)) || + ((static_cast(*this) == other) && (Tangent == other.Tangent) && (Binormal < other.Binormal))); + } + + E_VERTEX_TYPE getType() const + { + return EVT_TANGENTS; + } + + S3DVertexTangents getInterpolated(const S3DVertexTangents& other, f32 d) + { + d = core::clamp(d, 0.0f, 1.0f); + return S3DVertexTangents(Pos.getInterpolated(other.Pos, d), + Normal.getInterpolated(other.Normal, d), + Color.getInterpolated(other.Color, d), + TCoords.getInterpolated(other.TCoords, d), + Tangent.getInterpolated(other.Tangent, d), + Binormal.getInterpolated(other.Binormal, d)); + } +}; + + + +inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType) +{ + switch (vertexType) + { + case video::EVT_2TCOORDS: + return sizeof(video::S3DVertex2TCoords); + case video::EVT_TANGENTS: + return sizeof(video::S3DVertexTangents); + default: + return sizeof(video::S3DVertex); + } +} + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/SAnimatedMesh.h b/inc/SAnimatedMesh.h new file mode 100644 index 0000000..f962f30 --- /dev/null +++ b/inc/SAnimatedMesh.h @@ -0,0 +1,189 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_ANIMATED_MESH_H_INCLUDED__ +#define __S_ANIMATED_MESH_H_INCLUDED__ + +#include "IAnimatedMesh.h" +#include "IMesh.h" +#include "aabbox3d.h" +#include "irrArray.h" + +namespace irr +{ +namespace scene +{ + + //! Simple implementation of the IAnimatedMesh interface. + struct SAnimatedMesh : public IAnimatedMesh + { + //! constructor + SAnimatedMesh(scene::IMesh* mesh=0, scene::E_ANIMATED_MESH_TYPE type=scene::EAMT_UNKNOWN) : IAnimatedMesh(), FramesPerSecond(25.f), Type(type) + { + #ifdef _DEBUG + setDebugName("SAnimatedMesh"); + #endif + addMesh(mesh); + recalculateBoundingBox(); + } + + //! destructor + virtual ~SAnimatedMesh() + { + // drop meshes + for (u32 i=0; idrop(); + } + + //! Gets the frame count of the animated mesh. + /** \return Amount of frames. If the amount is 1, it is a static, non animated mesh. */ + virtual u32 getFrameCount() const + { + return Meshes.size(); + } + + //! Gets the default animation speed of the animated mesh. + /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ + virtual f32 getAnimationSpeed() const + { + return FramesPerSecond; + } + + //! Gets the frame count of the animated mesh. + /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. + The actual speed is set in the scene node the mesh is instantiated in.*/ + virtual void setAnimationSpeed(f32 fps) + { + FramesPerSecond=fps; + } + + //! Returns the IMesh interface for a frame. + /** \param frame: Frame number as zero based index. The maximum frame number is + getFrameCount() - 1; + \param detailLevel: Level of detail. 0 is the lowest, + 255 the highest level of detail. Most meshes will ignore the detail level. + \param startFrameLoop: start frame + \param endFrameLoop: end frame + \return The animated mesh based on a detail level. */ + virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1) + { + if (Meshes.empty()) + return 0; + + return Meshes[frame]; + } + + //! adds a Mesh + void addMesh(IMesh* mesh) + { + if (mesh) + { + mesh->grab(); + Meshes.push_back(mesh); + } + } + + //! Returns an axis aligned bounding box of the mesh. + /** \return A bounding box of this mesh is returned. */ + virtual const core::aabbox3d& getBoundingBox() const + { + return Box; + } + + //! set user axis aligned bounding box + virtual void setBoundingBox(const core::aabbox3df& box) + { + Box = box; + } + + //! Recalculates the bounding box. + void recalculateBoundingBox() + { + Box.reset(0,0,0); + + if (Meshes.empty()) + return; + + Box = Meshes[0]->getBoundingBox(); + + for (u32 i=1; igetBoundingBox()); + } + + //! Returns the type of the animated mesh. + virtual E_ANIMATED_MESH_TYPE getMeshType() const + { + return Type; + } + + //! returns amount of mesh buffers. + virtual u32 getMeshBufferCount() const + { + if (Meshes.empty()) + return 0; + + return Meshes[0]->getMeshBufferCount(); + } + + //! returns pointer to a mesh buffer + virtual IMeshBuffer* getMeshBuffer(u32 nr) const + { + if (Meshes.empty()) + return 0; + + return Meshes[0]->getMeshBuffer(nr); + } + + //! Returns pointer to a mesh buffer which fits a material + /** \param material: material to search for + \return Returns the pointer to the mesh buffer or + NULL if there is no such mesh buffer. */ + virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const + { + if (Meshes.empty()) + return 0; + + return Meshes[0]->getMeshBuffer(material); + } + + //! Set a material flag for all meshbuffers of this mesh. + virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) + { + for (u32 i=0; isetMaterialFlag(flag, newvalue); + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) + { + for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); + } + + //! flags the meshbuffer as changed, reloads hardware buffers + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) + { + for (u32 i=0; isetDirty(buffer); + } + + //! All meshes defining the animated mesh + core::array Meshes; + + //! The bounding box of this mesh + core::aabbox3d Box; + + //! Default animation speed of this mesh. + f32 FramesPerSecond; + + //! The type of the mesh. + E_ANIMATED_MESH_TYPE Type; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SColor.h b/inc/SColor.h new file mode 100644 index 0000000..f57b4a9 --- /dev/null +++ b/inc/SColor.h @@ -0,0 +1,697 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __COLOR_H_INCLUDED__ +#define __COLOR_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrMath.h" + +namespace irr +{ +namespace video +{ + //! An enum for the color format of textures used by the Irrlicht Engine. + /** A color format specifies how color information is stored. */ + enum ECOLOR_FORMAT + { + //! 16 bit color format used by the software driver. + /** It is thus preferred by all other irrlicht engine video drivers. + There are 5 bits for every color component, and a single bit is left + for alpha information. */ + ECF_A1R5G5B5 = 0, + + //! Standard 16 bit color format. + ECF_R5G6B5, + + //! 24 bit color, no alpha channel, but 8 bit for red, green and blue. + ECF_R8G8B8, + + //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha. + ECF_A8R8G8B8, + + /** Floating Point formats. The following formats may only be used for render target textures. */ + + //! 16 bit floating point format using 16 bits for the red channel. + ECF_R16F, + + //! 32 bit floating point format using 16 bits for the red channel and 16 bits for the green channel. + ECF_G16R16F, + + //! 64 bit floating point format 16 bits are used for the red, green, blue and alpha channels. + ECF_A16B16G16R16F, + + //! 32 bit floating point format using 32 bits for the red channel. + ECF_R32F, + + //! 64 bit floating point format using 32 bits for the red channel and 32 bits for the green channel. + ECF_G32R32F, + + //! 128 bit floating point format. 32 bits are used for the red, green, blue and alpha channels. + ECF_A32B32G32R32F, + + //! Unknown color format: + ECF_UNKNOWN + }; + + + //! Creates a 16 bit A1R5G5B5 color + inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF) + { + return (u16)((a & 0x80) << 8 | + (r & 0xF8) << 7 | + (g & 0xF8) << 2 | + (b & 0xF8) >> 3); + } + + + //! Creates a 16 bit A1R5G5B5 color + inline u16 RGB16(u32 r, u32 g, u32 b) + { + return RGBA16(r,g,b); + } + + + //! Creates a 16bit A1R5G5B5 color, based on 16bit input values + inline u16 RGB16from16(u16 r, u16 g, u16 b) + { + return (0x8000 | + (r & 0x1F) << 10 | + (g & 0x1F) << 5 | + (b & 0x1F)); + } + + + //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color + inline u16 X8R8G8B8toA1R5G5B5(u32 color) + { + return (u16)(0x8000 | + ( color & 0x00F80000) >> 9 | + ( color & 0x0000F800) >> 6 | + ( color & 0x000000F8) >> 3); + } + + + //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color + inline u16 A8R8G8B8toA1R5G5B5(u32 color) + { + return (u16)(( color & 0x80000000) >> 16| + ( color & 0x00F80000) >> 9 | + ( color & 0x0000F800) >> 6 | + ( color & 0x000000F8) >> 3); + } + + + //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color + inline u16 A8R8G8B8toR5G6B5(u32 color) + { + return (u16)(( color & 0x00F80000) >> 8 | + ( color & 0x0000FC00) >> 5 | + ( color & 0x000000F8) >> 3); + } + + + //! Convert A8R8G8B8 Color from A1R5G5B5 color + /** build a nicer 32bit Color by extending dest lower bits with source high bits. */ + inline u32 A1R5G5B5toA8R8G8B8(u16 color) + { + return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) | + (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) | + (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) | + (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2) + ); + } + + + //! Returns A8R8G8B8 Color from R5G6B5 color + inline u32 R5G6B5toA8R8G8B8(u16 color) + { + return 0xFF000000 | + ((color & 0xF800) << 8)| + ((color & 0x07E0) << 5)| + ((color & 0x001F) << 3); + } + + + //! Returns A1R5G5B5 Color from R5G6B5 color + inline u16 R5G6B5toA1R5G5B5(u16 color) + { + return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F)); + } + + + //! Returns R5G6B5 Color from A1R5G5B5 color + inline u16 A1R5G5B5toR5G6B5(u16 color) + { + return (((color & 0x7FE0) << 1) | (color & 0x1F)); + } + + + + //! Returns the alpha component from A1R5G5B5 color + /** In Irrlicht, alpha refers to opacity. + \return The alpha value of the color. 0 is transparent, 1 is opaque. */ + inline u32 getAlpha(u16 color) + { + return ((color >> 15)&0x1); + } + + + //! Returns the red component from A1R5G5B5 color. + /** Shift left by 3 to get 8 bit value. */ + inline u32 getRed(u16 color) + { + return ((color >> 10)&0x1F); + } + + + //! Returns the green component from A1R5G5B5 color + /** Shift left by 3 to get 8 bit value. */ + inline u32 getGreen(u16 color) + { + return ((color >> 5)&0x1F); + } + + + //! Returns the blue component from A1R5G5B5 color + /** Shift left by 3 to get 8 bit value. */ + inline u32 getBlue(u16 color) + { + return (color & 0x1F); + } + + + //! Returns the average from a 16 bit A1R5G5B5 color + inline s32 getAverage(s16 color) + { + return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3; + } + + + //! Class representing a 32 bit ARGB color. + /** The color values for alpha, red, green, and blue are + stored in a single u32. So all four values may be between 0 and 255. + Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid). + This class is used by most parts of the Irrlicht Engine + to specify a color. Another way is using the class SColorf, which + stores the color values in 4 floats. + This class must consist of only one u32 and must not use virtual functions. + */ + class SColor + { + public: + + //! Constructor of the Color. Does nothing. + /** The color value is not initialized to save time. */ + SColor() {} + + //! Constructs the color from 4 values representing the alpha, red, green and blue component. + /** Must be values between 0 and 255. */ + SColor (u32 a, u32 r, u32 g, u32 b) + : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {} + + //! Constructs the color from a 32 bit value. Could be another color. + SColor(u32 clr) + : color(clr) {} + + //! Returns the alpha component of the color. + /** The alpha component defines how opaque a color is. + \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ + u32 getAlpha() const { return color>>24; } + + //! Returns the red component of the color. + /** \return Value between 0 and 255, specifying how red the color is. + 0 means no red, 255 means full red. */ + u32 getRed() const { return (color>>16) & 0xff; } + + //! Returns the green component of the color. + /** \return Value between 0 and 255, specifying how green the color is. + 0 means no green, 255 means full green. */ + u32 getGreen() const { return (color>>8) & 0xff; } + + //! Returns the blue component of the color. + /** \return Value between 0 and 255, specifying how blue the color is. + 0 means no blue, 255 means full blue. */ + u32 getBlue() const { return color & 0xff; } + + //! Get lightness of the color in the range [0,255] + f32 getLightness() const + { + return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue())); + } + + //! Get luminance of the color in the range [0,255]. + f32 getLuminance() const + { + return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue(); + } + + //! Get average intensity of the color in the range [0,255]. + u32 getAverage() const + { + return ( getRed() + getGreen() + getBlue() ) / 3; + } + + //! Sets the alpha component of the Color. + /** The alpha component defines how transparent a color should be. + \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ + void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); } + + //! Sets the red component of the Color. + /** \param r: Has to be a value between 0 and 255. + 0 means no red, 255 means full red. */ + void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); } + + //! Sets the green component of the Color. + /** \param g: Has to be a value between 0 and 255. + 0 means no green, 255 means full green. */ + void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); } + + //! Sets the blue component of the Color. + /** \param b: Has to be a value between 0 and 255. + 0 means no blue, 255 means full blue. */ + void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); } + + //! Calculates a 16 bit A1R5G5B5 value of this color. + /** \return 16 bit A1R5G5B5 value of this color. */ + u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); } + + //! Converts color to OpenGL color format + /** From ARGB to RGBA in 4 byte components for endian aware + passing to OpenGL + \param dest: address where the 4x8 bit OpenGL color is stored. */ + void toOpenGLColor(u8* dest) const + { + *dest = (u8)getRed(); + *++dest = (u8)getGreen(); + *++dest = (u8)getBlue(); + *++dest = (u8)getAlpha(); + } + + //! Sets all four components of the color at once. + /** Constructs the color from 4 values representing the alpha, + red, green and blue components of the color. Must be values + between 0 and 255. + \param a: Alpha component of the color. The alpha component + defines how transparent a color should be. Has to be a value + between 0 and 255. 255 means not transparent (opaque), 0 means + fully transparent. + \param r: Sets the red component of the Color. Has to be a + value between 0 and 255. 0 means no red, 255 means full red. + \param g: Sets the green component of the Color. Has to be a + value between 0 and 255. 0 means no green, 255 means full + green. + \param b: Sets the blue component of the Color. Has to be a + value between 0 and 255. 0 means no blue, 255 means full blue. */ + void set(u32 a, u32 r, u32 g, u32 b) + { + color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); + } + void set(u32 col) { color = col; } + + //! Compares the color to another color. + /** \return True if the colors are the same, and false if not. */ + bool operator==(const SColor& other) const { return other.color == color; } + + //! Compares the color to another color. + /** \return True if the colors are different, and false if they are the same. */ + bool operator!=(const SColor& other) const { return other.color != color; } + + //! comparison operator + /** \return True if this color is smaller than the other one */ + bool operator<(const SColor& other) const { return (color < other.color); } + + //! Adds two colors, result is clamped to 0..255 values + /** \param other Color to add to this color + \return Addition of the two colors, clamped to 0..255 values */ + SColor operator+(const SColor& other) const + { + return SColor(core::min_(getAlpha() + other.getAlpha(), 255u), + core::min_(getRed() + other.getRed(), 255u), + core::min_(getGreen() + other.getGreen(), 255u), + core::min_(getBlue() + other.getBlue(), 255u)); + } + + //! Interpolates the color with a f32 value to another color + /** \param other: Other color + \param d: value between 0.0f and 1.0f + \return Interpolated color. */ + SColor getInterpolated(const SColor &other, f32 d) const + { + d = core::clamp(d, 0.f, 1.f); + const f32 inv = 1.0f - d; + return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d), + (u32)core::round32(other.getRed()*inv + getRed()*d), + (u32)core::round32(other.getGreen()*inv + getGreen()*d), + (u32)core::round32(other.getBlue()*inv + getBlue()*d)); + } + + //! Returns interpolated color. ( quadratic ) + /** \param c1: first color to interpolate with + \param c2: second color to interpolate with + \param d: value between 0.0f and 1.0f. */ + SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const + { + // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; + d = core::clamp(d, 0.f, 1.f); + const f32 inv = 1.f - d; + const f32 mul0 = inv * inv; + const f32 mul1 = 2.f * d * inv; + const f32 mul2 = d * d; + + return SColor( + core::clamp( core::floor32( + getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ), + core::clamp( core::floor32( + getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ), + core::clamp ( core::floor32( + getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ), + core::clamp ( core::floor32( + getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 )); + } + + //! set the color by expecting data in the given format + /** \param data: must point to valid memory containing color information in the given format + \param format: tells the format in which data is available + */ + void setData(const void *data, ECOLOR_FORMAT format) + { + switch (format) + { + case ECF_A1R5G5B5: + color = A1R5G5B5toA8R8G8B8(*(u16*)data); + break; + case ECF_R5G6B5: + color = R5G6B5toA8R8G8B8(*(u16*)data); + break; + case ECF_A8R8G8B8: + color = *(u32*)data; + break; + case ECF_R8G8B8: + { + u8* p = (u8*)data; + set(255, p[0],p[1],p[2]); + } + break; + default: + color = 0xffffffff; + break; + } + } + + //! Write the color to data in the defined format + /** \param data: target to write the color. Must contain sufficiently large memory to receive the number of bytes neede for format + \param format: tells the format used to write the color into data + */ + void getData(void *data, ECOLOR_FORMAT format) + { + switch(format) + { + case ECF_A1R5G5B5: + { + u16 * dest = (u16*)data; + *dest = video::A8R8G8B8toA1R5G5B5( color ); + } + break; + + case ECF_R5G6B5: + { + u16 * dest = (u16*)data; + *dest = video::A8R8G8B8toR5G6B5( color ); + } + break; + + case ECF_R8G8B8: + { + u8* dest = (u8*)data; + dest[0] = (u8)getRed(); + dest[1] = (u8)getGreen(); + dest[2] = (u8)getBlue(); + } + break; + + case ECF_A8R8G8B8: + { + u32 * dest = (u32*)data; + *dest = color; + } + break; + + default: + break; + } + } + + //! color in A8R8G8B8 Format + u32 color; + }; + + + //! Class representing a color with four floats. + /** The color values for red, green, blue + and alpha are each stored in a 32 bit floating point variable. + So all four values may be between 0.0f and 1.0f. + Another, faster way to define colors is using the class SColor, which + stores the color values in a single 32 bit integer. + */ + class SColorf + { + public: + //! Default constructor for SColorf. + /** Sets red, green and blue to 0.0f and alpha to 1.0f. */ + SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} + + //! Constructs a color from up to four color values: red, green, blue, and alpha. + /** \param r: Red color component. Should be a value between + 0.0f meaning no red and 1.0f, meaning full red. + \param g: Green color component. Should be a value between 0.0f + meaning no green and 1.0f, meaning full green. + \param b: Blue color component. Should be a value between 0.0f + meaning no blue and 1.0f, meaning full blue. + \param a: Alpha color component of the color. The alpha + component defines how transparent a color should be. Has to be + a value between 0.0f and 1.0f, 1.0f means not transparent + (opaque), 0.0f means fully transparent. */ + SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {} + + //! Constructs a color from 32 bit Color. + /** \param c: 32 bit color from which this SColorf class is + constructed from. */ + SColorf(SColor c) + { + const f32 inv = 1.0f / 255.0f; + r = c.getRed() * inv; + g = c.getGreen() * inv; + b = c.getBlue() * inv; + a = c.getAlpha() * inv; + } + + //! Converts this color to a SColor without floats. + SColor toSColor() const + { + return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f)); + } + + //! Sets three color components to new values at once. + /** \param rr: Red color component. Should be a value between 0.0f meaning + no red (=black) and 1.0f, meaning full red. + \param gg: Green color component. Should be a value between 0.0f meaning + no green (=black) and 1.0f, meaning full green. + \param bb: Blue color component. Should be a value between 0.0f meaning + no blue (=black) and 1.0f, meaning full blue. */ + void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; } + + //! Sets all four color components to new values at once. + /** \param aa: Alpha component. Should be a value between 0.0f meaning + fully transparent and 1.0f, meaning opaque. + \param rr: Red color component. Should be a value between 0.0f meaning + no red and 1.0f, meaning full red. + \param gg: Green color component. Should be a value between 0.0f meaning + no green and 1.0f, meaning full green. + \param bb: Blue color component. Should be a value between 0.0f meaning + no blue and 1.0f, meaning full blue. */ + void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; } + + //! Interpolates the color with a f32 value to another color + /** \param other: Other color + \param d: value between 0.0f and 1.0f + \return Interpolated color. */ + SColorf getInterpolated(const SColorf &other, f32 d) const + { + d = core::clamp(d, 0.f, 1.f); + const f32 inv = 1.0f - d; + return SColorf(other.r*inv + r*d, + other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d); + } + + //! Returns interpolated color. ( quadratic ) + /** \param c1: first color to interpolate with + \param c2: second color to interpolate with + \param d: value between 0.0f and 1.0f. */ + inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2, + f32 d) const + { + d = core::clamp(d, 0.f, 1.f); + // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; + const f32 inv = 1.f - d; + const f32 mul0 = inv * inv; + const f32 mul1 = 2.f * d * inv; + const f32 mul2 = d * d; + + return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2, + g * mul0 + c1.g * mul1 + c2.g * mul2, + b * mul0 + c1.b * mul1 + c2.b * mul2, + a * mul0 + c1.a * mul1 + c2.a * mul2); + } + + + //! Sets a color component by index. R=0, G=1, B=2, A=3 + void setColorComponentValue(s32 index, f32 value) + { + switch(index) + { + case 0: r = value; break; + case 1: g = value; break; + case 2: b = value; break; + case 3: a = value; break; + } + } + + //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque) + f32 getAlpha() const { return a; } + + //! Returns the red component of the color in the range 0.0 to 1.0 + f32 getRed() const { return r; } + + //! Returns the green component of the color in the range 0.0 to 1.0 + f32 getGreen() const { return g; } + + //! Returns the blue component of the color in the range 0.0 to 1.0 + f32 getBlue() const { return b; } + + //! red color component + f32 r; + + //! green color component + f32 g; + + //! blue component + f32 b; + + //! alpha color component + f32 a; + }; + + + //! Class representing a color in HSL format + /** The color values for hue, saturation, luminance + are stored in 32bit floating point variables. Hue is in range [0,360], + Luminance and Saturation are in percent [0,100] + */ + class SColorHSL + { + public: + SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f ) + : Hue ( h ), Saturation ( s ), Luminance ( l ) {} + + void fromRGB(const SColorf &color); + void toRGB(SColorf &color) const; + + f32 Hue; + f32 Saturation; + f32 Luminance; + + private: + inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const; + + }; + + inline void SColorHSL::fromRGB(const SColorf &color) + { + const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue()); + const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue()); + Luminance = (maxVal+minVal)*50; + if (core::equals(maxVal, minVal)) + { + Hue=0.f; + Saturation=0.f; + return; + } + + const f32 delta = maxVal-minVal; + if ( Luminance <= 50 ) + { + Saturation = (delta)/(maxVal+minVal); + } + else + { + Saturation = (delta)/(2-maxVal-minVal); + } + Saturation *= 100; + + if (core::equals(maxVal, color.getRed())) + Hue = (color.getGreen()-color.getBlue())/delta; + else if (core::equals(maxVal, color.getGreen())) + Hue = 2+((color.getBlue()-color.getRed())/delta); + else // blue is max + Hue = 4+((color.getRed()-color.getGreen())/delta); + + Hue *= 60.0f; + while ( Hue < 0.f ) + Hue += 360; + } + + + inline void SColorHSL::toRGB(SColorf &color) const + { + const f32 l = Luminance/100; + if (core::iszero(Saturation)) // grey + { + color.set(l, l, l); + return; + } + + f32 rm2; + + if ( Luminance <= 50 ) + { + rm2 = l + l * (Saturation/100); + } + else + { + rm2 = l + (1 - l) * (Saturation/100); + } + + const f32 rm1 = 2.0f * l - rm2; + + const f32 h = Hue / 360.0f; + color.set( toRGB1(rm1, rm2, h + 1.f/3.f), + toRGB1(rm1, rm2, h), + toRGB1(rm1, rm2, h - 1.f/3.f) + ); + } + + + // algorithm from Foley/Van-Dam + inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const + { + if (rh<0) + rh += 1; + if (rh>1) + rh -= 1; + + if (rh < 1.f/6.f) + rm1 = rm1 + (rm2 - rm1) * rh*6.f; + else if (rh < 0.5f) + rm1 = rm2; + else if (rh < 2.f/3.f) + rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f; + + return rm1; + } + +} // end namespace video +} // end namespace irr + +#endif diff --git a/inc/SExposedVideoData.h b/inc/SExposedVideoData.h new file mode 100644 index 0000000..2415d55 --- /dev/null +++ b/inc/SExposedVideoData.h @@ -0,0 +1,90 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_EXPOSED_VIDEO_DATA_H_INCLUDED__ +#define __S_EXPOSED_VIDEO_DATA_H_INCLUDED__ + +// forward declarations for internal pointers +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3D8; +struct IDirect3DDevice8; + +namespace irr +{ +namespace video +{ + +//! structure for holding data describing a driver and operating system specific data. +/** This data can be retrived by IVideoDriver::getExposedVideoData(). Use this with caution. +This only should be used to make it possible to extend the engine easily without +modification of its source. Note that this structure does not contain any valid data, if +you are using the software or the null device. +*/ +struct SExposedVideoData +{ + SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;} + explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;} + + union + { + struct + { + //! Pointer to the IDirect3D9 interface + IDirect3D9* D3D9; + + //! Pointer to the IDirect3DDevice9 interface + IDirect3DDevice9* D3DDev9; + + //! Window handle. + /** Get with for example HWND h = reinterpret_cast(exposedData.D3D9.HWnd) */ + void* HWnd; + + } D3D9; + + struct + { + //! Pointer to the IDirect3D8 interface + IDirect3D8* D3D8; + + //! Pointer to the IDirect3DDevice8 interface + IDirect3DDevice8* D3DDev8; + + //! Window handle. + /** Get with for example with: HWND h = reinterpret_cast(exposedData.D3D8.HWnd) */ + void* HWnd; + + } D3D8; + + struct + { + //! Private GDI Device Context. + /** Get if for example with: HDC h = reinterpret_cast(exposedData.OpenGLWin32.HDc) */ + void* HDc; + + //! Permanent Rendering Context. + /** Get if for example with: HGLRC h = reinterpret_cast(exposedData.OpenGLWin32.HRc) */ + void* HRc; + + //! Window handle. + /** Get with for example with: HWND h = reinterpret_cast(exposedData.OpenGLWin32.HWnd) */ + void* HWnd; + } OpenGLWin32; + + struct + { + // XWindow handles + void* X11Display; + void* X11Context; + unsigned long X11Window; + } OpenGLLinux; + }; +}; + +} // end namespace video +} // end namespace irr + + +#endif + diff --git a/inc/SIrrCreationParameters.h b/inc/SIrrCreationParameters.h new file mode 100644 index 0000000..0c30b74 --- /dev/null +++ b/inc/SIrrCreationParameters.h @@ -0,0 +1,296 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_IRRLICHT_CREATION_PARAMETERS_H_INCLUDED__ +#define __I_IRRLICHT_CREATION_PARAMETERS_H_INCLUDED__ + +#include "EDriverTypes.h" +#include "EDeviceTypes.h" +#include "dimension2d.h" +#include "ILogger.h" + +namespace irr +{ + class IEventReceiver; + + //! Structure for holding Irrlicht Device creation parameters. + /** This structure is used in the createDeviceEx() function. */ + struct SIrrlichtCreationParameters + { + //! Constructs a SIrrlichtCreationParameters structure with default values. + SIrrlichtCreationParameters() : + DeviceType(EIDT_BEST), + DriverType(video::EDT_BURNINGSVIDEO), + WindowSize(core::dimension2d(800, 600)), + Bits(16), + ZBufferBits(16), + Fullscreen(false), + Stencilbuffer(false), + Vsync(false), + AntiAlias(0), + HandleSRGB(false), + WithAlphaChannel(false), + Doublebuffer(true), + IgnoreInput(false), + Stereobuffer(false), + HighPrecisionFPU(false), + EventReceiver(0), + WindowId(0), +#ifdef _DEBUG + LoggingLevel(ELL_DEBUG), +#else + LoggingLevel(ELL_INFORMATION), +#endif + DisplayAdapter(0), + DriverMultithreaded(false), + UsePerformanceTimer(true), + SDK_version_do_not_use(IRRLICHT_SDK_VERSION) + { + } + + SIrrlichtCreationParameters(const SIrrlichtCreationParameters& other) : + SDK_version_do_not_use(IRRLICHT_SDK_VERSION) + {*this = other;} + + SIrrlichtCreationParameters& operator=(const SIrrlichtCreationParameters& other) + { + DeviceType = other.DeviceType; + DriverType = other.DriverType; + WindowSize = other.WindowSize; + Bits = other.Bits; + ZBufferBits = other.ZBufferBits; + Fullscreen = other.Fullscreen; + Stencilbuffer = other.Stencilbuffer; + Vsync = other.Vsync; + AntiAlias = other.AntiAlias; + HandleSRGB = other.HandleSRGB; + WithAlphaChannel = other.WithAlphaChannel; + Doublebuffer = other.Doublebuffer; + IgnoreInput = other.IgnoreInput; + Stereobuffer = other.Stereobuffer; + HighPrecisionFPU = other.HighPrecisionFPU; + EventReceiver = other.EventReceiver; + WindowId = other.WindowId; + LoggingLevel = other.LoggingLevel; + DriverMultithreaded = other.DriverMultithreaded; + DisplayAdapter = other.DisplayAdapter; + UsePerformanceTimer = other.UsePerformanceTimer; + return *this; + } + + //! Type of the device. + /** This setting decides the windowing system used by the device, most device types are native + to a specific operating system and so may not be available. + EIDT_WIN32 is only available on Windows desktops, + EIDT_WINCE is only available on Windows mobile devices, + EIDT_COCOA is only available on Mac OSX, + EIDT_X11 is available on Linux, Solaris, BSD and other operating systems which use X11, + EIDT_SDL is available on most systems if compiled in, + EIDT_CONSOLE is usually available but can only render to text, + EIDT_BEST will select the best available device for your operating system. + Default: EIDT_BEST. */ + E_DEVICE_TYPE DeviceType; + + //! Type of video driver used to render graphics. + /** This can currently be video::EDT_NULL, video::EDT_SOFTWARE, + video::EDT_BURNINGSVIDEO, video::EDT_DIRECT3D8, + video::EDT_DIRECT3D9, and video::EDT_OPENGL. + Default: Software. */ + video::E_DRIVER_TYPE DriverType; + + //! Size of the window or the video mode in fullscreen mode. Default: 800x600 + core::dimension2d WindowSize; + + //! Minimum Bits per pixel of the color buffer in fullscreen mode. Ignored if windowed mode. Default: 16. + u8 Bits; + + //! Minimum Bits per pixel of the depth buffer. Default: 16. + u8 ZBufferBits; + + //! Should be set to true if the device should run in fullscreen. + /** Otherwise the device runs in windowed mode. Default: false. */ + bool Fullscreen; + + //! Specifies if the stencil buffer should be enabled. + /** Set this to true, if you want the engine be able to draw + stencil buffer shadows. Note that not all drivers are able to + use the stencil buffer, hence it can be ignored during device + creation. Without the stencil buffer no shadows will be drawn. + Default: false. */ + bool Stencilbuffer; + + //! Specifies vertical syncronisation. + /** If set to true, the driver will wait for the vertical + retrace period, otherwise not. May be silently ignored. + Default: false */ + bool Vsync; + + //! Specifies if the device should use fullscreen anti aliasing + /** Makes sharp/pixelated edges softer, but requires more + performance. Also, 2D elements might look blurred with this + switched on. The resulting rendering quality also depends on + the hardware and driver you are using, your program might look + different on different hardware with this. So if you are + writing a game/application with AntiAlias switched on, it would + be a good idea to make it possible to switch this option off + again by the user. + The value is the maximal antialiasing factor requested for + the device. The cretion method will automatically try smaller + values if no window can be created with the given value. + Value one is usually the same as 0 (disabled), but might be a + special value on some platforms. On D3D devices it maps to + NONMASKABLE. + Default value: 0 - disabled */ + u8 AntiAlias; + + //! Flag to enable proper sRGB and linear color handling + /** In most situations, it is desireable to have the color handling in + non-linear sRGB color space, and only do the intermediate color + calculations in linear RGB space. If this flag is enabled, the device and + driver try to assure that all color input and output are color corrected + and only the internal color representation is linear. This means, that + the color output is properly gamma-adjusted to provide the brighter + colors for monitor display. And that blending and lighting give a more + natural look, due to proper conversion from non-linear colors into linear + color space for blend operations. If this flag is enabled, all texture colors + (which are usually in sRGB space) are correctly displayed. However vertex colors + and other explicitly set values have to be manually encoded in linear color space. + Default value: false. */ + bool HandleSRGB; + + //! Whether the main framebuffer uses an alpha channel. + /** In some situations it might be desireable to get a color + buffer with an alpha channel, e.g. when rendering into a + transparent window or overlay. If this flag is set the device + tries to create a framebuffer with alpha channel. + If this flag is set, only color buffers with alpha channel + are considered. Otherwise, it depends on the actual hardware + if the colorbuffer has an alpha channel or not. + Default value: false */ + bool WithAlphaChannel; + + //! Whether the main framebuffer uses doublebuffering. + /** This should be usually enabled, in order to avoid render + artifacts on the visible framebuffer. However, it might be + useful to use only one buffer on very small devices. If no + doublebuffering is available, the drivers will fall back to + single buffers. Default value: true */ + bool Doublebuffer; + + //! Specifies if the device should ignore input events + /** This is only relevant when using external I/O handlers. + External windows need to take care of this themselves. + Currently only supported by X11. + Default value: false */ + bool IgnoreInput; + + //! Specifies if the device should use stereo buffers + /** Some high-end gfx cards support two framebuffers for direct + support of stereoscopic output devices. If this flag is set the + device tries to create a stereo context. + Currently only supported by OpenGL. + Default value: false */ + bool Stereobuffer; + + //! Specifies if the device should use high precision FPU setting + /** This is only relevant for DirectX Devices, which switch to + low FPU precision by default for performance reasons. However, + this may lead to problems with the other computations of the + application. In this case setting this flag to true should help + - on the expense of performance loss, though. + Default value: false */ + bool HighPrecisionFPU; + + //! A user created event receiver. + IEventReceiver* EventReceiver; + + //! Window Id. + /** If this is set to a value other than 0, the Irrlicht Engine + will be created in an already existing window. For windows, set + this to the HWND of the window you want. The windowSize and + FullScreen options will be ignored when using the WindowId + parameter. Default this is set to 0. + To make Irrlicht run inside the custom window, you still will + have to draw Irrlicht on your own. You can use this loop, as + usual: + \code + while (device->run()) + { + driver->beginScene(true, true, 0); + smgr->drawAll(); + driver->endScene(); + } + \endcode + Instead of this, you can also simply use your own message loop + using GetMessage, DispatchMessage and whatever. Calling + IrrlichtDevice::run() will cause Irrlicht to dispatch messages + internally too. You need not call Device->run() if you want to + do your own message dispatching loop, but Irrlicht will not be + able to fetch user input then and you have to do it on your own + using the window messages, DirectInput, or whatever. Also, + you'll have to increment the Irrlicht timer. + An alternative, own message dispatching loop without + device->run() would look like this: + \code + MSG msg; + while (true) + { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + break; + } + + // increase virtual timer time + device->getTimer()->tick(); + + // draw engine picture + driver->beginScene(true, true, 0); + smgr->drawAll(); + driver->endScene(); + } + \endcode + However, there is no need to draw the picture this often. Just + do it how you like. */ + void* WindowId; + + //! Specifies the logging level used in the logging interface. + /** The default value is ELL_INFORMATION. You can access the ILogger interface + later on from the IrrlichtDevice with getLogger() and set another level. + But if you need more or less logging information already from device creation, + then you have to change it here. + */ + ELOG_LEVEL LoggingLevel; + + //! Allows to select which graphic card is used for rendering when more than one card is in the system. + /** So far only supported on D3D */ + u32 DisplayAdapter; + + //! Create the driver multithreaded. + /** Default is false. Enabling this can slow down your application. + Note that this does _not_ make Irrlicht threadsafe, but only the underlying driver-API for the graphiccard. + So far only supported on D3D. */ + bool DriverMultithreaded; + + //! Enables use of high performance timers on Windows platform. + /** When performance timers are not used, standard GetTickCount() + is used instead which usually has worse resolution, but also less + problems with speed stepping and other techniques. + */ + bool UsePerformanceTimer; + + //! Don't use or change this parameter. + /** Always set it to IRRLICHT_SDK_VERSION, which is done by default. + This is needed for sdk version checks. */ + const c8* const SDK_version_do_not_use; + }; + + +} // end namespace irr + +#endif + diff --git a/inc/SKeyMap.h b/inc/SKeyMap.h new file mode 100644 index 0000000..55aa5f9 --- /dev/null +++ b/inc/SKeyMap.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_KEY_MAP_H_INCLUDED__ +#define __S_KEY_MAP_H_INCLUDED__ + +#include "Keycodes.h" + +namespace irr +{ + + //! enumeration for key actions. Used for example in the FPS Camera. + enum EKEY_ACTION + { + EKA_MOVE_FORWARD = 0, + EKA_MOVE_BACKWARD, + EKA_STRAFE_LEFT, + EKA_STRAFE_RIGHT, + EKA_JUMP_UP, + EKA_CROUCH, + EKA_COUNT, + + //! This value is not used. It only forces this enumeration to compile in 32 bit. + EKA_FORCE_32BIT = 0x7fffffff + }; + + //! Struct storing which key belongs to which action. + struct SKeyMap + { + SKeyMap() {} + SKeyMap(EKEY_ACTION action, EKEY_CODE keyCode) : Action(action), KeyCode(keyCode) {} + + EKEY_ACTION Action; + EKEY_CODE KeyCode; + }; + +} // end namespace irr + +#endif + diff --git a/inc/SLight.h b/inc/SLight.h new file mode 100644 index 0000000..022c40a --- /dev/null +++ b/inc/SLight.h @@ -0,0 +1,98 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_LIGHT_H_INCLUDED__ +#define __S_LIGHT_H_INCLUDED__ + +#include "SColor.h" + +namespace irr +{ +namespace video +{ + +//! Enumeration for different types of lights +enum E_LIGHT_TYPE +{ + //! point light, it has a position in space and radiates light in all directions + ELT_POINT, + //! spot light, it has a position in space, a direction, and a limited cone of influence + ELT_SPOT, + //! directional light, coming from a direction from an infinite distance + ELT_DIRECTIONAL, + + //! Only used for counting the elements of this enum + ELT_COUNT +}; + +//! Names for light types +const c8* const LightTypeNames[] = +{ + "Point", + "Spot", + "Directional", + 0 +}; + +//! structure for holding data describing a dynamic point light. +/** Irrlicht supports point lights, spot lights, and directional lights. +*/ +struct SLight +{ + SLight() : AmbientColor(0.f,0.f,0.f), DiffuseColor(1.f,1.f,1.f), + SpecularColor(1.f,1.f,1.f), Attenuation(1.f,0.f,0.f), + OuterCone(45.f), InnerCone(0.f), Falloff(2.f), + Position(0.f,0.f,0.f), Direction(0.f,0.f,1.f), + Radius(100.f), Type(ELT_POINT), CastShadows(true) + {} + + //! Ambient color emitted by the light + SColorf AmbientColor; + + //! Diffuse color emitted by the light. + /** This is the primary color you want to set. */ + SColorf DiffuseColor; + + //! Specular color emitted by the light. + /** For details how to use specular highlights, see SMaterial::Shininess */ + SColorf SpecularColor; + + //! Attenuation factors (constant, linear, quadratic) + /** Changes the light strength fading over distance. + Can also be altered by setting the radius, Attenuation will change to + (0,1.f/radius,0). Can be overridden after radius was set. */ + core::vector3df Attenuation; + + //! The angle of the spot's outer cone. Ignored for other lights. + f32 OuterCone; + + //! The angle of the spot's inner cone. Ignored for other lights. + f32 InnerCone; + + //! The light strength's decrease between Outer and Inner cone. + f32 Falloff; + + //! Read-ONLY! Position of the light. + /** If Type is ELT_DIRECTIONAL, it is ignored. Changed via light scene node's position. */ + core::vector3df Position; + + //! Read-ONLY! Direction of the light. + /** If Type is ELT_POINT, it is ignored. Changed via light scene node's rotation. */ + core::vector3df Direction; + + //! Read-ONLY! Radius of light. Everything within this radius will be lighted. + f32 Radius; + + //! Read-ONLY! Type of the light. Default: ELT_POINT + E_LIGHT_TYPE Type; + + //! Read-ONLY! Does the light cast shadows? + bool CastShadows:1; +}; + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/SMaterial.h b/inc/SMaterial.h new file mode 100644 index 0000000..a1c3ff4 --- /dev/null +++ b/inc/SMaterial.h @@ -0,0 +1,685 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_MATERIAL_H_INCLUDED__ +#define __S_MATERIAL_H_INCLUDED__ + +#include "SColor.h" +#include "matrix4.h" +#include "irrArray.h" +#include "irrMath.h" +#include "EMaterialTypes.h" +#include "EMaterialFlags.h" +#include "SMaterialLayer.h" + +namespace irr +{ +namespace video +{ + class ITexture; + + //! Flag for EMT_ONETEXTURE_BLEND, ( BlendFactor ) BlendFunc = source * sourceFactor + dest * destFactor + enum E_BLEND_FACTOR + { + EBF_ZERO = 0, //!< src & dest (0, 0, 0, 0) + EBF_ONE, //!< src & dest (1, 1, 1, 1) + EBF_DST_COLOR, //!< src (destR, destG, destB, destA) + EBF_ONE_MINUS_DST_COLOR, //!< src (1-destR, 1-destG, 1-destB, 1-destA) + EBF_SRC_COLOR, //!< dest (srcR, srcG, srcB, srcA) + EBF_ONE_MINUS_SRC_COLOR, //!< dest (1-srcR, 1-srcG, 1-srcB, 1-srcA) + EBF_SRC_ALPHA, //!< src & dest (srcA, srcA, srcA, srcA) + EBF_ONE_MINUS_SRC_ALPHA, //!< src & dest (1-srcA, 1-srcA, 1-srcA, 1-srcA) + EBF_DST_ALPHA, //!< src & dest (destA, destA, destA, destA) + EBF_ONE_MINUS_DST_ALPHA, //!< src & dest (1-destA, 1-destA, 1-destA, 1-destA) + EBF_SRC_ALPHA_SATURATE //!< src (min(srcA, 1-destA), idem, ...) + }; + + //! Values defining the blend operation used when blend is enabled + enum E_BLEND_OPERATION + { + EBO_NONE = 0, //!< No blending happens + EBO_ADD, //!< Default blending adds the color values + EBO_SUBTRACT, //!< This mode subtracts the color values + EBO_REVSUBTRACT,//!< This modes subtracts destination from source + EBO_MIN, //!< Choose minimum value of each color channel + EBO_MAX, //!< Choose maximum value of each color channel + EBO_MIN_FACTOR, //!< Choose minimum value of each color channel after applying blend factors, not widely supported + EBO_MAX_FACTOR, //!< Choose maximum value of each color channel after applying blend factors, not widely supported + EBO_MIN_ALPHA, //!< Choose minimum value of each color channel based on alpha value, not widely supported + EBO_MAX_ALPHA //!< Choose maximum value of each color channel based on alpha value, not widely supported + }; + + //! MaterialTypeParam: e.g. DirectX: D3DTOP_MODULATE, D3DTOP_MODULATE2X, D3DTOP_MODULATE4X + enum E_MODULATE_FUNC + { + EMFN_MODULATE_1X = 1, + EMFN_MODULATE_2X = 2, + EMFN_MODULATE_4X = 4 + }; + + //! Comparison function, e.g. for depth buffer test + enum E_COMPARISON_FUNC + { + //! Test never succeeds, this equals disable + ECFN_NEVER=0, + //! <= test, default for e.g. depth test + ECFN_LESSEQUAL=1, + //! Exact equality + ECFN_EQUAL=2, + //! exclusive less comparison, i.e. < + ECFN_LESS, + //! Succeeds almost always, except for exact equality + ECFN_NOTEQUAL, + //! >= test + ECFN_GREATEREQUAL, + //! inverse of <= + ECFN_GREATER, + //! test succeeds always + ECFN_ALWAYS + }; + + //! Enum values for enabling/disabling color planes for rendering + enum E_COLOR_PLANE + { + //! No color enabled + ECP_NONE=0, + //! Alpha enabled + ECP_ALPHA=1, + //! Red enabled + ECP_RED=2, + //! Green enabled + ECP_GREEN=4, + //! Blue enabled + ECP_BLUE=8, + //! All colors, no alpha + ECP_RGB=14, + //! All planes enabled + ECP_ALL=15 + }; + + //! Source of the alpha value to take + /** This is currently only supported in EMT_ONETEXTURE_BLEND. You can use an + or'ed combination of values. Alpha values are modulated (multiplicated). */ + enum E_ALPHA_SOURCE + { + //! Use no alpha, somewhat redundant with other settings + EAS_NONE=0, + //! Use vertex color alpha + EAS_VERTEX_COLOR, + //! Use texture alpha channel + EAS_TEXTURE + }; + + //! EMT_ONETEXTURE_BLEND: pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam + /** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */ + inline f32 pack_textureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) + { + const u32 tmp = (alphaSource << 12) | (modulate << 8) | (srcFact << 4) | dstFact; + return FR(tmp); + } + + //! EMT_ONETEXTURE_BLEND: unpack srcFact & dstFact and Modulo to MaterialTypeParam + /** The fields don't use the full byte range, so we could pack even more... */ + inline void unpack_textureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, + E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) + { + const u32 state = IR(param); + alphaSource = (state & 0x0000F000) >> 12; + modulo = E_MODULATE_FUNC( ( state & 0x00000F00 ) >> 8 ); + srcFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 ); + dstFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) ); + } + + //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending + inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor ) + { + switch ( factor ) + { + case EBF_SRC_ALPHA: + case EBF_ONE_MINUS_SRC_ALPHA: + case EBF_DST_ALPHA: + case EBF_ONE_MINUS_DST_ALPHA: + case EBF_SRC_ALPHA_SATURATE: + return true; + default: + return false; + } + } + + + //! These flags are used to specify the anti-aliasing and smoothing modes + /** Techniques supported are multisampling, geometry smoothing, and alpha + to coverage. + Some drivers don't support a per-material setting of the anti-aliasing + modes. In those cases, FSAA/multisampling is defined by the device mode + chosen upon creation via irr::SIrrCreationParameters. + */ + enum E_ANTI_ALIASING_MODE + { + //! Use to turn off anti-aliasing for this material + EAAM_OFF=0, + //! Default anti-aliasing mode + EAAM_SIMPLE=1, + //! High-quality anti-aliasing, not always supported, automatically enables SIMPLE mode + EAAM_QUALITY=3, + //! Line smoothing + EAAM_LINE_SMOOTH=4, + //! point smoothing, often in software and slow, only with OpenGL + EAAM_POINT_SMOOTH=8, + //! All typical anti-alias and smooth modes + EAAM_FULL_BASIC=15, + //! Enhanced anti-aliasing for transparent materials + /** Usually used with EMT_TRANSPARENT_ALPHA_REF and multisampling. */ + EAAM_ALPHA_TO_COVERAGE=16 + }; + + //! These flags allow to define the interpretation of vertex color when lighting is enabled + /** Without lighting being enabled the vertex color is the only value defining the fragment color. + Once lighting is enabled, the four values for diffuse, ambient, emissive, and specular take over. + With these flags it is possible to define which lighting factor shall be defined by the vertex color + instead of the lighting factor which is the same for all faces of that material. + The default is to use vertex color for the diffuse value, another pretty common value is to use + vertex color for both diffuse and ambient factor. */ + enum E_COLOR_MATERIAL + { + //! Don't use vertex color for lighting + ECM_NONE=0, + //! Use vertex color for diffuse light, this is default + ECM_DIFFUSE, + //! Use vertex color for ambient light + ECM_AMBIENT, + //! Use vertex color for emissive light + ECM_EMISSIVE, + //! Use vertex color for specular light + ECM_SPECULAR, + //! Use vertex color for both diffuse and ambient light + ECM_DIFFUSE_AND_AMBIENT + }; + + //! Flags for the definition of the polygon offset feature + /** These flags define whether the offset should be into the screen, or towards the eye. */ + enum E_POLYGON_OFFSET + { + //! Push pixel towards the far plane, away from the eye + /** This is typically used for rendering inner areas. */ + EPO_BACK=0, + //! Pull pixels towards the camera. + /** This is typically used for polygons which should appear on top + of other elements, such as decals. */ + EPO_FRONT=1 + }; + + //! Names for polygon offset direction + const c8* const PolygonOffsetDirectionNames[] = + { + "Back", + "Front", + 0 + }; + + + //! Maximum number of texture an SMaterial can have. + const u32 MATERIAL_MAX_TEXTURES = _IRR_MATERIAL_MAX_TEXTURES_; + + //! Struct for holding parameters for a material renderer + class SMaterial + { + public: + //! Default constructor. Creates a solid, lit material with white colors + SMaterial() + : MaterialType(EMT_SOLID), AmbientColor(255,255,255,255), DiffuseColor(255,255,255,255), + EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255), + Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f), + ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), + ColorMaterial(ECM_DIFFUSE), BlendOperation(EBO_NONE), + PolygonOffsetFactor(0), PolygonOffsetDirection(EPO_FRONT), + Wireframe(false), PointCloud(false), GouraudShading(true), + Lighting(true), ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false), + FogEnable(false), NormalizeNormals(false), UseMipMaps(true) + { } + + //! Copy constructor + /** \param other Material to copy from. */ + SMaterial(const SMaterial& other) + { + // These pointers are checked during assignment + for (u32 i=0; igetMaterial(0).Shininess = 20.0f; + \endcode + + You can change the color of the highlights using + \code + sceneNode->getMaterial(0).SpecularColor.set(255,255,255,255); + \endcode + + The specular color of the dynamic lights + (SLight::SpecularColor) will influence the the highlight color + too, but they are set to a useful value by default when + creating the light scene node. Here is a simple example on how + to use specular highlights: + \code + // load and display mesh + scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( + smgr->getMesh("data/faerie.md2")); + node->setMaterialTexture(0, driver->getTexture("data/Faerie2.pcx")); // set diffuse texture + node->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting + node->getMaterial(0).Shininess = 20.0f; // set size of specular highlights + + // add white light + scene::ILightSceneNode* light = smgr->addLightSceneNode(0, + core::vector3df(5,5,5), video::SColorf(1.0f, 1.0f, 1.0f)); + \endcode */ + f32 Shininess; + + //! Free parameter, dependent on the material type. + /** Mostly ignored, used for example in EMT_PARALLAX_MAP_SOLID + and EMT_TRANSPARENT_ALPHA_CHANNEL. */ + f32 MaterialTypeParam; + + //! Second free parameter, dependent on the material type. + /** Mostly ignored. */ + f32 MaterialTypeParam2; + + //! Thickness of non-3dimensional elements such as lines and points. + f32 Thickness; + + //! Is the ZBuffer enabled? Default: ECFN_LESSEQUAL + /** Values are from E_COMPARISON_FUNC. */ + u8 ZBuffer; + + //! Sets the antialiasing mode + /** Values are chosen from E_ANTI_ALIASING_MODE. Default is + EAAM_SIMPLE|EAAM_LINE_SMOOTH, i.e. simple multi-sample + anti-aliasing and lime smoothing is enabled. */ + u8 AntiAliasing; + + //! Defines the enabled color planes + /** Values are defined as or'ed values of the E_COLOR_PLANE enum. + Only enabled color planes will be rendered to the current render + target. Typical use is to disable all colors when rendering only to + depth or stencil buffer, or using Red and Green for Stereo rendering. */ + u8 ColorMask:4; + + //! Defines the interpretation of vertex color in the lighting equation + /** Values should be chosen from E_COLOR_MATERIAL. + When lighting is enabled, vertex color can be used instead of the + material values for light modulation. This allows to easily change e.g. the + diffuse light behavior of each face. The default, ECM_DIFFUSE, will result in + a very similar rendering as with lighting turned off, just with light shading. */ + u8 ColorMaterial:3; + + //! Store the blend operation of choice + /** Values to be chosen from E_BLEND_OPERATION. The actual way to use this value + is not yet determined, so ignore it for now. */ + E_BLEND_OPERATION BlendOperation:4; + + //! Factor specifying how far the polygon offset should be made + /** Specifying 0 disables the polygon offset. The direction is specified spearately. + The factor can be from 0 to 7.*/ + u8 PolygonOffsetFactor:3; + + //! Flag defining the direction the polygon offset is applied to. + /** Can be to front or to back, specififed by values from E_POLYGON_OFFSET. */ + E_POLYGON_OFFSET PolygonOffsetDirection:1; + + //! Draw as wireframe or filled triangles? Default: false + /** The user can access a material flag using + \code material.Wireframe=true \endcode + or \code material.setFlag(EMF_WIREFRAME, true); \endcode */ + bool Wireframe:1; + + //! Draw as point cloud or filled triangles? Default: false + bool PointCloud:1; + + //! Flat or Gouraud shading? Default: true + bool GouraudShading:1; + + //! Will this material be lighted? Default: true + bool Lighting:1; + + //! Is the zbuffer writeable or is it read-only. Default: true. + /** This flag is forced to false if the MaterialType is a + transparent type and the scene parameter + ALLOW_ZWRITE_ON_TRANSPARENT is not set. */ + bool ZWriteEnable:1; + + //! Is backface culling enabled? Default: true + bool BackfaceCulling:1; + + //! Is frontface culling enabled? Default: false + bool FrontfaceCulling:1; + + //! Is fog enabled? Default: false + bool FogEnable:1; + + //! Should normals be normalized? + /** Always use this if the mesh lit and scaled. Default: false */ + bool NormalizeNormals:1; + + //! Shall mipmaps be used if available + /** Sometimes, disabling mipmap usage can be useful. Default: true */ + bool UseMipMaps:1; + + //! Gets the texture transformation matrix for level i + /** \param i The desired level. Must not be larger than MATERIAL_MAX_TEXTURES. + \return Texture matrix for texture level i. */ + core::matrix4& getTextureMatrix(u32 i) + { + return TextureLayer[i].getTextureMatrix(); + } + + //! Gets the immutable texture transformation matrix for level i + /** \param i The desired level. + \return Texture matrix for texture level i, or identity matrix for levels larger than MATERIAL_MAX_TEXTURES. */ + const core::matrix4& getTextureMatrix(u32 i) const + { + if (i=MATERIAL_MAX_TEXTURES) + return; + TextureLayer[i].setTextureMatrix(mat); + } + + //! Gets the i-th texture + /** \param i The desired level. + \return Texture for texture level i, if defined, else 0. */ + ITexture* getTexture(u32 i) const + { + return i < MATERIAL_MAX_TEXTURES ? TextureLayer[i].Texture : 0; + } + + //! Sets the i-th texture + /** If i>=MATERIAL_MAX_TEXTURES this setting will be ignored. + \param i The desired level. + \param tex Texture for texture level i. */ + void setTexture(u32 i, ITexture* tex) + { + if (i>=MATERIAL_MAX_TEXTURES) + return; + TextureLayer[i].Texture = tex; + } + + //! Sets the Material flag to the given value + /** \param flag The flag to be set. + \param value The new value for the flag. */ + void setFlag(E_MATERIAL_FLAG flag, bool value) + { + switch (flag) + { + case EMF_WIREFRAME: + Wireframe = value; break; + case EMF_POINTCLOUD: + PointCloud = value; break; + case EMF_GOURAUD_SHADING: + GouraudShading = value; break; + case EMF_LIGHTING: + Lighting = value; break; + case EMF_ZBUFFER: + ZBuffer = value; break; + case EMF_ZWRITE_ENABLE: + ZWriteEnable = value; break; + case EMF_BACK_FACE_CULLING: + BackfaceCulling = value; break; + case EMF_FRONT_FACE_CULLING: + FrontfaceCulling = value; break; + case EMF_BILINEAR_FILTER: + { + for (u32 i=0; i MatrixAllocator; + + //! Texture Matrix + /** Do not access this element directly as the internal + ressource management has to cope with Null pointers etc. */ + core::matrix4* TextureMatrix; + }; + +} // end namespace video +} // end namespace irr + +#endif // __S_MATERIAL_LAYER_H_INCLUDED__ diff --git a/inc/SMesh.h b/inc/SMesh.h new file mode 100644 index 0000000..efac56e --- /dev/null +++ b/inc/SMesh.h @@ -0,0 +1,140 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_MESH_H_INCLUDED__ +#define __S_MESH_H_INCLUDED__ + +#include "IMesh.h" +#include "IMeshBuffer.h" +#include "aabbox3d.h" +#include "irrArray.h" + +namespace irr +{ +namespace scene +{ + //! Simple implementation of the IMesh interface. + struct SMesh : public IMesh + { + //! constructor + SMesh() + { + #ifdef _DEBUG + setDebugName("SMesh"); + #endif + } + + //! destructor + virtual ~SMesh() + { + // drop buffers + for (u32 i=0; idrop(); + } + + //! clean mesh + virtual void clear() + { + for (u32 i=0; idrop(); + MeshBuffers.clear(); + BoundingBox.reset ( 0.f, 0.f, 0.f ); + } + + + //! returns amount of mesh buffers. + virtual u32 getMeshBufferCount() const + { + return MeshBuffers.size(); + } + + //! returns pointer to a mesh buffer + virtual IMeshBuffer* getMeshBuffer(u32 nr) const + { + return MeshBuffers[nr]; + } + + //! returns a meshbuffer which fits a material + /** reverse search */ + virtual IMeshBuffer* getMeshBuffer( const video::SMaterial & material) const + { + for (s32 i = (s32)MeshBuffers.size()-1; i >= 0; --i) + { + if ( material == MeshBuffers[i]->getMaterial()) + return MeshBuffers[i]; + } + + return 0; + } + + //! returns an axis aligned bounding box + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + //! set user axis aligned bounding box + virtual void setBoundingBox( const core::aabbox3df& box) + { + BoundingBox = box; + } + + //! recalculates the bounding box + void recalculateBoundingBox() + { + if (MeshBuffers.size()) + { + BoundingBox = MeshBuffers[0]->getBoundingBox(); + for (u32 i=1; igetBoundingBox()); + } + else + BoundingBox.reset(0.0f, 0.0f, 0.0f); + } + + //! adds a MeshBuffer + /** The bounding box is not updated automatically. */ + void addMeshBuffer(IMeshBuffer* buf) + { + if (buf) + { + buf->grab(); + MeshBuffers.push_back(buf); + } + } + + //! sets a flag of all contained materials to a new value + virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) + { + for (u32 i=0; igetMaterial().setFlag(flag, newvalue); + } + + //! set the hardware mapping hint, for driver + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) + { + for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); + } + + //! flags the meshbuffer as changed, reloads hardware buffers + virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) + { + for (u32 i=0; isetDirty(buffer); + } + + //! The meshbuffers of this mesh + core::array MeshBuffers; + + //! The bounding box of this mesh + core::aabbox3d BoundingBox; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SMeshBuffer.h b/inc/SMeshBuffer.h new file mode 100644 index 0000000..2c3b7e2 --- /dev/null +++ b/inc/SMeshBuffer.h @@ -0,0 +1,7 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// replaced by template +#include "CMeshBuffer.h" + diff --git a/inc/SMeshBufferLightMap.h b/inc/SMeshBufferLightMap.h new file mode 100644 index 0000000..2c3b7e2 --- /dev/null +++ b/inc/SMeshBufferLightMap.h @@ -0,0 +1,7 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// replaced by template +#include "CMeshBuffer.h" + diff --git a/inc/SMeshBufferTangents.h b/inc/SMeshBufferTangents.h new file mode 100644 index 0000000..2c3b7e2 --- /dev/null +++ b/inc/SMeshBufferTangents.h @@ -0,0 +1,7 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// replaced by template +#include "CMeshBuffer.h" + diff --git a/inc/SParticle.h b/inc/SParticle.h new file mode 100644 index 0000000..c69c483 --- /dev/null +++ b/inc/SParticle.h @@ -0,0 +1,56 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_PARTICLE_H_INCLUDED__ +#define __S_PARTICLE_H_INCLUDED__ + +#include "vector3d.h" +#include "dimension2d.h" +#include "SColor.h" + +namespace irr +{ +namespace scene +{ + //! Struct for holding particle data + struct SParticle + { + //! Position of the particle + core::vector3df pos; + + //! Direction and speed of the particle + core::vector3df vector; + + //! Start life time of the particle + u32 startTime; + + //! End life time of the particle + u32 endTime; + + //! Current color of the particle + video::SColor color; + + //! Original color of the particle. + /** That's the color of the particle it had when it was emitted. */ + video::SColor startColor; + + //! Original direction and speed of the particle. + /** The direction and speed the particle had when it was emitted. */ + core::vector3df startVector; + + //! Scale of the particle. + /** The current scale of the particle. */ + core::dimension2df size; + + //! Original scale of the particle. + /** The scale of the particle when it was emitted. */ + core::dimension2df startSize; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SSharedMeshBuffer.h b/inc/SSharedMeshBuffer.h new file mode 100644 index 0000000..016b796 --- /dev/null +++ b/inc/SSharedMeshBuffer.h @@ -0,0 +1,242 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_SHARED_MESH_BUFFER_H_INCLUDED__ +#define __S_SHARED_MESH_BUFFER_H_INCLUDED__ + +#include "irrArray.h" +#include "IMeshBuffer.h" + +namespace irr +{ +namespace scene +{ + //! Implementation of the IMeshBuffer interface with shared vertex list + struct SSharedMeshBuffer : public IMeshBuffer + { + //! constructor + SSharedMeshBuffer() : IMeshBuffer(), Vertices(0), ChangedID_Vertex(1), ChangedID_Index(1), MappingHintVertex(EHM_NEVER), MappingHintIndex(EHM_NEVER) + { + #ifdef _DEBUG + setDebugName("SSharedMeshBuffer"); + #endif + } + + //! constructor + SSharedMeshBuffer(core::array *vertices) : IMeshBuffer(), Vertices(vertices) + { + #ifdef _DEBUG + setDebugName("SSharedMeshBuffer"); + #endif + } + + //! returns the material of this meshbuffer + virtual const video::SMaterial& getMaterial() const + { + return Material; + } + + //! returns the material of this meshbuffer + virtual video::SMaterial& getMaterial() + { + return Material; + } + + //! returns pointer to vertices + virtual const void* getVertices() const + { + if (Vertices) + return Vertices->const_pointer(); + else + return 0; + } + + //! returns pointer to vertices + virtual void* getVertices() + { + if (Vertices) + return Vertices->pointer(); + else + return 0; + } + + //! returns amount of vertices + virtual u32 getVertexCount() const + { + if (Vertices) + return Vertices->size(); + else + return 0; + } + + //! returns pointer to Indices + virtual const u16* getIndices() const + { + return Indices.const_pointer(); + } + + //! returns pointer to Indices + virtual u16* getIndices() + { + return Indices.pointer(); + } + + //! returns amount of indices + virtual u32 getIndexCount() const + { + return Indices.size(); + } + + //! Get type of index data which is stored in this meshbuffer. + virtual video::E_INDEX_TYPE getIndexType() const + { + return video::EIT_16BIT; + } + + //! returns an axis aligned bounding box + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + //! set user axis aligned bounding box + virtual void setBoundingBox( const core::aabbox3df& box) + { + BoundingBox = box; + } + + //! returns which type of vertex data is stored. + virtual video::E_VERTEX_TYPE getVertexType() const + { + return video::EVT_STANDARD; + } + + //! recalculates the bounding box. should be called if the mesh changed. + virtual void recalculateBoundingBox() + { + if (!Vertices || Vertices->empty() || Indices.empty()) + BoundingBox.reset(0,0,0); + else + { + BoundingBox.reset((*Vertices)[Indices[0]].Pos); + for (u32 i=1; i *Vertices; + + //! Array of Indices + core::array Indices; + + //! ID used for hardware buffer management + u32 ChangedID_Vertex; + + //! ID used for hardware buffer management + u32 ChangedID_Index; + + //! Bounding box + core::aabbox3df BoundingBox; + + //! hardware mapping hint + E_HARDWARE_MAPPING MappingHintVertex; + E_HARDWARE_MAPPING MappingHintIndex; + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SSkinMeshBuffer.h b/inc/SSkinMeshBuffer.h new file mode 100644 index 0000000..d47de19 --- /dev/null +++ b/inc/SSkinMeshBuffer.h @@ -0,0 +1,404 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SKIN_MESH_BUFFER_H_INCLUDED__ +#define __I_SKIN_MESH_BUFFER_H_INCLUDED__ + +#include "IMeshBuffer.h" +#include "S3DVertex.h" + + +namespace irr +{ +namespace scene +{ + + +//! A mesh buffer able to choose between S3DVertex2TCoords, S3DVertex and S3DVertexTangents at runtime +struct SSkinMeshBuffer : public IMeshBuffer +{ + //! Default constructor + SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) : + ChangedID_Vertex(1), ChangedID_Index(1), VertexType(vt), + MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER), + BoundingBoxNeedsRecalculated(true) + { + #ifdef _DEBUG + setDebugName("SSkinMeshBuffer"); + #endif + } + + //! Get Material of this buffer. + virtual const video::SMaterial& getMaterial() const + { + return Material; + } + + //! Get Material of this buffer. + virtual video::SMaterial& getMaterial() + { + return Material; + } + + //! Get standard vertex at given index + virtual video::S3DVertex *getVertex(u32 index) + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return (video::S3DVertex*)&Vertices_2TCoords[index]; + case video::EVT_TANGENTS: + return (video::S3DVertex*)&Vertices_Tangents[index]; + default: + return &Vertices_Standard[index]; + } + } + + //! Get pointer to vertex array + virtual const void* getVertices() const + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.const_pointer(); + case video::EVT_TANGENTS: + return Vertices_Tangents.const_pointer(); + default: + return Vertices_Standard.const_pointer(); + } + } + + //! Get pointer to vertex array + virtual void* getVertices() + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.pointer(); + case video::EVT_TANGENTS: + return Vertices_Tangents.pointer(); + default: + return Vertices_Standard.pointer(); + } + } + + //! Get vertex count + virtual u32 getVertexCount() const + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords.size(); + case video::EVT_TANGENTS: + return Vertices_Tangents.size(); + default: + return Vertices_Standard.size(); + } + } + + //! Get type of index data which is stored in this meshbuffer. + /** \return Index type of this buffer. */ + virtual video::E_INDEX_TYPE getIndexType() const + { + return video::EIT_16BIT; + } + + //! Get pointer to index array + virtual const u16* getIndices() const + { + return Indices.const_pointer(); + } + + //! Get pointer to index array + virtual u16* getIndices() + { + return Indices.pointer(); + } + + //! Get index count + virtual u32 getIndexCount() const + { + return Indices.size(); + } + + //! Get bounding box + virtual const core::aabbox3d& getBoundingBox() const + { + return BoundingBox; + } + + //! Set bounding box + virtual void setBoundingBox( const core::aabbox3df& box) + { + BoundingBox = box; + } + + //! Recalculate bounding box + virtual void recalculateBoundingBox() + { + if(!BoundingBoxNeedsRecalculated) + return; + + BoundingBoxNeedsRecalculated = false; + + switch (VertexType) + { + case video::EVT_STANDARD: + { + if (Vertices_Standard.empty()) + BoundingBox.reset(0,0,0); + else + { + BoundingBox.reset(Vertices_Standard[0].Pos); + for (u32 i=1; i Vertices_Tangents; + core::array Vertices_2TCoords; + core::array Vertices_Standard; + core::array Indices; + + u32 ChangedID_Vertex; + u32 ChangedID_Index; + + //ISkinnedMesh::SJoint *AttachedJoint; + core::matrix4 Transformation; + + video::SMaterial Material; + video::E_VERTEX_TYPE VertexType; + + core::aabbox3d BoundingBox; + + // hardware mapping hint + E_HARDWARE_MAPPING MappingHint_Vertex:3; + E_HARDWARE_MAPPING MappingHint_Index:3; + + bool BoundingBoxNeedsRecalculated:1; +}; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SVertexIndex.h b/inc/SVertexIndex.h new file mode 100644 index 0000000..bc775ec --- /dev/null +++ b/inc/SVertexIndex.h @@ -0,0 +1,79 @@ +// Copyright (C) 2008-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_VERTEX_INDEX_H_INCLUDED__ +#define __S_VERTEX_INDEX_H_INCLUDED__ + +#include "irrTypes.h" + + +namespace irr +{ +namespace video +{ +enum E_INDEX_TYPE +{ + EIT_16BIT = 0, + EIT_32BIT +}; + + +/* +//! vertex index used by the Irrlicht engine. +template +struct SSpecificVertexIndex +{ + T Index; + + //! default constructor + SSpecificVertexIndex() {} + + //! constructor + SSpecificVertexIndex(u32 _index) :Index(_index) {} + + bool operator==(const SSpecificVertexIndex& other) const + { + return (Index == other.Index); + } + + bool operator!=(const SSpecificVertexIndex& other) const + { + return (Index != other.Index); + } + + bool operator<(const SSpecificVertexIndex& other) const + { + return (Index < other.Index); + } + + SSpecificVertexIndex operator+(const u32& other) const + { + return SSpecificVertexIndex(Index + other); + } + + operator const u32() const + { + return (const u32)Index; + } + + E_INDEX_TYPE getType() const + { + if (sizeof(T)==sizeof(u16)) + return video::EIT_16BIT; + return video::EIT_32BIT; + } + +}; + +//typedef SSpecificVertexIndex SVertexIndex; + +typedef u32 SVertexIndex; +*/ + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/inc/SVertexManipulator.h b/inc/SVertexManipulator.h new file mode 100644 index 0000000..592544b --- /dev/null +++ b/inc/SVertexManipulator.h @@ -0,0 +1,292 @@ +// Copyright (C) 2009-2012 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_VERTEX_MANIPULATOR_H_INCLUDED__ +#define __S_VERTEX_MANIPULATOR_H_INCLUDED__ + +#include "S3DVertex.h" +#include "SColor.h" + +namespace irr +{ +namespace scene +{ + + class IMesh; + class IMeshBuffer; + struct SMesh; + + //! Interface for vertex manipulators. + /** You should derive your manipulator from this class if it shall be called for every vertex, getting as parameter just the vertex. + */ + struct IVertexManipulator + { + }; + //! Vertex manipulator to set color to a fixed color for all vertices + class SVertexColorSetManipulator : public IVertexManipulator + { + public: + SVertexColorSetManipulator(video::SColor color) : Color(color) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=Color; + } + private: + video::SColor Color; + }; + //! Vertex manipulator to set the alpha value of the vertex color to a fixed value + class SVertexColorSetAlphaManipulator : public IVertexManipulator + { + public: + SVertexColorSetAlphaManipulator(u32 alpha) : Alpha(alpha) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setAlpha(Alpha); + } + private: + u32 Alpha; + }; + //! Vertex manipulator which invertes the RGB values + class SVertexColorInvertManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(255-vertex.Color.getRed()); + vertex.Color.setGreen(255-vertex.Color.getGreen()); + vertex.Color.setBlue(255-vertex.Color.getBlue()); + } + }; + //! Vertex manipulator to set vertex color to one of two values depending on a given threshold + /** If average of the color value is >Threshold the High color is chosen, else Low. */ + class SVertexColorThresholdManipulator : public IVertexManipulator + { + public: + SVertexColorThresholdManipulator(u8 threshold, video::SColor low, + video::SColor high) : Threshold(threshold), Low(low), High(high) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color = ((u8)vertex.Color.getAverage()>Threshold)?High:Low; + } + private: + u8 Threshold; + video::SColor Low; + video::SColor High; + }; + //! Vertex manipulator which adjusts the brightness by the given amount + /** A positive value increases brightness, a negative value darkens the colors. */ + class SVertexColorBrightnessManipulator : public IVertexManipulator + { + public: + SVertexColorBrightnessManipulator(s32 amount) : Amount(amount) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(vertex.Color.getRed()+Amount, 0u, 255u)); + vertex.Color.setGreen(core::clamp(vertex.Color.getGreen()+Amount, 0u, 255u)); + vertex.Color.setBlue(core::clamp(vertex.Color.getBlue()+Amount, 0u, 255u)); + } + private: + s32 Amount; + }; + //! Vertex manipulator which adjusts the contrast by the given factor + /** Factors over 1 increase contrast, below 1 reduce it. */ + class SVertexColorContrastManipulator : public IVertexManipulator + { + public: + SVertexColorContrastManipulator(f32 factor) : Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+128, 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+128, 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+128, 0, 255)); + } + private: + f32 Factor; + }; + //! Vertex manipulator which adjusts the contrast by the given factor and brightness by a signed amount. + /** Factors over 1 increase contrast, below 1 reduce it. + A positive amount increases brightness, a negative one darkens the colors. */ + class SVertexColorContrastBrightnessManipulator : public IVertexManipulator + { + public: + SVertexColorContrastBrightnessManipulator(f32 factor, s32 amount) : Factor(factor), Amount(amount+128) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+Amount, 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+Amount, 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+Amount, 0, 255)); + } + private: + f32 Factor; + s32 Amount; + }; + //! Vertex manipulator which adjusts the brightness by a gamma operation + /** A value over one increases brightness, one below darkens the colors. */ + class SVertexColorGammaManipulator : public IVertexManipulator + { + public: + SVertexColorGammaManipulator(f32 gamma) : Gamma(1.f) + { + if (gamma != 0.f) + Gamma = 1.f/gamma; + } + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32(powf((f32)(vertex.Color.getRed()),Gamma)), 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32(powf((f32)(vertex.Color.getGreen()),Gamma)), 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32(powf((f32)(vertex.Color.getBlue()),Gamma)), 0, 255)); + } + private: + f32 Gamma; + }; + //! Vertex manipulator which scales the color values + /** Can e.g be used for white balance, factor would be 255.f/brightest color. */ + class SVertexColorScaleManipulator : public IVertexManipulator + { + public: + SVertexColorScaleManipulator(f32 factor) : Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color.setRed(core::clamp(core::round32(vertex.Color.getRed()*Factor), 0, 255)); + vertex.Color.setGreen(core::clamp(core::round32(vertex.Color.getGreen()*Factor), 0, 255)); + vertex.Color.setBlue(core::clamp(core::round32(vertex.Color.getBlue()*Factor), 0, 255)); + } + private: + f32 Factor; + }; + //! Vertex manipulator which desaturates the color values + /** Uses the lightness value of the color. */ + class SVertexColorDesaturateToLightnessManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=core::round32(vertex.Color.getLightness()); + } + }; + //! Vertex manipulator which desaturates the color values + /** Uses the average value of the color. */ + class SVertexColorDesaturateToAverageManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getAverage(); + } + }; + //! Vertex manipulator which desaturates the color values + /** Uses the luminance value of the color. */ + class SVertexColorDesaturateToLuminanceManipulator : public IVertexManipulator + { + public: + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=core::round32(vertex.Color.getLuminance()); + } + }; + //! Vertex manipulator which interpolates the color values + /** Uses linear interpolation. */ + class SVertexColorInterpolateLinearManipulator : public IVertexManipulator + { + public: + SVertexColorInterpolateLinearManipulator(video::SColor color, f32 factor) : + Color(color), Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getInterpolated(Color, Factor); + } + private: + video::SColor Color; + f32 Factor; + }; + //! Vertex manipulator which interpolates the color values + /** Uses linear interpolation. */ + class SVertexColorInterpolateQuadraticManipulator : public IVertexManipulator + { + public: + SVertexColorInterpolateQuadraticManipulator(video::SColor color1, video::SColor color2, f32 factor) : + Color1(color1), Color2(color2), Factor(factor) {} + void operator()(video::S3DVertex& vertex) const + { + vertex.Color=vertex.Color.getInterpolated_quadratic(Color1, Color2, Factor); + } + private: + video::SColor Color1; + video::SColor Color2; + f32 Factor; + }; + + //! Vertex manipulator which scales the position of the vertex + class SVertexPositionScaleManipulator : public IVertexManipulator + { + public: + SVertexPositionScaleManipulator(const core::vector3df& factor) : Factor(factor) {} + template + void operator()(VType& vertex) const + { + vertex.Pos *= Factor; + } + private: + core::vector3df Factor; + }; + + //! Vertex manipulator which scales the position of the vertex along the normals + /** This can look more pleasing than the usual Scale operator, but + depends on the mesh geometry. + */ + class SVertexPositionScaleAlongNormalsManipulator : public IVertexManipulator + { + public: + SVertexPositionScaleAlongNormalsManipulator(const core::vector3df& factor) : Factor(factor) {} + template + void operator()(VType& vertex) const + { + vertex.Pos += vertex.Normal*Factor; + } + private: + core::vector3df Factor; + }; + + //! Vertex manipulator which transforms the position of the vertex + class SVertexPositionTransformManipulator : public IVertexManipulator + { + public: + SVertexPositionTransformManipulator(const core::matrix4& m) : Transformation(m) {} + template + void operator()(VType& vertex) const + { + Transformation.transformVect(vertex.Pos); + } + private: + core::matrix4 Transformation; + }; + + //! Vertex manipulator which scales the TCoords of the vertex + class SVertexTCoordsScaleManipulator : public IVertexManipulator + { + public: + SVertexTCoordsScaleManipulator(const core::vector2df& factor, u32 uvSet=1) : Factor(factor), UVSet(uvSet) {} + void operator()(video::S3DVertex2TCoords& vertex) const + { + if (1==UVSet) + vertex.TCoords *= Factor; + else if (2==UVSet) + vertex.TCoords2 *= Factor; + } + template + void operator()(VType& vertex) const + { + if (1==UVSet) + vertex.TCoords *= Factor; + } + private: + core::vector2df Factor; + u32 UVSet; + }; + +} // end namespace scene +} // end namespace irr + + +#endif diff --git a/inc/SViewFrustum.h b/inc/SViewFrustum.h new file mode 100644 index 0000000..d2b5b9a --- /dev/null +++ b/inc/SViewFrustum.h @@ -0,0 +1,370 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __S_VIEW_FRUSTUM_H_INCLUDED__ +#define __S_VIEW_FRUSTUM_H_INCLUDED__ + +#include "plane3d.h" +#include "vector3d.h" +#include "line3d.h" +#include "aabbox3d.h" +#include "matrix4.h" +#include "IVideoDriver.h" + +namespace irr +{ +namespace scene +{ + + //! Defines the view frustum. That's the space visible by the camera. + /** The view frustum is enclosed by 6 planes. These six planes share + eight points. A bounding box around these eight points is also stored in + this structure. + */ + struct SViewFrustum + { + enum VFPLANES + { + //! Far plane of the frustum. That is the plane farest away from the eye. + VF_FAR_PLANE = 0, + //! Near plane of the frustum. That is the plane nearest to the eye. + VF_NEAR_PLANE, + //! Left plane of the frustum. + VF_LEFT_PLANE, + //! Right plane of the frustum. + VF_RIGHT_PLANE, + //! Bottom plane of the frustum. + VF_BOTTOM_PLANE, + //! Top plane of the frustum. + VF_TOP_PLANE, + + //! Amount of planes enclosing the view frustum. Should be 6. + VF_PLANE_COUNT + }; + + + //! Default Constructor + SViewFrustum() {} + + //! Copy Constructor + SViewFrustum(const SViewFrustum& other); + + //! This constructor creates a view frustum based on a projection and/or view matrix. + SViewFrustum(const core::matrix4& mat); + + //! This constructor creates a view frustum based on a projection and/or view matrix. + inline void setFrom(const core::matrix4& mat); + + //! transforms the frustum by the matrix + /** \param mat: Matrix by which the view frustum is transformed.*/ + void transform(const core::matrix4& mat); + + //! returns the point which is on the far left upper corner inside the the view frustum. + core::vector3df getFarLeftUp() const; + + //! returns the point which is on the far left bottom corner inside the the view frustum. + core::vector3df getFarLeftDown() const; + + //! returns the point which is on the far right top corner inside the the view frustum. + core::vector3df getFarRightUp() const; + + //! returns the point which is on the far right bottom corner inside the the view frustum. + core::vector3df getFarRightDown() const; + + //! returns the point which is on the near left upper corner inside the the view frustum. + core::vector3df getNearLeftUp() const; + + //! returns the point which is on the near left bottom corner inside the the view frustum. + core::vector3df getNearLeftDown() const; + + //! returns the point which is on the near right top corner inside the the view frustum. + core::vector3df getNearRightUp() const; + + //! returns the point which is on the near right bottom corner inside the the view frustum. + core::vector3df getNearRightDown() const; + + //! returns a bounding box enclosing the whole view frustum + const core::aabbox3d &getBoundingBox() const; + + //! recalculates the bounding box member based on the planes + inline void recalculateBoundingBox(); + + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE + core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); + + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE + const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; + + //! clips a line to the view frustum. + /** \return True if the line was clipped, false if not */ + bool clipLine(core::line3d& line) const; + + //! the position of the camera + core::vector3df cameraPosition; + + //! all planes enclosing the view frustum. + core::plane3d planes[VF_PLANE_COUNT]; + + //! bounding box around the view frustum + core::aabbox3d boundingBox; + + private: + //! Hold a copy of important transform matrices + enum E_TRANSFORMATION_STATE_FRUSTUM + { + ETS_VIEW = 0, + ETS_PROJECTION = 1, + ETS_COUNT_FRUSTUM + }; + + //! Hold a copy of important transform matrices + core::matrix4 Matrices[ETS_COUNT_FRUSTUM]; + }; + + + /*! + Copy constructor ViewFrustum + */ + inline SViewFrustum::SViewFrustum(const SViewFrustum& other) + { + cameraPosition=other.cameraPosition; + boundingBox=other.boundingBox; + + u32 i; + for (i=0; i &SViewFrustum::getBoundingBox() const + { + return boundingBox; + } + + inline void SViewFrustum::recalculateBoundingBox() + { + boundingBox.reset ( cameraPosition ); + + boundingBox.addInternalPoint(getFarLeftUp()); + boundingBox.addInternalPoint(getFarRightUp()); + boundingBox.addInternalPoint(getFarLeftDown()); + boundingBox.addInternalPoint(getFarRightDown()); + } + + //! This constructor creates a view frustum based on a projection + //! and/or view matrix. + inline void SViewFrustum::setFrom(const core::matrix4& mat) + { + // left clipping plane + planes[VF_LEFT_PLANE].Normal.X = mat[3 ] + mat[0]; + planes[VF_LEFT_PLANE].Normal.Y = mat[7 ] + mat[4]; + planes[VF_LEFT_PLANE].Normal.Z = mat[11] + mat[8]; + planes[VF_LEFT_PLANE].D = mat[15] + mat[12]; + + // right clipping plane + planes[VF_RIGHT_PLANE].Normal.X = mat[3 ] - mat[0]; + planes[VF_RIGHT_PLANE].Normal.Y = mat[7 ] - mat[4]; + planes[VF_RIGHT_PLANE].Normal.Z = mat[11] - mat[8]; + planes[VF_RIGHT_PLANE].D = mat[15] - mat[12]; + + // top clipping plane + planes[VF_TOP_PLANE].Normal.X = mat[3 ] - mat[1]; + planes[VF_TOP_PLANE].Normal.Y = mat[7 ] - mat[5]; + planes[VF_TOP_PLANE].Normal.Z = mat[11] - mat[9]; + planes[VF_TOP_PLANE].D = mat[15] - mat[13]; + + // bottom clipping plane + planes[VF_BOTTOM_PLANE].Normal.X = mat[3 ] + mat[1]; + planes[VF_BOTTOM_PLANE].Normal.Y = mat[7 ] + mat[5]; + planes[VF_BOTTOM_PLANE].Normal.Z = mat[11] + mat[9]; + planes[VF_BOTTOM_PLANE].D = mat[15] + mat[13]; + + // far clipping plane + planes[VF_FAR_PLANE].Normal.X = mat[3 ] - mat[2]; + planes[VF_FAR_PLANE].Normal.Y = mat[7 ] - mat[6]; + planes[VF_FAR_PLANE].Normal.Z = mat[11] - mat[10]; + planes[VF_FAR_PLANE].D = mat[15] - mat[14]; + + // near clipping plane + planes[VF_NEAR_PLANE].Normal.X = mat[2]; + planes[VF_NEAR_PLANE].Normal.Y = mat[6]; + planes[VF_NEAR_PLANE].Normal.Z = mat[10]; + planes[VF_NEAR_PLANE].D = mat[14]; + + // normalize normals + u32 i; + for ( i=0; i != VF_PLANE_COUNT; ++i) + { + const f32 len = -core::reciprocal_squareroot( + planes[i].Normal.getLengthSQ()); + planes[i].Normal *= len; + planes[i].D *= len; + } + + // make bounding box + recalculateBoundingBox(); + } + + /*! + View Frustum depends on Projection & View Matrix + */ + inline core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) + { + u32 index = 0; + switch ( state ) + { + case video::ETS_PROJECTION: + index = SViewFrustum::ETS_PROJECTION; break; + case video::ETS_VIEW: + index = SViewFrustum::ETS_VIEW; break; + default: + break; + } + return Matrices [ index ]; + } + + /*! + View Frustum depends on Projection & View Matrix + */ + inline const core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) const + { + u32 index = 0; + switch ( state ) + { + case video::ETS_PROJECTION: + index = SViewFrustum::ETS_PROJECTION; break; + case video::ETS_VIEW: + index = SViewFrustum::ETS_VIEW; break; + default: + break; + } + return Matrices [ index ]; + } + + //! Clips a line to the frustum + inline bool SViewFrustum::clipLine(core::line3d& line) const + { + bool wasClipped = false; + for (u32 i=0; i < VF_PLANE_COUNT; ++i) + { + if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT) + { + line.start = line.start.getInterpolated(line.end, + planes[i].getKnownIntersectionWithLine(line.start, line.end)); + wasClipped = true; + } + if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT) + { + line.end = line.start.getInterpolated(line.end, + planes[i].getKnownIntersectionWithLine(line.start, line.end)); + wasClipped = true; + } + } + return wasClipped; + } + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/SceneParameters.h b/inc/SceneParameters.h new file mode 100644 index 0000000..827ae42 --- /dev/null +++ b/inc/SceneParameters.h @@ -0,0 +1,182 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_PARAMETERS_H_INCLUDED__ +#define __I_SCENE_PARAMETERS_H_INCLUDED__ + +/*! \file SceneParameters.h + \brief Header file containing all scene parameters for modifying mesh loading etc. + + This file includes all parameter names which can be set using ISceneManager::getParameters() + to modify the behavior of plugins and mesh loaders. +*/ + +namespace irr +{ +namespace scene +{ + //! Name of the parameter for changing how Irrlicht handles the ZWrite flag for transparent (blending) materials + /** The default behavior in Irrlicht is to disable writing to the + z-buffer for all really transparent, i.e. blending materials. This + avoids problems with intersecting faces, but can also break renderings. + If transparent materials should use the SMaterial flag for ZWriteEnable + just as other material types use this attribute. + Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); + \endcode + **/ + const c8* const ALLOW_ZWRITE_ON_TRANSPARENT = "Allow_ZWrite_On_Transparent"; + + //! Name of the parameter for changing the texture path of the built-in csm loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::CSM_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const CSM_TEXTURE_PATH = "CSM_TexturePath"; + + //! Name of the parameter for changing the texture path of the built-in lmts loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::LMTS_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const LMTS_TEXTURE_PATH = "LMTS_TexturePath"; + + //! Name of the parameter for changing the texture path of the built-in my3d loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::MY3D_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const MY3D_TEXTURE_PATH = "MY3D_TexturePath"; + + //! Name of the parameter specifying the COLLADA mesh loading mode + /** + Specifies if the COLLADA loader should create instances of the models, lights and + cameras when loading COLLADA meshes. By default, this is set to false. If this is + set to true, the ISceneManager::getMesh() method will only return a pointer to a + dummy mesh and create instances of all meshes and lights and cameras in the collada + file by itself. Example: + \code + SceneManager->getParameters()->setAttribute(scene::COLLADA_CREATE_SCENE_INSTANCES, true); + \endcode + */ + const c8* const COLLADA_CREATE_SCENE_INSTANCES = "COLLADA_CreateSceneInstances"; + + //! Name of the parameter for changing the texture path of the built-in DMF loader. + /** This path is prefixed to the file names defined in the Deled file when loading + textures. This allows to alter the paths for a specific project setting. + Use it like this: + \code + SceneManager->getStringParameters()->setAttribute(scene::DMF_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const DMF_TEXTURE_PATH = "DMF_TexturePath"; + + //! Name of the parameter for preserving DMF textures dir structure with built-in DMF loader. + /** If this parameter is set to true, the texture directory defined in the Deled file + is ignored, and only the texture name is used to find the proper file. Otherwise, the + texture path is also used, which allows to use a nicer media layout. + Use it like this: + \code + //this way you won't use this setting (default) + SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, false); + \endcode + \code + //this way you'll use this setting + SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, true); + \endcode + **/ + const c8* const DMF_IGNORE_MATERIALS_DIRS = "DMF_IgnoreMaterialsDir"; + + //! Name of the parameter for setting reference value of alpha in transparent materials. + /** Use it like this: + \code + //this way you'll set alpha ref to 0.1 + SceneManager->getParameters()->setAttribute(scene::DMF_ALPHA_CHANNEL_REF, 0.1); + \endcode + **/ + const c8* const DMF_ALPHA_CHANNEL_REF = "DMF_AlphaRef"; + + //! Name of the parameter for choose to flip or not tga files. + /** Use it like this: + \code + //this way you'll choose to flip alpha textures + SceneManager->getParameters()->setAttribute(scene::DMF_FLIP_ALPHA_TEXTURES, true); + \endcode + **/ + const c8* const DMF_FLIP_ALPHA_TEXTURES = "DMF_FlipAlpha"; + + + //! Name of the parameter for changing the texture path of the built-in obj loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const OBJ_TEXTURE_PATH = "OBJ_TexturePath"; + + //! Flag to avoid loading group structures in .obj files + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_GROUPS, true); + \endcode + **/ + const c8* const OBJ_LOADER_IGNORE_GROUPS = "OBJ_IgnoreGroups"; + + + //! Flag to avoid loading material .mtl file for .obj files + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true); + \endcode + **/ + const c8* const OBJ_LOADER_IGNORE_MATERIAL_FILES = "OBJ_IgnoreMaterialFiles"; + + + //! Flag to ignore the b3d file's mipmapping flag + /** Instead Irrlicht's texture creation flag is used. Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::B3D_LOADER_IGNORE_MIPMAP_FLAG, true); + \endcode + **/ + const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; + + //! Name of the parameter for changing the texture path of the built-in b3d loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::B3D_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const B3D_TEXTURE_PATH = "B3D_TexturePath"; + + //! Flag set as parameter when the scene manager is used as editor + /** In this way special animators like deletion animators can be stopped from + deleting scene nodes for example */ + const c8* const IRR_SCENE_MANAGER_IS_EDITOR = "IRR_Editor"; + + //! Name of the parameter for setting the length of debug normals. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::DEBUG_NORMAL_LENGTH, 1.5f); + \endcode + **/ + const c8* const DEBUG_NORMAL_LENGTH = "DEBUG_Normal_Length"; + + //! Name of the parameter for setting the color of debug normals. + /** Use it like this: + \code + SceneManager->getParameters()->setAttributeAsColor(scene::DEBUG_NORMAL_COLOR, video::SColor(255, 255, 255, 255)); + \endcode + **/ + const c8* const DEBUG_NORMAL_COLOR = "DEBUG_Normal_Color"; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/inc/aabbox3d.h b/inc/aabbox3d.h new file mode 100644 index 0000000..ae4e3ae --- /dev/null +++ b/inc/aabbox3d.h @@ -0,0 +1,332 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_AABBOX_3D_H_INCLUDED__ +#define __IRR_AABBOX_3D_H_INCLUDED__ + +#include "irrMath.h" +#include "plane3d.h" +#include "line3d.h" + +namespace irr +{ +namespace core +{ + +//! Axis aligned bounding box in 3d dimensional space. +/** Has some useful methods used with occlusion culling or clipping. +*/ +template +class aabbox3d +{ + public: + + //! Default Constructor. + aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {} + //! Constructor with min edge and max edge. + aabbox3d(const vector3d& min, const vector3d& max): MinEdge(min), MaxEdge(max) {} + //! Constructor with only one point. + aabbox3d(const vector3d& init): MinEdge(init), MaxEdge(init) {} + //! Constructor with min edge and max edge as single values, not vectors. + aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {} + + // operators + //! Equality operator + /** \param other box to compare with. + \return True if both boxes are equal, else false. */ + inline bool operator==(const aabbox3d& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} + //! Inequality operator + /** \param other box to compare with. + \return True if both boxes are different, else false. */ + inline bool operator!=(const aabbox3d& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} + + // functions + + //! Resets the bounding box to a one-point box. + /** \param x X coord of the point. + \param y Y coord of the point. + \param z Z coord of the point. */ + void reset(T x, T y, T z) + { + MaxEdge.set(x,y,z); + MinEdge = MaxEdge; + } + + //! Resets the bounding box. + /** \param initValue New box to set this one to. */ + void reset(const aabbox3d& initValue) + { + *this = initValue; + } + + //! Resets the bounding box to a one-point box. + /** \param initValue New point. */ + void reset(const vector3d& initValue) + { + MaxEdge = initValue; + MinEdge = initValue; + } + + //! Adds a point to the bounding box + /** The box grows bigger, if point was outside of the box. + \param p: Point to add into the box. */ + void addInternalPoint(const vector3d& p) + { + addInternalPoint(p.X, p.Y, p.Z); + } + + //! Adds another bounding box + /** The box grows bigger, if the new box was outside of the box. + \param b: Other bounding box to add into this box. */ + void addInternalBox(const aabbox3d& b) + { + addInternalPoint(b.MaxEdge); + addInternalPoint(b.MinEdge); + } + + //! Adds a point to the bounding box + /** The box grows bigger, if point is outside of the box. + \param x X coordinate of the point to add to this box. + \param y Y coordinate of the point to add to this box. + \param z Z coordinate of the point to add to this box. */ + void addInternalPoint(T x, T y, T z) + { + if (x>MaxEdge.X) MaxEdge.X = x; + if (y>MaxEdge.Y) MaxEdge.Y = y; + if (z>MaxEdge.Z) MaxEdge.Z = z; + + if (x getCenter() const + { + return (MinEdge + MaxEdge) / 2; + } + + //! Get extent of the box (maximal distance of two points in the box) + /** \return Extent of the bounding box. */ + vector3d getExtent() const + { + return MaxEdge - MinEdge; + } + + //! Check if the box is empty. + /** This means that there is no space between the min and max edge. + \return True if box is empty, else false. */ + bool isEmpty() const + { + return MinEdge.equals ( MaxEdge ); + } + + //! Get the volume enclosed by the box in cubed units + T getVolume() const + { + const vector3d e = getExtent(); + return e.X * e.Y * e.Z; + } + + //! Get the surface area of the box in squared units + T getArea() const + { + const vector3d e = getExtent(); + return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); + } + + //! Stores all 8 edges of the box into an array + /** \param edges: Pointer to array of 8 edges. */ + void getEdges(vector3d *edges) const + { + const core::vector3d middle = getCenter(); + const core::vector3d diag = middle - MaxEdge; + + /* + Edges are stored in this way: + Hey, am I an ascii artist, or what? :) niko. + /3--------/7 + / | / | + / | / | + 1---------5 | + | /2- - -|- -6 + | / | / + |/ | / + 0---------4/ + */ + + edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + } + + //! Repairs the box. + /** Necessary if for example MinEdge and MaxEdge are swapped. */ + void repair() + { + T t; + + if (MinEdge.X > MaxEdge.X) + { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } + if (MinEdge.Y > MaxEdge.Y) + { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } + if (MinEdge.Z > MaxEdge.Z) + { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } + } + + //! Calculates a new interpolated bounding box. + /** d=0 returns other, d=1 returns this, all other values blend between + the two boxes. + \param other Other box to interpolate between + \param d Value between 0.0f and 1.0f. + \return Interpolated box. */ + aabbox3d getInterpolated(const aabbox3d& other, f32 d) const + { + f32 inv = 1.0f - d; + return aabbox3d((other.MinEdge*inv) + (MinEdge*d), + (other.MaxEdge*inv) + (MaxEdge*d)); + } + + //! Determines if a point is within this box. + /** Border is included (IS part of the box)! + \param p: Point to check. + \return True if the point is within the box and false if not */ + bool isPointInside(const vector3d& p) const + { + return (p.X >= MinEdge.X && p.X <= MaxEdge.X && + p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y && + p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z); + } + + //! Determines if a point is within this box and not its borders. + /** Border is excluded (NOT part of the box)! + \param p: Point to check. + \return True if the point is within the box and false if not. */ + bool isPointTotalInside(const vector3d& p) const + { + return (p.X > MinEdge.X && p.X < MaxEdge.X && + p.Y > MinEdge.Y && p.Y < MaxEdge.Y && + p.Z > MinEdge.Z && p.Z < MaxEdge.Z); + } + + //! Check if this box is completely inside the 'other' box. + /** \param other: Other box to check against. + \return True if this box is completly inside the other box, + otherwise false. */ + bool isFullInside(const aabbox3d& other) const + { + return (MinEdge.X >= other.MinEdge.X && MinEdge.Y >= other.MinEdge.Y && MinEdge.Z >= other.MinEdge.Z && + MaxEdge.X <= other.MaxEdge.X && MaxEdge.Y <= other.MaxEdge.Y && MaxEdge.Z <= other.MaxEdge.Z); + } + + //! Determines if the axis-aligned box intersects with another axis-aligned box. + /** \param other: Other box to check a intersection with. + \return True if there is an intersection with the other box, + otherwise false. */ + bool intersectsWithBox(const aabbox3d& other) const + { + return (MinEdge.X <= other.MaxEdge.X && MinEdge.Y <= other.MaxEdge.Y && MinEdge.Z <= other.MaxEdge.Z && + MaxEdge.X >= other.MinEdge.X && MaxEdge.Y >= other.MinEdge.Y && MaxEdge.Z >= other.MinEdge.Z); + } + + //! Tests if the box intersects with a line + /** \param line: Line to test intersection with. + \return True if there is an intersection , else false. */ + bool intersectsWithLine(const line3d& line) const + { + return intersectsWithLine(line.getMiddle(), line.getVector().normalize(), + (T)(line.getLength() * 0.5)); + } + + //! Tests if the box intersects with a line + /** \param linemiddle Center of the line. + \param linevect Vector of the line. + \param halflength Half length of the line. + \return True if there is an intersection, else false. */ + bool intersectsWithLine(const vector3d& linemiddle, + const vector3d& linevect, T halflength) const + { + const vector3d e = getExtent() * (T)0.5; + const vector3d t = getCenter() - linemiddle; + + if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) || + (fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) || + (fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) ) + return false; + + T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y); + if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r ) + return false; + + r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X); + if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r ) + return false; + + r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X); + if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r) + return false; + + return true; + } + + //! Classifies a relation with a plane. + /** \param plane Plane to classify relation to. + \return Returns ISREL3D_FRONT if the box is in front of the plane, + ISREL3D_BACK if the box is behind the plane, and + ISREL3D_CLIPPED if it is on both sides of the plane. */ + EIntersectionRelation3D classifyPlaneRelation(const plane3d& plane) const + { + vector3d nearPoint(MaxEdge); + vector3d farPoint(MinEdge); + + if (plane.Normal.X > (T)0) + { + nearPoint.X = MinEdge.X; + farPoint.X = MaxEdge.X; + } + + if (plane.Normal.Y > (T)0) + { + nearPoint.Y = MinEdge.Y; + farPoint.Y = MaxEdge.Y; + } + + if (plane.Normal.Z > (T)0) + { + nearPoint.Z = MinEdge.Z; + farPoint.Z = MaxEdge.Z; + } + + if (plane.Normal.dotProduct(nearPoint) + plane.D > (T)0) + return ISREL3D_FRONT; + + if (plane.Normal.dotProduct(farPoint) + plane.D > (T)0) + return ISREL3D_CLIPPED; + + return ISREL3D_BACK; + } + + //! The near edge + vector3d MinEdge; + + //! The far edge + vector3d MaxEdge; +}; + + //! Typedef for a f32 3d bounding box. + typedef aabbox3d aabbox3df; + //! Typedef for an integer 3d bounding box. + typedef aabbox3d aabbox3di; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/coreutil.h b/inc/coreutil.h new file mode 100644 index 0000000..eaf0097 --- /dev/null +++ b/inc/coreutil.h @@ -0,0 +1,188 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_CORE_UTIL_H_INCLUDED__ +#define __IRR_CORE_UTIL_H_INCLUDED__ + +#include "irrString.h" +#include "path.h" + +namespace irr +{ +namespace core +{ + +/*! \file coreutil.h + \brief File containing useful basic utility functions +*/ + +// ----------- some basic quite often used string functions ----------------- + +//! search if a filename has a proper extension +inline s32 isFileExtension ( const io::path& filename, + const io::path& ext0, + const io::path& ext1, + const io::path& ext2) +{ + s32 extPos = filename.findLast ( '.' ); + if ( extPos < 0 ) + return 0; + + extPos += 1; + if ( filename.equals_substring_ignore_case ( ext0, extPos ) ) return 1; + if ( filename.equals_substring_ignore_case ( ext1, extPos ) ) return 2; + if ( filename.equals_substring_ignore_case ( ext2, extPos ) ) return 3; + return 0; +} + +//! search if a filename has a proper extension +inline bool hasFileExtension ( const io::path& filename, + const io::path& ext0, + const io::path& ext1 = "", + const io::path& ext2 = "") +{ + return isFileExtension ( filename, ext0, ext1, ext2 ) > 0; +} + +//! cut the filename extension from a source file path and store it in a dest file path +inline io::path& cutFilenameExtension ( io::path &dest, const io::path &source ) +{ + s32 endPos = source.findLast ( '.' ); + dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); + return dest; +} + +//! get the filename extension from a file path +inline io::path& getFileNameExtension ( io::path &dest, const io::path &source ) +{ + s32 endPos = source.findLast ( '.' ); + if ( endPos < 0 ) + dest = ""; + else + dest = source.subString ( endPos, source.size () ); + return dest; +} + +//! delete path from filename +inline io::path& deletePathFromFilename(io::path& filename) +{ + // delete path from filename + const fschar_t* s = filename.c_str(); + const fschar_t* p = s + filename.size(); + + // search for path separator or beginning + while ( *p != '/' && *p != '\\' && p != s ) + p--; + + if ( p != s ) + { + ++p; + filename = p; + } + return filename; +} + +//! trim paths +inline io::path& deletePathFromPath(io::path& filename, s32 pathCount) +{ + // delete path from filename + s32 i = filename.size(); + + // search for path separator or beginning + while ( i>=0 ) + { + if ( filename[i] == '/' || filename[i] == '\\' ) + { + if ( --pathCount <= 0 ) + break; + } + --i; + } + + if ( i>0 ) + { + filename [ i + 1 ] = 0; + filename.validate(); + } + else + filename=""; + return filename; +} + +//! looks if file is in the same directory of path. returns offset of directory. +//! 0 means in same directory. 1 means file is direct child of path +inline s32 isInSameDirectory ( const io::path& path, const io::path& file ) +{ + s32 subA = 0; + s32 subB = 0; + s32 pos; + + if ( path.size() && !path.equalsn ( file, path.size() ) ) + return -1; + + pos = 0; + while ( (pos = path.findNext ( '/', pos )) >= 0 ) + { + subA += 1; + pos += 1; + } + + pos = 0; + while ( (pos = file.findNext ( '/', pos )) >= 0 ) + { + subB += 1; + pos += 1; + } + + return subB - subA; +} + +// splits a path into components +static inline void splitFilename(const io::path &name, io::path* path=0, + io::path* filename=0, io::path* extension=0, bool make_lower=false) +{ + s32 i = name.size(); + s32 extpos = i; + + // search for path separator or beginning + while ( i >= 0 ) + { + if ( name[i] == '.' ) + { + extpos = i; + if ( extension ) + *extension = name.subString ( extpos + 1, name.size() - (extpos + 1), make_lower ); + } + else + if ( name[i] == '/' || name[i] == '\\' ) + { + if ( filename ) + *filename = name.subString ( i + 1, extpos - (i + 1), make_lower ); + if ( path ) + { + *path = name.subString ( 0, i + 1, make_lower ); + path->replace ( '\\', '/' ); + } + return; + } + i -= 1; + } + if ( filename ) + *filename = name.subString ( 0, extpos, make_lower ); +} + + +//! some standard function ( to remove dependencies ) +#undef isdigit +#undef isspace +#undef isupper +inline s32 isdigit(s32 c) { return c >= '0' && c <= '9'; } +inline s32 isspace(s32 c) { return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; } +inline s32 isupper(s32 c) { return c >= 'A' && c <= 'Z'; } + + +} // end namespace core +} // end namespace irr + +#endif diff --git a/inc/dimension2d.h b/inc/dimension2d.h new file mode 100644 index 0000000..c9d0652 --- /dev/null +++ b/inc/dimension2d.h @@ -0,0 +1,224 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_DIMENSION2D_H_INCLUDED__ +#define __IRR_DIMENSION2D_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrMath.h" // for irr::core::equals() + +namespace irr +{ +namespace core +{ + template + class vector2d; + + //! Specifies a 2 dimensional size. + template + class dimension2d + { + public: + //! Default constructor for empty dimension + dimension2d() : Width(0), Height(0) {} + //! Constructor with width and height + dimension2d(const T& width, const T& height) + : Width(width), Height(height) {} + + dimension2d(const vector2d& other); // Defined in vector2d.h + + //! Use this constructor only where you are sure that the conversion is valid. + template + explicit dimension2d(const dimension2d& other) : + Width((T)other.Width), Height((T)other.Height) { } + + template + dimension2d& operator=(const dimension2d& other) + { + Width = (T) other.Width; + Height = (T) other.Height; + return *this; + } + + + //! Equality operator + bool operator==(const dimension2d& other) const + { + return core::equals(Width, other.Width) && + core::equals(Height, other.Height); + } + + //! Inequality operator + bool operator!=(const dimension2d& other) const + { + return ! (*this == other); + } + + bool operator==(const vector2d& other) const; // Defined in vector2d.h + + bool operator!=(const vector2d& other) const + { + return !(*this == other); + } + + //! Set to new values + dimension2d& set(const T& width, const T& height) + { + Width = width; + Height = height; + return *this; + } + + //! Divide width and height by scalar + dimension2d& operator/=(const T& scale) + { + Width /= scale; + Height /= scale; + return *this; + } + + //! Divide width and height by scalar + dimension2d operator/(const T& scale) const + { + return dimension2d(Width/scale, Height/scale); + } + + //! Multiply width and height by scalar + dimension2d& operator*=(const T& scale) + { + Width *= scale; + Height *= scale; + return *this; + } + + //! Multiply width and height by scalar + dimension2d operator*(const T& scale) const + { + return dimension2d(Width*scale, Height*scale); + } + + //! Add another dimension to this one. + dimension2d& operator+=(const dimension2d& other) + { + Width += other.Width; + Height += other.Height; + return *this; + } + + //! Add two dimensions + dimension2d operator+(const dimension2d& other) const + { + return dimension2d(Width+other.Width, Height+other.Height); + } + + //! Subtract a dimension from this one + dimension2d& operator-=(const dimension2d& other) + { + Width -= other.Width; + Height -= other.Height; + return *this; + } + + //! Subtract one dimension from another + dimension2d operator-(const dimension2d& other) const + { + return dimension2d(Width-other.Width, Height-other.Height); + } + + //! Get area + T getArea() const + { + return Width*Height; + } + + //! Get the optimal size according to some properties + /** This is a function often used for texture dimension + calculations. The function returns the next larger or + smaller dimension which is a power-of-two dimension + (2^n,2^m) and/or square (Width=Height). + \param requirePowerOfTwo Forces the result to use only + powers of two as values. + \param requireSquare Makes width==height in the result + \param larger Choose whether the result is larger or + smaller than the current dimension. If one dimension + need not be changed it is kept with any value of larger. + \param maxValue Maximum texturesize. if value > 0 size is + clamped to maxValue + \return The optimal dimension under the given + constraints. */ + dimension2d getOptimalSize( + bool requirePowerOfTwo=true, + bool requireSquare=false, + bool larger=true, + u32 maxValue = 0) const + { + u32 i=1; + u32 j=1; + if (requirePowerOfTwo) + { + while (i<(u32)Width) + i<<=1; + if (!larger && i!=1 && i!=(u32)Width) + i>>=1; + while (j<(u32)Height) + j<<=1; + if (!larger && j!=1 && j!=(u32)Height) + j>>=1; + } + else + { + i=(u32)Width; + j=(u32)Height; + } + + if (requireSquare) + { + if ((larger && (i>j)) || (!larger && (i 0 && i > maxValue) + i = maxValue; + + if ( maxValue > 0 && j > maxValue) + j = maxValue; + + return dimension2d((T)i,(T)j); + } + + //! Get the interpolated dimension + /** \param other Other dimension to interpolate with. + \param d Value between 0.0f and 1.0f. + \return Interpolated dimension. */ + dimension2d getInterpolated(const dimension2d& other, f32 d) const + { + f32 inv = (1.0f - d); + return dimension2d( (T)(other.Width*inv + Width*d), (T)(other.Height*inv + Height*d)); + } + + + //! Width of the dimension. + T Width; + //! Height of the dimension. + T Height; + }; + + //! Typedef for an f32 dimension. + typedef dimension2d dimension2df; + //! Typedef for an unsigned integer dimension. + typedef dimension2d dimension2du; + + //! Typedef for an integer dimension. + /** There are few cases where negative dimensions make sense. Please consider using + dimension2du instead. */ + typedef dimension2d dimension2di; + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/driverChoice.h b/inc/driverChoice.h new file mode 100644 index 0000000..8f17c38 --- /dev/null +++ b/inc/driverChoice.h @@ -0,0 +1,45 @@ +// Copyright (C) 2009-2012 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_DRIVER_CHOICE_H_INCLUDED__ +#define __E_DRIVER_CHOICE_H_INCLUDED__ + +#include +#include +#include "EDriverTypes.h" +#include "irrTypes.h" +#include "IrrlichtDevice.h" + +namespace irr +{ + +//! ask user for driver +static irr::video::E_DRIVER_TYPE driverChoiceConsole(bool allDrivers=true) +{ + const char* const names[] = {"NullDriver","Software Renderer","Burning's Video","Direct3D 8.1","Direct3D 9.0c","OpenGL 1.x/2.x/3.x"}; + printf("Please select the driver you want:\n"); + irr::u32 i=0; + for (i=irr::video::EDT_COUNT; i>0; --i) + { + if (allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1)))) + printf(" (%c) %s\n", 'a'+irr::video::EDT_COUNT-i, names[i-1]); + } + + char c; + std::cin >> c; + c = irr::video::EDT_COUNT+'a'-c; + + for (i=irr::video::EDT_COUNT; i>0; --i) + { + if (!(allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1))))) + --c; + if ((char)i==c) + return irr::video::E_DRIVER_TYPE(i-1); + } + return irr::video::EDT_COUNT; +} + +} // end namespace irr + +#endif diff --git a/inc/fast_atof.h b/inc/fast_atof.h new file mode 100644 index 0000000..d11f7b4 --- /dev/null +++ b/inc/fast_atof.h @@ -0,0 +1,364 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __FAST_ATOF_H_INCLUDED__ +#define __FAST_ATOF_H_INCLUDED__ + +#include "irrMath.h" +#include "irrString.h" + +namespace irr +{ +namespace core +{ + //! Selection of characters which count as decimal point in fast_atof + // TODO: This should probably also be used in irr::core::string, but the float-to-string code + // used there has to be rewritten first. + IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS; + +// we write [17] here instead of [] to work around a swig bug +const float fast_atof_table[17] = { + 0.f, + 0.1f, + 0.01f, + 0.001f, + 0.0001f, + 0.00001f, + 0.000001f, + 0.0000001f, + 0.00000001f, + 0.000000001f, + 0.0000000001f, + 0.00000000001f, + 0.000000000001f, + 0.0000000000001f, + 0.00000000000001f, + 0.000000000000001f, + 0.0000000000000001f +}; + +//! Convert a simple string of base 10 digits into an unsigned 32 bit integer. +/** \param[in] in: The string of digits to convert. No leading chars are + allowed, only digits 0 to 9. Parsing stops at the first non-digit. + \param[out] out: (optional) If provided, it will be set to point at the + first character not used in the calculation. + \return The unsigned integer value of the digits. If the string specifies + too many digits to encode in an u32 then INT_MAX will be returned. +*/ +inline u32 strtoul10(const char* in, const char** out=0) +{ + if (!in) + { + if (out) + *out = in; + return 0; + } + + bool overflow=false; + u32 unsignedValue = 0; + while ( ( *in >= '0') && ( *in <= '9' )) + { + const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' ); + if (tmp (u32)INT_MAX) + { + if (negative) + return (s32)INT_MIN; + else + return (s32)INT_MAX; + } + else + { + if (negative) + return -((s32)unsignedValue); + else + return (s32)unsignedValue; + } +} + +//! Convert a hex-encoded character to an unsigned integer. +/** \param[in] in The digit to convert. Only digits 0 to 9 and chars A-F,a-f + will be considered. + \return The unsigned integer value of the digit. 0xffffffff if the input is + not hex +*/ +inline u32 ctoul16(char in) +{ + if (in >= '0' && in <= '9') + return in - '0'; + else if (in >= 'a' && in <= 'f') + return 10u + in - 'a'; + else if (in >= 'A' && in <= 'F') + return 10u + in - 'A'; + else + return 0xffffffff; +} + +//! Convert a simple string of base 16 digits into an unsigned 32 bit integer. +/** \param[in] in: The string of digits to convert. No leading chars are + allowed, only digits 0 to 9 and chars A-F,a-f are allowed. Parsing stops + at the first illegal char. + \param[out] out: (optional) If provided, it will be set to point at the + first character not used in the calculation. + \return The unsigned integer value of the digits. If the string specifies + too many digits to encode in an u32 then INT_MAX will be returned. +*/ +inline u32 strtoul16(const char* in, const char** out=0) +{ + if (!in) + { + if (out) + *out = in; + return 0; + } + + bool overflow=false; + u32 unsignedValue = 0; + while (true) + { + u32 tmp = 0; + if ((*in >= '0') && (*in <= '9')) + tmp = (unsignedValue << 4u) + (*in - '0'); + else if ((*in >= 'A') && (*in <= 'F')) + tmp = (unsignedValue << 4u) + (*in - 'A') + 10; + else if ((*in >= 'a') && (*in <= 'f')) + tmp = (unsignedValue << 4u) + (*in - 'a') + 10; + else + break; + if (tmp= '0') && (*in <= '7')) + tmp = (unsignedValue << 3u) + (*in - '0'); + else + break; + if (tmp= '0') && ( *in <= '9' ) ) + { + // If it looks like we're going to overflow, bail out + // now and start using floating point. + if (intValue >= MAX_SAFE_U32_VALUE) + break; + + intValue = (intValue * 10) + (*in - '0'); + ++in; + } + + f32 floatValue = (f32)intValue; + + // If there are any digits left to parse, then we need to use + // floating point arithmetic from here. + while ( ( *in >= '0') && ( *in <= '9' ) ) + { + floatValue = (floatValue * 10.f) + (f32)(*in - '0'); + ++in; + if (floatValue > FLT_MAX) // Just give up. + break; + } + + if (out) + *out = in; + + return floatValue; +} + +//! Provides a fast function for converting a string into a float. +/** This is not guaranteed to be as accurate as atof(), but is + approximately 6 to 8 times as fast. + \param[in] in The string to convert. + \param[out] result The resultant float will be written here. + \return Pointer to the first character in the string that wasn't used + to create the float value. +*/ +inline const char* fast_atof_move(const char* in, f32& result) +{ + // Please run the regression test when making any modifications to this function. + + result = 0.f; + if (!in) + return 0; + + const bool negative = ('-' == *in); + if (negative || ('+'==*in)) + ++in; + + f32 value = strtof10(in, &in); + + if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 ) + { + const char* afterDecimal = ++in; + const f32 decimal = strtof10(in, &afterDecimal); + value += decimal * fast_atof_table[afterDecimal - in]; + in = afterDecimal; + } + + if ('e' == *in || 'E' == *in) + { + ++in; + // Assume that the exponent is a whole number. + // strtol10() will deal with both + and - signs, + // but calculate as f32 to prevent overflow at FLT_MAX + value *= powf(10.f, (f32)strtol10(in, &in)); + } + + result = negative?-value:value; + return in; +} + +//! Convert a string to a floating point number +/** \param floatAsString The string to convert. + \param out Optional pointer to the first character in the string that + wasn't used to create the float value. + \result Float value parsed from the input string +*/ +inline float fast_atof(const char* floatAsString, const char** out=0) +{ + float ret; + if (out) + *out=fast_atof_move(floatAsString, ret); + else + fast_atof_move(floatAsString, ret); + return ret; +} + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/heapsort.h b/inc/heapsort.h new file mode 100644 index 0000000..a2e2c38 --- /dev/null +++ b/inc/heapsort.h @@ -0,0 +1,70 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_HEAPSORT_H_INCLUDED__ +#define __IRR_HEAPSORT_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Sinks an element into the heap. +template +inline void heapsink(T*array, s32 element, s32 max) +{ + while ((element<<1) < max) // there is a left child + { + s32 j = (element<<1); + + if (j+1 < max && array[j] < array[j+1]) + j = j+1; // take right child + + if (array[element] < array[j]) + { + T t = array[j]; // swap elements + array[j] = array[element]; + array[element] = t; + element = j; + } + else + return; + } +} + + +//! Sorts an array with size 'size' using heapsort. +template +inline void heapsort(T* array_, s32 size) +{ + // for heapsink we pretent this is not c++, where + // arrays start with index 0. So we decrease the array pointer, + // the maximum always +2 and the element always +1 + + T* virtualArray = array_ - 1; + s32 virtualSize = size + 2; + s32 i; + + // build heap + + for (i=((size-1)/2); i>=0; --i) + heapsink(virtualArray, i+1, virtualSize-1); + + // sort array, leave out the last element (0) + for (i=size-1; i>0; --i) + { + T t = array_[0]; + array_[0] = array_[i]; + array_[i] = t; + heapsink(virtualArray, 1, i + 1); + } +} + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/irrAllocator.h b/inc/irrAllocator.h new file mode 100644 index 0000000..8a80359 --- /dev/null +++ b/inc/irrAllocator.h @@ -0,0 +1,124 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_ALLOCATOR_H_INCLUDED__ +#define __IRR_ALLOCATOR_H_INCLUDED__ + +#include "irrTypes.h" +#include +// necessary for older compilers +#include + +namespace irr +{ +namespace core +{ + +#ifdef DEBUG_CLIENTBLOCK +#undef DEBUG_CLIENTBLOCK +#define DEBUG_CLIENTBLOCK new +#endif + +//! Very simple allocator implementation, containers using it can be used across dll boundaries +template +class irrAllocator +{ +public: + + //! Destructor + virtual ~irrAllocator() {} + + //! Allocate memory for an array of objects + T* allocate(size_t cnt) + { + return (T*)internal_new(cnt* sizeof(T)); + } + + //! Deallocate memory for an array of objects + void deallocate(T* ptr) + { + internal_delete(ptr); + } + + //! Construct an element + void construct(T* ptr, const T&e) + { + new ((void*)ptr) T(e); + } + + //! Destruct an element + void destruct(T* ptr) + { + ptr->~T(); + } + +protected: + + virtual void* internal_new(size_t cnt) + { + return operator new(cnt); + } + + virtual void internal_delete(void* ptr) + { + operator delete(ptr); + } + +}; + + +//! Fast allocator, only to be used in containers inside the same memory heap. +/** Containers using it are NOT able to be used it across dll boundaries. Use this +when using in an internal class or function or when compiled into a static lib */ +template +class irrAllocatorFast +{ +public: + + //! Allocate memory for an array of objects + T* allocate(size_t cnt) + { + return (T*)operator new(cnt* sizeof(T)); + } + + //! Deallocate memory for an array of objects + void deallocate(T* ptr) + { + operator delete(ptr); + } + + //! Construct an element + void construct(T* ptr, const T&e) + { + new ((void*)ptr) T(e); + } + + //! Destruct an element + void destruct(T* ptr) + { + ptr->~T(); + } +}; + + + +#ifdef DEBUG_CLIENTBLOCK +#undef DEBUG_CLIENTBLOCK +#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) +#endif + +//! defines an allocation strategy +enum eAllocStrategy +{ + ALLOC_STRATEGY_SAFE = 0, + ALLOC_STRATEGY_DOUBLE = 1, + ALLOC_STRATEGY_SQRT = 2 +}; + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/irrArray.h b/inc/irrArray.h new file mode 100644 index 0000000..f9d338d --- /dev/null +++ b/inc/irrArray.h @@ -0,0 +1,627 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_ARRAY_H_INCLUDED__ +#define __IRR_ARRAY_H_INCLUDED__ + +#include "irrTypes.h" +#include "heapsort.h" +#include "irrAllocator.h" +#include "irrMath.h" + +namespace irr +{ +namespace core +{ + +//! Self reallocating template array (like stl vector) with additional features. +/** Some features are: Heap sorting, binary search methods, easier debugging. +*/ +template > +class array +{ + +public: + + //! Default constructor for empty array. + array() + : data(0), allocated(0), used(0), + strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) + { + } + + + //! Constructs an array and allocates an initial chunk of memory. + /** \param start_count Amount of elements to pre-allocate. */ + array(u32 start_count) + : data(0), allocated(0), used(0), + strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) + { + reallocate(start_count); + } + + + //! Copy constructor + array(const array& other) : data(0) + { + *this = other; + } + + + //! Destructor. + /** Frees allocated memory, if set_free_when_destroyed was not set to + false by the user before. */ + ~array() + { + clear(); + } + + + //! Reallocates the array, make it bigger or smaller. + /** \param new_size New size of array. + \param canShrink Specifies whether the array is reallocated even if + enough space is available. Setting this flag to false can speed up + array usage, but may use more memory than required by the data. + */ + void reallocate(u32 new_size, bool canShrink=true) + { + if (allocated==new_size) + return; + if (!canShrink && (new_size < allocated)) + return; + + T* old_data = data; + + data = allocator.allocate(new_size); //new T[new_size]; + allocated = new_size; + + // copy old data + s32 end = used < new_size ? used : new_size; + + for (s32 i=0; iused) // access violation + + if (used + 1 > allocated) + { + // this doesn't work if the element is in the same + // array. So we'll copy the element first to be sure + // we'll get no data corruption + const T e(element); + + // increase data block + u32 newAlloc; + switch ( strategy ) + { + case ALLOC_STRATEGY_DOUBLE: + newAlloc = used + 1 + (allocated < 500 ? + (allocated < 5 ? 5 : used) : used >> 2); + break; + default: + case ALLOC_STRATEGY_SAFE: + newAlloc = used + 1; + break; + } + reallocate( newAlloc); + + // move array content and construct new element + // first move end one up + for (u32 i=used; i>index; --i) + { + if (i index) + allocator.destruct(&data[index]); + allocator.construct(&data[index], e); // data[index] = e; + } + else + { + // element inserted not at end + if ( used > index ) + { + // create one new element at the end + allocator.construct(&data[used], data[used-1]); + + // move the rest of the array content + for (u32 i=used-1; i>index; --i) + { + data[i] = data[i-1]; + } + // insert the new element + data[index] = element; + } + else + { + // insert the new element to the end + allocator.construct(&data[index], element); + } + } + // set to false as we don't know if we have the comparison operators + is_sorted = false; + ++used; + } + + + //! Clears the array and deletes all allocated memory. + void clear() + { + if (free_when_destroyed) + { + for (u32 i=0; i& operator=(const array& other) + { + if (this == &other) + return *this; + strategy = other.strategy; + + if (data) + clear(); + + //if (allocated < other.allocated) + if (other.allocated == 0) + data = 0; + else + data = allocator.allocate(other.allocated); // new T[other.allocated]; + + used = other.used; + free_when_destroyed = true; + is_sorted = other.is_sorted; + allocated = other.allocated; + + for (u32 i=0; i& other) const + { + if (used != other.used) + return false; + + for (u32 i=0; i& other) const + { + return !(*this==other); + } + + + //! Direct access operator + T& operator [](u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + + //! Direct const access operator + const T& operator [](u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + + //! Gets last element. + T& getLast() + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + + //! Gets last element + const T& getLast() const + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + + //! Gets a pointer to the array. + /** \return Pointer to the array. */ + T* pointer() + { + return data; + } + + + //! Gets a const pointer to the array. + /** \return Pointer to the array. */ + const T* const_pointer() const + { + return data; + } + + + //! Get number of occupied elements of the array. + /** \return Size of elements in the array which are actually occupied. */ + u32 size() const + { + return used; + } + + + //! Get amount of memory allocated. + /** \return Amount of memory allocated. The amount of bytes + allocated would be allocated_size() * sizeof(ElementTypeUsed); */ + u32 allocated_size() const + { + return allocated; + } + + + //! Check if array is empty. + /** \return True if the array is empty false if not. */ + bool empty() const + { + return used == 0; + } + + + //! Sorts the array using heapsort. + /** There is no additional memory waste and the algorithm performs + O(n*log n) in worst case. */ + void sort() + { + if (!is_sorted && used>1) + heapsort(data, used); + is_sorted = true; + } + + + //! Performs a binary search for an element, returns -1 if not found. + /** The array will be sorted before the binary search if it is not + already sorted. Caution is advised! Be careful not to call this on + unsorted const arrays, or the slower method will be used. + \param element Element to search for. + \return Position of the searched element if it was found, + otherwise -1 is returned. */ + s32 binary_search(const T& element) + { + sort(); + return binary_search(element, 0, used-1); + } + + + //! Performs a binary search for an element if possible, returns -1 if not found. + /** This method is for const arrays and so cannot call sort(), if the array is + not sorted then linear_search will be used instead. Potentially very slow! + \param element Element to search for. + \return Position of the searched element if it was found, + otherwise -1 is returned. */ + s32 binary_search(const T& element) const + { + if (is_sorted) + return binary_search(element, 0, used-1); + else + return linear_search(element); + } + + + //! Performs a binary search for an element, returns -1 if not found. + /** \param element: Element to search for. + \param left First left index + \param right Last right index. + \return Position of the searched element if it was found, otherwise -1 + is returned. */ + s32 binary_search(const T& element, s32 left, s32 right) const + { + if (!used) + return -1; + + s32 m; + + do + { + m = (left+right)>>1; + + if (element < data[m]) + right = m - 1; + else + left = m + 1; + + } while((element < data[m] || data[m] < element) && left<=right); + // this last line equals to: + // " while((element != array[m]) && left<=right);" + // but we only want to use the '<' operator. + // the same in next line, it is "(element == array[m])" + + + if (!(element < data[m]) && !(data[m] < element)) + return m; + + return -1; + } + + + //! Performs a binary search for an element, returns -1 if not found. + //! it is used for searching a multiset + /** The array will be sorted before the binary search if it is not + already sorted. + \param element Element to search for. + \param &last return lastIndex of equal elements + \return Position of the first searched element if it was found, + otherwise -1 is returned. */ + s32 binary_search_multi(const T& element, s32 &last) + { + sort(); + s32 index = binary_search(element, 0, used-1); + if ( index < 0 ) + return index; + + // The search can be somewhere in the middle of the set + // look linear previous and past the index + last = index; + + while ( index > 0 && !(element < data[index - 1]) && !(data[index - 1] < element) ) + { + index -= 1; + } + // look linear up + while ( last < (s32) used - 1 && !(element < data[last + 1]) && !(data[last + 1] < element) ) + { + last += 1; + } + + return index; + } + + + //! Finds an element in linear time, which is very slow. + /** Use binary_search for faster finding. Only works if ==operator is + implemented. + \param element Element to search for. + \return Position of the searched element if it was found, otherwise -1 + is returned. */ + s32 linear_search(const T& element) const + { + for (u32 i=0; i=0; --i) + if (data[i] == element) + return i; + + return -1; + } + + + //! Erases an element from the array. + /** May be slow, because all elements following after the erased + element have to be copied. + \param index: Index of element to be erased. */ + void erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + for (u32 i=index+1; i=used || count<1) + return; + if (index+count>used) + count = used-index; + + u32 i; + for (i=index; i= index+count) // not already destructed before loop + allocator.destruct(&data[i-count]); + + allocator.construct(&data[i-count], data[i]); // data[i-count] = data[i]; + + if (i >= used-count) // those which are not overwritten + allocator.destruct(&data[i]); + } + + used-= count; + } + + + //! Sets if the array is sorted + void set_sorted(bool _is_sorted) + { + is_sorted = _is_sorted; + } + + + //! Swap the content of this array container with the content of another array + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. + \param other Swap content with this object */ + void swap(array& other) + { + core::swap(data, other.data); + core::swap(allocated, other.allocated); + core::swap(used, other.used); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + eAllocStrategy helper_strategy(strategy); // can't use core::swap with bitfields + strategy = other.strategy; + other.strategy = helper_strategy; + bool helper_free_when_destroyed(free_when_destroyed); + free_when_destroyed = other.free_when_destroyed; + other.free_when_destroyed = helper_free_when_destroyed; + bool helper_is_sorted(is_sorted); + is_sorted = other.is_sorted; + other.is_sorted = helper_is_sorted; + } + + +private: + T* data; + u32 allocated; + u32 used; + TAlloc allocator; + eAllocStrategy strategy:4; + bool free_when_destroyed:1; + bool is_sorted:1; +}; + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/irrList.h b/inc/irrList.h new file mode 100644 index 0000000..a84afd5 --- /dev/null +++ b/inc/irrList.h @@ -0,0 +1,416 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_LIST_H_INCLUDED__ +#define __IRR_LIST_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrAllocator.h" +#include "irrMath.h" + +namespace irr +{ +namespace core +{ + + +//! Doubly linked list template. +template +class list +{ +private: + + //! List element node with pointer to previous and next element in the list. + struct SKListNode + { + SKListNode(const T& e) : Next(0), Prev(0), Element(e) {} + + SKListNode* Next; + SKListNode* Prev; + T Element; + }; + +public: + class ConstIterator; + + //! List iterator. + class Iterator + { + public: + Iterator() : Current(0) {} + + Iterator& operator ++() { Current = Current->Next; return *this; } + Iterator& operator --() { Current = Current->Prev; return *this; } + Iterator operator ++(s32) { Iterator tmp = *this; Current = Current->Next; return tmp; } + Iterator operator --(s32) { Iterator tmp = *this; Current = Current->Prev; return tmp; } + + Iterator& operator +=(s32 num) + { + if(num > 0) + { + while (num-- && this->Current != 0) ++(*this); + } + else + { + while(num++ && this->Current != 0) --(*this); + } + return *this; + } + + Iterator operator + (s32 num) const { Iterator tmp = *this; return tmp += num; } + Iterator& operator -=(s32 num) { return (*this)+=(-num); } + Iterator operator - (s32 num) const { return (*this)+ (-num); } + + bool operator ==(const Iterator& other) const { return Current == other.Current; } + bool operator !=(const Iterator& other) const { return Current != other.Current; } + bool operator ==(const ConstIterator& other) const { return Current == other.Current; } + bool operator !=(const ConstIterator& other) const { return Current != other.Current; } + + #if defined (_MSC_VER) && (_MSC_VER < 1300) + #pragma warning(disable:4284) // infix notation problem when using iterator operator -> + #endif + + T & operator * () { return Current->Element; } + T * operator ->() { return &Current->Element; } + + private: + explicit Iterator(SKListNode* begin) : Current(begin) {} + + SKListNode* Current; + + friend class list; + friend class ConstIterator; + }; + + //! List iterator for const access. + class ConstIterator + { + public: + + ConstIterator() : Current(0) {} + ConstIterator(const Iterator& iter) : Current(iter.Current) {} + + ConstIterator& operator ++() { Current = Current->Next; return *this; } + ConstIterator& operator --() { Current = Current->Prev; return *this; } + ConstIterator operator ++(s32) { ConstIterator tmp = *this; Current = Current->Next; return tmp; } + ConstIterator operator --(s32) { ConstIterator tmp = *this; Current = Current->Prev; return tmp; } + + ConstIterator& operator +=(s32 num) + { + if(num > 0) + { + while(num-- && this->Current != 0) ++(*this); + } + else + { + while(num++ && this->Current != 0) --(*this); + } + return *this; + } + + ConstIterator operator + (s32 num) const { ConstIterator tmp = *this; return tmp += num; } + ConstIterator& operator -=(s32 num) { return (*this)+=(-num); } + ConstIterator operator - (s32 num) const { return (*this)+ (-num); } + + bool operator ==(const ConstIterator& other) const { return Current == other.Current; } + bool operator !=(const ConstIterator& other) const { return Current != other.Current; } + bool operator ==(const Iterator& other) const { return Current == other.Current; } + bool operator !=(const Iterator& other) const { return Current != other.Current; } + + const T & operator * () { return Current->Element; } + const T * operator ->() { return &Current->Element; } + + ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; } + + private: + explicit ConstIterator(SKListNode* begin) : Current(begin) {} + + SKListNode* Current; + + friend class Iterator; + friend class list; + }; + + //! Default constructor for empty list. + list() + : First(0), Last(0), Size(0) {} + + + //! Copy constructor. + list(const list& other) : First(0), Last(0), Size(0) + { + *this = other; + } + + + //! Destructor + ~list() + { + clear(); + } + + + //! Assignment operator + void operator=(const list& other) + { + if(&other == this) + { + return; + } + + clear(); + + SKListNode* node = other.First; + while(node) + { + push_back(node->Element); + node = node->Next; + } + } + + + //! Returns amount of elements in list. + /** \return Amount of elements in the list. */ + u32 size() const + { + return Size; + } + u32 getSize() const + { + return Size; + } + + + //! Clears the list, deletes all elements in the list. + /** All existing iterators of this list will be invalid. */ + void clear() + { + while(First) + { + SKListNode * next = First->Next; + allocator.destruct(First); + allocator.deallocate(First); + First = next; + } + + //First = 0; handled by loop + Last = 0; + Size = 0; + } + + + //! Checks for empty list. + /** \return True if the list is empty and false if not. */ + bool empty() const + { + return (First == 0); + } + + + //! Adds an element at the end of the list. + /** \param element Element to add to the list. */ + void push_back(const T& element) + { + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); + + ++Size; + + if (First == 0) + First = node; + + node->Prev = Last; + + if (Last != 0) + Last->Next = node; + + Last = node; + } + + + //! Adds an element at the begin of the list. + /** \param element: Element to add to the list. */ + void push_front(const T& element) + { + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); + + ++Size; + + if (First == 0) + { + Last = node; + First = node; + } + else + { + node->Next = First; + First->Prev = node; + First = node; + } + } + + + //! Gets first node. + /** \return A list iterator pointing to the beginning of the list. */ + Iterator begin() + { + return Iterator(First); + } + + + //! Gets first node. + /** \return A const list iterator pointing to the beginning of the list. */ + ConstIterator begin() const + { + return ConstIterator(First); + } + + + //! Gets end node. + /** \return List iterator pointing to null. */ + Iterator end() + { + return Iterator(0); + } + + + //! Gets end node. + /** \return Const list iterator pointing to null. */ + ConstIterator end() const + { + return ConstIterator(0); + } + + + //! Gets last element. + /** \return List iterator pointing to the last element of the list. */ + Iterator getLast() + { + return Iterator(Last); + } + + + //! Gets last element. + /** \return Const list iterator pointing to the last element of the list. */ + ConstIterator getLast() const + { + return ConstIterator(Last); + } + + + //! Inserts an element after an element. + /** \param it Iterator pointing to element after which the new element + should be inserted. + \param element The new element to be inserted into the list. + */ + void insert_after(const Iterator& it, const T& element) + { + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); + + node->Next = it.Current->Next; + + if (it.Current->Next) + it.Current->Next->Prev = node; + + node->Prev = it.Current; + it.Current->Next = node; + ++Size; + + if (it.Current == Last) + Last = node; + } + + + //! Inserts an element before an element. + /** \param it Iterator pointing to element before which the new element + should be inserted. + \param element The new element to be inserted into the list. + */ + void insert_before(const Iterator& it, const T& element) + { + SKListNode* node = allocator.allocate(1); + allocator.construct(node, element); + + node->Prev = it.Current->Prev; + + if (it.Current->Prev) + it.Current->Prev->Next = node; + + node->Next = it.Current; + it.Current->Prev = node; + ++Size; + + if (it.Current == First) + First = node; + } + + + //! Erases an element. + /** \param it Iterator pointing to the element which shall be erased. + \return Iterator pointing to next element. */ + Iterator erase(Iterator& it) + { + // suggest changing this to a const Iterator& and + // working around line: it.Current = 0 (possibly with a mutable, or just let it be garbage?) + + Iterator returnIterator(it); + ++returnIterator; + + if(it.Current == First) + { + First = it.Current->Next; + } + else + { + it.Current->Prev->Next = it.Current->Next; + } + + if(it.Current == Last) + { + Last = it.Current->Prev; + } + else + { + it.Current->Next->Prev = it.Current->Prev; + } + + allocator.destruct(it.Current); + allocator.deallocate(it.Current); + it.Current = 0; + --Size; + + return returnIterator; + } + + //! Swap the content of this list container with the content of another list + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(list& other) + { + core::swap(First, other.First); + core::swap(Last, other.Last); + core::swap(Size, other.Size); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + } + + +private: + + SKListNode* First; + SKListNode* Last; + u32 Size; + irrAllocator allocator; + +}; + + +} // end namespace core +}// end namespace irr + +#endif + diff --git a/inc/irrMap.h b/inc/irrMap.h new file mode 100644 index 0000000..6e15174 --- /dev/null +++ b/inc/irrMap.h @@ -0,0 +1,1127 @@ +// Copyright (C) 2006-2012 by Kat'Oun +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_MAP_H_INCLUDED__ +#define __IRR_MAP_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrMath.h" + +namespace irr +{ +namespace core +{ + +//! map template for associative arrays using a red-black tree +template +class map +{ + //! red/black tree for map + template + class RBTree + { + public: + + RBTree(const KeyTypeRB& k, const ValueTypeRB& v) + : LeftChild(0), RightChild(0), Parent(0), Key(k), + Value(v), IsRed(true) {} + + void setLeftChild(RBTree* p) + { + LeftChild=p; + if (p) + p->setParent(this); + } + + void setRightChild(RBTree* p) + { + RightChild=p; + if (p) + p->setParent(this); + } + + void setParent(RBTree* p) { Parent=p; } + + void setValue(const ValueTypeRB& v) { Value = v; } + + void setRed() { IsRed = true; } + void setBlack() { IsRed = false; } + + RBTree* getLeftChild() const { return LeftChild; } + RBTree* getRightChild() const { return RightChild; } + RBTree* getParent() const { return Parent; } + + const ValueTypeRB& getValue() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Value; + } + + ValueTypeRB& getValue() + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Value; + } + + const KeyTypeRB& getKey() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Key; + } + + bool isRoot() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Parent==0; + } + + bool isLeftChild() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return (Parent != 0) && (Parent->getLeftChild()==this); + } + + bool isRightChild() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return (Parent!=0) && (Parent->getRightChild()==this); + } + + bool isLeaf() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return (LeftChild==0) && (RightChild==0); + } + + unsigned int getLevel() const + { + if (isRoot()) + return 1; + else + return getParent()->getLevel() + 1; + } + + + bool isRed() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return IsRed; + } + + bool isBlack() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return !IsRed; + } + + private: + RBTree(); + + RBTree* LeftChild; + RBTree* RightChild; + + RBTree* Parent; + + KeyTypeRB Key; + ValueTypeRB Value; + + bool IsRed; + }; // RBTree + + public: + + typedef RBTree Node; + // We need the forwad declaration for the friend declaration + class ConstIterator; + + //! Normal Iterator + class Iterator + { + friend class ConstIterator; + public: + + Iterator() : Root(0), Cur(0) {} + + // Constructor(Node*) + Iterator(Node* root) : Root(root) + { + reset(); + } + + // Copy constructor + Iterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {} + + void reset(bool atLowest=true) + { + if (atLowest) + Cur = getMin(Root); + else + Cur = getMax(Root); + } + + bool atEnd() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Cur==0; + } + + Node* getNode() const + { + return Cur; + } + + Iterator& operator=(const Iterator& src) + { + Root = src.Root; + Cur = src.Cur; + return (*this); + } + + void operator++(int) + { + inc(); + } + + void operator--(int) + { + dec(); + } + + Node* operator->() + { + return getNode(); + } + + Node& operator*() + { + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + + return *Cur; + } + + private: + + Node* getMin(Node* n) const + { + while(n && n->getLeftChild()) + n = n->getLeftChild(); + return n; + } + + Node* getMax(Node* n) const + { + while(n && n->getRightChild()) + n = n->getRightChild(); + return n; + } + + void inc() + { + // Already at end? + if (Cur==0) + return; + + if (Cur->getRightChild()) + { + // If current node has a right child, the next higher node is the + // node with lowest key beneath the right child. + Cur = getMin(Cur->getRightChild()); + } + else if (Cur->isLeftChild()) + { + // No right child? Well if current node is a left child then + // the next higher node is the parent + Cur = Cur->getParent(); + } + else + { + // Current node neither is left child nor has a right child. + // Ie it is either right child or root + // The next higher node is the parent of the first non-right + // child (ie either a left child or the root) up in the + // hierarchy. Root's parent is 0. + while(Cur->isRightChild()) + Cur = Cur->getParent(); + Cur = Cur->getParent(); + } + } + + void dec() + { + // Already at end? + if (Cur==0) + return; + + if (Cur->getLeftChild()) + { + // If current node has a left child, the next lower node is the + // node with highest key beneath the left child. + Cur = getMax(Cur->getLeftChild()); + } + else if (Cur->isRightChild()) + { + // No left child? Well if current node is a right child then + // the next lower node is the parent + Cur = Cur->getParent(); + } + else + { + // Current node neither is right child nor has a left child. + // Ie it is either left child or root + // The next higher node is the parent of the first non-left + // child (ie either a right child or the root) up in the + // hierarchy. Root's parent is 0. + + while(Cur->isLeftChild()) + Cur = Cur->getParent(); + Cur = Cur->getParent(); + } + } + + Node* Root; + Node* Cur; + }; // Iterator + + //! Const Iterator + class ConstIterator + { + friend class Iterator; + public: + + ConstIterator() : Root(0), Cur(0) {} + + // Constructor(Node*) + ConstIterator(const Node* root) : Root(root) + { + reset(); + } + + // Copy constructor + ConstIterator(const ConstIterator& src) : Root(src.Root), Cur(src.Cur) {} + ConstIterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {} + + void reset(bool atLowest=true) + { + if (atLowest) + Cur = getMin(Root); + else + Cur = getMax(Root); + } + + bool atEnd() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Cur==0; + } + + const Node* getNode() const + { + return Cur; + } + + ConstIterator& operator=(const ConstIterator& src) + { + Root = src.Root; + Cur = src.Cur; + return (*this); + } + + void operator++(int) + { + inc(); + } + + void operator--(int) + { + dec(); + } + + const Node* operator->() + { + return getNode(); + } + + const Node& operator*() + { + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + + return *Cur; + } + + private: + + const Node* getMin(const Node* n) const + { + while(n && n->getLeftChild()) + n = n->getLeftChild(); + return n; + } + + const Node* getMax(const Node* n) const + { + while(n && n->getRightChild()) + n = n->getRightChild(); + return n; + } + + void inc() + { + // Already at end? + if (Cur==0) + return; + + if (Cur->getRightChild()) + { + // If current node has a right child, the next higher node is the + // node with lowest key beneath the right child. + Cur = getMin(Cur->getRightChild()); + } + else if (Cur->isLeftChild()) + { + // No right child? Well if current node is a left child then + // the next higher node is the parent + Cur = Cur->getParent(); + } + else + { + // Current node neither is left child nor has a right child. + // Ie it is either right child or root + // The next higher node is the parent of the first non-right + // child (ie either a left child or the root) up in the + // hierarchy. Root's parent is 0. + while(Cur->isRightChild()) + Cur = Cur->getParent(); + Cur = Cur->getParent(); + } + } + + void dec() + { + // Already at end? + if (Cur==0) + return; + + if (Cur->getLeftChild()) + { + // If current node has a left child, the next lower node is the + // node with highest key beneath the left child. + Cur = getMax(Cur->getLeftChild()); + } + else if (Cur->isRightChild()) + { + // No left child? Well if current node is a right child then + // the next lower node is the parent + Cur = Cur->getParent(); + } + else + { + // Current node neither is right child nor has a left child. + // Ie it is either left child or root + // The next higher node is the parent of the first non-left + // child (ie either a right child or the root) up in the + // hierarchy. Root's parent is 0. + + while(Cur->isLeftChild()) + Cur = Cur->getParent(); + Cur = Cur->getParent(); + } + } + + const Node* Root; + const Node* Cur; + }; // ConstIterator + + + //! Parent First Iterator. + /** Traverses the tree from top to bottom. Typical usage is + when storing the tree structure, because when reading it + later (and inserting elements) the tree structure will + be the same. */ + class ParentFirstIterator + { + public: + + ParentFirstIterator() : Root(0), Cur(0) {} + + explicit ParentFirstIterator(Node* root) : Root(root), Cur(0) + { + reset(); + } + + void reset() + { + Cur = Root; + } + + bool atEnd() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Cur==0; + } + + Node* getNode() + { + return Cur; + } + + ParentFirstIterator& operator=(const ParentFirstIterator& src) + { + Root = src.Root; + Cur = src.Cur; + return (*this); + } + + void operator++(int) + { + inc(); + } + + Node* operator -> () + { + return getNode(); + } + + Node& operator* () + { + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + + return *getNode(); + } + + private: + + void inc() + { + // Already at end? + if (Cur==0) + return; + + // First we try down to the left + if (Cur->getLeftChild()) + { + Cur = Cur->getLeftChild(); + } + else if (Cur->getRightChild()) + { + // No left child? The we go down to the right. + Cur = Cur->getRightChild(); + } + else + { + // No children? Move up in the hierarcy until + // we either reach 0 (and are finished) or + // find a right uncle. + while (Cur!=0) + { + // But if parent is left child and has a right "uncle" the parent + // has already been processed but the uncle hasn't. Move to + // the uncle. + if (Cur->isLeftChild() && Cur->getParent()->getRightChild()) + { + Cur = Cur->getParent()->getRightChild(); + return; + } + Cur = Cur->getParent(); + } + } + } + + Node* Root; + Node* Cur; + + }; // ParentFirstIterator + + + //! Parent Last Iterator + /** Traverse the tree from bottom to top. + Typical usage is when deleting all elements in the tree + because you must delete the children before you delete + their parent. */ + class ParentLastIterator + { + public: + + ParentLastIterator() : Root(0), Cur(0) {} + + explicit ParentLastIterator(Node* root) : Root(root), Cur(0) + { + reset(); + } + + void reset() + { + Cur = getMin(Root); + } + + bool atEnd() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Cur==0; + } + + Node* getNode() + { + return Cur; + } + + ParentLastIterator& operator=(const ParentLastIterator& src) + { + Root = src.Root; + Cur = src.Cur; + return (*this); + } + + void operator++(int) + { + inc(); + } + + Node* operator -> () + { + return getNode(); + } + + Node& operator* () + { + _IRR_DEBUG_BREAK_IF(atEnd()) // access violation + + return *getNode(); + } + private: + + Node* getMin(Node* n) + { + while(n!=0 && (n->getLeftChild()!=0 || n->getRightChild()!=0)) + { + if (n->getLeftChild()) + n = n->getLeftChild(); + else + n = n->getRightChild(); + } + return n; + } + + void inc() + { + // Already at end? + if (Cur==0) + return; + + // Note: Starting point is the node as far down to the left as possible. + + // If current node has an uncle to the right, go to the + // node as far down to the left from the uncle as possible + // else just go up a level to the parent. + if (Cur->isLeftChild() && Cur->getParent()->getRightChild()) + { + Cur = getMin(Cur->getParent()->getRightChild()); + } + else + Cur = Cur->getParent(); + } + + Node* Root; + Node* Cur; + }; // ParentLastIterator + + + // AccessClass is a temporary class used with the [] operator. + // It makes it possible to have different behavior in situations like: + // myTree["Foo"] = 32; + // If "Foo" already exists update its value else insert a new element. + // int i = myTree["Foo"] + // If "Foo" exists return its value. + class AccessClass + { + // Let map be the only one who can instantiate this class. + friend class map; + + public: + + // Assignment operator. Handles the myTree["Foo"] = 32; situation + void operator=(const ValueType& value) + { + // Just use the Set method, it handles already exist/not exist situation + Tree.set(Key,value); + } + + // ValueType operator + operator ValueType() + { + Node* node = Tree.find(Key); + + // Not found + _IRR_DEBUG_BREAK_IF(node==0) // access violation + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return node->getValue(); + } + + private: + + AccessClass(map& tree, const KeyType& key) : Tree(tree), Key(key) {} + + AccessClass(); + + map& Tree; + const KeyType& Key; + }; // AccessClass + + + // Constructor. + map() : Root(0), Size(0) {} + + // Destructor + ~map() + { + clear(); + } + + //------------------------------ + // Public Commands + //------------------------------ + + //! Inserts a new node into the tree + /** \param keyNew: the index for this value + \param v: the value to insert + \return True if successful, false if it fails (already exists) */ + bool insert(const KeyType& keyNew, const ValueType& v) + { + // First insert node the "usual" way (no fancy balance logic yet) + Node* newNode = new Node(keyNew,v); + if (!insert(newNode)) + { + delete newNode; + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + // Then attend a balancing party + while (!newNode->isRoot() && (newNode->getParent()->isRed())) + { + if (newNode->getParent()->isLeftChild()) + { + // If newNode is a left child, get its right 'uncle' + Node* newNodesUncle = newNode->getParent()->getParent()->getRightChild(); + if ( newNodesUncle!=0 && newNodesUncle->isRed()) + { + // case 1 - change the colors + newNode->getParent()->setBlack(); + newNodesUncle->setBlack(); + newNode->getParent()->getParent()->setRed(); + // Move newNode up the tree + newNode = newNode->getParent()->getParent(); + } + else + { + // newNodesUncle is a black node + if ( newNode->isRightChild()) + { + // and newNode is to the right + // case 2 - move newNode up and rotate + newNode = newNode->getParent(); + rotateLeft(newNode); + } + // case 3 + newNode->getParent()->setBlack(); + newNode->getParent()->getParent()->setRed(); + rotateRight(newNode->getParent()->getParent()); + } + } + else + { + // If newNode is a right child, get its left 'uncle' + Node* newNodesUncle = newNode->getParent()->getParent()->getLeftChild(); + if ( newNodesUncle!=0 && newNodesUncle->isRed()) + { + // case 1 - change the colors + newNode->getParent()->setBlack(); + newNodesUncle->setBlack(); + newNode->getParent()->getParent()->setRed(); + // Move newNode up the tree + newNode = newNode->getParent()->getParent(); + } + else + { + // newNodesUncle is a black node + if (newNode->isLeftChild()) + { + // and newNode is to the left + // case 2 - move newNode up and rotate + newNode = newNode->getParent(); + rotateRight(newNode); + } + // case 3 + newNode->getParent()->setBlack(); + newNode->getParent()->getParent()->setRed(); + rotateLeft(newNode->getParent()->getParent()); + } + + } + } + // Color the root black + Root->setBlack(); + return true; + } + + //! Replaces the value if the key already exists, otherwise inserts a new element. + /** \param k The index for this value + \param v The new value of */ + void set(const KeyType& k, const ValueType& v) + { + Node* p = find(k); + if (p) + p->setValue(v); + else + insert(k,v); + } + + //! Removes a node from the tree and returns it. + /** The returned node must be deleted by the user + \param k the key to remove + \return A pointer to the node, or 0 if not found */ + Node* delink(const KeyType& k) + { + Node* p = find(k); + if (p == 0) + return 0; + + // Rotate p down to the left until it has no right child, will get there + // sooner or later. + while(p->getRightChild()) + { + // "Pull up my right child and let it knock me down to the left" + rotateLeft(p); + } + // p now has no right child but might have a left child + Node* left = p->getLeftChild(); + + // Let p's parent point to p's child instead of point to p + if (p->isLeftChild()) + p->getParent()->setLeftChild(left); + + else if (p->isRightChild()) + p->getParent()->setRightChild(left); + + else + { + // p has no parent => p is the root. + // Let the left child be the new root. + setRoot(left); + } + + // p is now gone from the tree in the sense that + // no one is pointing at it, so return it. + + --Size; + return p; + } + + //! Removes a node from the tree and deletes it. + /** \return True if the node was found and deleted */ + bool remove(const KeyType& k) + { + Node* p = find(k); + return remove(p); + } + + //! Removes a node from the tree and deletes it. + /** \return True if the node was found and deleted */ + bool remove(Node* p) + { + if (p == 0) + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + // Rotate p down to the left until it has no right child, will get there + // sooner or later. + while(p->getRightChild()) + { + // "Pull up my right child and let it knock me down to the left" + rotateLeft(p); + } + // p now has no right child but might have a left child + Node* left = p->getLeftChild(); + + // Let p's parent point to p's child instead of point to p + if (p->isLeftChild()) + p->getParent()->setLeftChild(left); + + else if (p->isRightChild()) + p->getParent()->setRightChild(left); + + else + { + // p has no parent => p is the root. + // Let the left child be the new root. + setRoot(left); + } + + // p is now gone from the tree in the sense that + // no one is pointing at it. Let's get rid of it. + delete p; + + --Size; + return true; + } + + //! Clear the entire tree + void clear() + { + ParentLastIterator i(getParentLastIterator()); + + while(!i.atEnd()) + { + Node* p = i.getNode(); + i++; // Increment it before it is deleted + // else iterator will get quite confused. + delete p; + } + Root = 0; + Size= 0; + } + + //! Is the tree empty? + //! \return Returns true if empty, false if not + bool empty() const + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Root == 0; + } + + //! \deprecated Use empty() instead. This method may be removed by Irrlicht 1.9 + _IRR_DEPRECATED_ bool isEmpty() const + { + return empty(); + } + + //! Search for a node with the specified key. + //! \param keyToFind: The key to find + //! \return Returns 0 if node couldn't be found. + Node* find(const KeyType& keyToFind) const + { + Node* pNode = Root; + + while(pNode!=0) + { + const KeyType& key=pNode->getKey(); + + if (keyToFind == key) + return pNode; + else if (keyToFind < key) + pNode = pNode->getLeftChild(); + else //keyToFind > key + pNode = pNode->getRightChild(); + } + + return 0; + } + + //! Gets the root element. + //! \return Returns a pointer to the root node, or + //! 0 if the tree is empty. + Node* getRoot() const + { + return Root; + } + + //! Returns the number of nodes in the tree. + u32 size() const + { + return Size; + } + + //! Swap the content of this map container with the content of another map + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(map& other) + { + core::swap(Root, other.Root); + core::swap(Size, other.Size); + } + + //------------------------------ + // Public Iterators + //------------------------------ + + //! Returns an iterator + Iterator getIterator() const + { + Iterator it(getRoot()); + return it; + } + + //! Returns a Constiterator + ConstIterator getConstIterator() const + { + Iterator it(getRoot()); + return it; + } + + //! Returns a ParentFirstIterator. + //! Traverses the tree from top to bottom. Typical usage is + //! when storing the tree structure, because when reading it + //! later (and inserting elements) the tree structure will + //! be the same. + ParentFirstIterator getParentFirstIterator() const + { + ParentFirstIterator it(getRoot()); + return it; + } + + //! Returns a ParentLastIterator to traverse the tree from + //! bottom to top. + //! Typical usage is when deleting all elements in the tree + //! because you must delete the children before you delete + //! their parent. + ParentLastIterator getParentLastIterator() const + { + ParentLastIterator it(getRoot()); + return it; + } + + //------------------------------ + // Public Operators + //------------------------------ + + //! operator [] for access to elements + /** for example myMap["key"] */ + AccessClass operator[](const KeyType& k) + { + return AccessClass(*this, k); + } + private: + + //------------------------------ + // Disabled methods + //------------------------------ + // Copy constructor and assignment operator deliberately + // defined but not implemented. The tree should never be + // copied, pass along references to it instead. + explicit map(const map& src); + map& operator = (const map& src); + + //! Set node as new root. + /** The node will be set to black, otherwise core dumps may arise + (patch provided by rogerborg). + \param newRoot Node which will be the new root + */ + void setRoot(Node* newRoot) + { + Root = newRoot; + if (Root != 0) + { + Root->setParent(0); + Root->setBlack(); + } + } + + //! Insert a node into the tree without using any fancy balancing logic. + /** \return false if that key already exist in the tree. */ + bool insert(Node* newNode) + { + bool result=true; // Assume success + + if (Root==0) + { + setRoot(newNode); + Size = 1; + } + else + { + Node* pNode = Root; + const KeyType& keyNew = newNode->getKey(); + while (pNode) + { + const KeyType& key=pNode->getKey(); + + if (keyNew == key) + { + result = false; + pNode = 0; + } + else if (keyNew < key) + { + if (pNode->getLeftChild() == 0) + { + pNode->setLeftChild(newNode); + pNode = 0; + } + else + pNode = pNode->getLeftChild(); + } + else // keyNew > key + { + if (pNode->getRightChild()==0) + { + pNode->setRightChild(newNode); + pNode = 0; + } + else + { + pNode = pNode->getRightChild(); + } + } + } + + if (result) + ++Size; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return result; + } + + //! Rotate left. + //! Pull up node's right child and let it knock node down to the left + void rotateLeft(Node* p) + { + Node* right = p->getRightChild(); + + p->setRightChild(right->getLeftChild()); + + if (p->isLeftChild()) + p->getParent()->setLeftChild(right); + else if (p->isRightChild()) + p->getParent()->setRightChild(right); + else + setRoot(right); + + right->setLeftChild(p); + } + + //! Rotate right. + //! Pull up node's left child and let it knock node down to the right + void rotateRight(Node* p) + { + Node* left = p->getLeftChild(); + + p->setLeftChild(left->getRightChild()); + + if (p->isLeftChild()) + p->getParent()->setLeftChild(left); + else if (p->isRightChild()) + p->getParent()->setRightChild(left); + else + setRoot(left); + + left->setRightChild(p); + } + + //------------------------------ + // Private Members + //------------------------------ + Node* Root; // The top node. 0 if empty. + u32 Size; // Number of nodes in the tree +}; + +} // end namespace core +} // end namespace irr + +#endif // __IRR_MAP_H_INCLUDED__ + diff --git a/inc/irrMath.h b/inc/irrMath.h new file mode 100644 index 0000000..4351027 --- /dev/null +++ b/inc/irrMath.h @@ -0,0 +1,732 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_MATH_H_INCLUDED__ +#define __IRR_MATH_H_INCLUDED__ + +#include "IrrCompileConfig.h" +#include "irrTypes.h" +#include +#include +#include // for abs() etc. +#include // For INT_MAX / UINT_MAX + +#if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE) + #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X)) + #define sinf(X) (irr::f32)sin((irr::f64)(X)) + #define cosf(X) (irr::f32)cos((irr::f64)(X)) + #define asinf(X) (irr::f32)asin((irr::f64)(X)) + #define acosf(X) (irr::f32)acos((irr::f64)(X)) + #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y)) + #define ceilf(X) (irr::f32)ceil((irr::f64)(X)) + #define floorf(X) (irr::f32)floor((irr::f64)(X)) + #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y)) + #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y)) + #define fabsf(X) (irr::f32)fabs((irr::f64)(X)) + #define logf(X) (irr::f32)log((irr::f64)(X)) +#endif + +#ifndef FLT_MAX +#define FLT_MAX 3.402823466E+38F +#endif + +#ifndef FLT_MIN +#define FLT_MIN 1.17549435e-38F +#endif + +namespace irr +{ +namespace core +{ + + //! Rounding error constant often used when comparing f32 values. + + const s32 ROUNDING_ERROR_S32 = 0; +#ifdef __IRR_HAS_S64 + const s64 ROUNDING_ERROR_S64 = 0; +#endif + const f32 ROUNDING_ERROR_f32 = 0.000001f; + const f64 ROUNDING_ERROR_f64 = 0.00000001; + +#ifdef PI // make sure we don't collide with a define +#undef PI +#endif + //! Constant for PI. + const f32 PI = 3.14159265359f; + + //! Constant for reciprocal of PI. + const f32 RECIPROCAL_PI = 1.0f/PI; + + //! Constant for half of PI. + const f32 HALF_PI = PI/2.0f; + +#ifdef PI64 // make sure we don't collide with a define +#undef PI64 +#endif + //! Constant for 64bit PI. + const f64 PI64 = 3.1415926535897932384626433832795028841971693993751; + + //! Constant for 64bit reciprocal of PI. + const f64 RECIPROCAL_PI64 = 1.0/PI64; + + //! 32bit Constant for converting from degrees to radians + const f32 DEGTORAD = PI / 180.0f; + + //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI) + const f32 RADTODEG = 180.0f / PI; + + //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2) + const f64 DEGTORAD64 = PI64 / 180.0; + + //! 64bit constant for converting from radians to degrees + const f64 RADTODEG64 = 180.0 / PI64; + + //! Utility function to convert a radian value to degrees + /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X + \param radians The radians value to convert to degrees. + */ + inline f32 radToDeg(f32 radians) + { + return RADTODEG * radians; + } + + //! Utility function to convert a radian value to degrees + /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X + \param radians The radians value to convert to degrees. + */ + inline f64 radToDeg(f64 radians) + { + return RADTODEG64 * radians; + } + + //! Utility function to convert a degrees value to radians + /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X + \param degrees The degrees value to convert to radians. + */ + inline f32 degToRad(f32 degrees) + { + return DEGTORAD * degrees; + } + + //! Utility function to convert a degrees value to radians + /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X + \param degrees The degrees value to convert to radians. + */ + inline f64 degToRad(f64 degrees) + { + return DEGTORAD64 * degrees; + } + + //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& min_(const T& a, const T& b) + { + return a < b ? a : b; + } + + //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& min_(const T& a, const T& b, const T& c) + { + return a < b ? min_(a, c) : min_(b, c); + } + + //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& max_(const T& a, const T& b) + { + return a < b ? b : a; + } + + //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& max_(const T& a, const T& b, const T& c) + { + return a < b ? max_(b, c) : max_(a, c); + } + + //! returns abs of two values. Own implementation to get rid of STL (VS6 problems) + template + inline T abs_(const T& a) + { + return a < (T)0 ? -a : a; + } + + //! returns linear interpolation of a and b with ratio t + //! \return: a if t==0, b if t==1, and the linear interpolation else + template + inline T lerp(const T& a, const T& b, const f32 t) + { + return (T)(a*(1.f-t)) + (b*t); + } + + //! clamps a value between low and high + template + inline const T clamp (const T& value, const T& low, const T& high) + { + return min_ (max_(value,low), high); + } + + //! swaps the content of the passed parameters + // Note: We use the same trick as boost and use two template arguments to + // avoid ambiguity when swapping objects of an Irrlicht type that has not + // it's own swap overload. Otherwise we get conflicts with some compilers + // in combination with stl. + template + inline void swap(T1& a, T2& b) + { + T1 c(a); + a = b; + b = c; + } + + //! returns if a equals b, taking possible rounding errors into account + inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + //! returns if a equals b, taking possible rounding errors into account + inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + union FloatIntUnion32 + { + FloatIntUnion32(float f1 = 0.0f) : f(f1) {} + // Portable sign-extraction + bool sign() const { return (i >> 31) != 0; } + + irr::s32 i; + irr::f32 f; + }; + + //! We compare the difference in ULP's (spacing between floating-point numbers, aka ULP=1 means there exists no float between). + //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign. + inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff) + { + // Based on the ideas and code from Bruce Dawson on + // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ + // When floats are interpreted as integers the two nearest possible float numbers differ just + // by one integer number. Also works the other way round, an integer of 1 interpreted as float + // is for example the smallest possible float number. + + FloatIntUnion32 fa(a); + FloatIntUnion32 fb(b); + + // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better. + if ( fa.sign() != fb.sign() ) + { + // Check for equality to make sure +0==-0 + if (fa.i == fb.i) + return true; + return false; + } + + // Find the difference in ULPs. + int ulpsDiff = abs_(fa.i- fb.i); + if (ulpsDiff <= maxUlpDiff) + return true; + + return false; + } + +#if 0 + //! returns if a equals b, not using any rounding tolerance + inline bool equals(const s32 a, const s32 b) + { + return (a == b); + } + + //! returns if a equals b, not using any rounding tolerance + inline bool equals(const u32 a, const u32 b) + { + return (a == b); + } +#endif + //! returns if a equals b, taking an explicit rounding tolerance into account + inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + //! returns if a equals b, taking an explicit rounding tolerance into account + inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + +#ifdef __IRR_HAS_S64 + //! returns if a equals b, taking an explicit rounding tolerance into account + inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } +#endif + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64) + { + return fabs(a) <= tolerance; + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) + { + return fabsf(a) <= tolerance; + } + + //! returns if a equals not zero, taking rounding errors into account + inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) + { + return fabsf(a) > tolerance; + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const s32 a, const s32 tolerance = 0) + { + return ( a & 0x7ffffff ) <= tolerance; + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const u32 a, const u32 tolerance = 0) + { + return a <= tolerance; + } + +#ifdef __IRR_HAS_S64 + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const s64 a, const s64 tolerance = 0) + { + return abs_(a) <= tolerance; + } +#endif + + inline s32 s32_min(s32 a, s32 b) + { + const s32 mask = (a - b) >> 31; + return (a & mask) | (b & ~mask); + } + + inline s32 s32_max(s32 a, s32 b) + { + const s32 mask = (a - b) >> 31; + return (b & mask) | (a & ~mask); + } + + inline s32 s32_clamp (s32 value, s32 low, s32 high) + { + return s32_min(s32_max(value,low), high); + } + + /* + float IEEE-754 bit represenation + + 0 0x00000000 + 1.0 0x3f800000 + 0.5 0x3f000000 + 3 0x40400000 + +inf 0x7f800000 + -inf 0xff800000 + +NaN 0x7fc00000 or 0x7ff00000 + in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits) + */ + + typedef union { u32 u; s32 s; f32 f; } inttofloat; + + #define F32_AS_S32(f) (*((s32 *) &(f))) + #define F32_AS_U32(f) (*((u32 *) &(f))) + #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f))) + + #define F32_VALUE_0 0x00000000 + #define F32_VALUE_1 0x3f800000 + #define F32_SIGN_BIT 0x80000000U + #define F32_EXPON_MANTISSA 0x7FFFFFFFU + + //! code is taken from IceFPU + //! Integer representation of a floating-point value. +#ifdef IRRLICHT_FAST_MATH + #define IR(x) ((u32&)(x)) +#else + inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;} +#endif + + //! Absolute integer representation of a floating-point value + #define AIR(x) (IR(x)&0x7fffffff) + + //! Floating-point representation of an integer value. +#ifdef IRRLICHT_FAST_MATH + #define FR(x) ((f32&)(x)) +#else + inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;} + inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;} +#endif + + //! integer representation of 1.0 + #define IEEE_1_0 0x3f800000 + //! integer representation of 255.0 + #define IEEE_255_0 0x437f0000 + +#ifdef IRRLICHT_FAST_MATH + #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT) + #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0) + #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0) + #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT) + #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1) + #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0) + + // only same sign + #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b))) + +#else + + #define F32_LOWER_0(n) ((n) < 0.0f) + #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f) + #define F32_GREATER_0(n) ((n) > 0.0f) + #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f) + #define F32_EQUAL_1(n) ((n) == 1.0f) + #define F32_EQUAL_0(n) ((n) == 0.0f) + #define F32_A_GREATER_B(a,b) ((a) > (b)) +#endif + + +#ifndef REALINLINE + #ifdef _MSC_VER + #define REALINLINE __forceinline + #else + #define REALINLINE inline + #endif +#endif + +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) + + // 8-bit bools in borland builder + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b ) + { + return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b; + } + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a ) + { + return ( -condition >> 31 ) & a; + } +#else + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b ) + { + return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b; + } + + //! conditional set based on mask and arithmetic shift + REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b ) + { + return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b; + } + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a ) + { + return ( -condition >> 31 ) & a; + } +#endif + + /* + if (condition) state |= m; else state &= ~m; + */ + REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask ) + { + // 0, or any postive to mask + //s32 conmask = -condition >> 31; + state ^= ( ( -condition >> 31 ) ^ state ) & mask; + } + + inline f32 round_( f32 x ) + { + return floorf( x + 0.5f ); + } + + REALINLINE void clearFPUException () + { +#ifdef IRRLICHT_FAST_MATH + return; +#ifdef feclearexcept + feclearexcept(FE_ALL_EXCEPT); +#elif defined(_MSC_VER) + __asm fnclex; +#elif defined(__GNUC__) && defined(__x86__) + __asm__ __volatile__ ("fclex \n\t"); +#else +# warn clearFPUException not supported. +#endif +#endif + } + + // calculate: sqrt ( x ) + REALINLINE f32 squareroot(const f32 f) + { + return sqrtf(f); + } + + // calculate: sqrt ( x ) + REALINLINE f64 squareroot(const f64 f) + { + return sqrt(f); + } + + // calculate: sqrt ( x ) + REALINLINE s32 squareroot(const s32 f) + { + return static_cast(squareroot(static_cast(f))); + } + +#ifdef __IRR_HAS_S64 + // calculate: sqrt ( x ) + REALINLINE s64 squareroot(const s64 f) + { + return static_cast(squareroot(static_cast(f))); + } +#endif + + // calculate: 1 / sqrt ( x ) + REALINLINE f64 reciprocal_squareroot(const f64 x) + { + return 1.0 / sqrt(x); + } + + // calculate: 1 / sqrtf ( x ) + REALINLINE f32 reciprocal_squareroot(const f32 f) + { +#if defined ( IRRLICHT_FAST_MATH ) + #if defined(_MSC_VER) + // SSE reciprocal square root estimate, accurate to 12 significant + // bits of the mantissa + f32 recsqrt; + __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f) + __asm movss recsqrt, xmm0 // return xmm0 + return recsqrt; + +/* + // comes from Nvidia + u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1; + f32 y = *(f32*)&tmp; + return y * (1.47f - 0.47f * x * y * y); +*/ + #else + return 1.f / sqrtf(f); + #endif +#else // no fast math + return 1.f / sqrtf(f); +#endif + } + + // calculate: 1 / sqrtf( x ) + REALINLINE s32 reciprocal_squareroot(const s32 x) + { + return static_cast(reciprocal_squareroot(static_cast(x))); + } + + // calculate: 1 / x + REALINLINE f32 reciprocal( const f32 f ) + { +#if defined (IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + + //! i do not divide through 0.. (fpu expection) + // instead set f to a high value to get a return value near zero.. + // -1000000000000.f.. is use minus to stay negative.. + // must test's here (plane.normal dot anything ) checks on <= 0.f + //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5; + //return 1.f / FR ( x ); + +#else // no fast math + return 1.f / f; +#endif + } + + // calculate: 1 / x + REALINLINE f64 reciprocal ( const f64 f ) + { + return 1.0 / f; + } + + + // calculate: 1 / x, low precision allowed + REALINLINE f32 reciprocal_approxim ( const f32 f ) + { +#if defined( IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + +/* + // SSE reciprocal estimate, accurate to 12 significant bits of + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss rec , xmm0 // return xmm0 + return rec; +*/ +/* + register u32 x = 0x7F000000 - IR ( p ); + const f32 r = FR ( x ); + return r * (2.0f - p * r); +*/ +#else // no fast math + return 1.f / f; +#endif + } + + + REALINLINE s32 floor32(f32 x) + { +#ifdef IRRLICHT_FAST_MATH + const f32 h = 0.5f; + + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fsub h + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fsub %2 \n\t" + "fistpl %0" + : "=m" (t) + : "t" (x), "f" (h) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) floorf ( x ); +#endif + return t; +#else // no fast math + return (s32) floorf ( x ); +#endif + } + + + REALINLINE s32 ceil32 ( f32 x ) + { +#ifdef IRRLICHT_FAST_MATH + const f32 h = 0.5f; + + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fadd h + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fadd %2 \n\t" + "fistpl %0 \n\t" + : "=m"(t) + : "t"(x), "f"(h) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) ceilf ( x ); +#endif + return t; +#else // not fast math + return (s32) ceilf ( x ); +#endif + } + + + + REALINLINE s32 round32(f32 x) + { +#if defined(IRRLICHT_FAST_MATH) + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fistpl %0 \n\t" + : "=m"(t) + : "t"(x) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) round_(x); +#endif + return t; +#else // no fast math + return (s32) round_(x); +#endif + } + + inline f32 f32_max3(const f32 a, const f32 b, const f32 c) + { + return a > b ? (a > c ? a : c) : (b > c ? b : c); + } + + inline f32 f32_min3(const f32 a, const f32 b, const f32 c) + { + return a < b ? (a < c ? a : c) : (b < c ? b : c); + } + + inline f32 fract ( f32 x ) + { + return x - floorf ( x ); + } + +} // end namespace core +} // end namespace irr + +#ifndef IRRLICHT_FAST_MATH + using irr::core::IR; + using irr::core::FR; +#endif + +#endif + diff --git a/inc/irrString.h b/inc/irrString.h new file mode 100644 index 0000000..752ea1a --- /dev/null +++ b/inc/irrString.h @@ -0,0 +1,1368 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_STRING_H_INCLUDED__ +#define __IRR_STRING_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrAllocator.h" +#include "irrMath.h" +#include +#include +#include + +namespace irr +{ +namespace core +{ + +//! Very simple string class with some useful features. +/** string and string both accept Unicode AND ASCII/Latin-1, +so you can assign Unicode to string and ASCII/Latin-1 to string +(and the other way round) if you want to. + +However, note that the conversation between both is not done using any encoding. +This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and +are simply expanded to the equivalent wchar_t, while Unicode/wchar_t +characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all +other information in the wchar_t. +*/ + +enum eLocaleID +{ + IRR_LOCALE_ANSI = 0, + IRR_LOCALE_GERMAN = 1 +}; + +static eLocaleID locale_current = IRR_LOCALE_ANSI; +static inline void locale_set ( eLocaleID id ) +{ + locale_current = id; +} + +//! Returns a character converted to lower case +static inline u32 locale_lower ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + case IRR_LOCALE_ANSI: + break; + } + // ansi + return x >= 'A' && x <= 'Z' ? x + 0x20 : x; +} + +//! Returns a character converted to upper case +static inline u32 locale_upper ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + case IRR_LOCALE_ANSI: + break; + } + + // ansi + return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; +} + + +template > +class string +{ +public: + + typedef T char_type; + + //! Default constructor + string() + : array(0), allocated(1), used(1) + { + array = allocator.allocate(1); // new T[1]; + array[0] = 0; + } + + + //! Constructor + string(const string& other) + : array(0), allocated(0), used(0) + { + *this = other; + } + + //! Constructor from other string types + template + string(const string& other) + : array(0), allocated(0), used(0) + { + *this = other; + } + + + //! Constructs a string from a float + explicit string(const double number) + : array(0), allocated(0), used(0) + { + c8 tmpbuf[255]; + snprintf(tmpbuf, 255, "%0.6f", number); + *this = tmpbuf; + } + + + //! Constructs a string from an int + explicit string(int number) + : array(0), allocated(0), used(0) + { + // store if negative and make positive + + bool negative = false; + if (number < 0) + { + number *= -1; + negative = true; + } + + // temporary buffer for 16 numbers + + c8 tmpbuf[16]={0}; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + // add sign + + if (negative) + { + --idx; + tmpbuf[idx] = '-'; + } + + *this = &tmpbuf[idx]; + } + + + //! Constructs a string from an unsigned int + explicit string(unsigned int number) + : array(0), allocated(0), used(0) + { + // temporary buffer for 16 numbers + + c8 tmpbuf[16]={0}; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + *this = &tmpbuf[idx]; + } + + + //! Constructs a string from a long + explicit string(long number) + : array(0), allocated(0), used(0) + { + // store if negative and make positive + + bool negative = false; + if (number < 0) + { + number *= -1; + negative = true; + } + + // temporary buffer for 16 numbers + + c8 tmpbuf[16]={0}; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + // add sign + + if (negative) + { + --idx; + tmpbuf[idx] = '-'; + } + + *this = &tmpbuf[idx]; + } + + + //! Constructs a string from an unsigned long + explicit string(unsigned long number) + : array(0), allocated(0), used(0) + { + // temporary buffer for 16 numbers + + c8 tmpbuf[16]={0}; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + *this = &tmpbuf[idx]; + } + + + //! Constructor for copying a string from a pointer with a given length + template + string(const B* const c, u32 length) + : array(0), allocated(0), used(0) + { + if (!c) + { + // correctly init the string to an empty one + *this=""; + return; + } + + allocated = used = length+1; + array = allocator.allocate(used); // new T[used]; + + for (u32 l = 0; l + string(const B* const c) + : array(0), allocated(0), used(0) + { + *this = c; + } + + + //! Destructor + ~string() + { + allocator.deallocate(array); // delete [] array; + } + + + //! Assignment operator + string& operator=(const string& other) + { + if (this == &other) + return *this; + + used = other.size()+1; + if (used>allocated) + { + allocator.deallocate(array); // delete [] array; + allocated = used; + array = allocator.allocate(used); //new T[used]; + } + + const T* p = other.c_str(); + for (u32 i=0; i + string& operator=(const string& other) + { + *this = other.c_str(); + return *this; + } + + + //! Assignment operator for strings, ascii and unicode + template + string& operator=(const B* const c) + { + if (!c) + { + if (!array) + { + array = allocator.allocate(1); //new T[1]; + allocated = 1; + } + used = 1; + array[0] = 0x0; + return *this; + } + + if ((void*)c == (void*)array) + return *this; + + u32 len = 0; + const B* p = c; + do + { + ++len; + } while(*p++); + + // we'll keep the old string for a while, because the new + // string could be a part of the current string. + T* oldArray = array; + + used = len; + if (used>allocated) + { + allocated = used; + array = allocator.allocate(used); //new T[used]; + } + + for (u32 l = 0; l operator+(const string& other) const + { + string str(*this); + str.append(other); + + return str; + } + + + //! Append operator for strings, ascii and unicode + template + string operator+(const B* const c) const + { + string str(*this); + str.append(c); + + return str; + } + + + //! Direct access operator + T& operator [](const u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + return array[index]; + } + + + //! Direct access operator + const T& operator [](const u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + return array[index]; + } + + + //! Equality operator + bool operator==(const T* const str) const + { + if (!str) + return false; + + u32 i; + for (i=0; array[i] && str[i]; ++i) + if (array[i] != str[i]) + return false; + + return (!array[i] && !str[i]); + } + + + //! Equality operator + bool operator==(const string& other) const + { + for (u32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return false; + + return used == other.used; + } + + + //! Is smaller comparator + bool operator<(const string& other) const + { + for (u32 i=0; array[i] && other.array[i]; ++i) + { + const s32 diff = array[i] - other.array[i]; + if (diff) + return (diff < 0); + } + + return (used < other.used); + } + + + //! Inequality operator + bool operator!=(const T* const str) const + { + return !(*this == str); + } + + + //! Inequality operator + bool operator!=(const string& other) const + { + return !(*this == other); + } + + + //! Returns length of the string's content + /** \return Length of the string's content in characters, excluding + the trailing NUL. */ + u32 size() const + { + return used-1; + } + + //! Informs if the string is empty or not. + //! \return True if the string is empty, false if not. + bool empty() const + { + return (size() == 0); + } + + //! Returns character string + /** \return pointer to C-style NUL terminated string. */ + const T* c_str() const + { + return array; + } + + + //! Makes the string lower case. + string& make_lower() + { + for (u32 i=0; array[i]; ++i) + array[i] = locale_lower ( array[i] ); + return *this; + } + + + //! Makes the string upper case. + string& make_upper() + { + for (u32 i=0; array[i]; ++i) + array[i] = locale_upper ( array[i] ); + return *this; + } + + + //! Compares the strings ignoring case. + /** \param other: Other string to compare. + \return True if the strings are equal ignoring case. */ + bool equals_ignore_case(const string& other) const + { + for(u32 i=0; array[i] && other[i]; ++i) + if (locale_lower( array[i]) != locale_lower(other[i])) + return false; + + return used == other.used; + } + + //! Compares the strings ignoring case. + /** \param other: Other string to compare. + \param sourcePos: where to start to compare in the string + \return True if the strings are equal ignoring case. */ + bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const + { + if ( (u32) sourcePos >= used ) + return false; + + u32 i; + for( i=0; array[sourcePos + i] && other[i]; ++i) + if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) + return false; + + return array[sourcePos + i] == 0 && other[i] == 0; + } + + + //! Compares the strings ignoring case. + /** \param other: Other string to compare. + \return True if this string is smaller ignoring case. */ + bool lower_ignore_case(const string& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + { + s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); + if ( diff ) + return diff < 0; + } + + return used < other.used; + } + + + //! compares the first n characters of the strings + /** \param other Other string to compare. + \param n Number of characters to compare + \return True if the n first characters of both strings are equal. */ + bool equalsn(const string& other, u32 n) const + { + u32 i; + for(i=0; array[i] && other[i] && i < n; ++i) + if (array[i] != other[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (used == other.used); + } + + + //! compares the first n characters of the strings + /** \param str Other string to compare. + \param n Number of characters to compare + \return True if the n first characters of both strings are equal. */ + bool equalsn(const T* const str, u32 n) const + { + if (!str) + return false; + u32 i; + for(i=0; array[i] && str[i] && i < n; ++i) + if (array[i] != str[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (array[i] == 0 && str[i] == 0); + } + + + //! Appends a character to this string + /** \param character: Character to append. */ + string& append(T character) + { + if (used + 1 > allocated) + reallocate(used + 1); + + ++used; + + array[used-2] = character; + array[used-1] = 0; + + return *this; + } + + + //! Appends a char string to this string + /** \param other: Char string to append. */ + /** \param length: The length of the string to append. */ + string& append(const T* const other, u32 length=0xffffffff) + { + if (!other) + return *this; + + u32 len = 0; + const T* p = other; + while(*p) + { + ++len; + ++p; + } + if (len > length) + len = length; + + if (used + len > allocated) + reallocate(used + len); + + --used; + ++len; + + for (u32 l=0; l& append(const string& other) + { + if (other.size() == 0) + return *this; + + --used; + u32 len = other.size()+1; + + if (used + len > allocated) + reallocate(used + len); + + for (u32 l=0; l& append(const string& other, u32 length) + { + if (other.size() == 0) + return *this; + + if (other.size() < length) + { + append(other); + return *this; + } + + if (used + length > allocated) + reallocate(used + length); + + --used; + + for (u32 l=0; l + s32 findFirstCharNotInList(const B* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + for (u32 i=0; i + s32 findLastCharNotInList(const B* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + for (s32 i=(s32)(used-2); i>=0; --i) + { + u32 j; + for (j=0; j=0; --i) + if (array[i] == c) + return i; + + return -1; + } + + //! finds last occurrence of a character of a list in string + /** \param c: List of strings to find. For example if the method + should find the last occurrence of 'a' or 'b', this parameter should be "ab". + \param count: Amount of characters in the list. Usually, + this should be strlen(c) + \return Position where one of the characters has been found, + or -1 if not found. */ + s32 findLastChar(const T* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + for (s32 i=(s32)used-2; i>=0; --i) + for (u32 j=0; j + s32 find(const B* const str, const u32 start = 0) const + { + if (str && *str) + { + u32 len = 0; + + while (str[len]) + ++len; + + if (len > used-1) + return -1; + + for (u32 i=start; i subString(u32 begin, s32 length, bool make_lower = false ) const + { + // if start after string + // or no proper substring length + if ((length <= 0) || (begin>=size())) + return string(""); + // clamp length to maximal value + if ((length+begin) > size()) + length = size()-begin; + + string o; + o.reserve(length+1); + + s32 i; + if ( !make_lower ) + { + for (i=0; i& operator += (T c) + { + append(c); + return *this; + } + + + //! Appends a char string to this string + /** \param c Char string to append. */ + string& operator += (const T* const c) + { + append(c); + return *this; + } + + + //! Appends a string to this string + /** \param other String to append. */ + string& operator += (const string& other) + { + append(other); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const int i) + { + append(string(i)); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const unsigned int i) + { + append(string(i)); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const long i) + { + append(string(i)); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const unsigned long i) + { + append(string(i)); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const double i) + { + append(string(i)); + return *this; + } + + + //! Appends a string representation of a number to this string + /** \param i Number to append. */ + string& operator += (const float i) + { + append(string(i)); + return *this; + } + + + //! Replaces all characters of a special type with another one + /** \param toReplace Character to replace. + \param replaceWith Character replacing the old one. */ + string& replace(T toReplace, T replaceWith) + { + for (u32 i=0; i& replace(const string& toReplace, const string& replaceWith) + { + if (toReplace.size() == 0) + return *this; + + const T* other = toReplace.c_str(); + const T* replace = replaceWith.c_str(); + const u32 other_size = toReplace.size(); + const u32 replace_size = replaceWith.size(); + + // Determine the delta. The algorithm will change depending on the delta. + s32 delta = replace_size - other_size; + + // A character for character replace. The string will not shrink or grow. + if (delta == 0) + { + s32 pos = 0; + while ((pos = find(other, pos)) != -1) + { + for (u32 i = 0; i < replace_size; ++i) + array[pos + i] = replace[i]; + ++pos; + } + return *this; + } + + // We are going to be removing some characters. The string will shrink. + if (delta < 0) + { + u32 i = 0; + for (u32 pos = 0; pos < used; ++i, ++pos) + { + // Is this potentially a match? + if (array[pos] == *other) + { + // Check to see if we have a match. + u32 j; + for (j = 0; j < other_size; ++j) + { + if (array[pos + j] != other[j]) + break; + } + + // If we have a match, replace characters. + if (j == other_size) + { + for (j = 0; j < replace_size; ++j) + array[i + j] = replace[j]; + i += replace_size - 1; + pos += other_size - 1; + continue; + } + } + + // No match found, just copy characters. + array[i] = array[pos]; + } + array[i-1] = 0; + used = i; + + return *this; + } + + // We are going to be adding characters, so the string size will increase. + // Count the number of times toReplace exists in the string so we can allocate the new size. + u32 find_count = 0; + s32 pos = 0; + while ((pos = find(other, pos)) != -1) + { + ++find_count; + ++pos; + } + + // Re-allocate the string now, if needed. + u32 len = delta * find_count; + if (used + len > allocated) + reallocate(used + len); + + // Start replacing. + pos = 0; + while ((pos = find(other, pos)) != -1) + { + T* start = array + pos + other_size - 1; + T* ptr = array + used - 1; + T* end = array + delta + used -1; + + // Shift characters to make room for the string. + while (ptr != start) + { + *end = *ptr; + --ptr; + --end; + } + + // Add the new string now. + for (u32 i = 0; i < replace_size; ++i) + array[pos + i] = replace[i]; + + pos += replace_size; + used += delta; + } + + return *this; + } + + + //! Removes characters from a string. + /** \param c: Character to remove. */ + string& remove(T c) + { + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i& remove(const string& toRemove) + { + u32 size = toRemove.size(); + if ( size == 0 ) + return *this; + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i& removeChars(const string & characters) + { + if (characters.size() == 0) + return *this; + + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i& trim(const string & whitespace = " \t\n\r") + { + // find start and end of the substring without the specified characters + const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); + if (begin == -1) + return (*this=""); + + const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); + + return (*this = subString(begin, (end +1) - begin)); + } + + + //! Erases a character from the string. + /** May be slow, because all elements + following after the erased element have to be copied. + \param index: Index of element to be erased. */ + string& erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + for (u32 i=index+1; i& validate() + { + // terminate on existing null + for (u32 i=0; i 0 ) + { + used = allocated; + array[used-1] = 0; + } + else + { + used = 0; + } + + return *this; + } + + //! gets the last char of a string or null + T lastChar() const + { + return used > 1 ? array[used-2] : 0; + } + + //! split string into parts. + /** This method will split a string at certain delimiter characters + into the container passed in as reference. The type of the container + has to be given as template parameter. It must provide a push_back and + a size method. + \param ret The result container + \param c C-style string of delimiter characters + \param count Number of delimiter characters + \param ignoreEmptyTokens Flag to avoid empty substrings in the result + container. If two delimiters occur without a character in between, an + empty substring would be placed in the result. If this flag is set, + only non-empty strings are stored. + \param keepSeparators Flag which allows to add the separator to the + result string. If this flag is true, the concatenation of the + substrings results in the original string. Otherwise, only the + characters between the delimiters are returned. + \return The number of resulting substrings + */ + template + u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const + { + if (!c) + return 0; + + const u32 oldSize=ret.size(); + u32 lastpos = 0; + bool lastWasSeparator = false; + for (u32 i=0; i(&array[lastpos], i - lastpos)); + foundSeparator = true; + lastpos = (keepSeparators ? i : i + 1); + break; + } + } + lastWasSeparator = foundSeparator; + } + if ((used - 1) > lastpos) + ret.push_back(string(&array[lastpos], (used - 1) - lastpos)); + return ret.size()-oldSize; + } + +private: + + //! Reallocate the array, make it bigger or smaller + void reallocate(u32 new_size) + { + T* old_array = array; + + array = allocator.allocate(new_size); //new T[new_size]; + allocated = new_size; + + u32 amount = used < new_size ? used : new_size; + for (u32 i=0; i stringc; + +//! Typedef for wide character strings +typedef string stringw; + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/irrTypes.h b/inc/irrTypes.h new file mode 100644 index 0000000..cfeaf84 --- /dev/null +++ b/inc/irrTypes.h @@ -0,0 +1,250 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_TYPES_H_INCLUDED__ +#define __IRR_TYPES_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +namespace irr +{ + +//! 8 bit unsigned variable. +/** This is a typedef for unsigned char, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef unsigned __int8 u8; +#else +typedef unsigned char u8; +#endif + +//! 8 bit signed variable. +/** This is a typedef for signed char, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef __int8 s8; +#else +typedef signed char s8; +#endif + +//! 8 bit character variable. +/** This is a typedef for char, it ensures portability of the engine. */ +typedef char c8; + + + +//! 16 bit unsigned variable. +/** This is a typedef for unsigned short, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef unsigned __int16 u16; +#else +typedef unsigned short u16; +#endif + +//! 16 bit signed variable. +/** This is a typedef for signed short, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef __int16 s16; +#else +typedef signed short s16; +#endif + + + +//! 32 bit unsigned variable. +/** This is a typedef for unsigned int, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef unsigned __int32 u32; +#else +typedef unsigned int u32; +#endif + +//! 32 bit signed variable. +/** This is a typedef for signed int, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef __int32 s32; +#else +typedef signed int s32; +#endif + + +#ifdef __IRR_HAS_S64 +//! 64 bit unsigned variable. +/** This is a typedef for 64bit uint, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef unsigned __int64 u64; +#elif __GNUC__ +#if __WORDSIZE == 64 +typedef unsigned long int u64; +#else +__extension__ typedef unsigned long long u64; +#endif +#else +typedef unsigned long long u64; +#endif + +//! 64 bit signed variable. +/** This is a typedef for 64bit int, it ensures portability of the engine. */ +#if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +typedef __int64 s64; +#elif __GNUC__ +#if __WORDSIZE == 64 +typedef long int s64; +#else +__extension__ typedef long long s64; +#endif +#else +typedef long long s64; +#endif +#endif // __IRR_HAS_S64 + + + +//! 32 bit floating point variable. +/** This is a typedef for float, it ensures portability of the engine. */ +typedef float f32; + +//! 64 bit floating point variable. +/** This is a typedef for double, it ensures portability of the engine. */ +typedef double f64; + + +} // end namespace irr + + +#include +#ifdef _IRR_WINDOWS_API_ +//! Defines for s{w,n}printf because these methods do not match the ISO C +//! standard on Windows platforms, but it does on all others. +//! These should be int snprintf(char *str, size_t size, const char *format, ...); +//! and int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...); +#if defined(_MSC_VER) && _MSC_VER > 1310 && !defined (_WIN32_WCE) +#define swprintf swprintf_s +#define snprintf sprintf_s +#elif !defined(__CYGWIN__) +#define swprintf _snwprintf +#define snprintf _snprintf +#endif + +// define the wchar_t type if not already built in. +#ifdef _MSC_VER +#ifndef _WCHAR_T_DEFINED +//! A 16 bit wide character type. +/** + Defines the wchar_t-type. + In VS6, its not possible to tell + the standard compiler to treat wchar_t as a built-in type, and + sometimes we just don't want to include the huge stdlib.h or wchar.h, + so we'll use this. +*/ +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif // wchar is not defined +#endif // microsoft compiler +#endif // _IRR_WINDOWS_API_ + +namespace irr +{ + +//! Type name for character type used by the file system. +/** Should the wide character version of the FileSystem be used it is a +16 bit character variable. Used for unicode Filesystem and unicode strings. +Else it is a 8 bit character variable. Used for ansi Filesystem and non-unicode +strings +*/ +#if defined(_IRR_WCHAR_FILESYSTEM) + typedef wchar_t fschar_t; + #define _IRR_TEXT(X) L##X +#else + typedef char fschar_t; + #define _IRR_TEXT(X) X +#endif + +} // end namespace irr + +//! define a break macro for debugging. +#if defined(_DEBUG) +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) + #if defined(WIN64) || defined(_WIN64) // using portable common solution for x64 configuration + #include + #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_CrtDbgBreak();} + #else + #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3} + #endif +#else +#include "assert.h" +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) assert( !(_CONDITION_) ); +#endif +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif + +//! Defines a deprecated macro which generates a warning at compile time +/** The usage is simple +For typedef: typedef _IRR_DEPRECATED_ int test1; +For classes/structs: class _IRR_DEPRECATED_ test2 { ... }; +For methods: class test3 { _IRR_DEPRECATED_ virtual void foo() {} }; +For functions: template _IRR_DEPRECATED_ void test4(void) {} +**/ +#if defined(IGNORE_DEPRECATED_WARNING) +#define _IRR_DEPRECATED_ +#elif _MSC_VER >= 1310 //vs 2003 or higher +#define _IRR_DEPRECATED_ __declspec(deprecated) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) // all versions above 3.0 should support this feature +#define _IRR_DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _IRR_DEPRECATED_ +#endif + +//! Defines a small statement to work around a microsoft compiler bug. +/** The microsoft compiler 7.0 - 7.1 has a bug: +When you call unmanaged code that returns a bool type value of false from managed code, +the return value may appear as true. See +http://support.microsoft.com/default.aspx?kbid=823071 for details. +Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100 +#else +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX +#endif // _IRR_MANAGED_MARSHALLING_BUGFIX + + +// memory debugging +#if defined(_DEBUG) && defined(IRRLICHT_EXPORTS) && defined(_MSC_VER) && \ + (_MSC_VER > 1299) && !defined(_IRR_DONT_DO_MEMORY_DEBUGGING_HERE) && !defined(_WIN32_WCE) + + #define CRTDBG_MAP_ALLOC + #define _CRTDBG_MAP_ALLOC + #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) + #include + #include + #define new DEBUG_CLIENTBLOCK +#endif + +// disable truncated debug information warning in visual studio 6 by default +#if defined(_MSC_VER) && (_MSC_VER < 1300 ) +#pragma warning( disable: 4786) +#endif // _MSC + + +//! ignore VC8 warning deprecated +/** The microsoft compiler */ +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER >= 1400) + //#pragma warning( disable: 4996) + //#define _CRT_SECURE_NO_DEPRECATE 1 + //#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + + +//! creates four CC codes used in Irrlicht for simple ids +/** some compilers can create those by directly writing the +code like 'code', but some generate warnings so we use this macro here */ +#define MAKE_IRR_ID(c0, c1, c2, c3) \ + ((irr::u32)(irr::u8)(c0) | ((irr::u32)(irr::u8)(c1) << 8) | \ + ((irr::u32)(irr::u8)(c2) << 16) | ((irr::u32)(irr::u8)(c3) << 24 )) + +#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +#define _strcmpi(a,b) strcmpi(a,b) +#endif + +#endif // __IRR_TYPES_H_INCLUDED__ + diff --git a/inc/irrXML.h b/inc/irrXML.h new file mode 100644 index 0000000..2ca2d31 --- /dev/null +++ b/inc/irrXML.h @@ -0,0 +1,575 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +#ifndef __IRR_XML_H_INCLUDED__ +#define __IRR_XML_H_INCLUDED__ + +#include +#include "IrrCompileConfig.h" + +/** \mainpage irrXML 1.2 API documentation +
+ + \section intro Introduction + + Welcome to the irrXML API documentation. + Here you'll find any information you'll need to develop applications with + irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, + at the homepage of irrXML at www.ambiera.com/irrxml/ + or into the SDK in the directory example. + + irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and + this documentation is an important part of it. If you have any questions or + suggestions, just send a email to the author of the engine, Nikolaus Gebhardt + (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. + + \section features Features + + irrXML provides forward-only, read-only + access to a stream of non validated XML data. It was fully implemented by + Nikolaus Gebhardt. Its current features are: + + - It it fast as lighting and has very low memory usage. It was + developed with the intention of being used in 3D games, as it already has been. + - irrXML is very small: It only consists of 60 KB of code and can be added easily + to your existing project. + - Of course, it is platform independent and works with lots of compilers. + - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in + little and big endian format. + - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, + UTF-16 and UTF-32 format. + - With its optional file access abstraction it has the advantage that it can read not + only from files but from any type of data (memory, network, ...). For example when + used with the Irrlicht Engine, it directly reads from compressed .zip files. + - Just like the Irrlicht Engine for which it was originally created, it is extremely easy + to use. + - It has no external dependencies, it does not even need the STL. + + Although irrXML has some strenghts, it currently also has the following limitations: + + - The input xml file is not validated and assumed to be correct. + + \section irrxmlexample Example + + The following code demonstrates the basic usage of irrXML. A simple xml + file like this is parsed: + \code + + + + + + Welcome to the Mesh Viewer of the "Irrlicht Engine". + + + \endcode + + The code for parsing this file would look like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + #include // we use STL strings to store data in this example + + void main() + { + // create the reader using one of the factory functions + + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + // strings for storing the data we want to get out of the file + std::string modelFile; + std::string messageText; + std::string caption; + + // parse the file until end reached + + while(xml && xml->read()) + { + switch(xml->getNodeType()) + { + case EXN_TEXT: + // in this xml file, the only text which occurs is the messageText + messageText = xml->getNodeData(); + break; + case EXN_ELEMENT: + { + if (!strcmp("model", xml->getNodeName())) + modelFile = xml->getAttributeValue("file"); + else + if (!strcmp("messageText", xml->getNodeName())) + caption = xml->getAttributeValue("caption"); + } + break; + } + } + + // delete the xml parser after usage + delete xml; + } + \endcode + + \section howto How to use + + Simply add the source files in the /src directory of irrXML to your project. Done. + + \section license License + + The irrXML license is based on the zlib license. Basicly, this means you can do with + irrXML whatever you want: + + Copyright (C) 2002-2012 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + \section history History + + As lots of references in this documentation and the source show, this xml + parser has originally been a part of the + Irrlicht Engine. But because + the parser has become very useful with the latest release, people asked for a + separate version of it, to be able to use it in non Irrlicht projects. With + irrXML 1.0, this has now been done. +*/ + +namespace irr +{ +namespace io +{ + //! Enumeration of all supported source text file formats + enum ETEXT_FORMAT + { + //! ASCII, file without byte order mark, or not a text file + ETF_ASCII, + + //! UTF-8 format + ETF_UTF8, + + //! UTF-16 format, big endian + ETF_UTF16_BE, + + //! UTF-16 format, little endian + ETF_UTF16_LE, + + //! UTF-32 format, big endian + ETF_UTF32_BE, + + //! UTF-32 format, little endian + ETF_UTF32_LE + }; + + + //! Enumeration for all xml nodes which are parsed by IrrXMLReader + enum EXML_NODE + { + //! No xml node. This is usually the node if you did not read anything yet. + EXN_NONE, + + //! An xml element such as <foo> + EXN_ELEMENT, + + //! End of an xml element such as </foo> + EXN_ELEMENT_END, + + //! Text within an xml element: <foo> this is the text. </foo> + //! Also text between 2 xml elements: </foo> this is the text. <foo> + EXN_TEXT, + + //! An xml comment like <!-- I am a comment --> or a DTD definition. + EXN_COMMENT, + + //! An xml cdata section like <![CDATA[ this is some CDATA ]]> + EXN_CDATA, + + //! Unknown element. + EXN_UNKNOWN + }; + + //! Callback class for file read abstraction. + /** With this, it is possible to make the xml parser read in other + things than just files. The Irrlicht engine is using this for example to + read xml from compressed .zip files. To make the parser read in + any other data, derive a class from this interface, implement the + two methods to read your data and give a pointer to an instance of + your implementation when calling createIrrXMLReader(), + createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ + class IFileReadCallBack + { + public: + + //! Destructor + virtual ~IFileReadCallBack() {} + + //! Reads an amount of bytes from the file. + /** \param buffer: Pointer to buffer where to read bytes will be written to. + \param sizeToRead: Amount of bytes to read from the file. + \return Returns how much bytes were read. */ + virtual int read(void* buffer, int sizeToRead) = 0; + + //! Returns size of file in bytes + virtual long getSize() const = 0; + }; + + //! Empty class to be used as parent class for IrrXMLReader. + /** If you need another class as base class for the xml reader, you can do this by creating + the reader using for example new CXMLReaderImpl(yourcallback); + The Irrlicht Engine for example needs IReferenceCounted as base class for every object to + let it automaticly reference countend, hence it replaces IXMLBase with IReferenceCounted. + See irrXML.cpp on how this can be done in detail. */ + class IXMLBase + { + }; + + //! Interface providing easy read access to a XML file. + /** You can create an instance of this reader using one of the factory functions + createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). + If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() + instead. + For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. + + The typical usage of this parser looks like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + void main() + { + // create the reader using one of the factory functions + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + if (xml == 0) + return; // file could not be opened + + // parse the file until end reached + while(xml->read()) + { + // based on xml->getNodeType(), do something. + } + + // delete the xml parser after usage + delete xml; + } + \endcode + See \ref irrxmlexample for a more detailed example. + */ + template + class IIrrXMLReader : public super_class + { + public: + + //! Destructor + virtual ~IIrrXMLReader() {} + + //! Reads forward to the next xml node. + /** \return Returns false, if there was no further node. */ + virtual bool read() = 0; + + //! Returns the type of the current XML node. + virtual EXML_NODE getNodeType() const = 0; + + //! Returns attribute count of the current XML node. + /** This is usually + non null if the current node is EXN_ELEMENT, and the element has attributes. + \return Returns amount of attributes of this xml node. */ + virtual unsigned int getAttributeCount() const = 0; + + //! Returns name of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Name of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeName(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeValue(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param name: Name of the attribute. + \return Value of the attribute, 0 if an attribute with this name does not exist. */ + virtual const char_type* getAttributeValue(const char_type* name) const = 0; + + //! Returns the value of an attribute in a safe way. + /** Like getAttributeValue(), but does not + return 0 if the attribute does not exist. An empty string ("") is returned then. + \param name: Name of the attribute. + \return Value of the attribute, and "" if an attribute with this name does not exist */ + virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param name Name of the attribute. + \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(int idx) const = 0; + + //! Returns the value of an attribute as float. + /** \param name: Name of the attribute. + \return Value of the attribute as float, and 0 if an attribute with this name does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(const char_type* name) const = 0; + + //! Returns the value of an attribute as float. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as float, and 0 if an attribute with this index does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(int idx) const = 0; + + //! Returns the name of the current node. + /** Only valid, if the node type is EXN_ELEMENT. + \return Name of the current node or 0 if the node has no name. */ + virtual const char_type* getNodeName() const = 0; + + //! Returns data of the current node. + /** Only valid if the node has some + data and it is of type EXN_TEXT, EXN_COMMENT, EXN_CDATA or EXN_UNKNOWN. */ + virtual const char_type* getNodeData() const = 0; + + //! Returns if an element is an empty element, like <foo /> + virtual bool isEmptyElement() const = 0; + + //! Returns format of the source xml file. + /** It is not necessary to use + this method because the parser will convert the input file format + to the format wanted by the user when creating the parser. This + method is useful to get/display additional informations. */ + virtual ETEXT_FORMAT getSourceFormat() const = 0; + + //! Returns format of the strings returned by the parser. + /** This will be UTF8 for example when you created a parser with + IrrXMLReaderUTF8() and UTF32 when it has been created using + IrrXMLReaderUTF32. It should not be necessary to call this + method and only exists for informational purposes. */ + virtual ETEXT_FORMAT getParserFormat() const = 0; + }; + + + template + struct xmlChar + { + T c; + xmlChar() {} + xmlChar(char in) : c(static_cast(in)) {} + xmlChar(wchar_t in) : c(static_cast(in)) {} +#if defined(__BORLANDC__) + // Note - removing explicit for borland was to get it to even compile. + // There haven't been any kind of tests for that besides that. + xmlChar(unsigned char in) : c(static_cast(in)) {} + xmlChar(unsigned short in) : c(static_cast(in)) {} + xmlChar(unsigned int in) : c(static_cast(in)) {} + xmlChar(unsigned long in) : c(static_cast(in)) {} +#else + explicit xmlChar(unsigned char in) : c(static_cast(in)) {} + explicit xmlChar(unsigned short in) : c(static_cast(in)) {} + explicit xmlChar(unsigned int in) : c(static_cast(in)) {} + explicit xmlChar(unsigned long in) : c(static_cast(in)) {} +#endif + operator T() const { return c; } + void operator=(int t) { c=static_cast(t); } + }; + + //! defines the utf-16 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef xmlChar char16; + + //! defines the utf-32 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef xmlChar char32; + + //! A UTF-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. + The file to read can be in any format, it will be converted to UTF-8 if it is not + in this format. + Create an instance of this with createIrrXMLReader(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReader; + + //! A UTF-16 xml parser. + /** This means that all character data will be returned in UTF-16 by this parser. + The file to read can be in any format, it will be converted to UTF-16 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF16(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF16; + + //! A UTF-32 xml parser. + /** This means that all character data will be returned in UTF-32 by this parser. + The file to read can be in any format, it will be converted to UTF-32 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF32(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF32; + + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. + The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(const char* filename); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(FILE* file); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback, + bool deleteCallback = false); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that + all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(const char* filename); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(FILE* file); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback, + bool deleteCallback = false); + + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(const char* filename); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + if you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(FILE* file); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that + all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \param deleteCallback: if true, the callback will be deleted after the file + has been read. Otherwise the caller si responsible for cleaning it up. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(IFileReadCallBack* callback, + bool deleteCallback = false); + + + /*! \file irrXML.h + \brief Header file of the irrXML, the Irrlicht XML parser. + + This file includes everything needed for using irrXML, + the XML parser of the Irrlicht Engine. To use irrXML, + you only need to include this file in your project: + + \code + #include + \endcode + + It is also common to use the two namespaces in which irrXML is included, + directly after including irrXML.h: + + \code + #include + using namespace irr; + using namespace io; + \endcode + */ + +} // end namespace io +} // end namespace irr + +#endif // __IRR_XML_H_INCLUDED__ + diff --git a/inc/irrlicht.h b/inc/irrlicht.h new file mode 100644 index 0000000..184c896 --- /dev/null +++ b/inc/irrlicht.h @@ -0,0 +1,394 @@ +/* irrlicht.h -- interface of the 'Irrlicht Engine' + + Copyright (C) 2002-2012 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Please note that the Irrlicht Engine is based in part on the work of the + Independent JPEG Group, the zlib and the libPng. This means that if you use + the Irrlicht Engine in your product, you must acknowledge somewhere in your + documentation that you've used the IJG code. It would also be nice to mention + that you use the Irrlicht Engine, the zlib and libPng. See the README files + in the jpeglib, the zlib and libPng for further informations. +*/ + +#ifndef __IRRLICHT_H_INCLUDED__ +#define __IRRLICHT_H_INCLUDED__ + +#include "IrrCompileConfig.h" +#include "aabbox3d.h" +#include "CDynamicMeshBuffer.h" +#include "CIndexBuffer.h" +#include "CMeshBuffer.h" +#include "coreutil.h" +#include "CVertexBuffer.h" +#include "dimension2d.h" +#include "ECullingTypes.h" +#include "EDebugSceneTypes.h" +#include "EDriverFeatures.h" +#include "EDriverTypes.h" +#include "EGUIAlignment.h" +#include "EGUIElementTypes.h" +#include "EHardwareBufferFlags.h" +#include "EMaterialFlags.h" +#include "EMaterialTypes.h" +#include "EMeshWriterEnums.h" +#include "EMessageBoxFlags.h" +#include "ESceneNodeAnimatorTypes.h" +#include "ESceneNodeTypes.h" +#include "ETerrainElements.h" +#include "fast_atof.h" +#include "heapsort.h" +#include "IAnimatedMesh.h" +#include "IAnimatedMeshMD2.h" +#include "IAnimatedMeshMD3.h" +#include "IAnimatedMeshSceneNode.h" +#include "IAttributeExchangingObject.h" +#include "IAttributes.h" +#include "IBillboardSceneNode.h" +#include "IBillboardTextSceneNode.h" +#include "IBoneSceneNode.h" +#include "ICameraSceneNode.h" +#include "ICursorControl.h" +#include "IDummyTransformationSceneNode.h" +#include "IDynamicMeshBuffer.h" +#include "IEventReceiver.h" +#include "IFileList.h" +#include "IFileSystem.h" +#include "IGeometryCreator.h" +#include "IGPUProgrammingServices.h" +#include "IGUIButton.h" +#include "IGUICheckBox.h" +#include "IGUIColorSelectDialog.h" +#include "IGUIComboBox.h" +#include "IGUIContextMenu.h" +#include "IGUIEditBox.h" +#include "IGUIElement.h" +#include "IGUIElementFactory.h" +#include "IGUIEnvironment.h" +#include "IGUIFileOpenDialog.h" +#include "IGUIFont.h" +#include "IGUIFontBitmap.h" +#include "IGUIImage.h" +#include "IGUIInOutFader.h" +#include "IGUIListBox.h" +#include "IGUIMeshViewer.h" +#include "IGUIScrollBar.h" +#include "IGUISkin.h" +#include "IGUISpinBox.h" +#include "IGUISpriteBank.h" +#include "IGUIStaticText.h" +#include "IGUITabControl.h" +#include "IGUITable.h" +#include "IGUIToolbar.h" +#include "IGUIWindow.h" +#include "IGUITreeView.h" +#include "IImage.h" +#include "IImageLoader.h" +#include "IImageWriter.h" +#include "IIndexBuffer.h" +#include "ILightSceneNode.h" +#include "ILogger.h" +#include "IMaterialRenderer.h" +#include "IMaterialRendererServices.h" +#include "IMesh.h" +#include "IMeshBuffer.h" +#include "IMeshCache.h" +#include "IMeshLoader.h" +#include "IMeshManipulator.h" +#include "IMeshSceneNode.h" +#include "IMeshWriter.h" +#include "IColladaMeshWriter.h" +#include "IMetaTriangleSelector.h" +#include "IOSOperator.h" +#include "IParticleSystemSceneNode.h" // also includes all emitters and attractors +#include "IQ3LevelMesh.h" +#include "IQ3Shader.h" +#include "IReadFile.h" +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "IRandomizer.h" +#include "IrrlichtDevice.h" +#include "irrList.h" +#include "irrMap.h" +#include "irrMath.h" +#include "irrString.h" +#include "irrTypes.h" +#include "path.h" +#include "irrXML.h" +#include "ISceneCollisionManager.h" +#include "ISceneLoader.h" +#include "ISceneManager.h" +#include "ISceneNode.h" +#include "ISceneNodeAnimator.h" +#include "ISceneNodeAnimatorCameraFPS.h" +#include "ISceneNodeAnimatorCameraMaya.h" +#include "ISceneNodeAnimatorCollisionResponse.h" +#include "ISceneNodeAnimatorFactory.h" +#include "ISceneNodeFactory.h" +#include "ISceneUserDataSerializer.h" +#include "IShaderConstantSetCallBack.h" +#include "IShadowVolumeSceneNode.h" +#include "ISkinnedMesh.h" +#include "ITerrainSceneNode.h" +#include "ITextSceneNode.h" +#include "ITexture.h" +#include "ITimer.h" +#include "ITriangleSelector.h" +#include "IVertexBuffer.h" +#include "IVideoDriver.h" +#include "IVideoModeList.h" +#include "IVolumeLightSceneNode.h" +#include "IWriteFile.h" +#include "IXMLReader.h" +#include "IXMLWriter.h" +#include "ILightManager.h" +#include "Keycodes.h" +#include "line2d.h" +#include "line3d.h" +#include "matrix4.h" +#include "plane3d.h" +#include "position2d.h" +#include "quaternion.h" +#include "rect.h" +#include "S3DVertex.h" +#include "SAnimatedMesh.h" +#include "SceneParameters.h" +#include "SColor.h" +#include "SExposedVideoData.h" +#include "SIrrCreationParameters.h" +#include "SKeyMap.h" +#include "SLight.h" +#include "SMaterial.h" +#include "SMesh.h" +#include "SMeshBuffer.h" +#include "SMeshBufferLightMap.h" +#include "SMeshBufferTangents.h" +#include "SParticle.h" +#include "SSharedMeshBuffer.h" +#include "SSkinMeshBuffer.h" +#include "SVertexIndex.h" +#include "SViewFrustum.h" +#include "triangle3d.h" +#include "vector2d.h" +#include "vector3d.h" + +/*! \mainpage Irrlicht Engine 1.8 API documentation + * + *
+ * + * \section intro Introduction + * + * Welcome to the Irrlicht Engine API documentation. + * Here you'll find any information you'll need to develop applications with + * the Irrlicht Engine. If you are looking for a tutorial on how to start, you'll + * find some on the homepage of the Irrlicht Engine at + * irrlicht.sourceforge.net + * or inside the SDK in the examples directory. + * + * The Irrlicht Engine is intended to be an easy-to-use 3d engine, so + * this documentation is an important part of it. If you have any questions or + * suggestions, just send a email to the author of the engine, Nikolaus Gebhardt + * (niko (at) irrlicht3d.org). + * + * + * \section links Links + * + * Namespaces: A very good place to start reading + * the documentation.
+ * Class list: List of all classes with descriptions.
+ * Class members: Good place to find forgotten features.
+ * + * \section irrexample Short example + * + * A simple application, starting up the engine, loading a Quake 2 animated + * model file and the corresponding texture, animating and displaying it + * in front of a blue background and placing a user controlable 3d camera + * would look like the following code. I think this example shows the usage + * of the engine quite well: + * + * \code + * #include + * using namespace irr; + * + * int main() + * { + * // start up the engine + * IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D8, + * core::dimension2d(640,480)); + * + * video::IVideoDriver* driver = device->getVideoDriver(); + * scene::ISceneManager* scenemgr = device->getSceneManager(); + * + * device->setWindowCaption(L"Hello World!"); + * + * // load and show quake2 .md2 model + * scene::ISceneNode* node = scenemgr->addAnimatedMeshSceneNode( + * scenemgr->getMesh("quake2model.md2")); + * + * // if everything worked, add a texture and disable lighting + * if (node) + * { + * node->setMaterialTexture(0, driver->getTexture("texture.bmp")); + * node->setMaterialFlag(video::EMF_LIGHTING, false); + * } + * + * // add a first person shooter style user controlled camera + * scenemgr->addCameraSceneNodeFPS(); + * + * // draw everything + * while(device->run() && driver) + * { + * driver->beginScene(true, true, video::SColor(255,0,0,255)); + * scenemgr->drawAll(); + * driver->endScene(); + * } + * + * // delete device + * device->drop(); + * return 0; + * } + * \endcode + * + * Irrlicht can load a lot of file formats automaticly, see irr::scene::ISceneManager::getMesh() + * for a detailed list. So if you would like to replace the simple blue screen background by + * a cool Quake 3 Map, optimized by an octree, just insert this code + * somewhere before the while loop: + * + * \code + * // add .pk3 archive to the file system + * device->getFileSystem()->addZipFileArchive("quake3map.pk3"); + * + * // load .bsp file and show it using an octree + * scenemgr->addOctreeSceneNode( + * scenemgr->getMesh("quake3map.bsp")); + * \endcode + * + * As you can see, the engine uses namespaces. Everything in the engine is + * placed into the namespace 'irr', but there are also 5 sub namespaces. + * You can find a list of all namespaces with descriptions at the + * namespaces page. + * This is also a good place to start reading the documentation. If you + * don't want to write the namespace names all the time, just use all namespaces like + * this: + * \code + * using namespace core; + * using namespace scene; + * using namespace video; + * using namespace io; + * using namespace gui; + * \endcode + * + * There is a lot more the engine can do, but I hope this gave a short + * overview over the basic features of the engine. For more examples, please take + * a look into the examples directory of the SDK. + */ + +#include "SIrrCreationParameters.h" + +//! Everything in the Irrlicht Engine can be found in this namespace. +namespace irr +{ + //! Creates an Irrlicht device. The Irrlicht device is the root object for using the engine. + /** If you need more parameters to be passed to the creation of the Irrlicht Engine device, + use the createDeviceEx() function. + \param deviceType: Type of the device. This can currently be video::EDT_NULL, + video::EDT_SOFTWARE, video::EDT_BURNINGSVIDEO, video::EDT_DIRECT3D8, video::EDT_DIRECT3D9 and video::EDT_OPENGL. + \param windowSize: Size of the window or the video mode in fullscreen mode. + \param bits: Bits per pixel in fullscreen mode. Ignored if windowed mode. + \param fullscreen: Should be set to true if the device should run in fullscreen. Otherwise + the device runs in windowed mode. + \param stencilbuffer: Specifies if the stencil buffer should be enabled. Set this to true, + if you want the engine be able to draw stencil buffer shadows. Note that not all + devices are able to use the stencil buffer. If they don't no shadows will be drawn. + \param vsync: Specifies vertical syncronisation: If set to true, the driver will wait + for the vertical retrace period, otherwise not. + \param receiver: A user created event receiver. + \return Returns pointer to the created IrrlichtDevice or null if the + device could not be created. + */ + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( + video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, + // parantheses are necessary for some compilers + const core::dimension2d& windowSize = (core::dimension2d(640,480)), + u32 bits = 16, + bool fullscreen = false, + bool stencilbuffer = false, + bool vsync = false, + IEventReceiver* receiver = 0); + + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDevice )( + video::E_DRIVER_TYPE deviceType, + const core::dimension2d& windowSize, + u32 bits, + bool fullscreen, + bool stencilbuffer, + bool vsync, + IEventReceiver* receiver); + + + //! Creates an Irrlicht device with the option to specify advanced parameters. + /** Usually you should used createDevice() for creating an Irrlicht Engine device. + Use this function only if you wish to specify advanced parameters like a window + handle in which the device should be created. + \param parameters: Structure containing advanced parameters for the creation of the device. + See irr::SIrrlichtCreationParameters for details. + \return Returns pointer to the created IrrlichtDevice or null if the + device could not be created. */ + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( + const SIrrlichtCreationParameters& parameters); + + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDeviceEx )( const SIrrlichtCreationParameters& parameters ); + + + // THE FOLLOWING IS AN EMPTY LIST OF ALL SUB NAMESPACES + // EXISTING ONLY FOR THE DOCUMENTATION SOFTWARE DOXYGEN. + + //! Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace. + namespace core + { + } + + //! The gui namespace contains useful classes for easy creation of a graphical user interface. + namespace gui + { + } + + //! This namespace provides interfaces for input/output: Reading and writing files, accessing zip archives, xml files, ... + namespace io + { + } + + //! All scene management can be found in this namespace: Mesh loading, special scene nodes like octrees and billboards, ... + namespace scene + { + } + + //! The video namespace contains classes for accessing the video driver. All 2d and 3d rendering is done here. + namespace video + { + } +} + +/*! \file irrlicht.h + \brief Main header file of the irrlicht, the only file needed to include. +*/ + +#endif + diff --git a/inc/irrpack.h b/inc/irrpack.h new file mode 100644 index 0000000..d030b6b --- /dev/null +++ b/inc/irrpack.h @@ -0,0 +1,39 @@ +// Copyright (C) 2007-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// include this file right before the data structures to be 1-aligned +// and add to each structure the PACK_STRUCT define just like this: +// struct mystruct +// { +// ... +// } PACK_STRUCT; +// Always include the irrunpack.h file right after the last type declared +// like this, and do not put any other types with different alignment +// in between! + +// byte-align structures +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma warning(disable: 4103) +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __DMC__ ) +# pragma pack( push, 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) + // Using pragma pack might work with earlier gcc versions already, but + // it started to be necessary with gcc 4.7 on mingw unless compiled with -mno-ms-bitfields. + // And I found some hints on the web that older gcc versions on the other hand had sometimes + // trouble with pragma pack while they worked with __attribute__((packed)). +# if (__GNUC__ > 4 ) || ((__GNUC__ == 4 ) && (__GNUC_MINOR__ >= 7)) +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +# else +# define PACK_STRUCT __attribute__((packed)) + #endif +#else +# error compiler not supported +#endif + diff --git a/inc/irrunpack.h b/inc/irrunpack.h new file mode 100644 index 0000000..e86f351 --- /dev/null +++ b/inc/irrunpack.h @@ -0,0 +1,20 @@ +// Copyright (C) 2007-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// include this file to switch back to default alignment +// file belongs to irrpack.h, see there for more info + +// Default alignment +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop, packing ) +#elif defined (__DMC__) +# pragma pack( pop ) +#elif defined( __GNUC__ ) +# if (__GNUC__ > 4 ) || ((__GNUC__ == 4 ) && (__GNUC_MINOR__ >= 7)) +# pragma pack( pop, packing ) +# endif +#endif + +#undef PACK_STRUCT + diff --git a/inc/line2d.h b/inc/line2d.h new file mode 100644 index 0000000..22590dc --- /dev/null +++ b/inc/line2d.h @@ -0,0 +1,274 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_LINE_2D_H_INCLUDED__ +#define __IRR_LINE_2D_H_INCLUDED__ + +#include "irrTypes.h" +#include "vector2d.h" + +namespace irr +{ +namespace core +{ + +//! 2D line between two points with intersection methods. +template +class line2d +{ + public: + //! Default constructor for line going from (0,0) to (1,1). + line2d() : start(0,0), end(1,1) {} + //! Constructor for line between the two points. + line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {} + //! Constructor for line between the two points given as vectors. + line2d(const vector2d& start, const vector2d& end) : start(start), end(end) {} + //! Copy constructor. + line2d(const line2d& other) : start(other.start), end(other.end) {} + + // operators + + line2d operator+(const vector2d& point) const { return line2d(start + point, end + point); } + line2d& operator+=(const vector2d& point) { start += point; end += point; return *this; } + + line2d operator-(const vector2d& point) const { return line2d(start - point, end - point); } + line2d& operator-=(const vector2d& point) { start -= point; end -= point; return *this; } + + bool operator==(const line2d& other) const + { return (start==other.start && end==other.end) || (end==other.start && start==other.end);} + bool operator!=(const line2d& other) const + { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);} + + // functions + //! Set this line to new line going through the two points. + void setLine(const T& xa, const T& ya, const T& xb, const T& yb){start.set(xa, ya); end.set(xb, yb);} + //! Set this line to new line going through the two points. + void setLine(const vector2d& nstart, const vector2d& nend){start.set(nstart); end.set(nend);} + //! Set this line to new line given as parameter. + void setLine(const line2d& line){start.set(line.start); end.set(line.end);} + + //! Get length of line + /** \return Length of the line. */ + T getLength() const { return start.getDistanceFrom(end); } + + //! Get squared length of the line + /** \return Squared length of line. */ + T getLengthSQ() const { return start.getDistanceFromSQ(end); } + + //! Get middle of the line + /** \return center of the line. */ + vector2d getMiddle() const + { + return (start + end)/(T)2; + } + + //! Get the vector of the line. + /** \return The vector of the line. */ + vector2d getVector() const { return vector2d(end.X - start.X, end.Y - start.Y); } + + //! Tests if this line intersects with another line. + /** \param l: Other line to test intersection with. + \param checkOnlySegments: Default is to check intersection between the begin and endpoints. + When set to false the function will check for the first intersection point when extending the lines. + \param out: If there is an intersection, the location of the + intersection will be stored in this vector. + \return True if there is an intersection, false if not. */ + bool intersectWith(const line2d& l, vector2d& out, bool checkOnlySegments=true) const + { + // Uses the method given at: + // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ + const f32 commonDenominator = (f32)(l.end.Y - l.start.Y)*(end.X - start.X) - + (l.end.X - l.start.X)*(end.Y - start.Y); + + const f32 numeratorA = (f32)(l.end.X - l.start.X)*(start.Y - l.start.Y) - + (l.end.Y - l.start.Y)*(start.X -l.start.X); + + const f32 numeratorB = (f32)(end.X - start.X)*(start.Y - l.start.Y) - + (end.Y - start.Y)*(start.X -l.start.X); + + if(equals(commonDenominator, 0.f)) + { + // The lines are either coincident or parallel + // if both numerators are 0, the lines are coincident + if(equals(numeratorA, 0.f) && equals(numeratorB, 0.f)) + { + // Try and find a common endpoint + if(l.start == start || l.end == start) + out = start; + else if(l.end == end || l.start == end) + out = end; + // now check if the two segments are disjunct + else if (l.start.X>start.X && l.end.X>start.X && l.start.X>end.X && l.end.X>end.X) + return false; + else if (l.start.Y>start.Y && l.end.Y>start.Y && l.start.Y>end.Y && l.end.Y>end.Y) + return false; + else if (l.start.X maxp; + vector2d minp; + if ((start.X>l.start.X && start.X>l.end.X && start.X>end.X) || (start.Y>l.start.Y && start.Y>l.end.Y && start.Y>end.Y)) + maxp=start; + else if ((end.X>l.start.X && end.X>l.end.X && end.X>start.X) || (end.Y>l.start.Y && end.Y>l.end.Y && end.Y>start.Y)) + maxp=end; + else if ((l.start.X>start.X && l.start.X>l.end.X && l.start.X>end.X) || (l.start.Y>start.Y && l.start.Y>l.end.Y && l.start.Y>end.Y)) + maxp=l.start; + else + maxp=l.end; + if (maxp != start && ((start.X(); + if (start != maxp && start != minp) + out += start; + if (end != maxp && end != minp) + out += end; + if (l.start != maxp && l.start != minp) + out += l.start; + if (l.end != maxp && l.end != minp) + out += l.end; + out.X = (T)(out.X/2); + out.Y = (T)(out.Y/2); + } + + return true; // coincident + } + + return false; // parallel + } + + // Get the point of intersection on this line, checking that + // it is within the line segment. + const f32 uA = numeratorA / commonDenominator; + if(checkOnlySegments && (uA < 0.f || uA > 1.f) ) + return false; // Outside the line segment + + const f32 uB = numeratorB / commonDenominator; + if(checkOnlySegments && (uB < 0.f || uB > 1.f)) + return false; // Outside the line segment + + // Calculate the intersection point. + out.X = (T)(start.X + uA * (end.X - start.X)); + out.Y = (T)(start.Y + uA * (end.Y - start.Y)); + return true; + } + + //! Get unit vector of the line. + /** \return Unit vector of this line. */ + vector2d getUnitVector() const + { + T len = (T)(1.0 / getLength()); + return vector2d((end.X - start.X) * len, (end.Y - start.Y) * len); + } + + //! Get angle between this line and given line. + /** \param l Other line for test. + \return Angle in degrees. */ + f64 getAngleWith(const line2d& l) const + { + vector2d vect = getVector(); + vector2d vect2 = l.getVector(); + return vect.getAngleWith(vect2); + } + + //! Tells us if the given point lies to the left, right, or on the line. + /** \return 0 if the point is on the line + <0 if to the left, or >0 if to the right. */ + T getPointOrientation(const vector2d& point) const + { + return ( (end.X - start.X) * (point.Y - start.Y) - + (point.X - start.X) * (end.Y - start.Y) ); + } + + //! Check if the given point is a member of the line + /** \return True if point is between start and end, else false. */ + bool isPointOnLine(const vector2d& point) const + { + T d = getPointOrientation(point); + return (d == 0 && point.isBetweenPoints(start, end)); + } + + //! Check if the given point is between start and end of the line. + /** Assumes that the point is already somewhere on the line. */ + bool isPointBetweenStartAndEnd(const vector2d& point) const + { + return point.isBetweenPoints(start, end); + } + + //! Get the closest point on this line to a point + /** \param checkOnlySegments: Default (true) is to return a point on the line-segment (between begin and end) of the line. + When set to false the function will check for the first the closest point on the the line even when outside the segment. */ + vector2d getClosestPoint(const vector2d& point, bool checkOnlySegments=true) const + { + vector2d c((f64)(point.X-start.X), (f64)(point.Y- start.Y)); + vector2d v((f64)(end.X-start.X), (f64)(end.Y-start.Y)); + f64 d = v.getLength(); + if ( d == 0 ) // can't tell much when the line is just a single point + return start; + v /= d; + f64 t = v.dotProduct(c); + + if ( checkOnlySegments ) + { + if (t < 0) return vector2d((T)start.X, (T)start.Y); + if (t > d) return vector2d((T)end.X, (T)end.Y); + } + + v *= t; + return vector2d((T)(start.X + v.X), (T)(start.Y + v.Y)); + } + + //! Start point of the line. + vector2d start; + //! End point of the line. + vector2d end; +}; + + // partial specialization to optimize lines (avoiding casts) + template <> + inline vector2df line2d::getClosestPoint(const vector2df& point, bool checkOnlySegments) const + { + vector2df c = point - start; + vector2df v = end - start; + f32 d = (f32)v.getLength(); + if ( d == 0 ) // can't tell much when the line is just a single point + return start; + v /= d; + f32 t = v.dotProduct(c); + + if ( checkOnlySegments ) + { + if (t < 0) return start; + if (t > d) return end; + } + + v *= t; + return start + v; + } + + + //! Typedef for an f32 line. + typedef line2d line2df; + //! Typedef for an integer line. + typedef line2d line2di; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/line3d.h b/inc/line3d.h new file mode 100644 index 0000000..5e1437a --- /dev/null +++ b/inc/line3d.h @@ -0,0 +1,144 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_LINE_3D_H_INCLUDED__ +#define __IRR_LINE_3D_H_INCLUDED__ + +#include "irrTypes.h" +#include "vector3d.h" + +namespace irr +{ +namespace core +{ + +//! 3D line between two points with intersection methods. +template +class line3d +{ + public: + + //! Default constructor + /** line from (0,0,0) to (1,1,1) */ + line3d() : start(0,0,0), end(1,1,1) {} + //! Constructor with two points + line3d(T xa, T ya, T za, T xb, T yb, T zb) : start(xa, ya, za), end(xb, yb, zb) {} + //! Constructor with two points as vectors + line3d(const vector3d& start, const vector3d& end) : start(start), end(end) {} + + // operators + + line3d operator+(const vector3d& point) const { return line3d(start + point, end + point); } + line3d& operator+=(const vector3d& point) { start += point; end += point; return *this; } + + line3d operator-(const vector3d& point) const { return line3d(start - point, end - point); } + line3d& operator-=(const vector3d& point) { start -= point; end -= point; return *this; } + + bool operator==(const line3d& other) const + { return (start==other.start && end==other.end) || (end==other.start && start==other.end);} + bool operator!=(const line3d& other) const + { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);} + + // functions + //! Set this line to a new line going through the two points. + void setLine(const T& xa, const T& ya, const T& za, const T& xb, const T& yb, const T& zb) + {start.set(xa, ya, za); end.set(xb, yb, zb);} + //! Set this line to a new line going through the two points. + void setLine(const vector3d& nstart, const vector3d& nend) + {start.set(nstart); end.set(nend);} + //! Set this line to new line given as parameter. + void setLine(const line3d& line) + {start.set(line.start); end.set(line.end);} + + //! Get length of line + /** \return Length of line. */ + T getLength() const { return start.getDistanceFrom(end); } + + //! Get squared length of line + /** \return Squared length of line. */ + T getLengthSQ() const { return start.getDistanceFromSQ(end); } + + //! Get middle of line + /** \return Center of line. */ + vector3d getMiddle() const + { + return (start + end)/(T)2; + } + + //! Get vector of line + /** \return vector of line. */ + vector3d getVector() const + { + return end - start; + } + + //! Check if the given point is between start and end of the line. + /** Assumes that the point is already somewhere on the line. + \param point The point to test. + \return True if point is on the line between start and end, else false. + */ + bool isPointBetweenStartAndEnd(const vector3d& point) const + { + return point.isBetweenPoints(start, end); + } + + //! Get the closest point on this line to a point + /** \param point The point to compare to. + \return The nearest point which is part of the line. */ + vector3d getClosestPoint(const vector3d& point) const + { + vector3d c = point - start; + vector3d v = end - start; + T d = (T)v.getLength(); + v /= d; + T t = v.dotProduct(c); + + if (t < (T)0.0) + return start; + if (t > d) + return end; + + v *= t; + return start + v; + } + + //! Check if the line intersects with a shpere + /** \param sorigin: Origin of the shpere. + \param sradius: Radius of the sphere. + \param outdistance: The distance to the first intersection point. + \return True if there is an intersection. + If there is one, the distance to the first intersection point + is stored in outdistance. */ + bool getIntersectionWithSphere(vector3d sorigin, T sradius, f64& outdistance) const + { + const vector3d q = sorigin - start; + T c = q.getLength(); + T v = q.dotProduct(getVector().normalize()); + T d = sradius * sradius - (c*c - v*v); + + if (d < 0.0) + return false; + + outdistance = v - core::squareroot ( d ); + return true; + } + + // member variables + + //! Start point of line + vector3d start; + //! End point of line + vector3d end; +}; + + //! Typedef for an f32 line. + typedef line3d line3df; + //! Typedef for an integer line. + typedef line3d line3di; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/matrix4.h b/inc/matrix4.h new file mode 100644 index 0000000..6a29d55 --- /dev/null +++ b/inc/matrix4.h @@ -0,0 +1,2244 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_MATRIX_H_INCLUDED__ +#define __IRR_MATRIX_H_INCLUDED__ + +#include "irrMath.h" +#include "vector3d.h" +#include "vector2d.h" +#include "plane3d.h" +#include "aabbox3d.h" +#include "rect.h" +#include "irrString.h" + +// enable this to keep track of changes to the matrix +// and make simpler identity check for seldomly changing matrices +// otherwise identity check will always compare the elements +//#define USE_MATRIX_TEST + +// this is only for debugging purposes +//#define USE_MATRIX_TEST_DEBUG + +#if defined( USE_MATRIX_TEST_DEBUG ) + +struct MatrixTest +{ + MatrixTest () : ID(0), Calls(0) {} + char buf[256]; + int Calls; + int ID; +}; +static MatrixTest MTest; + +#endif + +namespace irr +{ +namespace core +{ + + //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations. + /** The matrix is a D3D style matrix, row major with translations in the 4th row. */ + template + class CMatrix4 + { + public: + + //! Constructor Flags + enum eConstructor + { + EM4CONST_NOTHING = 0, + EM4CONST_COPY, + EM4CONST_IDENTITY, + EM4CONST_TRANSPOSED, + EM4CONST_INVERSE, + EM4CONST_INVERSE_TRANSPOSED + }; + + //! Default constructor + /** \param constructor Choose the initialization style */ + CMatrix4( eConstructor constructor = EM4CONST_IDENTITY ); + //! Copy constructor + /** \param other Other matrix to copy from + \param constructor Choose the initialization style */ + CMatrix4(const CMatrix4& other, eConstructor constructor = EM4CONST_COPY); + + //! Simple operator for directly accessing every element of the matrix. + T& operator()(const s32 row, const s32 col) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[ row * 4 + col ]; + } + + //! Simple operator for directly accessing every element of the matrix. + const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; } + + //! Simple operator for linearly accessing every element of the matrix. + T& operator[](u32 index) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[index]; + } + + //! Simple operator for linearly accessing every element of the matrix. + const T& operator[](u32 index) const { return M[index]; } + + //! Sets this matrix equal to the other matrix. + inline CMatrix4& operator=(const CMatrix4 &other); + + //! Sets all elements of this matrix to the value. + inline CMatrix4& operator=(const T& scalar); + + //! Returns pointer to internal array + const T* pointer() const { return M; } + T* pointer() + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M; + } + + //! Returns true if other matrix is equal to this matrix. + bool operator==(const CMatrix4 &other) const; + + //! Returns true if other matrix is not equal to this matrix. + bool operator!=(const CMatrix4 &other) const; + + //! Add another matrix. + CMatrix4 operator+(const CMatrix4& other) const; + + //! Add another matrix. + CMatrix4& operator+=(const CMatrix4& other); + + //! Subtract another matrix. + CMatrix4 operator-(const CMatrix4& other) const; + + //! Subtract another matrix. + CMatrix4& operator-=(const CMatrix4& other); + + //! set this matrix to the product of two matrices + /** Calculate b*a */ + inline CMatrix4& setbyproduct(const CMatrix4& other_a,const CMatrix4& other_b ); + + //! Set this matrix to the product of two matrices + /** Calculate b*a, no optimization used, + use it if you know you never have a identity matrix */ + CMatrix4& setbyproduct_nocheck(const CMatrix4& other_a,const CMatrix4& other_b ); + + //! Multiply by another matrix. + /** Calculate other*this */ + CMatrix4 operator*(const CMatrix4& other) const; + + //! Multiply by another matrix. + /** Calculate and return other*this */ + CMatrix4& operator*=(const CMatrix4& other); + + //! Multiply by scalar. + CMatrix4 operator*(const T& scalar) const; + + //! Multiply by scalar. + CMatrix4& operator*=(const T& scalar); + + //! Set matrix to identity. + inline CMatrix4& makeIdentity(); + + //! Returns true if the matrix is the identity matrix + inline bool isIdentity() const; + + //! Returns true if the matrix is orthogonal + inline bool isOrthogonal() const; + + //! Returns true if the matrix is the identity matrix + bool isIdentity_integer_base () const; + + //! Set the translation of the current matrix. Will erase any previous values. + CMatrix4& setTranslation( const vector3d& translation ); + + //! Gets the current translation + vector3d getTranslation() const; + + //! Set the inverse translation of the current matrix. Will erase any previous values. + CMatrix4& setInverseTranslation( const vector3d& translation ); + + //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. + inline CMatrix4& setRotationRadians( const vector3d& rotation ); + + //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. + CMatrix4& setRotationDegrees( const vector3d& rotation ); + + //! Returns the rotation, as set by setRotation(). + /** This code was orginally written by by Chev. */ + core::vector3d getRotationDegrees() const; + + //! Make an inverted rotation matrix from Euler angles. + /** The 4th row and column are unmodified. */ + inline CMatrix4& setInverseRotationRadians( const vector3d& rotation ); + + //! Make an inverted rotation matrix from Euler angles. + /** The 4th row and column are unmodified. */ + inline CMatrix4& setInverseRotationDegrees( const vector3d& rotation ); + + //! Make a rotation matrix from angle and axis, assuming left handed rotation. + /** The 4th row and column are unmodified. */ + inline CMatrix4& setRotationAxisRadians(const T& angle, const vector3d& axis); + + //! Set Scale + CMatrix4& setScale( const vector3d& scale ); + + //! Set Scale + CMatrix4& setScale( const T scale ) { return setScale(core::vector3d(scale,scale,scale)); } + + //! Get Scale + core::vector3d getScale() const; + + //! Translate a vector by the inverse of the translation part of this matrix. + void inverseTranslateVect( vector3df& vect ) const; + + //! Rotate a vector by the inverse of the rotation part of this matrix. + void inverseRotateVect( vector3df& vect ) const; + + //! Rotate a vector by the rotation part of this matrix. + void rotateVect( vector3df& vect ) const; + + //! An alternate transform vector method, writing into a second vector + void rotateVect(core::vector3df& out, const core::vector3df& in) const; + + //! An alternate transform vector method, writing into an array of 3 floats + void rotateVect(T *out,const core::vector3df &in) const; + + //! Transforms the vector by this matrix + void transformVect( vector3df& vect) const; + + //! Transforms input vector by this matrix and stores result in output vector + void transformVect( vector3df& out, const vector3df& in ) const; + + //! An alternate transform vector method, writing into an array of 4 floats + void transformVect(T *out,const core::vector3df &in) const; + + //! An alternate transform vector method, reading from and writing to an array of 3 floats + void transformVec3(T *out, const T * in) const; + + //! Translate a vector by the translation part of this matrix. + void translateVect( vector3df& vect ) const; + + //! Transforms a plane by this matrix + void transformPlane( core::plane3d &plane) const; + + //! Transforms a plane by this matrix + void transformPlane( const core::plane3d &in, core::plane3d &out) const; + + //! Transforms a axis aligned bounding box + /** The result box of this operation may not be accurate at all. For + correct results, use transformBoxEx() */ + void transformBox(core::aabbox3d& box) const; + + //! Transforms a axis aligned bounding box + /** The result box of this operation should by accurate, but this operation + is slower than transformBox(). */ + void transformBoxEx(core::aabbox3d& box) const; + + //! Multiplies this matrix by a 1x4 matrix + void multiplyWith1x4Matrix(T* matrix) const; + + //! Calculates inverse of matrix. Slow. + /** \return Returns false if there is no inverse matrix.*/ + bool makeInverse(); + + + //! Inverts a primitive matrix which only contains a translation and a rotation + /** \param out: where result matrix is written to. */ + bool getInversePrimitive ( CMatrix4& out ) const; + + //! Gets the inversed matrix of this one + /** \param out: where result matrix is written to. + \return Returns false if there is no inverse matrix. */ + bool getInverse(CMatrix4& out) const; + + //! Builds a right-handed perspective projection matrix based on a field of view + CMatrix4& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); + + //! Builds a left-handed perspective projection matrix based on a field of view + CMatrix4& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); + + //! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity + CMatrix4& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0); + + //! Builds a right-handed perspective projection matrix. + CMatrix4& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); + + //! Builds a left-handed perspective projection matrix. + CMatrix4& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); + + //! Builds a left-handed orthogonal projection matrix. + CMatrix4& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); + + //! Builds a right-handed orthogonal projection matrix. + CMatrix4& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); + + //! Builds a left-handed look-at matrix. + CMatrix4& buildCameraLookAtMatrixLH( + const vector3df& position, + const vector3df& target, + const vector3df& upVector); + + //! Builds a right-handed look-at matrix. + CMatrix4& buildCameraLookAtMatrixRH( + const vector3df& position, + const vector3df& target, + const vector3df& upVector); + + //! Builds a matrix that flattens geometry into a plane. + /** \param light: light source + \param plane: plane into which the geometry if flattened into + \param point: value between 0 and 1, describing the light source. + If this is 1, it is a point light, if it is 0, it is a directional light. */ + CMatrix4& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); + + //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. + /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */ + CMatrix4& buildNDCToDCMatrix( const core::rect& area, f32 zScale); + + //! Creates a new matrix as interpolated matrix from two other ones. + /** \param b: other matrix to interpolate with + \param time: Must be a value between 0 and 1. */ + CMatrix4 interpolate(const core::CMatrix4& b, f32 time) const; + + //! Gets transposed matrix + CMatrix4 getTransposed() const; + + //! Gets transposed matrix + inline void getTransposed( CMatrix4& dest ) const; + + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + */ + CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); + + //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards + /** \param center Position to rotate around + \param translate Translation applied after the rotation + */ + void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coo + \param center: object position in world-coo and rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + void buildAxisAlignedBillboard(const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from); + + /* + construct 2D Texture transformations + rotate about center, scale, and transform. + */ + //! Set to a texture transformation matrix with the given parameters. + CMatrix4& buildTextureTransform( f32 rotateRad, + const core::vector2df &rotatecenter, + const core::vector2df &translate, + const core::vector2df &scale); + + //! Set texture transformation rotation + /** Rotate about z axis, recenter at (0.5,0.5). + Doesn't clear other elements than those affected + \param radAngle Angle in radians + \return Altered matrix */ + CMatrix4& setTextureRotationCenter( f32 radAngle ); + + //! Set texture transformation translation + /** Doesn't clear other elements than those affected. + \param x Offset on x axis + \param y Offset on y axis + \return Altered matrix */ + CMatrix4& setTextureTranslate( f32 x, f32 y ); + + //! Set texture transformation translation, using a transposed representation + /** Doesn't clear other elements than those affected. + \param x Offset on x axis + \param y Offset on y axis + \return Altered matrix */ + CMatrix4& setTextureTranslateTransposed( f32 x, f32 y ); + + //! Set texture transformation scale + /** Doesn't clear other elements than those affected. + \param sx Scale factor on x axis + \param sy Scale factor on y axis + \return Altered matrix. */ + CMatrix4& setTextureScale( f32 sx, f32 sy ); + + //! Set texture transformation scale, and recenter at (0.5,0.5) + /** Doesn't clear other elements than those affected. + \param sx Scale factor on x axis + \param sy Scale factor on y axis + \return Altered matrix. */ + CMatrix4& setTextureScaleCenter( f32 sx, f32 sy ); + + //! Sets all matrix data members at once + CMatrix4& setM(const T* data); + + //! Sets if the matrix is definitely identity matrix + void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix); + + //! Gets if the matrix is definitely identity matrix + bool getDefinitelyIdentityMatrix() const; + + //! Compare two matrices using the equal method + bool equals(const core::CMatrix4& other, const T tolerance=(T)ROUNDING_ERROR_f64) const; + + private: + //! Matrix data, stored in row-major order + T M[16]; +#if defined ( USE_MATRIX_TEST ) + //! Flag is this matrix is identity matrix + mutable u32 definitelyIdentityMatrix; +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + u32 id; + mutable u32 calls; +#endif + + }; + + // Default constructor + template + inline CMatrix4::CMatrix4( eConstructor constructor ) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif + { + switch ( constructor ) + { + case EM4CONST_NOTHING: + case EM4CONST_COPY: + break; + case EM4CONST_IDENTITY: + case EM4CONST_INVERSE: + default: + makeIdentity(); + break; + } + } + + // Copy constructor + template + inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif + { + switch ( constructor ) + { + case EM4CONST_IDENTITY: + makeIdentity(); + break; + case EM4CONST_NOTHING: + break; + case EM4CONST_COPY: + *this = other; + break; + case EM4CONST_TRANSPOSED: + other.getTransposed(*this); + break; + case EM4CONST_INVERSE: + if (!other.getInverse(*this)) + memset(M, 0, 16*sizeof(T)); + break; + case EM4CONST_INVERSE_TRANSPOSED: + if (!other.getInverse(*this)) + memset(M, 0, 16*sizeof(T)); + else + *this=getTransposed(); + break; + } + } + + //! Add another matrix. + template + inline CMatrix4 CMatrix4::operator+(const CMatrix4& other) const + { + CMatrix4 temp ( EM4CONST_NOTHING ); + + temp[0] = M[0]+other[0]; + temp[1] = M[1]+other[1]; + temp[2] = M[2]+other[2]; + temp[3] = M[3]+other[3]; + temp[4] = M[4]+other[4]; + temp[5] = M[5]+other[5]; + temp[6] = M[6]+other[6]; + temp[7] = M[7]+other[7]; + temp[8] = M[8]+other[8]; + temp[9] = M[9]+other[9]; + temp[10] = M[10]+other[10]; + temp[11] = M[11]+other[11]; + temp[12] = M[12]+other[12]; + temp[13] = M[13]+other[13]; + temp[14] = M[14]+other[14]; + temp[15] = M[15]+other[15]; + + return temp; + } + + //! Add another matrix. + template + inline CMatrix4& CMatrix4::operator+=(const CMatrix4& other) + { + M[0]+=other[0]; + M[1]+=other[1]; + M[2]+=other[2]; + M[3]+=other[3]; + M[4]+=other[4]; + M[5]+=other[5]; + M[6]+=other[6]; + M[7]+=other[7]; + M[8]+=other[8]; + M[9]+=other[9]; + M[10]+=other[10]; + M[11]+=other[11]; + M[12]+=other[12]; + M[13]+=other[13]; + M[14]+=other[14]; + M[15]+=other[15]; + + return *this; + } + + //! Subtract another matrix. + template + inline CMatrix4 CMatrix4::operator-(const CMatrix4& other) const + { + CMatrix4 temp ( EM4CONST_NOTHING ); + + temp[0] = M[0]-other[0]; + temp[1] = M[1]-other[1]; + temp[2] = M[2]-other[2]; + temp[3] = M[3]-other[3]; + temp[4] = M[4]-other[4]; + temp[5] = M[5]-other[5]; + temp[6] = M[6]-other[6]; + temp[7] = M[7]-other[7]; + temp[8] = M[8]-other[8]; + temp[9] = M[9]-other[9]; + temp[10] = M[10]-other[10]; + temp[11] = M[11]-other[11]; + temp[12] = M[12]-other[12]; + temp[13] = M[13]-other[13]; + temp[14] = M[14]-other[14]; + temp[15] = M[15]-other[15]; + + return temp; + } + + //! Subtract another matrix. + template + inline CMatrix4& CMatrix4::operator-=(const CMatrix4& other) + { + M[0]-=other[0]; + M[1]-=other[1]; + M[2]-=other[2]; + M[3]-=other[3]; + M[4]-=other[4]; + M[5]-=other[5]; + M[6]-=other[6]; + M[7]-=other[7]; + M[8]-=other[8]; + M[9]-=other[9]; + M[10]-=other[10]; + M[11]-=other[11]; + M[12]-=other[12]; + M[13]-=other[13]; + M[14]-=other[14]; + M[15]-=other[15]; + + return *this; + } + + //! Multiply by scalar. + template + inline CMatrix4 CMatrix4::operator*(const T& scalar) const + { + CMatrix4 temp ( EM4CONST_NOTHING ); + + temp[0] = M[0]*scalar; + temp[1] = M[1]*scalar; + temp[2] = M[2]*scalar; + temp[3] = M[3]*scalar; + temp[4] = M[4]*scalar; + temp[5] = M[5]*scalar; + temp[6] = M[6]*scalar; + temp[7] = M[7]*scalar; + temp[8] = M[8]*scalar; + temp[9] = M[9]*scalar; + temp[10] = M[10]*scalar; + temp[11] = M[11]*scalar; + temp[12] = M[12]*scalar; + temp[13] = M[13]*scalar; + temp[14] = M[14]*scalar; + temp[15] = M[15]*scalar; + + return temp; + } + + //! Multiply by scalar. + template + inline CMatrix4& CMatrix4::operator*=(const T& scalar) + { + M[0]*=scalar; + M[1]*=scalar; + M[2]*=scalar; + M[3]*=scalar; + M[4]*=scalar; + M[5]*=scalar; + M[6]*=scalar; + M[7]*=scalar; + M[8]*=scalar; + M[9]*=scalar; + M[10]*=scalar; + M[11]*=scalar; + M[12]*=scalar; + M[13]*=scalar; + M[14]*=scalar; + M[15]*=scalar; + + return *this; + } + + //! Multiply by another matrix. + template + inline CMatrix4& CMatrix4::operator*=(const CMatrix4& other) + { +#if defined ( USE_MATRIX_TEST ) + // do checks on your own in order to avoid copy creation + if ( !other.isIdentity() ) + { + if ( this->isIdentity() ) + { + return (*this = other); + } + else + { + CMatrix4 temp ( *this ); + return setbyproduct_nocheck( temp, other ); + } + } + return *this; +#else + CMatrix4 temp ( *this ); + return setbyproduct_nocheck( temp, other ); +#endif + } + + //! multiply by another matrix + // set this matrix to the product of two other matrices + // goal is to reduce stack use and copy + template + inline CMatrix4& CMatrix4::setbyproduct_nocheck(const CMatrix4& other_a,const CMatrix4& other_b ) + { + const T *m1 = other_a.M; + const T *m2 = other_b.M; + + M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; + M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; + M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; + M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; + + M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; + M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; + M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; + M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; + + M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; + M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; + M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; + M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; + + M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; + M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; + M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; + M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + //! multiply by another matrix + // set this matrix to the product of two other matrices + // goal is to reduce stack use and copy + template + inline CMatrix4& CMatrix4::setbyproduct(const CMatrix4& other_a, const CMatrix4& other_b ) + { +#if defined ( USE_MATRIX_TEST ) + if ( other_a.isIdentity () ) + return (*this = other_b); + else + if ( other_b.isIdentity () ) + return (*this = other_a); + else + return setbyproduct_nocheck(other_a,other_b); +#else + return setbyproduct_nocheck(other_a,other_b); +#endif + } + + //! multiply by another matrix + template + inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const + { +#if defined ( USE_MATRIX_TEST ) + // Testing purpose.. + if ( this->isIdentity() ) + return m2; + if ( m2.isIdentity() ) + return *this; +#endif + + CMatrix4 m3 ( EM4CONST_NOTHING ); + + const T *m1 = M; + + m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; + m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; + m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; + m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; + + m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; + m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; + m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; + m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; + + m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; + m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; + m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; + m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; + + m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; + m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; + m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; + m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; + return m3; + } + + + + template + inline vector3d CMatrix4::getTranslation() const + { + return vector3d(M[12], M[13], M[14]); + } + + + template + inline CMatrix4& CMatrix4::setTranslation( const vector3d& translation ) + { + M[12] = translation.X; + M[13] = translation.Y; + M[14] = translation.Z; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + template + inline CMatrix4& CMatrix4::setInverseTranslation( const vector3d& translation ) + { + M[12] = -translation.X; + M[13] = -translation.Y; + M[14] = -translation.Z; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + template + inline CMatrix4& CMatrix4::setScale( const vector3d& scale ) + { + M[0] = scale.X; + M[5] = scale.Y; + M[10] = scale.Z; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + //! Returns the absolute values of the scales of the matrix. + /** + Note that this returns the absolute (positive) values unless only scale is set. + Unfortunately it does not appear to be possible to extract any original negative + values. The best that we could do would be to arbitrarily make one scale + negative if one or three of them were negative. + FIXME - return the original values. + */ + template + inline vector3d CMatrix4::getScale() const + { + // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices + + // Deal with the 0 rotation case first + // Prior to Irrlicht 1.6, we always returned this value. + if(core::iszero(M[1]) && core::iszero(M[2]) && + core::iszero(M[4]) && core::iszero(M[6]) && + core::iszero(M[8]) && core::iszero(M[9])) + return vector3d(M[0], M[5], M[10]); + + // We have to do the full calculation. + return vector3d(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]), + sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]), + sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10])); + } + + template + inline CMatrix4& CMatrix4::setRotationDegrees( const vector3d& rotation ) + { + return setRotationRadians( rotation * core::DEGTORAD ); + } + + template + inline CMatrix4& CMatrix4::setInverseRotationDegrees( const vector3d& rotation ) + { + return setInverseRotationRadians( rotation * core::DEGTORAD ); + } + + template + inline CMatrix4& CMatrix4::setRotationRadians( const vector3d& rotation ) + { + const f64 cr = cos( rotation.X ); + const f64 sr = sin( rotation.X ); + const f64 cp = cos( rotation.Y ); + const f64 sp = sin( rotation.Y ); + const f64 cy = cos( rotation.Z ); + const f64 sy = sin( rotation.Z ); + + M[0] = (T)( cp*cy ); + M[1] = (T)( cp*sy ); + M[2] = (T)( -sp ); + + const f64 srsp = sr*sp; + const f64 crsp = cr*sp; + + M[4] = (T)( srsp*cy-cr*sy ); + M[5] = (T)( srsp*sy+cr*cy ); + M[6] = (T)( sr*cp ); + + M[8] = (T)( crsp*cy+sr*sy ); + M[9] = (T)( crsp*sy-sr*cy ); + M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + //! Returns a rotation that is equivalent to that set by setRotationDegrees(). + /** This code was sent in by Chev. Note that it does not necessarily return + the *same* Euler angles as those set by setRotationDegrees(), but the rotation will + be equivalent, i.e. will have the same result when used to rotate a vector or node. */ + template + inline core::vector3d CMatrix4::getRotationDegrees() const + { + const CMatrix4 &mat = *this; + core::vector3d scale = getScale(); + // we need to check for negative scale on to axes, which would bring up wrong results + if (scale.Y<0 && scale.Z<0) + { + scale.Y =-scale.Y; + scale.Z =-scale.Z; + } + else if (scale.X<0 && scale.Z<0) + { + scale.X =-scale.X; + scale.Z =-scale.Z; + } + else if (scale.X<0 && scale.Y<0) + { + scale.X =-scale.X; + scale.Y =-scale.Y; + } + const core::vector3d invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z)); + + f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0)); + const f64 C = cos(Y); + Y *= RADTODEG64; + + f64 rotx, roty, X, Z; + + if (!core::iszero(C)) + { + const f64 invC = core::reciprocal(C); + rotx = mat[10] * invC * invScale.Z; + roty = mat[6] * invC * invScale.Y; + X = atan2( roty, rotx ) * RADTODEG64; + rotx = mat[0] * invC * invScale.X; + roty = mat[1] * invC * invScale.X; + Z = atan2( roty, rotx ) * RADTODEG64; + } + else + { + X = 0.0; + rotx = mat[5] * invScale.Y; + roty = -mat[4] * invScale.Y; + Z = atan2( roty, rotx ) * RADTODEG64; + } + + // fix values that get below zero + if (X < 0.0) X += 360.0; + if (Y < 0.0) Y += 360.0; + if (Z < 0.0) Z += 360.0; + + return vector3d((T)X,(T)Y,(T)Z); + } + + + //! Sets matrix to rotation matrix of inverse angles given as parameters + template + inline CMatrix4& CMatrix4::setInverseRotationRadians( const vector3d& rotation ) + { + f64 cr = cos( rotation.X ); + f64 sr = sin( rotation.X ); + f64 cp = cos( rotation.Y ); + f64 sp = sin( rotation.Y ); + f64 cy = cos( rotation.Z ); + f64 sy = sin( rotation.Z ); + + M[0] = (T)( cp*cy ); + M[4] = (T)( cp*sy ); + M[8] = (T)( -sp ); + + f64 srsp = sr*sp; + f64 crsp = cr*sp; + + M[1] = (T)( srsp*cy-cr*sy ); + M[5] = (T)( srsp*sy+cr*cy ); + M[9] = (T)( sr*cp ); + + M[2] = (T)( crsp*cy+sr*sy ); + M[6] = (T)( crsp*sy-sr*cy ); + M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation + template + inline CMatrix4& CMatrix4::setRotationAxisRadians( const T& angle, const vector3d& axis ) + { + const f64 c = cos(angle); + const f64 s = sin(angle); + const f64 t = 1.0 - c; + + const f64 tx = t * axis.X; + const f64 ty = t * axis.Y; + const f64 tz = t * axis.Z; + + const f64 sx = s * axis.X; + const f64 sy = s * axis.Y; + const f64 sz = s * axis.Z; + + M[0] = (T)(tx * axis.X + c); + M[1] = (T)(tx * axis.Y + sz); + M[2] = (T)(tx * axis.Z - sy); + + M[4] = (T)(ty * axis.X - sz); + M[5] = (T)(ty * axis.Y + c); + M[6] = (T)(ty * axis.Z + sx); + + M[8] = (T)(tz * axis.X + sy); + M[9] = (T)(tz * axis.Y - sx); + M[10] = (T)(tz * axis.Z + c); + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + /*! + */ + template + inline CMatrix4& CMatrix4::makeIdentity() + { + memset(M, 0, 16*sizeof(T)); + M[0] = M[5] = M[10] = M[15] = (T)1; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=true; +#endif + return *this; + } + + + /* + check identity with epsilon + solve floating range problems.. + */ + template + inline bool CMatrix4::isIdentity() const + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix) + return true; +#endif + if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 )) + return false; + + if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 )) + return false; + + if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 )) + return false; + + if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 )) + return false; +/* + if (!core::equals( M[ 0], (T)1 ) || + !core::equals( M[ 5], (T)1 ) || + !core::equals( M[10], (T)1 ) || + !core::equals( M[15], (T)1 )) + return false; + + for (s32 i=0; i<4; ++i) + for (s32 j=0; j<4; ++j) + if ((j != i) && (!iszero((*this)(i,j)))) + return false; +*/ +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=true; +#endif + return true; + } + + + /* Check orthogonality of matrix. */ + template + inline bool CMatrix4::isOrthogonal() const + { + T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ]; + if (!iszero(dp)) + return false; + dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11]; + if (!iszero(dp)) + return false; + dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15]; + if (!iszero(dp)) + return false; + dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11]; + if (!iszero(dp)) + return false; + dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15]; + if (!iszero(dp)) + return false; + dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15]; + return (iszero(dp)); + } + + + /* + doesn't solve floating range problems.. + but takes care on +/- 0 on translation because we are changing it.. + reducing floating point branches + but it needs the floats in memory.. + */ + template + inline bool CMatrix4::isIdentity_integer_base() const + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix) + return true; +#endif + if(IR(M[0])!=F32_VALUE_1) return false; + if(IR(M[1])!=0) return false; + if(IR(M[2])!=0) return false; + if(IR(M[3])!=0) return false; + + if(IR(M[4])!=0) return false; + if(IR(M[5])!=F32_VALUE_1) return false; + if(IR(M[6])!=0) return false; + if(IR(M[7])!=0) return false; + + if(IR(M[8])!=0) return false; + if(IR(M[9])!=0) return false; + if(IR(M[10])!=F32_VALUE_1) return false; + if(IR(M[11])!=0) return false; + + if(IR(M[12])!=0) return false; + if(IR(M[13])!=0) return false; + if(IR(M[13])!=0) return false; + if(IR(M[15])!=F32_VALUE_1) return false; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=true; +#endif + return true; + } + + + template + inline void CMatrix4::rotateVect( vector3df& vect ) const + { + vector3df tmp = vect; + vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]; + vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]; + vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; + } + + //! An alternate transform vector method, writing into a second vector + template + inline void CMatrix4::rotateVect(core::vector3df& out, const core::vector3df& in) const + { + out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; + out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; + out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; + } + + //! An alternate transform vector method, writing into an array of 3 floats + template + inline void CMatrix4::rotateVect(T *out, const core::vector3df& in) const + { + out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; + out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; + out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; + } + + template + inline void CMatrix4::inverseRotateVect( vector3df& vect ) const + { + vector3df tmp = vect; + vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]; + vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]; + vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; + } + + template + inline void CMatrix4::transformVect( vector3df& vect) const + { + f32 vector[3]; + + vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12]; + vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13]; + vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14]; + + vect.X = vector[0]; + vect.Y = vector[1]; + vect.Z = vector[2]; + } + + template + inline void CMatrix4::transformVect( vector3df& out, const vector3df& in) const + { + out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; + out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; + out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; + } + + + template + inline void CMatrix4::transformVect(T *out, const core::vector3df &in) const + { + out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; + out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; + out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; + out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; + } + + template + inline void CMatrix4::transformVec3(T *out, const T * in) const + { + out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12]; + out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13]; + out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14]; + } + + + //! Transforms a plane by this matrix + template + inline void CMatrix4::transformPlane( core::plane3d &plane) const + { + vector3df member; + // Transform the plane member point, i.e. rotate, translate and scale it. + transformVect(member, plane.getMemberPoint()); + + // Transform the normal by the transposed inverse of the matrix + CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); + vector3df normal = plane.Normal; + transposedInverse.transformVect(normal); + + plane.setPlane(member, normal); + } + + //! Transforms a plane by this matrix + template + inline void CMatrix4::transformPlane( const core::plane3d &in, core::plane3d &out) const + { + out = in; + transformPlane( out ); + } + + //! Transforms the edge-points of a bounding box + //! Deprecated as it's usually not what people need (regards only 2 corners, but other corners might be outside the box after transformation) + //! Use transformBoxEx instead. + template + _IRR_DEPRECATED_ inline void CMatrix4::transformBox(core::aabbox3d& box) const + { +#if defined ( USE_MATRIX_TEST ) + if (isIdentity()) + return; +#endif + + transformVect(box.MinEdge); + transformVect(box.MaxEdge); + box.repair(); + } + + //! Transforms a axis aligned bounding box more accurately than transformBox() + template + inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const + { +#if defined ( USE_MATRIX_TEST ) + if (isIdentity()) + return; +#endif + + const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; + const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; + + f32 Bmin[3]; + f32 Bmax[3]; + + Bmin[0] = Bmax[0] = M[12]; + Bmin[1] = Bmax[1] = M[13]; + Bmin[2] = Bmax[2] = M[14]; + + const CMatrix4 &m = *this; + + for (u32 i = 0; i < 3; ++i) + { + for (u32 j = 0; j < 3; ++j) + { + const f32 a = m(j,i) * Amin[j]; + const f32 b = m(j,i) * Amax[j]; + + if (a < b) + { + Bmin[i] += a; + Bmax[i] += b; + } + else + { + Bmin[i] += b; + Bmax[i] += a; + } + } + } + + box.MinEdge.X = Bmin[0]; + box.MinEdge.Y = Bmin[1]; + box.MinEdge.Z = Bmin[2]; + + box.MaxEdge.X = Bmax[0]; + box.MaxEdge.Y = Bmax[1]; + box.MaxEdge.Z = Bmax[2]; + } + + + //! Multiplies this matrix by a 1x4 matrix + template + inline void CMatrix4::multiplyWith1x4Matrix(T* matrix) const + { + /* + 0 1 2 3 + 4 5 6 7 + 8 9 10 11 + 12 13 14 15 + */ + + T mat[4]; + mat[0] = matrix[0]; + mat[1] = matrix[1]; + mat[2] = matrix[2]; + mat[3] = matrix[3]; + + matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3]; + matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3]; + matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3]; + matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3]; + } + + template + inline void CMatrix4::inverseTranslateVect( vector3df& vect ) const + { + vect.X = vect.X-M[12]; + vect.Y = vect.Y-M[13]; + vect.Z = vect.Z-M[14]; + } + + template + inline void CMatrix4::translateVect( vector3df& vect ) const + { + vect.X = vect.X+M[12]; + vect.Y = vect.Y+M[13]; + vect.Z = vect.Z+M[14]; + } + + + template + inline bool CMatrix4::getInverse(CMatrix4& out) const + { + /// Calculates the inverse of this Matrix + /// The inverse is calculated using Cramers rule. + /// If no inverse exists then 'false' is returned. + +#if defined ( USE_MATRIX_TEST ) + if ( this->isIdentity() ) + { + out=*this; + return true; + } +#endif + const CMatrix4 &m = *this; + + f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) - + (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + + (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) + + (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) - + (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + + (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)); + + if( core::iszero ( d, FLT_MIN ) ) + return false; + + d = core::reciprocal ( d ); + + out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) + + m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) + + m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1))); + out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) + + m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) + + m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1))); + out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) + + m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) + + m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1))); + out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) + + m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) + + m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2))); + out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) + + m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) + + m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3))); + out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) + + m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) + + m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3))); + out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) + + m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) + + m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3))); + out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) + + m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) + + m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2))); + out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) + + m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + + m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3))); + out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) + + m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) + + m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3))); + out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) + + m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) + + m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3))); + out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) + + m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) + + m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0))); + out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) + + m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + + m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1))); + out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) + + m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) + + m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1))); + out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) + + m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) + + m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1))); + out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + + m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))); + +#if defined ( USE_MATRIX_TEST ) + out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif + return true; + } + + + //! Inverts a primitive matrix which only contains a translation and a rotation + //! \param out: where result matrix is written to. + template + inline bool CMatrix4::getInversePrimitive ( CMatrix4& out ) const + { + out.M[0 ] = M[0]; + out.M[1 ] = M[4]; + out.M[2 ] = M[8]; + out.M[3 ] = 0; + + out.M[4 ] = M[1]; + out.M[5 ] = M[5]; + out.M[6 ] = M[9]; + out.M[7 ] = 0; + + out.M[8 ] = M[2]; + out.M[9 ] = M[6]; + out.M[10] = M[10]; + out.M[11] = 0; + + out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]); + out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]); + out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]); + out.M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) + out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif + return true; + } + + /*! + */ + template + inline bool CMatrix4::makeInverse() + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix) + return true; +#endif + CMatrix4 temp ( EM4CONST_NOTHING ); + + if (getInverse(temp)) + { + *this = temp; + return true; + } + + return false; + } + + + template + inline CMatrix4& CMatrix4::operator=(const CMatrix4 &other) + { + if (this==&other) + return *this; + memcpy(M, other.M, 16*sizeof(T)); +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=other.definitelyIdentityMatrix; +#endif + return *this; + } + + + template + inline CMatrix4& CMatrix4::operator=(const T& scalar) + { + for (s32 i = 0; i < 16; ++i) + M[i]=scalar; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + template + inline bool CMatrix4::operator==(const CMatrix4 &other) const + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) + return true; +#endif + for (s32 i = 0; i < 16; ++i) + if (M[i] != other.M[i]) + return false; + + return true; + } + + + template + inline bool CMatrix4::operator!=(const CMatrix4 &other) const + { + return !(*this == other); + } + + + // Builds a right-handed perspective projection matrix based on a field of view + template + inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovRH( + f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) + { + const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); + _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero + const T w = static_cast(h / aspectRatio); + + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = w; + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)h; + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(zFar/(zNear-zFar)); // DirectX version +// M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version + M[11] = -1; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version +// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version + M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a left-handed perspective projection matrix based on a field of view + template + inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovLH( + f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) + { + const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); + _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero + const T w = static_cast(h / aspectRatio); + + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = w; + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)h; + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(zFar/(zFar-zNear)); + M[11] = 1; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(-zNear*zFar/(zFar-zNear)); + M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity + template + inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovInfinityLH( + f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon) + { + const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); + _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero + const T w = static_cast(h / aspectRatio); + + M[0] = w; + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)h; + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(1.f-epsilon); + M[11] = 1; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear*(epsilon-1.f)); + M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a left-handed orthogonal projection matrix. + template + inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoLH( + f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) + { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = (T)(2/widthOfViewVolume); + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)(2/heightOfViewVolume); + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(1/(zFar-zNear)); + M[11] = 0; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear/(zNear-zFar)); + M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a right-handed orthogonal projection matrix. + template + inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoRH( + f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) + { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = (T)(2/widthOfViewVolume); + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)(2/heightOfViewVolume); + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(1/(zNear-zFar)); + M[11] = 0; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear/(zNear-zFar)); + M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a right-handed perspective projection matrix. + template + inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveRH( + f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) + { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = (T)(2*zNear/widthOfViewVolume); + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)(2*zNear/heightOfViewVolume); + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(zFar/(zNear-zFar)); + M[11] = -1; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear*zFar/(zNear-zFar)); + M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a left-handed perspective projection matrix. + template + inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveLH( + f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) + { + _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero + _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero + M[0] = (T)(2*zNear/widthOfViewVolume); + M[1] = 0; + M[2] = 0; + M[3] = 0; + + M[4] = 0; + M[5] = (T)(2*zNear/heightOfViewVolume); + M[6] = 0; + M[7] = 0; + + M[8] = 0; + M[9] = 0; + M[10] = (T)(zFar/(zFar-zNear)); + M[11] = 1; + + M[12] = 0; + M[13] = 0; + M[14] = (T)(zNear*zFar/(zNear-zFar)); + M[15] = 0; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a matrix that flattens geometry into a plane. + template + inline CMatrix4& CMatrix4::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point) + { + plane.Normal.normalize(); + const f32 d = plane.Normal.dotProduct(light); + + M[ 0] = (T)(-plane.Normal.X * light.X + d); + M[ 1] = (T)(-plane.Normal.X * light.Y); + M[ 2] = (T)(-plane.Normal.X * light.Z); + M[ 3] = (T)(-plane.Normal.X * point); + + M[ 4] = (T)(-plane.Normal.Y * light.X); + M[ 5] = (T)(-plane.Normal.Y * light.Y + d); + M[ 6] = (T)(-plane.Normal.Y * light.Z); + M[ 7] = (T)(-plane.Normal.Y * point); + + M[ 8] = (T)(-plane.Normal.Z * light.X); + M[ 9] = (T)(-plane.Normal.Z * light.Y); + M[10] = (T)(-plane.Normal.Z * light.Z + d); + M[11] = (T)(-plane.Normal.Z * point); + + M[12] = (T)(-plane.D * light.X); + M[13] = (T)(-plane.D * light.Y); + M[14] = (T)(-plane.D * light.Z); + M[15] = (T)(-plane.D * point + d); +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + // Builds a left-handed look-at matrix. + template + inline CMatrix4& CMatrix4::buildCameraLookAtMatrixLH( + const vector3df& position, + const vector3df& target, + const vector3df& upVector) + { + vector3df zaxis = target - position; + zaxis.normalize(); + + vector3df xaxis = upVector.crossProduct(zaxis); + xaxis.normalize(); + + vector3df yaxis = zaxis.crossProduct(xaxis); + + M[0] = (T)xaxis.X; + M[1] = (T)yaxis.X; + M[2] = (T)zaxis.X; + M[3] = 0; + + M[4] = (T)xaxis.Y; + M[5] = (T)yaxis.Y; + M[6] = (T)zaxis.Y; + M[7] = 0; + + M[8] = (T)xaxis.Z; + M[9] = (T)yaxis.Z; + M[10] = (T)zaxis.Z; + M[11] = 0; + + M[12] = (T)-xaxis.dotProduct(position); + M[13] = (T)-yaxis.dotProduct(position); + M[14] = (T)-zaxis.dotProduct(position); + M[15] = 1; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // Builds a right-handed look-at matrix. + template + inline CMatrix4& CMatrix4::buildCameraLookAtMatrixRH( + const vector3df& position, + const vector3df& target, + const vector3df& upVector) + { + vector3df zaxis = position - target; + zaxis.normalize(); + + vector3df xaxis = upVector.crossProduct(zaxis); + xaxis.normalize(); + + vector3df yaxis = zaxis.crossProduct(xaxis); + + M[0] = (T)xaxis.X; + M[1] = (T)yaxis.X; + M[2] = (T)zaxis.X; + M[3] = 0; + + M[4] = (T)xaxis.Y; + M[5] = (T)yaxis.Y; + M[6] = (T)zaxis.Y; + M[7] = 0; + + M[8] = (T)xaxis.Z; + M[9] = (T)yaxis.Z; + M[10] = (T)zaxis.Z; + M[11] = 0; + + M[12] = (T)-xaxis.dotProduct(position); + M[13] = (T)-yaxis.dotProduct(position); + M[14] = (T)-zaxis.dotProduct(position); + M[15] = 1; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // creates a new matrix as interpolated matrix from this and the passed one. + template + inline CMatrix4 CMatrix4::interpolate(const core::CMatrix4& b, f32 time) const + { + CMatrix4 mat ( EM4CONST_NOTHING ); + + for (u32 i=0; i < 16; i += 4) + { + mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time); + mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time); + mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time); + mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time); + } + return mat; + } + + + // returns transposed matrix + template + inline CMatrix4 CMatrix4::getTransposed() const + { + CMatrix4 t ( EM4CONST_NOTHING ); + getTransposed ( t ); + return t; + } + + + // returns transposed matrix + template + inline void CMatrix4::getTransposed( CMatrix4& o ) const + { + o[ 0] = M[ 0]; + o[ 1] = M[ 4]; + o[ 2] = M[ 8]; + o[ 3] = M[12]; + + o[ 4] = M[ 1]; + o[ 5] = M[ 5]; + o[ 6] = M[ 9]; + o[ 7] = M[13]; + + o[ 8] = M[ 2]; + o[ 9] = M[ 6]; + o[10] = M[10]; + o[11] = M[14]; + + o[12] = M[ 3]; + o[13] = M[ 7]; + o[14] = M[11]; + o[15] = M[15]; +#if defined ( USE_MATRIX_TEST ) + o.definitelyIdentityMatrix=definitelyIdentityMatrix; +#endif + } + + + // used to scale <-1,-1><1,1> to viewport + template + inline CMatrix4& CMatrix4::buildNDCToDCMatrix( const core::rect& viewport, f32 zScale) + { + const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f; + const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f; + + const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); + const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); + + makeIdentity(); + M[12] = (T)dx; + M[13] = (T)dy; + return setScale(core::vector3d((T)scaleX, (T)scaleY, (T)zScale)); + } + + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + + http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm + */ + template + inline CMatrix4& CMatrix4::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to) + { + // unit vectors + core::vector3df f(from); + core::vector3df t(to); + f.normalize(); + t.normalize(); + + // axis multiplication by sin + core::vector3df vs(t.crossProduct(f)); + + // axis of rotation + core::vector3df v(vs); + v.normalize(); + + // cosinus angle + T ca = f.dotProduct(t); + + core::vector3df vt(v * (1 - ca)); + + M[0] = vt.X * v.X + ca; + M[5] = vt.Y * v.Y + ca; + M[10] = vt.Z * v.Z + ca; + + vt.X *= v.Y; + vt.Z *= v.X; + vt.Y *= v.Z; + + M[1] = vt.X - vs.Z; + M[2] = vt.Z + vs.Y; + M[3] = 0; + + M[4] = vt.X + vs.Z; + M[6] = vt.Y - vs.X; + M[7] = 0; + + M[8] = vt.Z - vs.Y; + M[9] = vt.Y + vs.X; + M[11] = 0; + + M[12] = 0; + M[13] = 0; + M[14] = 0; + M[15] = 1; + + return *this; + } + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coord + \param center: object position in world-coord, rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + template + inline void CMatrix4::buildAxisAlignedBillboard( + const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from) + { + // axis of rotation + core::vector3df up = axis; + up.normalize(); + const core::vector3df forward = (camPos - center).normalize(); + const core::vector3df right = up.crossProduct(forward).normalize(); + + // correct look vector + const core::vector3df look = right.crossProduct(up); + + // rotate from to + // axis multiplication by sin + const core::vector3df vs = look.crossProduct(from); + + // cosinus angle + const f32 ca = from.dotProduct(look); + + core::vector3df vt(up * (1.f - ca)); + + M[0] = static_cast(vt.X * up.X + ca); + M[5] = static_cast(vt.Y * up.Y + ca); + M[10] = static_cast(vt.Z * up.Z + ca); + + vt.X *= up.Y; + vt.Z *= up.X; + vt.Y *= up.Z; + + M[1] = static_cast(vt.X - vs.Z); + M[2] = static_cast(vt.Z + vs.Y); + M[3] = 0; + + M[4] = static_cast(vt.X + vs.Z); + M[6] = static_cast(vt.Y - vs.X); + M[7] = 0; + + M[8] = static_cast(vt.Z - vs.Y); + M[9] = static_cast(vt.Y + vs.X); + M[11] = 0; + + setRotationCenter(center, translation); + } + + + //! Builds a combined matrix which translate to a center before rotation and translate afterwards + template + inline void CMatrix4::setRotationCenter(const core::vector3df& center, const core::vector3df& translation) + { + M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X ); + M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y ); + M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z ); + M[15] = (T) 1.0; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + } + + /*! + Generate texture coordinates as linear functions so that: + u = Ux*x + Uy*y + Uz*z + Uw + v = Vx*x + Vy*y + Vz*z + Vw + The matrix M for this case is: + Ux Vx 0 0 + Uy Vy 0 0 + Uz Vz 0 0 + Uw Vw 0 0 + */ + + + template + inline CMatrix4& CMatrix4::buildTextureTransform( f32 rotateRad, + const core::vector2df &rotatecenter, + const core::vector2df &translate, + const core::vector2df &scale) + { + const f32 c = cosf(rotateRad); + const f32 s = sinf(rotateRad); + + M[0] = (T)(c * scale.X); + M[1] = (T)(s * scale.Y); + M[2] = 0; + M[3] = 0; + + M[4] = (T)(-s * scale.X); + M[5] = (T)(c * scale.Y); + M[6] = 0; + M[7] = 0; + + M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X); + M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y); + M[10] = 1; + M[11] = 0; + + M[12] = 0; + M[13] = 0; + M[14] = 0; + M[15] = 1; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // rotate about z axis, center ( 0.5, 0.5 ) + template + inline CMatrix4& CMatrix4::setTextureRotationCenter( f32 rotateRad ) + { + const f32 c = cosf(rotateRad); + const f32 s = sinf(rotateRad); + M[0] = (T)c; + M[1] = (T)s; + + M[4] = (T)-s; + M[5] = (T)c; + + M[8] = (T)(0.5f * ( s - c) + 0.5f); + M[9] = (T)(-0.5f * ( s + c) + 0.5f); + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f); +#endif + return *this; + } + + + template + inline CMatrix4& CMatrix4::setTextureTranslate ( f32 x, f32 y ) + { + M[8] = (T)x; + M[9] = (T)y; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f); +#endif + return *this; + } + + + template + inline CMatrix4& CMatrix4::setTextureTranslateTransposed ( f32 x, f32 y ) + { + M[2] = (T)x; + M[6] = (T)y; + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; +#endif + return *this; + } + + template + inline CMatrix4& CMatrix4::setTextureScale ( f32 sx, f32 sy ) + { + M[0] = (T)sx; + M[5] = (T)sy; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif + return *this; + } + + + template + inline CMatrix4& CMatrix4::setTextureScaleCenter( f32 sx, f32 sy ) + { + M[0] = (T)sx; + M[5] = (T)sy; + M[8] = (T)(0.5f - 0.5f * sx); + M[9] = (T)(0.5f - 0.5f * sy); + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif + return *this; + } + + + // sets all matrix data members at once + template + inline CMatrix4& CMatrix4::setM(const T* data) + { + memcpy(M,data, 16*sizeof(T)); + +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return *this; + } + + + // sets if the matrix is definitely identity matrix + template + inline void CMatrix4::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix = isDefinitelyIdentityMatrix; +#endif + } + + + // gets if the matrix is definitely identity matrix + template + inline bool CMatrix4::getDefinitelyIdentityMatrix() const + { +#if defined ( USE_MATRIX_TEST ) + return definitelyIdentityMatrix; +#else + return false; +#endif + } + + + //! Compare two matrices using the equal method + template + inline bool CMatrix4::equals(const core::CMatrix4& other, const T tolerance) const + { +#if defined ( USE_MATRIX_TEST ) + if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) + return true; +#endif + for (s32 i = 0; i < 16; ++i) + if (!core::equals(M[i],other.M[i], tolerance)) + return false; + + return true; + } + + + // Multiply by scalar. + template + inline CMatrix4 operator*(const T scalar, const CMatrix4& mat) + { + return mat*scalar; + } + + + //! Typedef for f32 matrix + typedef CMatrix4 matrix4; + + //! global const identity matrix + IRRLICHT_API extern const matrix4 IdentityMatrix; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/path.h b/inc/path.h new file mode 100644 index 0000000..ed7661c --- /dev/null +++ b/inc/path.h @@ -0,0 +1,88 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_PATH_H_INCLUDED__ +#define __IRR_PATH_H_INCLUDED__ + +#include "irrString.h" + +namespace irr +{ +namespace io +{ + +//! Type used for all file system related strings. +/** This type will transparently handle different file system encodings. */ +typedef core::string path; + +//! Used in places where we identify objects by a filename, but don't actually work with the real filename +/** Irrlicht is internally not case-sensitive when it comes to names. + Also this class is a first step towards support for correctly serializing renamed objects. +*/ +struct SNamedPath +{ + //! Constructor + SNamedPath() {} + + //! Constructor + SNamedPath(const path& p) : Path(p), InternalName( PathToName(p) ) + { + } + + //! Is smaller comparator + bool operator <(const SNamedPath& other) const + { + return InternalName < other.InternalName; + } + + //! Set the path. + void setPath(const path& p) + { + Path = p; + InternalName = PathToName(p); + } + + //! Get the path. + const path& getPath() const + { + return Path; + }; + + //! Get the name which is used to identify the file. + //! This string is similar to the names and filenames used before Irrlicht 1.7 + const path& getInternalName() const + { + return InternalName; + } + + //! Implicit cast to io::path + operator core::stringc() const + { + return core::stringc(getPath()); + } + //! Implicit cast to io::path + operator core::stringw() const + { + return core::stringw(getPath()); + } + +protected: + // convert the given path string to a name string. + path PathToName(const path& p) const + { + path name(p); + name.replace( '\\', '/' ); + name.make_lower(); + return name; + } + +private: + path Path; + path InternalName; +}; + +} // io +} // irr + +#endif // __IRR_PATH_H_INCLUDED__ diff --git a/inc/plane3d.h b/inc/plane3d.h new file mode 100644 index 0000000..02c6bf9 --- /dev/null +++ b/inc/plane3d.h @@ -0,0 +1,245 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_PLANE_3D_H_INCLUDED__ +#define __IRR_PLANE_3D_H_INCLUDED__ + +#include "irrMath.h" +#include "vector3d.h" + +namespace irr +{ +namespace core +{ + +//! Enumeration for intersection relations of 3d objects +enum EIntersectionRelation3D +{ + ISREL3D_FRONT = 0, + ISREL3D_BACK, + ISREL3D_PLANAR, + ISREL3D_SPANNING, + ISREL3D_CLIPPED +}; + +//! Template plane class with some intersection testing methods. +/** It has to be ensured, that the normal is always normalized. The constructors + and setters of this class will not ensure this automatically. So any normal + passed in has to be normalized in advance. No change to the normal will be + made by any of the class methods. +*/ +template +class plane3d +{ + public: + + // Constructors + + plane3d(): Normal(0,1,0) { recalculateD(vector3d(0,0,0)); } + + plane3d(const vector3d& MPoint, const vector3d& Normal) : Normal(Normal) { recalculateD(MPoint); } + + plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d(px, py, pz)); } + + plane3d(const vector3d& point1, const vector3d& point2, const vector3d& point3) + { setPlane(point1, point2, point3); } + + plane3d(const vector3d & normal, const T d) : Normal(normal), D(d) { } + + // operators + + inline bool operator==(const plane3d& other) const { return (equals(D, other.D) && Normal==other.Normal);} + + inline bool operator!=(const plane3d& other) const { return !(*this == other);} + + // functions + + void setPlane(const vector3d& point, const vector3d& nvector) + { + Normal = nvector; + recalculateD(point); + } + + void setPlane(const vector3d& nvect, T d) + { + Normal = nvect; + D = d; + } + + void setPlane(const vector3d& point1, const vector3d& point2, const vector3d& point3) + { + // creates the plane from 3 memberpoints + Normal = (point2 - point1).crossProduct(point3 - point1); + Normal.normalize(); + + recalculateD(point1); + } + + + //! Get an intersection with a 3d line. + /** \param lineVect Vector of the line to intersect with. + \param linePoint Point of the line to intersect with. + \param outIntersection Place to store the intersection point, if there is one. + \return True if there was an intersection, false if there was not. + */ + bool getIntersectionWithLine(const vector3d& linePoint, + const vector3d& lineVect, + vector3d& outIntersection) const + { + T t2 = Normal.dotProduct(lineVect); + + if (t2 == 0) + return false; + + T t =- (Normal.dotProduct(linePoint) + D) / t2; + outIntersection = linePoint + (lineVect * t); + return true; + } + + //! Get percentage of line between two points where an intersection with this plane happens. + /** Only useful if known that there is an intersection. + \param linePoint1 Point1 of the line to intersect with. + \param linePoint2 Point2 of the line to intersect with. + \return Where on a line between two points an intersection with this plane happened. + For example, 0.5 is returned if the intersection happened exactly in the middle of the two points. + */ + f32 getKnownIntersectionWithLine(const vector3d& linePoint1, + const vector3d& linePoint2) const + { + vector3d vect = linePoint2 - linePoint1; + T t2 = (f32)Normal.dotProduct(vect); + return (f32)-((Normal.dotProduct(linePoint1) + D) / t2); + } + + //! Get an intersection with a 3d line, limited between two 3d points. + /** \param linePoint1 Point 1 of the line. + \param linePoint2 Point 2 of the line. + \param outIntersection Place to store the intersection point, if there is one. + \return True if there was an intersection, false if there was not. + */ + bool getIntersectionWithLimitedLine( + const vector3d& linePoint1, + const vector3d& linePoint2, + vector3d& outIntersection) const + { + return (getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) && + outIntersection.isBetweenPoints(linePoint1, linePoint2)); + } + + //! Classifies the relation of a point to this plane. + /** \param point Point to classify its relation. + \return ISREL3D_FRONT if the point is in front of the plane, + ISREL3D_BACK if the point is behind of the plane, and + ISREL3D_PLANAR if the point is within the plane. */ + EIntersectionRelation3D classifyPointRelation(const vector3d& point) const + { + const T d = Normal.dotProduct(point) + D; + + if (d < -ROUNDING_ERROR_f32) + return ISREL3D_BACK; + + if (d > ROUNDING_ERROR_f32) + return ISREL3D_FRONT; + + return ISREL3D_PLANAR; + } + + //! Recalculates the distance from origin by applying a new member point to the plane. + void recalculateD(const vector3d& MPoint) + { + D = - MPoint.dotProduct(Normal); + } + + //! Gets a member point of the plane. + vector3d getMemberPoint() const + { + return Normal * -D; + } + + //! Tests if there is an intersection with the other plane + /** \return True if there is a intersection. */ + bool existsIntersection(const plane3d& other) const + { + vector3d cross = other.Normal.crossProduct(Normal); + return cross.getLength() > core::ROUNDING_ERROR_f32; + } + + //! Intersects this plane with another. + /** \param other Other plane to intersect with. + \param outLinePoint Base point of intersection line. + \param outLineVect Vector of intersection. + \return True if there is a intersection, false if not. */ + bool getIntersectionWithPlane(const plane3d& other, + vector3d& outLinePoint, + vector3d& outLineVect) const + { + const T fn00 = Normal.getLength(); + const T fn01 = Normal.dotProduct(other.Normal); + const T fn11 = other.Normal.getLength(); + const f64 det = fn00*fn11 - fn01*fn01; + + if (fabs(det) < ROUNDING_ERROR_f64 ) + return false; + + const f64 invdet = 1.0 / det; + const f64 fc0 = (fn11*-D + fn01*other.D) * invdet; + const f64 fc1 = (fn00*-other.D + fn01*D) * invdet; + + outLineVect = Normal.crossProduct(other.Normal); + outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1; + return true; + } + + //! Get the intersection point with two other planes if there is one. + bool getIntersectionWithPlanes(const plane3d& o1, + const plane3d& o2, vector3d& outPoint) const + { + vector3d linePoint, lineVect; + if (getIntersectionWithPlane(o1, linePoint, lineVect)) + return o2.getIntersectionWithLine(linePoint, lineVect, outPoint); + + return false; + } + + //! Test if the triangle would be front or backfacing from any point. + /** Thus, this method assumes a camera position from + which the triangle is definitely visible when looking into + the given direction. + Note that this only works if the normal is Normalized. + Do not use this method with points as it will give wrong results! + \param lookDirection: Look direction. + \return True if the plane is front facing and + false if it is backfacing. */ + bool isFrontFacing(const vector3d& lookDirection) const + { + const f32 d = Normal.dotProduct(lookDirection); + return F32_LOWER_EQUAL_0 ( d ); + } + + //! Get the distance to a point. + /** Note that this only works if the normal is normalized. */ + T getDistanceTo(const vector3d& point) const + { + return point.dotProduct(Normal) + D; + } + + //! Normal vector of the plane. + vector3d Normal; + + //! Distance from origin. + T D; +}; + + +//! Typedef for a f32 3d plane. +typedef plane3d plane3df; + +//! Typedef for an integer 3d plane. +typedef plane3d plane3di; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/position2d.h b/inc/position2d.h new file mode 100644 index 0000000..05a27c6 --- /dev/null +++ b/inc/position2d.h @@ -0,0 +1,32 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +//! As of Irrlicht 1.6, position2d is a synonym for vector2d. +/** You should consider position2d to be deprecated, and use vector2d by preference. */ + +#ifndef __IRR_POSITION_H_INCLUDED__ +#define __IRR_POSITION_H_INCLUDED__ + +#include "vector2d.h" + +namespace irr +{ +namespace core +{ + +// Use typedefs where possible as they are more explicit... + +//! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. +typedef vector2d position2df; + +//! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. +typedef vector2d position2di; +} // namespace core +} // namespace irr + +// ...and use a #define to catch the rest, for (e.g.) position2d +#define position2d vector2d + +#endif // __IRR_POSITION_H_INCLUDED__ + diff --git a/inc/quaternion.h b/inc/quaternion.h new file mode 100644 index 0000000..130ba8c --- /dev/null +++ b/inc/quaternion.h @@ -0,0 +1,696 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_QUATERNION_H_INCLUDED__ +#define __IRR_QUATERNION_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrMath.h" +#include "matrix4.h" +#include "vector3d.h" + +// Between Irrlicht 1.7 and Irrlicht 1.8 the quaternion-matrix conversions got fixed. +// This define disables all involved functions completely to allow finding all places +// where the wrong conversions had been in use. +#define IRR_TEST_BROKEN_QUATERNION_USE 0 + +namespace irr +{ +namespace core +{ + +//! Quaternion class for representing rotations. +/** It provides cheap combinations and avoids gimbal locks. +Also useful for interpolations. */ +class quaternion +{ + public: + + //! Default Constructor + quaternion() : X(0.0f), Y(0.0f), Z(0.0f), W(1.0f) {} + + //! Constructor + quaternion(f32 x, f32 y, f32 z, f32 w) : X(x), Y(y), Z(z), W(w) { } + + //! Constructor which converts euler angles (radians) to a quaternion + quaternion(f32 x, f32 y, f32 z); + + //! Constructor which converts euler angles (radians) to a quaternion + quaternion(const vector3df& vec); + +#if !IRR_TEST_BROKEN_QUATERNION_USE + //! Constructor which converts a matrix to a quaternion + quaternion(const matrix4& mat); +#endif + + //! Equalilty operator + bool operator==(const quaternion& other) const; + + //! inequality operator + bool operator!=(const quaternion& other) const; + + //! Assignment operator + inline quaternion& operator=(const quaternion& other); + +#if !IRR_TEST_BROKEN_QUATERNION_USE + //! Matrix assignment operator + inline quaternion& operator=(const matrix4& other); +#endif + + //! Add operator + quaternion operator+(const quaternion& other) const; + + //! Multiplication operator + quaternion operator*(const quaternion& other) const; + + //! Multiplication operator with scalar + quaternion operator*(f32 s) const; + + //! Multiplication operator with scalar + quaternion& operator*=(f32 s); + + //! Multiplication operator + vector3df operator*(const vector3df& v) const; + + //! Multiplication operator + quaternion& operator*=(const quaternion& other); + + //! Calculates the dot product + inline f32 dotProduct(const quaternion& other) const; + + //! Sets new quaternion + inline quaternion& set(f32 x, f32 y, f32 z, f32 w); + + //! Sets new quaternion based on euler angles (radians) + inline quaternion& set(f32 x, f32 y, f32 z); + + //! Sets new quaternion based on euler angles (radians) + inline quaternion& set(const core::vector3df& vec); + + //! Sets new quaternion from other quaternion + inline quaternion& set(const core::quaternion& quat); + + //! returns if this quaternion equals the other one, taking floating point rounding errors into account + inline bool equals(const quaternion& other, + const f32 tolerance = ROUNDING_ERROR_f32 ) const; + + //! Normalizes the quaternion + inline quaternion& normalize(); + +#if !IRR_TEST_BROKEN_QUATERNION_USE + //! Creates a matrix from this quaternion + matrix4 getMatrix() const; +#endif + + //! Creates a matrix from this quaternion + void getMatrix( matrix4 &dest, const core::vector3df &translation=core::vector3df() ) const; + + /*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrixCenter ( lookat, center, newPos ); + + core::matrix4 m2; + m2.setInverseTranslation ( center ); + lookat *= m2; + + core::matrix4 m3; + m2.setTranslation ( newPos ); + lookat *= m3; + + */ + void getMatrixCenter( matrix4 &dest, const core::vector3df ¢er, const core::vector3df &translation ) const; + + //! Creates a matrix from this quaternion + inline void getMatrix_transposed( matrix4 &dest ) const; + + //! Inverts this quaternion + quaternion& makeInverse(); + + //! Set this quaternion to the linear interpolation between two quaternions + /** \param q1 First quaternion to be interpolated. + \param q2 Second quaternion to be interpolated. + \param time Progress of interpolation. For time=0 the result is + q1, for time=1 the result is q2. Otherwise interpolation + between q1 and q2. + */ + quaternion& lerp(quaternion q1, quaternion q2, f32 time); + + //! Set this quaternion to the result of the spherical interpolation between two quaternions + /** \param q1 First quaternion to be interpolated. + \param q2 Second quaternion to be interpolated. + \param time Progress of interpolation. For time=0 the result is + q1, for time=1 the result is q2. Otherwise interpolation + between q1 and q2. + \param threshold To avoid inaccuracies at the end (time=1) the + interpolation switches to linear interpolation at some point. + This value defines how much of the remaining interpolation will + be calculated with lerp. Everything from 1-threshold up will be + linear interpolation. + */ + quaternion& slerp(quaternion q1, quaternion q2, + f32 time, f32 threshold=.05f); + + //! Create quaternion from rotation angle and rotation axis. + /** Axis must be unit length. + The quaternion representing the rotation is + q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k). + \param angle Rotation Angle in radians. + \param axis Rotation axis. */ + quaternion& fromAngleAxis (f32 angle, const vector3df& axis); + + //! Fills an angle (radians) around an axis (unit vector) + void toAngleAxis (f32 &angle, core::vector3df& axis) const; + + //! Output this quaternion to an euler angle (radians) + void toEuler(vector3df& euler) const; + + //! Set quaternion to identity + quaternion& makeIdentity(); + + //! Set quaternion to represent a rotation from one vector to another. + quaternion& rotationFromTo(const vector3df& from, const vector3df& to); + + //! Quaternion elements. + f32 X; // vectorial (imaginary) part + f32 Y; + f32 Z; + f32 W; // real part +}; + + +// Constructor which converts euler angles to a quaternion +inline quaternion::quaternion(f32 x, f32 y, f32 z) +{ + set(x,y,z); +} + + +// Constructor which converts euler angles to a quaternion +inline quaternion::quaternion(const vector3df& vec) +{ + set(vec.X,vec.Y,vec.Z); +} + +#if !IRR_TEST_BROKEN_QUATERNION_USE +// Constructor which converts a matrix to a quaternion +inline quaternion::quaternion(const matrix4& mat) +{ + (*this) = mat; +} +#endif + +// equal operator +inline bool quaternion::operator==(const quaternion& other) const +{ + return ((X == other.X) && + (Y == other.Y) && + (Z == other.Z) && + (W == other.W)); +} + +// inequality operator +inline bool quaternion::operator!=(const quaternion& other) const +{ + return !(*this == other); +} + +// assignment operator +inline quaternion& quaternion::operator=(const quaternion& other) +{ + X = other.X; + Y = other.Y; + Z = other.Z; + W = other.W; + return *this; +} + +#if !IRR_TEST_BROKEN_QUATERNION_USE +// matrix assignment operator +inline quaternion& quaternion::operator=(const matrix4& m) +{ + const f32 diag = m[0] + m[5] + m[10] + 1; + + if( diag > 0.0f ) + { + const f32 scale = sqrtf(diag) * 2.0f; // get scale from diagonal + + // TODO: speed this up + X = (m[6] - m[9]) / scale; + Y = (m[8] - m[2]) / scale; + Z = (m[1] - m[4]) / scale; + W = 0.25f * scale; + } + else + { + if (m[0]>m[5] && m[0]>m[10]) + { + // 1st element of diag is greatest value + // find scale according to 1st element, and double it + const f32 scale = sqrtf(1.0f + m[0] - m[5] - m[10]) * 2.0f; + + // TODO: speed this up + X = 0.25f * scale; + Y = (m[4] + m[1]) / scale; + Z = (m[2] + m[8]) / scale; + W = (m[6] - m[9]) / scale; + } + else if (m[5]>m[10]) + { + // 2nd element of diag is greatest value + // find scale according to 2nd element, and double it + const f32 scale = sqrtf(1.0f + m[5] - m[0] - m[10]) * 2.0f; + + // TODO: speed this up + X = (m[4] + m[1]) / scale; + Y = 0.25f * scale; + Z = (m[9] + m[6]) / scale; + W = (m[8] - m[2]) / scale; + } + else + { + // 3rd element of diag is greatest value + // find scale according to 3rd element, and double it + const f32 scale = sqrtf(1.0f + m[10] - m[0] - m[5]) * 2.0f; + + // TODO: speed this up + X = (m[8] + m[2]) / scale; + Y = (m[9] + m[6]) / scale; + Z = 0.25f * scale; + W = (m[1] - m[4]) / scale; + } + } + + return normalize(); +} +#endif + + +// multiplication operator +inline quaternion quaternion::operator*(const quaternion& other) const +{ + quaternion tmp; + + tmp.W = (other.W * W) - (other.X * X) - (other.Y * Y) - (other.Z * Z); + tmp.X = (other.W * X) + (other.X * W) + (other.Y * Z) - (other.Z * Y); + tmp.Y = (other.W * Y) + (other.Y * W) + (other.Z * X) - (other.X * Z); + tmp.Z = (other.W * Z) + (other.Z * W) + (other.X * Y) - (other.Y * X); + + return tmp; +} + + +// multiplication operator +inline quaternion quaternion::operator*(f32 s) const +{ + return quaternion(s*X, s*Y, s*Z, s*W); +} + + +// multiplication operator +inline quaternion& quaternion::operator*=(f32 s) +{ + X*=s; + Y*=s; + Z*=s; + W*=s; + return *this; +} + +// multiplication operator +inline quaternion& quaternion::operator*=(const quaternion& other) +{ + return (*this = other * (*this)); +} + +// add operator +inline quaternion quaternion::operator+(const quaternion& b) const +{ + return quaternion(X+b.X, Y+b.Y, Z+b.Z, W+b.W); +} + +#if !IRR_TEST_BROKEN_QUATERNION_USE +// Creates a matrix from this quaternion +inline matrix4 quaternion::getMatrix() const +{ + core::matrix4 m; + getMatrix(m); + return m; +} +#endif + +/*! + Creates a matrix from this quaternion +*/ +inline void quaternion::getMatrix(matrix4 &dest, + const core::vector3df ¢er) const +{ + dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + dest[1] = 2.0f*X*Y + 2.0f*Z*W; + dest[2] = 2.0f*X*Z - 2.0f*Y*W; + dest[3] = 0.0f; + + dest[4] = 2.0f*X*Y - 2.0f*Z*W; + dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + dest[6] = 2.0f*Z*Y + 2.0f*X*W; + dest[7] = 0.0f; + + dest[8] = 2.0f*X*Z + 2.0f*Y*W; + dest[9] = 2.0f*Z*Y - 2.0f*X*W; + dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + dest[11] = 0.0f; + + dest[12] = center.X; + dest[13] = center.Y; + dest[14] = center.Z; + dest[15] = 1.f; + + dest.setDefinitelyIdentityMatrix ( false ); +} + + +/*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo(vin[i].Normal, forward); + q.getMatrix(lookat, center); + + core::matrix4 m2; + m2.setInverseTranslation(center); + lookat *= m2; +*/ +inline void quaternion::getMatrixCenter(matrix4 &dest, + const core::vector3df ¢er, + const core::vector3df &translation) const +{ + dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + dest[1] = 2.0f*X*Y + 2.0f*Z*W; + dest[2] = 2.0f*X*Z - 2.0f*Y*W; + dest[3] = 0.0f; + + dest[4] = 2.0f*X*Y - 2.0f*Z*W; + dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + dest[6] = 2.0f*Z*Y + 2.0f*X*W; + dest[7] = 0.0f; + + dest[8] = 2.0f*X*Z + 2.0f*Y*W; + dest[9] = 2.0f*Z*Y - 2.0f*X*W; + dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + dest[11] = 0.0f; + + dest.setRotationCenter ( center, translation ); +} + +// Creates a matrix from this quaternion +inline void quaternion::getMatrix_transposed(matrix4 &dest) const +{ + dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + dest[4] = 2.0f*X*Y + 2.0f*Z*W; + dest[8] = 2.0f*X*Z - 2.0f*Y*W; + dest[12] = 0.0f; + + dest[1] = 2.0f*X*Y - 2.0f*Z*W; + dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + dest[9] = 2.0f*Z*Y + 2.0f*X*W; + dest[13] = 0.0f; + + dest[2] = 2.0f*X*Z + 2.0f*Y*W; + dest[6] = 2.0f*Z*Y - 2.0f*X*W; + dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + dest[14] = 0.0f; + + dest[3] = 0.f; + dest[7] = 0.f; + dest[11] = 0.f; + dest[15] = 1.f; + + dest.setDefinitelyIdentityMatrix(false); +} + + +// Inverts this quaternion +inline quaternion& quaternion::makeInverse() +{ + X = -X; Y = -Y; Z = -Z; + return *this; +} + + +// sets new quaternion +inline quaternion& quaternion::set(f32 x, f32 y, f32 z, f32 w) +{ + X = x; + Y = y; + Z = z; + W = w; + return *this; +} + + +// sets new quaternion based on euler angles +inline quaternion& quaternion::set(f32 x, f32 y, f32 z) +{ + f64 angle; + + angle = x * 0.5; + const f64 sr = sin(angle); + const f64 cr = cos(angle); + + angle = y * 0.5; + const f64 sp = sin(angle); + const f64 cp = cos(angle); + + angle = z * 0.5; + const f64 sy = sin(angle); + const f64 cy = cos(angle); + + const f64 cpcy = cp * cy; + const f64 spcy = sp * cy; + const f64 cpsy = cp * sy; + const f64 spsy = sp * sy; + + X = (f32)(sr * cpcy - cr * spsy); + Y = (f32)(cr * spcy + sr * cpsy); + Z = (f32)(cr * cpsy - sr * spcy); + W = (f32)(cr * cpcy + sr * spsy); + + return normalize(); +} + +// sets new quaternion based on euler angles +inline quaternion& quaternion::set(const core::vector3df& vec) +{ + return set(vec.X, vec.Y, vec.Z); +} + +// sets new quaternion based on other quaternion +inline quaternion& quaternion::set(const core::quaternion& quat) +{ + return (*this=quat); +} + + +//! returns if this quaternion equals the other one, taking floating point rounding errors into account +inline bool quaternion::equals(const quaternion& other, const f32 tolerance) const +{ + return core::equals(X, other.X, tolerance) && + core::equals(Y, other.Y, tolerance) && + core::equals(Z, other.Z, tolerance) && + core::equals(W, other.W, tolerance); +} + + +// normalizes the quaternion +inline quaternion& quaternion::normalize() +{ + const f32 n = X*X + Y*Y + Z*Z + W*W; + + if (n == 1) + return *this; + + //n = 1.0f / sqrtf(n); + return (*this *= reciprocal_squareroot ( n )); +} + + +// set this quaternion to the result of the linear interpolation between two quaternions +inline quaternion& quaternion::lerp(quaternion q1, quaternion q2, f32 time) +{ + const f32 scale = 1.0f - time; + return (*this = (q1*scale) + (q2*time)); +} + + +// set this quaternion to the result of the interpolation between two quaternions +inline quaternion& quaternion::slerp(quaternion q1, quaternion q2, f32 time, f32 threshold) +{ + f32 angle = q1.dotProduct(q2); + + // make sure we use the short rotation + if (angle < 0.0f) + { + q1 *= -1.0f; + angle *= -1.0f; + } + + if (angle <= (1-threshold)) // spherical interpolation + { + const f32 theta = acosf(angle); + const f32 invsintheta = reciprocal(sinf(theta)); + const f32 scale = sinf(theta * (1.0f-time)) * invsintheta; + const f32 invscale = sinf(theta * time) * invsintheta; + return (*this = (q1*scale) + (q2*invscale)); + } + else // linear interploation + return lerp(q1,q2,time); +} + + +// calculates the dot product +inline f32 quaternion::dotProduct(const quaternion& q2) const +{ + return (X * q2.X) + (Y * q2.Y) + (Z * q2.Z) + (W * q2.W); +} + + +//! axis must be unit length, angle in radians +inline quaternion& quaternion::fromAngleAxis(f32 angle, const vector3df& axis) +{ + const f32 fHalfAngle = 0.5f*angle; + const f32 fSin = sinf(fHalfAngle); + W = cosf(fHalfAngle); + X = fSin*axis.X; + Y = fSin*axis.Y; + Z = fSin*axis.Z; + return *this; +} + + +inline void quaternion::toAngleAxis(f32 &angle, core::vector3df &axis) const +{ + const f32 scale = sqrtf(X*X + Y*Y + Z*Z); + + if (core::iszero(scale) || W > 1.0f || W < -1.0f) + { + angle = 0.0f; + axis.X = 0.0f; + axis.Y = 1.0f; + axis.Z = 0.0f; + } + else + { + const f32 invscale = reciprocal(scale); + angle = 2.0f * acosf(W); + axis.X = X * invscale; + axis.Y = Y * invscale; + axis.Z = Z * invscale; + } +} + +inline void quaternion::toEuler(vector3df& euler) const +{ + const f64 sqw = W*W; + const f64 sqx = X*X; + const f64 sqy = Y*Y; + const f64 sqz = Z*Z; + const f64 test = 2.0 * (Y*W - X*Z); + + if (core::equals(test, 1.0, 0.000001)) + { + // heading = rotation about z-axis + euler.Z = (f32) (-2.0*atan2(X, W)); + // bank = rotation about x-axis + euler.X = 0; + // attitude = rotation about y-axis + euler.Y = (f32) (core::PI64/2.0); + } + else if (core::equals(test, -1.0, 0.000001)) + { + // heading = rotation about z-axis + euler.Z = (f32) (2.0*atan2(X, W)); + // bank = rotation about x-axis + euler.X = 0; + // attitude = rotation about y-axis + euler.Y = (f32) (core::PI64/-2.0); + } + else + { + // heading = rotation about z-axis + euler.Z = (f32) atan2(2.0 * (X*Y +Z*W),(sqx - sqy - sqz + sqw)); + // bank = rotation about x-axis + euler.X = (f32) atan2(2.0 * (Y*Z +X*W),(-sqx - sqy + sqz + sqw)); + // attitude = rotation about y-axis + euler.Y = (f32) asin( clamp(test, -1.0, 1.0) ); + } +} + + +inline vector3df quaternion::operator* (const vector3df& v) const +{ + // nVidia SDK implementation + + vector3df uv, uuv; + vector3df qvec(X, Y, Z); + uv = qvec.crossProduct(v); + uuv = qvec.crossProduct(uv); + uv *= (2.0f * W); + uuv *= 2.0f; + + return v + uv + uuv; +} + +// set quaternion to identity +inline core::quaternion& quaternion::makeIdentity() +{ + W = 1.f; + X = 0.f; + Y = 0.f; + Z = 0.f; + return *this; +} + +inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const vector3df& to) +{ + // Based on Stan Melax's article in Game Programming Gems + // Copy, since cannot modify local + vector3df v0 = from; + vector3df v1 = to; + v0.normalize(); + v1.normalize(); + + const f32 d = v0.dotProduct(v1); + if (d >= 1.0f) // If dot == 1, vectors are the same + { + return makeIdentity(); + } + else if (d <= -1.0f) // exactly opposite + { + core::vector3df axis(1.0f, 0.f, 0.f); + axis = axis.crossProduct(v0); + if (axis.getLength()==0) + { + axis.set(0.f,1.f,0.f); + axis = axis.crossProduct(v0); + } + // same as fromAngleAxis(core::PI, axis).normalize(); + return set(axis.X, axis.Y, axis.Z, 0).normalize(); + } + + const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt + const f32 invs = 1.f / s; + const vector3df c = v0.crossProduct(v1)*invs; + return set(c.X, c.Y, c.Z, s * 0.5f).normalize(); +} + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/rect.h b/inc/rect.h new file mode 100644 index 0000000..1e2572c --- /dev/null +++ b/inc/rect.h @@ -0,0 +1,279 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_RECT_H_INCLUDED__ +#define __IRR_RECT_H_INCLUDED__ + +#include "irrTypes.h" +#include "dimension2d.h" +#include "position2d.h" + +namespace irr +{ +namespace core +{ + + //! Rectangle template. + /** Mostly used by 2D GUI elements and for 2D drawing methods. + It has 2 positions instead of position and dimension and a fast + method for collision detection with other rectangles and points. + + Coordinates are (0,0) for top-left corner, and increasing to the right + and to the bottom. + */ + template + class rect + { + public: + + //! Default constructor creating empty rectangle at (0,0) + rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {} + + //! Constructor with two corners + rect(T x, T y, T x2, T y2) + : UpperLeftCorner(x,y), LowerRightCorner(x2,y2) {} + + //! Constructor with two corners + rect(const position2d& upperLeft, const position2d& lowerRight) + : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {} + + //! Constructor with upper left corner and dimension + template + rect(const position2d& pos, const dimension2d& size) + : UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {} + + //! move right by given numbers + rect operator+(const position2d& pos) const + { + rect ret(*this); + return ret+=pos; + } + + //! move right by given numbers + rect& operator+=(const position2d& pos) + { + UpperLeftCorner += pos; + LowerRightCorner += pos; + return *this; + } + + //! move left by given numbers + rect operator-(const position2d& pos) const + { + rect ret(*this); + return ret-=pos; + } + + //! move left by given numbers + rect& operator-=(const position2d& pos) + { + UpperLeftCorner -= pos; + LowerRightCorner -= pos; + return *this; + } + + //! equality operator + bool operator==(const rect& other) const + { + return (UpperLeftCorner == other.UpperLeftCorner && + LowerRightCorner == other.LowerRightCorner); + } + + //! inequality operator + bool operator!=(const rect& other) const + { + return (UpperLeftCorner != other.UpperLeftCorner || + LowerRightCorner != other.LowerRightCorner); + } + + //! compares size of rectangles + bool operator<(const rect& other) const + { + return getArea() < other.getArea(); + } + + //! Returns size of rectangle + T getArea() const + { + return getWidth() * getHeight(); + } + + //! Returns if a 2d point is within this rectangle. + /** \param pos Position to test if it lies within this rectangle. + \return True if the position is within the rectangle, false if not. */ + bool isPointInside(const position2d& pos) const + { + return (UpperLeftCorner.X <= pos.X && + UpperLeftCorner.Y <= pos.Y && + LowerRightCorner.X >= pos.X && + LowerRightCorner.Y >= pos.Y); + } + + //! Check if the rectangle collides with another rectangle. + /** \param other Rectangle to test collision with + \return True if the rectangles collide. */ + bool isRectCollided(const rect& other) const + { + return (LowerRightCorner.Y > other.UpperLeftCorner.Y && + UpperLeftCorner.Y < other.LowerRightCorner.Y && + LowerRightCorner.X > other.UpperLeftCorner.X && + UpperLeftCorner.X < other.LowerRightCorner.X); + } + + //! Clips this rectangle with another one. + /** \param other Rectangle to clip with */ + void clipAgainst(const rect& other) + { + if (other.LowerRightCorner.X < LowerRightCorner.X) + LowerRightCorner.X = other.LowerRightCorner.X; + if (other.LowerRightCorner.Y < LowerRightCorner.Y) + LowerRightCorner.Y = other.LowerRightCorner.Y; + + if (other.UpperLeftCorner.X > UpperLeftCorner.X) + UpperLeftCorner.X = other.UpperLeftCorner.X; + if (other.UpperLeftCorner.Y > UpperLeftCorner.Y) + UpperLeftCorner.Y = other.UpperLeftCorner.Y; + + // correct possible invalid rect resulting from clipping + if (UpperLeftCorner.Y > LowerRightCorner.Y) + UpperLeftCorner.Y = LowerRightCorner.Y; + if (UpperLeftCorner.X > LowerRightCorner.X) + UpperLeftCorner.X = LowerRightCorner.X; + } + + //! Moves this rectangle to fit inside another one. + /** \return True on success, false if not possible */ + bool constrainTo(const rect& other) + { + if (other.getWidth() < getWidth() || other.getHeight() < getHeight()) + return false; + + T diff = other.LowerRightCorner.X - LowerRightCorner.X; + if (diff < 0) + { + LowerRightCorner.X += diff; + UpperLeftCorner.X += diff; + } + + diff = other.LowerRightCorner.Y - LowerRightCorner.Y; + if (diff < 0) + { + LowerRightCorner.Y += diff; + UpperLeftCorner.Y += diff; + } + + diff = UpperLeftCorner.X - other.UpperLeftCorner.X; + if (diff < 0) + { + UpperLeftCorner.X -= diff; + LowerRightCorner.X -= diff; + } + + diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y; + if (diff < 0) + { + UpperLeftCorner.Y -= diff; + LowerRightCorner.Y -= diff; + } + + return true; + } + + //! Get width of rectangle. + T getWidth() const + { + return LowerRightCorner.X - UpperLeftCorner.X; + } + + //! Get height of rectangle. + T getHeight() const + { + return LowerRightCorner.Y - UpperLeftCorner.Y; + } + + //! If the lower right corner of the rect is smaller then the upper left, the points are swapped. + void repair() + { + if (LowerRightCorner.X < UpperLeftCorner.X) + { + T t = LowerRightCorner.X; + LowerRightCorner.X = UpperLeftCorner.X; + UpperLeftCorner.X = t; + } + + if (LowerRightCorner.Y < UpperLeftCorner.Y) + { + T t = LowerRightCorner.Y; + LowerRightCorner.Y = UpperLeftCorner.Y; + UpperLeftCorner.Y = t; + } + } + + //! Returns if the rect is valid to draw. + /** It would be invalid if the UpperLeftCorner is lower or more + right than the LowerRightCorner. */ + bool isValid() const + { + return ((LowerRightCorner.X >= UpperLeftCorner.X) && + (LowerRightCorner.Y >= UpperLeftCorner.Y)); + } + + //! Get the center of the rectangle + position2d getCenter() const + { + return position2d( + (UpperLeftCorner.X + LowerRightCorner.X) / 2, + (UpperLeftCorner.Y + LowerRightCorner.Y) / 2); + } + + //! Get the dimensions of the rectangle + dimension2d getSize() const + { + return dimension2d(getWidth(), getHeight()); + } + + + //! Adds a point to the rectangle + /** Causes the rectangle to grow bigger if point is outside of + the box + \param p Point to add to the box. */ + void addInternalPoint(const position2d& p) + { + addInternalPoint(p.X, p.Y); + } + + //! Adds a point to the bounding rectangle + /** Causes the rectangle to grow bigger if point is outside of + the box + \param x X-Coordinate of the point to add to this box. + \param y Y-Coordinate of the point to add to this box. */ + void addInternalPoint(T x, T y) + { + if (x>LowerRightCorner.X) + LowerRightCorner.X = x; + if (y>LowerRightCorner.Y) + LowerRightCorner.Y = y; + + if (x UpperLeftCorner; + //! Lower right corner + position2d LowerRightCorner; + }; + + //! Rectangle with float values + typedef rect rectf; + //! Rectangle with int values + typedef rect recti; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/triangle3d.h b/inc/triangle3d.h new file mode 100644 index 0000000..dbf8a8b --- /dev/null +++ b/inc/triangle3d.h @@ -0,0 +1,279 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_TRIANGLE_3D_H_INCLUDED__ +#define __IRR_TRIANGLE_3D_H_INCLUDED__ + +#include "vector3d.h" +#include "line3d.h" +#include "plane3d.h" +#include "aabbox3d.h" + +namespace irr +{ +namespace core +{ + + //! 3d triangle template class for doing collision detection and other things. + template + class triangle3d + { + public: + + //! Constructor for an all 0 triangle + triangle3d() {} + //! Constructor for triangle with given three vertices + triangle3d(vector3d v1, vector3d v2, vector3d v3) : pointA(v1), pointB(v2), pointC(v3) {} + + //! Equality operator + bool operator==(const triangle3d& other) const + { + return other.pointA==pointA && other.pointB==pointB && other.pointC==pointC; + } + + //! Inequality operator + bool operator!=(const triangle3d& other) const + { + return !(*this==other); + } + + //! Determines if the triangle is totally inside a bounding box. + /** \param box Box to check. + \return True if triangle is within the box, otherwise false. */ + bool isTotalInsideBox(const aabbox3d& box) const + { + return (box.isPointInside(pointA) && + box.isPointInside(pointB) && + box.isPointInside(pointC)); + } + + //! Determines if the triangle is totally outside a bounding box. + /** \param box Box to check. + \return True if triangle is outside the box, otherwise false. */ + bool isTotalOutsideBox(const aabbox3d& box) const + { + return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) || + + (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) || + (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) || + (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) || + (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) || + (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z)); + } + + //! Get the closest point on a triangle to a point on the same plane. + /** \param p Point which must be on the same plane as the triangle. + \return The closest point of the triangle */ + core::vector3d closestPointOnTriangle(const core::vector3d& p) const + { + const core::vector3d rab = line3d(pointA, pointB).getClosestPoint(p); + const core::vector3d rbc = line3d(pointB, pointC).getClosestPoint(p); + const core::vector3d rca = line3d(pointC, pointA).getClosestPoint(p); + + const T d1 = rab.getDistanceFrom(p); + const T d2 = rbc.getDistanceFrom(p); + const T d3 = rca.getDistanceFrom(p); + + if (d1 < d2) + return d1 < d3 ? rab : rca; + + return d2 < d3 ? rbc : rca; + } + + //! Check if a point is inside the triangle (border-points count also as inside) + /* + \param p Point to test. Assumes that this point is already + on the plane of the triangle. + \return True if the point is inside the triangle, otherwise false. */ + bool isPointInside(const vector3d& p) const + { + vector3d af64((f64)pointA.X, (f64)pointA.Y, (f64)pointA.Z); + vector3d bf64((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z); + vector3d cf64((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z); + vector3d pf64((f64)p.X, (f64)p.Y, (f64)p.Z); + return (isOnSameSide(pf64, af64, bf64, cf64) && + isOnSameSide(pf64, bf64, af64, cf64) && + isOnSameSide(pf64, cf64, af64, bf64)); + } + + //! Check if a point is inside the triangle (border-points count also as inside) + /** This method uses a barycentric coordinate system. + It is faster than isPointInside but is more susceptible to floating point rounding + errors. This will especially be noticable when the FPU is in single precision mode + (which is for example set on default by Direct3D). + \param p Point to test. Assumes that this point is already + on the plane of the triangle. + \return True if point is inside the triangle, otherwise false. */ + bool isPointInsideFast(const vector3d& p) const + { + const vector3d a = pointC - pointA; + const vector3d b = pointB - pointA; + const vector3d c = p - pointA; + + const f64 dotAA = a.dotProduct( a); + const f64 dotAB = a.dotProduct( b); + const f64 dotAC = a.dotProduct( c); + const f64 dotBB = b.dotProduct( b); + const f64 dotBC = b.dotProduct( c); + + // get coordinates in barycentric coordinate system + const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB); + const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom; + const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom; + + // We count border-points as inside to keep downward compatibility. + // Rounding-error also needed for some test-cases. + return (u > -ROUNDING_ERROR_f32) && (v >= 0) && (u + v < 1+ROUNDING_ERROR_f32); + + } + + + //! Get an intersection with a 3d line. + /** \param line Line to intersect with. + \param outIntersection Place to store the intersection point, if there is one. + \return True if there was an intersection, false if not. */ + bool getIntersectionWithLimitedLine(const line3d& line, + vector3d& outIntersection) const + { + return getIntersectionWithLine(line.start, + line.getVector(), outIntersection) && + outIntersection.isBetweenPoints(line.start, line.end); + } + + + //! Get an intersection with a 3d line. + /** Please note that also points are returned as intersection which + are on the line, but not between the start and end point of the line. + If you want the returned point be between start and end + use getIntersectionWithLimitedLine(). + \param linePoint Point of the line to intersect with. + \param lineVect Vector of the line to intersect with. + \param outIntersection Place to store the intersection point, if there is one. + \return True if there was an intersection, false if there was not. */ + bool getIntersectionWithLine(const vector3d& linePoint, + const vector3d& lineVect, vector3d& outIntersection) const + { + if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection)) + return isPointInside(outIntersection); + + return false; + } + + + //! Calculates the intersection between a 3d line and the plane the triangle is on. + /** \param lineVect Vector of the line to intersect with. + \param linePoint Point of the line to intersect with. + \param outIntersection Place to store the intersection point, if there is one. + \return True if there was an intersection, else false. */ + bool getIntersectionOfPlaneWithLine(const vector3d& linePoint, + const vector3d& lineVect, vector3d& outIntersection) const + { + // Work with f64 to get more precise results (makes enough difference to be worth the casts). + const vector3d linePointf64(linePoint.X, linePoint.Y, linePoint.Z); + const vector3d lineVectf64(lineVect.X, lineVect.Y, lineVect.Z); + vector3d outIntersectionf64; + + core::triangle3d trianglef64(vector3d((f64)pointA.X, (f64)pointA.Y, (f64)pointA.Z) + ,vector3d((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z) + , vector3d((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z)); + const vector3d normalf64 = trianglef64.getNormal().normalize(); + f64 t2; + + if ( core::iszero ( t2 = normalf64.dotProduct(lineVectf64) ) ) + return false; + + f64 d = trianglef64.pointA.dotProduct(normalf64); + f64 t = -(normalf64.dotProduct(linePointf64) - d) / t2; + outIntersectionf64 = linePointf64 + (lineVectf64 * t); + + outIntersection.X = (T)outIntersectionf64.X; + outIntersection.Y = (T)outIntersectionf64.Y; + outIntersection.Z = (T)outIntersectionf64.Z; + return true; + } + + + //! Get the normal of the triangle. + /** Please note: The normal is not always normalized. */ + vector3d getNormal() const + { + return (pointB - pointA).crossProduct(pointC - pointA); + } + + //! Test if the triangle would be front or backfacing from any point. + /** Thus, this method assumes a camera position from which the + triangle is definitely visible when looking at the given direction. + Do not use this method with points as it will give wrong results! + \param lookDirection Look direction. + \return True if the plane is front facing and false if it is backfacing. */ + bool isFrontFacing(const vector3d& lookDirection) const + { + const vector3d n = getNormal().normalize(); + const f32 d = (f32)n.dotProduct(lookDirection); + return F32_LOWER_EQUAL_0(d); + } + + //! Get the plane of this triangle. + plane3d getPlane() const + { + return plane3d(pointA, pointB, pointC); + } + + //! Get the area of the triangle + T getArea() const + { + return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f; + + } + + //! sets the triangle's points + void set(const core::vector3d& a, const core::vector3d& b, const core::vector3d& c) + { + pointA = a; + pointB = b; + pointC = c; + } + + //! the three points of the triangle + vector3d pointA; + vector3d pointB; + vector3d pointC; + + private: + // Using f64 instead of to avoid integer overflows when T=int (maybe also less floating point troubles). + bool isOnSameSide(const vector3d& p1, const vector3d& p2, + const vector3d& a, const vector3d& b) const + { + vector3d bminusa = b - a; + vector3d cp1 = bminusa.crossProduct(p1 - a); + vector3d cp2 = bminusa.crossProduct(p2 - a); + f64 res = cp1.dotProduct(cp2); + if ( res < 0 ) + { + // This catches some floating point troubles. + // Unfortunately slightly expensive and we don't really know the best epsilon for iszero. + vector3d cp1 = bminusa.normalize().crossProduct((p1 - a).normalize()); + if ( core::iszero(cp1.X, (f64)ROUNDING_ERROR_f32) + && core::iszero(cp1.Y, (f64)ROUNDING_ERROR_f32) + && core::iszero(cp1.Z, (f64)ROUNDING_ERROR_f32) ) + { + res = 0.f; + } + } + return (res >= 0.0f); + } + }; + + + //! Typedef for a f32 3d triangle. + typedef triangle3d triangle3df; + + //! Typedef for an integer 3d triangle. + typedef triangle3d triangle3di; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/vector2d.h b/inc/vector2d.h new file mode 100644 index 0000000..0927dfc --- /dev/null +++ b/inc/vector2d.h @@ -0,0 +1,342 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_POINT_2D_H_INCLUDED__ +#define __IRR_POINT_2D_H_INCLUDED__ + +#include "irrMath.h" +#include "dimension2d.h" + +namespace irr +{ +namespace core +{ + + +//! 2d vector template class with lots of operators and methods. +/** As of Irrlicht 1.6, this class supercedes position2d, which should + be considered deprecated. */ +template +class vector2d +{ +public: + //! Default constructor (null vector) + vector2d() : X(0), Y(0) {} + //! Constructor with two different values + vector2d(T nx, T ny) : X(nx), Y(ny) {} + //! Constructor with the same value for both members + explicit vector2d(T n) : X(n), Y(n) {} + //! Copy constructor + vector2d(const vector2d& other) : X(other.X), Y(other.Y) {} + + vector2d(const dimension2d& other) : X(other.Width), Y(other.Height) {} + + // operators + + vector2d operator-() const { return vector2d(-X, -Y); } + + vector2d& operator=(const vector2d& other) { X = other.X; Y = other.Y; return *this; } + + vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } + + vector2d operator+(const vector2d& other) const { return vector2d(X + other.X, Y + other.Y); } + vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } + vector2d& operator+=(const vector2d& other) { X+=other.X; Y+=other.Y; return *this; } + vector2d operator+(const T v) const { return vector2d(X + v, Y + v); } + vector2d& operator+=(const T v) { X+=v; Y+=v; return *this; } + vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } + + vector2d operator-(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y); } + vector2d operator-(const dimension2d& other) const { return vector2d(X - other.Width, Y - other.Height); } + vector2d& operator-=(const vector2d& other) { X-=other.X; Y-=other.Y; return *this; } + vector2d operator-(const T v) const { return vector2d(X - v, Y - v); } + vector2d& operator-=(const T v) { X-=v; Y-=v; return *this; } + vector2d& operator-=(const dimension2d& other) { X -= other.Width; Y -= other.Height; return *this; } + + vector2d operator*(const vector2d& other) const { return vector2d(X * other.X, Y * other.Y); } + vector2d& operator*=(const vector2d& other) { X*=other.X; Y*=other.Y; return *this; } + vector2d operator*(const T v) const { return vector2d(X * v, Y * v); } + vector2d& operator*=(const T v) { X*=v; Y*=v; return *this; } + + vector2d operator/(const vector2d& other) const { return vector2d(X / other.X, Y / other.Y); } + vector2d& operator/=(const vector2d& other) { X/=other.X; Y/=other.Y; return *this; } + vector2d operator/(const T v) const { return vector2d(X / v, Y / v); } + vector2d& operator/=(const T v) { X/=v; Y/=v; return *this; } + + //! sort in order X, Y. Equality with rounding tolerance. + bool operator<=(const vector2d&other) const + { + return (X=(const vector2d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))); + } + + //! sort in order X, Y. Difference must be above rounding tolerance. + bool operator<(const vector2d&other) const + { + return (X(const vector2d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)); + } + + bool operator==(const vector2d& other) const { return equals(other); } + bool operator!=(const vector2d& other) const { return !equals(other); } + + // functions + + //! Checks if this vector equals the other one. + /** Takes floating point rounding errors into account. + \param other Vector to compare with. + \return True if the two vector are (almost) equal, else false. */ + bool equals(const vector2d& other) const + { + return core::equals(X, other.X) && core::equals(Y, other.Y); + } + + vector2d& set(T nx, T ny) {X=nx; Y=ny; return *this; } + vector2d& set(const vector2d& p) { X=p.X; Y=p.Y; return *this; } + + //! Gets the length of the vector. + /** \return The length of the vector. */ + T getLength() const { return core::squareroot( X*X + Y*Y ); } + + //! Get the squared length of this vector + /** This is useful because it is much faster than getLength(). + \return The squared length of the vector. */ + T getLengthSQ() const { return X*X + Y*Y; } + + //! Get the dot product of this vector with another. + /** \param other Other vector to take dot product with. + \return The dot product of the two vectors. */ + T dotProduct(const vector2d& other) const + { + return X*other.X + Y*other.Y; + } + + //! Gets distance from another point. + /** Here, the vector is interpreted as a point in 2-dimensional space. + \param other Other vector to measure from. + \return Distance from other point. */ + T getDistanceFrom(const vector2d& other) const + { + return vector2d(X - other.X, Y - other.Y).getLength(); + } + + //! Returns squared distance from another point. + /** Here, the vector is interpreted as a point in 2-dimensional space. + \param other Other vector to measure from. + \return Squared distance from other point. */ + T getDistanceFromSQ(const vector2d& other) const + { + return vector2d(X - other.X, Y - other.Y).getLengthSQ(); + } + + //! rotates the point anticlockwise around a center by an amount of degrees. + /** \param degrees Amount of degrees to rotate by, anticlockwise. + \param center Rotation center. + \return This vector after transformation. */ + vector2d& rotateBy(f64 degrees, const vector2d& center=vector2d()) + { + degrees *= DEGTORAD64; + const f64 cs = cos(degrees); + const f64 sn = sin(degrees); + + X -= center.X; + Y -= center.Y; + + set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs)); + + X += center.X; + Y += center.Y; + return *this; + } + + //! Normalize the vector. + /** The null vector is left untouched. + \return Reference to this vector, after normalization. */ + vector2d& normalize() + { + f32 length = (f32)(X*X + Y*Y); + if ( length == 0 ) + return *this; + length = core::reciprocal_squareroot ( length ); + X = (T)(X * length); + Y = (T)(Y * length); + return *this; + } + + //! Calculates the angle of this vector in degrees in the trigonometric sense. + /** 0 is to the right (3 o'clock), values increase counter-clockwise. + This method has been suggested by Pr3t3nd3r. + \return Returns a value between 0 and 360. */ + f64 getAngleTrig() const + { + if (Y == 0) + return X < 0 ? 180 : 0; + else + if (X == 0) + return Y < 0 ? 270 : 90; + + if ( Y > 0) + if (X > 0) + return atan((irr::f64)Y/(irr::f64)X) * RADTODEG64; + else + return 180.0-atan((irr::f64)Y/-(irr::f64)X) * RADTODEG64; + else + if (X > 0) + return 360.0-atan(-(irr::f64)Y/(irr::f64)X) * RADTODEG64; + else + return 180.0+atan(-(irr::f64)Y/-(irr::f64)X) * RADTODEG64; + } + + //! Calculates the angle of this vector in degrees in the counter trigonometric sense. + /** 0 is to the right (3 o'clock), values increase clockwise. + \return Returns a value between 0 and 360. */ + inline f64 getAngle() const + { + if (Y == 0) // corrected thanks to a suggestion by Jox + return X < 0 ? 180 : 0; + else if (X == 0) + return Y < 0 ? 90 : 270; + + // don't use getLength here to avoid precision loss with s32 vectors + // avoid floating-point trouble as sqrt(y*y) is occasionally larger than y, so clamp + const f64 tmp = core::clamp(Y / sqrt((f64)(X*X + Y*Y)), -1.0, 1.0); + const f64 angle = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64; + + if (X>0 && Y>0) + return angle + 270; + else + if (X>0 && Y<0) + return angle + 90; + else + if (X<0 && Y<0) + return 90 - angle; + else + if (X<0 && Y>0) + return 270 - angle; + + return angle; + } + + //! Calculates the angle between this vector and another one in degree. + /** \param b Other vector to test with. + \return Returns a value between 0 and 90. */ + inline f64 getAngleWith(const vector2d& b) const + { + f64 tmp = (f64)(X*b.X + Y*b.Y); + + if (tmp == 0.0) + return 90.0; + + tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y))); + if (tmp < 0.0) + tmp = -tmp; + if ( tmp > 1.0 ) // avoid floating-point trouble + tmp = 1.0; + + return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64; + } + + //! Returns if this vector interpreted as a point is on a line between two other points. + /** It is assumed that the point is on the line. + \param begin Beginning vector to compare between. + \param end Ending vector to compare between. + \return True if this vector is between begin and end, false if not. */ + bool isBetweenPoints(const vector2d& begin, const vector2d& end) const + { + if (begin.X != end.X) + { + return ((begin.X <= X && X <= end.X) || + (begin.X >= X && X >= end.X)); + } + else + { + return ((begin.Y <= Y && Y <= end.Y) || + (begin.Y >= Y && Y >= end.Y)); + } + } + + //! Creates an interpolated vector between this vector and another vector. + /** \param other The other vector to interpolate with. + \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + \return An interpolated vector. This vector is not modified. */ + vector2d getInterpolated(const vector2d& other, f64 d) const + { + f64 inv = 1.0f - d; + return vector2d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d)); + } + + //! Creates a quadratically interpolated vector between this and two other vectors. + /** \param v2 Second vector to interpolate with. + \param v3 Third vector to interpolate with (maximum at 1.0f) + \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). + Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() + \return An interpolated vector. This vector is not modified. */ + vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, f64 d) const + { + // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; + const f64 inv = 1.0f - d; + const f64 mul0 = inv * inv; + const f64 mul1 = 2.0f * d * inv; + const f64 mul2 = d * d; + + return vector2d ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2), + (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2)); + } + + //! Sets this vector to the linearly interpolated vector between a and b. + /** \param a first vector to interpolate with, maximum at 1.0f + \param b second vector to interpolate with, maximum at 0.0f + \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a) + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + */ + vector2d& interpolate(const vector2d& a, const vector2d& b, f64 d) + { + X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); + Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); + return *this; + } + + //! X coordinate of vector. + T X; + + //! Y coordinate of vector. + T Y; +}; + + //! Typedef for f32 2d vector. + typedef vector2d vector2df; + + //! Typedef for integer 2d vector. + typedef vector2d vector2di; + + template + vector2d operator*(const S scalar, const vector2d& vector) { return vector*scalar; } + + // These methods are declared in dimension2d, but need definitions of vector2d + template + dimension2d::dimension2d(const vector2d& other) : Width(other.X), Height(other.Y) { } + + template + bool dimension2d::operator==(const vector2d& other) const { return Width == other.X && Height == other.Y; } + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/inc/vector3d.h b/inc/vector3d.h new file mode 100644 index 0000000..d582978 --- /dev/null +++ b/inc/vector3d.h @@ -0,0 +1,458 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_POINT_3D_H_INCLUDED__ +#define __IRR_POINT_3D_H_INCLUDED__ + +#include "irrMath.h" + +namespace irr +{ +namespace core +{ + + //! 3d vector template class with lots of operators and methods. + /** The vector3d class is used in Irrlicht for three main purposes: + 1) As a direction vector (most of the methods assume this). + 2) As a position in 3d space (which is synonymous with a direction vector from the origin to this position). + 3) To hold three Euler rotations, where X is pitch, Y is yaw and Z is roll. + */ + template + class vector3d + { + public: + //! Default constructor (null vector). + vector3d() : X(0), Y(0), Z(0) {} + //! Constructor with three different values + vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {} + //! Constructor with the same value for all elements + explicit vector3d(T n) : X(n), Y(n), Z(n) {} + //! Copy constructor + vector3d(const vector3d& other) : X(other.X), Y(other.Y), Z(other.Z) {} + + // operators + + vector3d operator-() const { return vector3d(-X, -Y, -Z); } + + vector3d& operator=(const vector3d& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; } + + vector3d operator+(const vector3d& other) const { return vector3d(X + other.X, Y + other.Y, Z + other.Z); } + vector3d& operator+=(const vector3d& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; } + vector3d operator+(const T val) const { return vector3d(X + val, Y + val, Z + val); } + vector3d& operator+=(const T val) { X+=val; Y+=val; Z+=val; return *this; } + + vector3d operator-(const vector3d& other) const { return vector3d(X - other.X, Y - other.Y, Z - other.Z); } + vector3d& operator-=(const vector3d& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; } + vector3d operator-(const T val) const { return vector3d(X - val, Y - val, Z - val); } + vector3d& operator-=(const T val) { X-=val; Y-=val; Z-=val; return *this; } + + vector3d operator*(const vector3d& other) const { return vector3d(X * other.X, Y * other.Y, Z * other.Z); } + vector3d& operator*=(const vector3d& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; } + vector3d operator*(const T v) const { return vector3d(X * v, Y * v, Z * v); } + vector3d& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; } + + vector3d operator/(const vector3d& other) const { return vector3d(X / other.X, Y / other.Y, Z / other.Z); } + vector3d& operator/=(const vector3d& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } + vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } + vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } + + //! sort in order X, Y, Z. Equality with rounding tolerance. + bool operator<=(const vector3d&other) const + { + return (X=(const vector3d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z))); + } + + //! sort in order X, Y, Z. Difference must be above rounding tolerance. + bool operator<(const vector3d&other) const + { + return (X(const vector3d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z)); + } + + //! use weak float compare + bool operator==(const vector3d& other) const + { + return this->equals(other); + } + + bool operator!=(const vector3d& other) const + { + return !this->equals(other); + } + + // functions + + //! returns if this vector equals the other one, taking floating point rounding errors into account + bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const + { + return core::equals(X, other.X, tolerance) && + core::equals(Y, other.Y, tolerance) && + core::equals(Z, other.Z, tolerance); + } + + vector3d& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;} + vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} + + //! Get length of the vector. + T getLength() const { return core::squareroot( X*X + Y*Y + Z*Z ); } + + //! Get squared length of the vector. + /** This is useful because it is much faster than getLength(). + \return Squared length of the vector. */ + T getLengthSQ() const { return X*X + Y*Y + Z*Z; } + + //! Get the dot product with another vector. + T dotProduct(const vector3d& other) const + { + return X*other.X + Y*other.Y + Z*other.Z; + } + + //! Get distance from another point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + T getDistanceFrom(const vector3d& other) const + { + return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLength(); + } + + //! Returns squared distance from another point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + T getDistanceFromSQ(const vector3d& other) const + { + return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLengthSQ(); + } + + //! Calculates the cross product with another vector. + /** \param p Vector to multiply with. + \return Crossproduct of this vector with p. */ + vector3d crossProduct(const vector3d& p) const + { + return vector3d(Y * p.Z - Z * p.Y, Z * p.X - X * p.Z, X * p.Y - Y * p.X); + } + + //! Returns if this vector interpreted as a point is on a line between two other points. + /** It is assumed that the point is on the line. + \param begin Beginning vector to compare between. + \param end Ending vector to compare between. + \return True if this vector is between begin and end, false if not. */ + bool isBetweenPoints(const vector3d& begin, const vector3d& end) const + { + const T f = (end - begin).getLengthSQ(); + return getDistanceFromSQ(begin) <= f && + getDistanceFromSQ(end) <= f; + } + + //! Normalizes the vector. + /** In case of the 0 vector the result is still 0, otherwise + the length of the vector will be 1. + \return Reference to this vector after normalization. */ + vector3d& normalize() + { + f64 length = X*X + Y*Y + Z*Z; + if (length == 0 ) // this check isn't an optimization but prevents getting NAN in the sqrt. + return *this; + length = core::reciprocal_squareroot(length); + + X = (T)(X * length); + Y = (T)(Y * length); + Z = (T)(Z * length); + return *this; + } + + //! Sets the length of the vector to a new value + vector3d& setLength(T newlength) + { + normalize(); + return (*this *= newlength); + } + + //! Inverts the vector. + vector3d& invert() + { + X *= -1; + Y *= -1; + Z *= -1; + return *this; + } + + //! Rotates the vector by a specified number of degrees around the Y axis and the specified center. + /** \param degrees Number of degrees to rotate around the Y axis. + \param center The center of the rotation. */ + void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + f64 cs = cos(degrees); + f64 sn = sin(degrees); + X -= center.X; + Z -= center.Z; + set((T)(X*cs - Z*sn), Y, (T)(X*sn + Z*cs)); + X += center.X; + Z += center.Z; + } + + //! Rotates the vector by a specified number of degrees around the Z axis and the specified center. + /** \param degrees: Number of degrees to rotate around the Z axis. + \param center: The center of the rotation. */ + void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + f64 cs = cos(degrees); + f64 sn = sin(degrees); + X -= center.X; + Y -= center.Y; + set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs), Z); + X += center.X; + Y += center.Y; + } + + //! Rotates the vector by a specified number of degrees around the X axis and the specified center. + /** \param degrees: Number of degrees to rotate around the X axis. + \param center: The center of the rotation. */ + void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + f64 cs = cos(degrees); + f64 sn = sin(degrees); + Z -= center.Z; + Y -= center.Y; + set(X, (T)(Y*cs - Z*sn), (T)(Y*sn + Z*cs)); + Z += center.Z; + Y += center.Y; + } + + //! Creates an interpolated vector between this vector and another vector. + /** \param other The other vector to interpolate with. + \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + \return An interpolated vector. This vector is not modified. */ + vector3d getInterpolated(const vector3d& other, f64 d) const + { + const f64 inv = 1.0 - d; + return vector3d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d), (T)(other.Z*inv + Z*d)); + } + + //! Creates a quadratically interpolated vector between this and two other vectors. + /** \param v2 Second vector to interpolate with. + \param v3 Third vector to interpolate with (maximum at 1.0f) + \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). + Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() + \return An interpolated vector. This vector is not modified. */ + vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, f64 d) const + { + // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; + const f64 inv = (T) 1.0 - d; + const f64 mul0 = inv * inv; + const f64 mul1 = (T) 2.0 * d * inv; + const f64 mul2 = d * d; + + return vector3d ((T)(X * mul0 + v2.X * mul1 + v3.X * mul2), + (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2), + (T)(Z * mul0 + v2.Z * mul1 + v3.Z * mul2)); + } + + //! Sets this vector to the linearly interpolated vector between a and b. + /** \param a first vector to interpolate with, maximum at 1.0f + \param b second vector to interpolate with, maximum at 0.0f + \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a) + Note that this is the opposite direction of interpolation to getInterpolated_quadratic() + */ + vector3d& interpolate(const vector3d& a, const vector3d& b, f64 d) + { + X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); + Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); + Z = (T)((f64)b.Z + ( ( a.Z - b.Z ) * d )); + return *this; + } + + + //! Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector. + /** Thanks to Arras on the Irrlicht forums for this method. This utility method is very useful for + orienting scene nodes towards specific targets. For example, if this vector represents the difference + between two scene nodes, then applying the result of getHorizontalAngle() to one scene node will point + it at the other one. + Example code: + // Where target and seeker are of type ISceneNode* + const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition()); + const vector3df requiredRotation = toTarget.getHorizontalAngle(); + seeker->setRotation(requiredRotation); + + \return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a + +Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation + is always 0, since two Euler rotations are sufficient to point in any given direction. */ + vector3d getHorizontalAngle() const + { + vector3d angle; + + const f64 tmp = (atan2((f64)X, (f64)Z) * RADTODEG64); + angle.Y = (T)tmp; + + if (angle.Y < 0) + angle.Y += 360; + if (angle.Y >= 360) + angle.Y -= 360; + + const f64 z1 = core::squareroot(X*X + Z*Z); + + angle.X = (T)(atan2((f64)z1, (f64)Y) * RADTODEG64 - 90.0); + + if (angle.X < 0) + angle.X += 360; + if (angle.X >= 360) + angle.X -= 360; + + return angle; + } + + //! Get the spherical coordinate angles + /** This returns Euler degrees for the point represented by + this vector. The calculation assumes the pole at (0,1,0) and + returns the angles in X and Y. + */ + vector3d getSphericalCoordinateAngles() const + { + vector3d angle; + const f64 length = X*X + Y*Y + Z*Z; + + if (length) + { + if (X!=0) + { + angle.Y = (T)(atan2((f64)Z,(f64)X) * RADTODEG64); + } + else if (Z<0) + angle.Y=180; + + angle.X = (T)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64); + } + return angle; + } + + //! Builds a direction vector from (this) rotation vector. + /** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees. + The implementation performs the same calculations as using a matrix to do the rotation. + + \param[in] forwards The direction representing "forwards" which will be rotated by this vector. + If you do not provide a direction, then the +Z axis (0, 0, 1) will be assumed to be forwards. + \return A direction vector calculated by rotating the forwards direction by the 3 Euler angles + (in degrees) represented by this vector. */ + vector3d rotationToDirection(const vector3d & forwards = vector3d(0, 0, 1)) const + { + const f64 cr = cos( core::DEGTORAD64 * X ); + const f64 sr = sin( core::DEGTORAD64 * X ); + const f64 cp = cos( core::DEGTORAD64 * Y ); + const f64 sp = sin( core::DEGTORAD64 * Y ); + const f64 cy = cos( core::DEGTORAD64 * Z ); + const f64 sy = sin( core::DEGTORAD64 * Z ); + + const f64 srsp = sr*sp; + const f64 crsp = cr*sp; + + const f64 pseudoMatrix[] = { + ( cp*cy ), ( cp*sy ), ( -sp ), + ( srsp*cy-cr*sy ), ( srsp*sy+cr*cy ), ( sr*cp ), + ( crsp*cy+sr*sy ), ( crsp*sy-sr*cy ), ( cr*cp )}; + + return vector3d( + (T)(forwards.X * pseudoMatrix[0] + + forwards.Y * pseudoMatrix[3] + + forwards.Z * pseudoMatrix[6]), + (T)(forwards.X * pseudoMatrix[1] + + forwards.Y * pseudoMatrix[4] + + forwards.Z * pseudoMatrix[7]), + (T)(forwards.X * pseudoMatrix[2] + + forwards.Y * pseudoMatrix[5] + + forwards.Z * pseudoMatrix[8])); + } + + //! Fills an array of 4 values with the vector data (usually floats). + /** Useful for setting in shader constants for example. The fourth value + will always be 0. */ + void getAs4Values(T* array) const + { + array[0] = X; + array[1] = Y; + array[2] = Z; + array[3] = 0; + } + + //! Fills an array of 3 values with the vector data (usually floats). + /** Useful for setting in shader constants for example.*/ + void getAs3Values(T* array) const + { + array[0] = X; + array[1] = Y; + array[2] = Z; + } + + + //! X coordinate of the vector + T X; + + //! Y coordinate of the vector + T Y; + + //! Z coordinate of the vector + T Z; + }; + + //! partial specialization for integer vectors + // Implementor note: inline keyword needed due to template specialization for s32. Otherwise put specialization into a .cpp + template <> + inline vector3d vector3d::operator /(s32 val) const {return core::vector3d(X/val,Y/val,Z/val);} + template <> + inline vector3d& vector3d::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;} + + template <> + inline vector3d vector3d::getSphericalCoordinateAngles() const + { + vector3d angle; + const f64 length = X*X + Y*Y + Z*Z; + + if (length) + { + if (X!=0) + { + angle.Y = round32((f32)(atan2((f64)Z,(f64)X) * RADTODEG64)); + } + else if (Z<0) + angle.Y=180; + + angle.X = round32((f32)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64)); + } + return angle; + } + + //! Typedef for a f32 3d vector. + typedef vector3d vector3df; + + //! Typedef for an integer 3d vector. + typedef vector3d vector3di; + + //! Function multiplying a scalar and a vector component-wise. + template + vector3d operator*(const S scalar, const vector3d& vector) { return vector*scalar; } + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/lib/Irrlicht.lib b/lib/Irrlicht.lib new file mode 100644 index 0000000..ef3cf6a Binary files /dev/null and b/lib/Irrlicht.lib differ