]> git.lizzy.rs Git - irrlicht.git/blob - include/IMeshManipulator.h
Add a unified cross platform OpenGL core profile binding (#52)
[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                 //! Flips the direction of surfaces.\r
34                 /** Changes backfacing triangles to frontfacing\r
35                 triangles and vice versa.\r
36                 \param mesh Mesh on which the operation is performed. */\r
37                 virtual void flipSurfaces(IMesh* mesh) const = 0;\r
38 \r
39                 //! Sets the alpha vertex color value of the whole mesh to a new value.\r
40                 /** \param mesh Mesh on which the operation is performed.\r
41                 \param alpha New alpha value. Must be a value between 0 and 255. */\r
42                 void setVertexColorAlpha(IMesh* mesh, s32 alpha) const\r
43                 {\r
44                         apply(scene::SVertexColorSetAlphaManipulator(alpha), mesh);\r
45                 }\r
46 \r
47                 //! Sets the alpha vertex color value of the whole mesh to a new value.\r
48                 /** \param buffer Meshbuffer on which the operation is performed.\r
49                 \param alpha New alpha value. Must be a value between 0 and 255. */\r
50                 void setVertexColorAlpha(IMeshBuffer* buffer, s32 alpha) const\r
51                 {\r
52                         apply(scene::SVertexColorSetAlphaManipulator(alpha), buffer);\r
53                 }\r
54 \r
55                 //! Sets the colors of all vertices to one color\r
56                 /** \param mesh Mesh on which the operation is performed.\r
57                 \param color New color. */\r
58                 void setVertexColors(IMesh* mesh, video::SColor color) const\r
59                 {\r
60                         apply(scene::SVertexColorSetManipulator(color), mesh);\r
61                 }\r
62 \r
63                 //! Sets the colors of all vertices to one color\r
64                 /** \param buffer Meshbuffer on which the operation is performed.\r
65                 \param color New color. */\r
66                 void setVertexColors(IMeshBuffer* buffer, video::SColor color) const\r
67                 {\r
68                         apply(scene::SVertexColorSetManipulator(color), buffer);\r
69                 }\r
70 \r
71                 //! Recalculates all normals of the mesh.\r
72                 /** \param mesh: Mesh on which the operation is performed.\r
73                 \param smooth: If the normals shall be smoothed.\r
74                 \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */\r
75                 virtual void recalculateNormals(IMesh* mesh, bool smooth = false,\r
76                                 bool angleWeighted = false) const=0;\r
77 \r
78                 //! Recalculates all normals of the mesh buffer.\r
79                 /** \param buffer: Mesh buffer on which the operation is performed.\r
80                 \param smooth: If the normals shall be smoothed.\r
81                 \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */\r
82                 virtual void recalculateNormals(IMeshBuffer* buffer,\r
83                                 bool smooth = false, bool angleWeighted = false) const=0;\r
84 \r
85                 //! Recalculates tangents, requires a tangent mesh\r
86                 /** \param mesh Mesh on which the operation is performed.\r
87                 \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged.\r
88                 \param smooth If the normals shall be smoothed.\r
89                 \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision.\r
90                 */\r
91                 virtual void recalculateTangents(IMesh* mesh,\r
92                                 bool recalculateNormals=false, bool smooth=false,\r
93                                 bool angleWeighted=false) const=0;\r
94 \r
95                 //! Recalculates tangents, requires a tangent mesh buffer\r
96                 /** \param buffer Meshbuffer on which the operation is performed.\r
97                 \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged.\r
98                 \param smooth If the normals shall be smoothed.\r
99                 \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision.\r
100                 */\r
101                 virtual void recalculateTangents(IMeshBuffer* buffer,\r
102                                 bool recalculateNormals=false, bool smooth=false,\r
103                                 bool angleWeighted=false) const=0;\r
104 \r
105                 //! Scales the actual mesh, not a scene node.\r
106                 /** \param mesh Mesh on which the operation is performed.\r
107                 \param factor Scale factor for each axis. */\r
108                 void scale(IMesh* mesh, const core::vector3df& factor) const\r
109                 {\r
110                         apply(SVertexPositionScaleManipulator(factor), mesh, true);\r
111                 }\r
112 \r
113                 //! Scales the actual meshbuffer, not a scene node.\r
114                 /** \param buffer Meshbuffer on which the operation is performed.\r
115                 \param factor Scale factor for each axis. */\r
116                 void scale(IMeshBuffer* buffer, const core::vector3df& factor) const\r
117                 {\r
118                         apply(SVertexPositionScaleManipulator(factor), buffer, true);\r
119                 }\r
120 \r
121                 //! Scales the actual mesh, not a scene node.\r
122                 /** \deprecated Use scale() instead. This method may be removed by Irrlicht 1.9\r
123                 \param mesh Mesh on which the operation is performed.\r
124                 \param factor Scale factor for each axis. */\r
125                 _IRR_DEPRECATED_ void scaleMesh(IMesh* mesh, const core::vector3df& factor) const {return scale(mesh,factor);}\r
126 \r
127                 //! Scale the texture coords of a mesh.\r
128                 /** \param mesh Mesh on which the operation is performed.\r
129                 \param factor Vector which defines the scale for each axis.\r
130                 \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */\r
131                 void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 level=1) const\r
132                 {\r
133                         apply(SVertexTCoordsScaleManipulator(factor, level), mesh);\r
134                 }\r
135 \r
136                 //! Scale the texture coords of a meshbuffer.\r
137                 /** \param buffer Meshbuffer on which the operation is performed.\r
138                 \param factor Vector which defines the scale for each axis.\r
139                 \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */\r
140                 void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const\r
141                 {\r
142                         apply(SVertexTCoordsScaleManipulator(factor, level), buffer);\r
143                 }\r
144 \r
145                 //! Applies a transformation to a mesh\r
146                 /** \param mesh Mesh on which the operation is performed.\r
147                 \param m transformation matrix. \r
148                 \param normalsUpdate When 0 - don't update normals. \r
149                                      When 1 - update normals with inverse transposed of the transformation matrix\r
150                 */\r
151                 void transform(IMesh* mesh, const core::matrix4& m, u32 normalsUpdate = 0) const\r
152                 {\r
153                         apply(SVertexPositionTransformManipulator(m), mesh, true);\r
154 \r
155                         if ( normalsUpdate == 1 )\r
156                         {\r
157                                 core::matrix4 invT;\r
158                                 if ( m.getInverse(invT) )\r
159                                 {\r
160                                         invT = invT.getTransposed();\r
161                                         apply(SVertexNormalTransformManipulator(invT), mesh, false);\r
162                                 }\r
163                         }\r
164                 }\r
165 \r
166                 //! Applies a transformation to a meshbuffer\r
167                 /** \param buffer Meshbuffer on which the operation is performed.\r
168                 \param m transformation matrix. \r
169                 \param normalsUpdate When 0 - don't update normals. \r
170                                      When 1 - update normals with inverse transposed of the transformation matrix\r
171                 */\r
172                 void transform(IMeshBuffer* buffer, const core::matrix4& m, u32 normalsUpdate = 0) const\r
173                 {\r
174                         apply(SVertexPositionTransformManipulator(m), buffer, true);\r
175 \r
176                         if ( normalsUpdate == 1 )\r
177                         {\r
178                                 core::matrix4 invT;\r
179                                 if ( m.getInverse(invT) )\r
180                                 {\r
181                                         invT = invT.getTransposed();\r
182                                         apply(SVertexNormalTransformManipulator(invT), buffer, false);\r
183                                 }\r
184                         }\r
185                 }\r
186 \r
187                 //! Applies a transformation to a mesh\r
188                 /** \deprecated Use transform() instead. This method may be removed by Irrlicht 1.9\r
189                 \param mesh Mesh on which the operation is performed.\r
190                 \param m transformation matrix. */\r
191                 _IRR_DEPRECATED_ virtual void transformMesh(IMesh* mesh, const core::matrix4& m) const {return transform(mesh,m);}\r
192 \r
193                 //! Creates a planar texture mapping on the mesh\r
194                 /** \param mesh: Mesh on which the operation is performed.\r
195                 \param resolution: resolution of the planar mapping. This is\r
196                 the value specifying which is the relation between world space\r
197                 and texture coordinate space. */\r
198                 virtual void makePlanarTextureMapping(IMesh* mesh, f32 resolution=0.001f) const=0;\r
199 \r
200                 //! Creates a planar texture mapping on the meshbuffer\r
201                 /** \param meshbuffer: Buffer on which the operation is performed.\r
202                 \param resolution: resolution of the planar mapping. This is\r
203                 the value specifying which is the relation between world space\r
204                 and texture coordinate space. */\r
205                 virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const=0;\r
206 \r
207                 //! Creates a planar texture mapping on the buffer\r
208                 /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required.\r
209                 \param mesh Mesh on which the operation is performed.\r
210                 \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space.\r
211                 \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space.\r
212                 \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z).\r
213                 \param offset Vector added to the vertex positions (in object coordinates).\r
214                 */\r
215                 virtual void makePlanarTextureMapping(scene::IMesh* mesh,\r
216                                 f32 resolutionS, f32 resolutionT,\r
217                                 u8 axis, const core::vector3df& offset) const=0;\r
218 \r
219                 //! Creates a planar texture mapping on the meshbuffer\r
220                 /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required.\r
221                 \param buffer Buffer on which the operation is performed.\r
222                 \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space.\r
223                 \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space.\r
224                 \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z).\r
225                 \param offset Vector added to the vertex positions (in object coordinates).\r
226                 */\r
227                 virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer,\r
228                                 f32 resolutionS, f32 resolutionT,\r
229                                 u8 axis, const core::vector3df& offset) const=0;\r
230 \r
231                 //! Clones a static IMesh into a modifiable SMesh.\r
232                 /** All meshbuffers in the returned SMesh\r
233                 are of type SMeshBuffer or SMeshBufferLightMap.\r
234                 \param mesh Mesh to copy.\r
235                 \return Cloned mesh. If you no longer need the\r
236                 cloned mesh, you should call SMesh::drop(). See\r
237                 IReferenceCounted::drop() for more information. */\r
238                 virtual SMesh* createMeshCopy(IMesh* mesh) const = 0;\r
239 \r
240                 //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices.\r
241                 /** This is useful if you want to draw tangent space normal\r
242                 mapped geometry because it calculates the tangent and binormal\r
243                 data which is needed there.\r
244                 \param mesh Input mesh\r
245                 \param recalculateNormals The normals are recalculated if set,\r
246                 otherwise the original ones are kept. Note that keeping the\r
247                 normals may introduce inaccurate tangents if the normals are\r
248                 very different to those calculated from the faces.\r
249                 \param smooth The normals/tangents are smoothed across the\r
250                 meshbuffer's faces if this flag is set.\r
251                 \param angleWeighted Improved smoothing calculation used\r
252                 \param recalculateTangents Whether are actually calculated, or just the mesh with proper type is created.\r
253                 \return Mesh consisting only of S3DVertexTangents vertices. If\r
254                 you no longer need the cloned mesh, you should call\r
255                 IMesh::drop(). See IReferenceCounted::drop() for more\r
256                 information. */\r
257                 virtual IMesh* createMeshWithTangents(IMesh* mesh,\r
258                                 bool recalculateNormals=false, bool smooth=false,\r
259                                 bool angleWeighted=false, bool recalculateTangents=true) const=0;\r
260 \r
261                 //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices.\r
262                 /** \param mesh Input mesh\r
263                 \return Mesh consisting only of S3DVertex2TCoord vertices. If\r
264                 you no longer need the cloned mesh, you should call\r
265                 IMesh::drop(). See IReferenceCounted::drop() for more\r
266                 information. */\r
267                 virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0;\r
268 \r
269                 //! Creates a copy of the mesh, which will only consist of S3DVertex vertices.\r
270                 /** \param mesh Input mesh\r
271                 \return Mesh consisting only of S3DVertex vertices. If\r
272                 you no longer need the cloned mesh, you should call\r
273                 IMesh::drop(). See IReferenceCounted::drop() for more\r
274                 information. */\r
275                 virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0;\r
276 \r
277                 //! Creates a copy of a mesh with all vertices unwelded\r
278                 /** \param mesh Input mesh\r
279                 \return Mesh consisting only of unique faces. All vertices\r
280                 which were previously shared are now duplicated. If you no\r
281                 longer need the cloned mesh, you should call IMesh::drop(). See\r
282                 IReferenceCounted::drop() for more information. */\r
283                 virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0;\r
284 \r
285                 //! Creates a copy of a mesh with vertices welded\r
286                 /** \param mesh Input mesh\r
287                 \param tolerance The threshold for vertex comparisons.\r
288                 \return Mesh without redundant vertices. If you no longer need\r
289                 the cloned mesh, you should call IMesh::drop(). See\r
290                 IReferenceCounted::drop() for more information. */\r
291                 virtual IMesh* createMeshWelded(IMesh* mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const = 0;\r
292 \r
293                 //! Get amount of polygons in mesh.\r
294                 /** \param mesh Input mesh\r
295                 \return Number of polygons in mesh. */\r
296                 virtual s32 getPolyCount(IMesh* mesh) const = 0;\r
297 \r
298                 //! Get amount of polygons in mesh.\r
299                 /** \param mesh Input mesh\r
300                 \return Number of polygons in mesh. */\r
301                 virtual s32 getPolyCount(IAnimatedMesh* mesh) const = 0;\r
302 \r
303                 //! Create a new AnimatedMesh and adds the mesh to it\r
304                 /** \param mesh Input mesh\r
305                 \param type The type of the animated mesh to create.\r
306                 \return Newly created animated mesh with mesh as its only\r
307                 content. When you don't need the animated mesh anymore, you\r
308                 should call IAnimatedMesh::drop(). See\r
309                 IReferenceCounted::drop() for more information. */\r
310                 virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh,\r
311                         scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0;\r
312 \r
313                 //! Vertex cache optimization according to the Forsyth paper\r
314                 /** More information can be found at\r
315                 http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html\r
316 \r
317                 The function is thread-safe (read: you can optimize several\r
318                 meshes in different threads).\r
319 \r
320                 \param mesh Source mesh for the operation.\r
321                 \return A new mesh optimized for the vertex cache. */\r
322                 virtual IMesh* createForsythOptimizedMesh(const IMesh *mesh) const = 0;\r
323 \r
324                 //! Optimize the mesh with an algorithm tuned for heightmaps.\r
325                 /**\r
326                 This differs from usual simplification methods in two ways:\r
327                 - it's intended to be lossless\r
328                 - it has special care for the borders, which are useful with heightmap tiles\r
329 \r
330                 This function is thread-safe. Remember to weld afterwards - this\r
331                 function only moves vertices, it does not weld.\r
332 \r
333                 \param mesh Mesh to operate on.\r
334                 */\r
335                 virtual void heightmapOptimizeMesh(IMesh * const mesh, const f32 tolerance = core::ROUNDING_ERROR_f32) const = 0;\r
336 \r
337                 //! Optimize the meshbuffer with an algorithm tuned for heightmaps.\r
338                 /**\r
339                 This differs from usual simplification methods in two ways:\r
340                 - it's intended to be lossless\r
341                 - it has special care for the borders, which are useful with heightmap tiles\r
342 \r
343                 This function is thread-safe. Remember to weld afterward - this\r
344                 function only moves vertices, it does not weld.\r
345 \r
346                 \param mb Meshbuffer to operate on.\r
347                 */\r
348                 virtual void heightmapOptimizeMesh(IMeshBuffer * const mb, const f32 tolerance = core::ROUNDING_ERROR_f32) const = 0;\r
349 \r
350                 //! Apply a manipulator on the Meshbuffer\r
351                 /** \param func A functor defining the mesh manipulation.\r
352                 \param buffer The Meshbuffer to apply the manipulator to.\r
353                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
354                 \return True if the functor was successfully applied, else false. */\r
355                 template <typename Functor>\r
356                 bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const\r
357                 {\r
358                         return apply_(func, buffer, boundingBoxUpdate, func);\r
359                 }\r
360 \r
361 \r
362                 //! Apply a manipulator on the Mesh\r
363                 /** \param func A functor defining the mesh manipulation.\r
364                 \param mesh The Mesh to apply the manipulator to.\r
365                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
366                 \return True if the functor was successfully applied, else false. */\r
367                 template <typename Functor>\r
368                 bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const\r
369                 {\r
370                         if (!mesh)\r
371                                 return true;\r
372                         bool result = true;\r
373                         core::aabbox3df bufferbox;\r
374                         for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)\r
375                         {\r
376                                 result &= apply(func, mesh->getMeshBuffer(i), boundingBoxUpdate);\r
377                                 if (boundingBoxUpdate)\r
378                                 {\r
379                                         if (0==i)\r
380                                                 bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox());\r
381                                         else\r
382                                                 bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox());\r
383                                 }\r
384                         }\r
385                         if (boundingBoxUpdate)\r
386                                 mesh->setBoundingBox(bufferbox);\r
387                         return result;\r
388                 }\r
389 \r
390 protected:\r
391                 //! Apply a manipulator based on the type of the functor\r
392                 /** \param func A functor defining the mesh manipulation.\r
393                 \param buffer The Meshbuffer to apply the manipulator to.\r
394                 \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation.\r
395                 \param typeTest Unused parameter, which handles the proper call selection based on the type of the Functor which is passed in two times.\r
396                 \return True if the functor was successfully applied, else false. */\r
397                 template <typename Functor>\r
398                 bool apply_(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate, const IVertexManipulator& typeTest) const\r
399                 {\r
400                         if (!buffer)\r
401                                 return true;\r
402 \r
403                         core::aabbox3df bufferbox;\r
404                         for (u32 i=0; i<buffer->getVertexCount(); ++i)\r
405                         {\r
406                                 switch (buffer->getVertexType())\r
407                                 {\r
408                                 case video::EVT_STANDARD:\r
409                                         {\r
410                                                 video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices();\r
411                                                 func(verts[i]);\r
412                                         }\r
413                                         break;\r
414                                 case video::EVT_2TCOORDS:\r
415                                         {\r
416                                                 video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices();\r
417                                                 func(verts[i]);\r
418                                         }\r
419                                         break;\r
420                                 case video::EVT_TANGENTS:\r
421                                         {\r
422                                                 video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices();\r
423                                                 func(verts[i]);\r
424                                         }\r
425                                         break;\r
426                                 }\r
427                                 if (boundingBoxUpdate)\r
428                                 {\r
429                                         if (0==i)\r
430                                                 bufferbox.reset(buffer->getPosition(0));\r
431                                         else\r
432                                                 bufferbox.addInternalPoint(buffer->getPosition(i));\r
433                                 }\r
434                         }\r
435                         if (boundingBoxUpdate)\r
436                                 buffer->setBoundingBox(bufferbox);\r
437                         return true;\r
438                 }\r
439 };\r
440 \r
441 } // end namespace scene\r
442 } // end namespace irr\r
443 \r
444 \r
445 #endif\r