]> git.lizzy.rs Git - irrlicht.git/blob - include/IMeshManipulator.h
Support both OpenGL3 and GLES2 on SDL2
[irrlicht.git] / include / IMeshManipulator.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __I_MESH_MANIPULATOR_H_INCLUDED__\r
6 #define __I_MESH_MANIPULATOR_H_INCLUDED__\r
7 \r
8 #include "IReferenceCounted.h"\r
9 #include "vector3d.h"\r
10 #include "aabbox3d.h"\r
11 #include "matrix4.h"\r
12 #include "IAnimatedMesh.h"\r
13 #include "IMeshBuffer.h"\r
14 #include "SVertexManipulator.h"\r
15 \r
16 namespace irr\r
17 {\r
18 namespace scene\r
19 {\r
20 \r
21         struct SMesh;\r
22 \r
23         //! An interface for easy manipulation of meshes.\r
24         /** Scale, set alpha value, flip surfaces, and so on. This exists for\r
25         fixing problems with wrong imported or exported meshes quickly after\r
26         loading. It is not intended for doing mesh modifications and/or\r
27         animations during runtime.\r
28         */\r
29         class IMeshManipulator : public virtual IReferenceCounted\r
30         {\r
31         public:\r
32 \r
33                 //! Recalculates all normals of the mesh.\r
34                 /** \param mesh: Mesh on which the operation is performed.\r
35                 \param smooth: If the normals shall be smoothed.\r
36                 \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */\r
37                 virtual void recalculateNormals(IMesh* mesh, bool smooth = false,\r
38                                 bool angleWeighted = false) const=0;\r
39 \r
40                 //! Recalculates all normals of the mesh buffer.\r
41                 /** \param buffer: Mesh buffer on which the operation is performed.\r
42                 \param smooth: If the normals shall be smoothed.\r
43                 \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */\r
44                 virtual void recalculateNormals(IMeshBuffer* buffer,\r
45                                 bool smooth = false, bool angleWeighted = false) const=0;\r
46 \r
47                 //! Scales the actual mesh, not a scene node.\r
48                 /** \param mesh Mesh on which the operation is performed.\r
49                 \param factor Scale factor for each axis. */\r
50                 void scale(IMesh* mesh, const core::vector3df& factor) const\r
51                 {\r
52                         apply(SVertexPositionScaleManipulator(factor), mesh, true);\r
53                 }\r
54 \r
55                 //! Scales the actual meshbuffer, not a scene node.\r
56                 /** \param buffer Meshbuffer on which the operation is performed.\r
57                 \param factor Scale factor for each axis. */\r
58                 void scale(IMeshBuffer* buffer, const core::vector3df& factor) const\r
59                 {\r
60                         apply(SVertexPositionScaleManipulator(factor), buffer, true);\r
61                 }\r
62 \r
63                 //! Clones a static IMesh into a modifiable SMesh.\r
64                 /** All meshbuffers in the returned SMesh\r
65                 are of type SMeshBuffer or SMeshBufferLightMap.\r
66                 \param mesh Mesh to copy.\r
67                 \return Cloned mesh. If you no longer need the\r
68                 cloned mesh, you should call SMesh::drop(). See\r
69                 IReferenceCounted::drop() for more information. */\r
70                 virtual SMesh* createMeshCopy(IMesh* mesh) const = 0;\r
71 \r
72                 //! Get amount of polygons in mesh.\r
73                 /** \param mesh Input mesh\r
74                 \return Number of polygons in mesh. */\r
75                 virtual s32 getPolyCount(IMesh* mesh) const = 0;\r
76 \r
77                 //! Get amount of polygons in mesh.\r
78                 /** \param mesh Input mesh\r
79                 \return Number of polygons in mesh. */\r
80                 virtual s32 getPolyCount(IAnimatedMesh* mesh) const = 0;\r
81 \r
82                 //! Create a new AnimatedMesh and adds the mesh to it\r
83                 /** \param mesh Input mesh\r
84                 \param type The type of the animated mesh to create.\r
85                 \return Newly created animated mesh with mesh as its only\r
86                 content. When you don't need the animated mesh anymore, you\r
87                 should call IAnimatedMesh::drop(). See\r
88                 IReferenceCounted::drop() for more information. */\r
89                 virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh,\r
90                         scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0;\r
91 \r
92                 //! Apply a manipulator on the Meshbuffer\r
93                 /** \param func A functor defining the mesh manipulation.\r
94                 \param buffer The Meshbuffer to apply the manipulator to.\r
95                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
96                 \return True if the functor was successfully applied, else false. */\r
97                 template <typename Functor>\r
98                 bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const\r
99                 {\r
100                         return apply_(func, buffer, boundingBoxUpdate, func);\r
101                 }\r
102 \r
103 \r
104                 //! Apply a manipulator on the Mesh\r
105                 /** \param func A functor defining the mesh manipulation.\r
106                 \param mesh The Mesh to apply the manipulator to.\r
107                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
108                 \return True if the functor was successfully applied, else false. */\r
109                 template <typename Functor>\r
110                 bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const\r
111                 {\r
112                         if (!mesh)\r
113                                 return true;\r
114                         bool result = true;\r
115                         core::aabbox3df bufferbox;\r
116                         for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)\r
117                         {\r
118                                 result &= apply(func, mesh->getMeshBuffer(i), boundingBoxUpdate);\r
119                                 if (boundingBoxUpdate)\r
120                                 {\r
121                                         if (0==i)\r
122                                                 bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox());\r
123                                         else\r
124                                                 bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox());\r
125                                 }\r
126                         }\r
127                         if (boundingBoxUpdate)\r
128                                 mesh->setBoundingBox(bufferbox);\r
129                         return result;\r
130                 }\r
131 \r
132 protected:\r
133                 //! Apply a manipulator based on the type of the functor\r
134                 /** \param func A functor defining the mesh manipulation.\r
135                 \param buffer The Meshbuffer to apply the manipulator to.\r
136                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
137                 \param typeTest Unused parameter, which handles the proper call selection based on the type of the Functor which is passed in two times.\r
138                 \return True if the functor was successfully applied, else false. */\r
139                 template <typename Functor>\r
140                 bool apply_(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate, const IVertexManipulator& typeTest) const\r
141                 {\r
142                         if (!buffer)\r
143                                 return true;\r
144 \r
145                         core::aabbox3df bufferbox;\r
146                         for (u32 i=0; i<buffer->getVertexCount(); ++i)\r
147                         {\r
148                                 switch (buffer->getVertexType())\r
149                                 {\r
150                                 case video::EVT_STANDARD:\r
151                                         {\r
152                                                 video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices();\r
153                                                 func(verts[i]);\r
154                                         }\r
155                                         break;\r
156                                 case video::EVT_2TCOORDS:\r
157                                         {\r
158                                                 video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices();\r
159                                                 func(verts[i]);\r
160                                         }\r
161                                         break;\r
162                                 case video::EVT_TANGENTS:\r
163                                         {\r
164                                                 video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices();\r
165                                                 func(verts[i]);\r
166                                         }\r
167                                         break;\r
168                                 }\r
169                                 if (boundingBoxUpdate)\r
170                                 {\r
171                                         if (0==i)\r
172                                                 bufferbox.reset(buffer->getPosition(0));\r
173                                         else\r
174                                                 bufferbox.addInternalPoint(buffer->getPosition(i));\r
175                                 }\r
176                         }\r
177                         if (boundingBoxUpdate)\r
178                                 buffer->setBoundingBox(bufferbox);\r
179                         return true;\r
180                 }\r
181 };\r
182 \r
183 } // end namespace scene\r
184 } // end namespace irr\r
185 \r
186 \r
187 #endif\r