IMeshManipulator.h 6.2 KB

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