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