diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index 0f4d0414..67a36f97 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -103,7 +103,9 @@ namespace scene bool angleWeighted=false) const=0; //! Scales the actual mesh, not a scene node. - /** \param mesh Mesh on which the operation is performed. + /** Note: When your scale are not uniform then + prefer the transform function to have correct normals. + \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 { @@ -111,7 +113,9 @@ namespace scene } //! Scales the actual meshbuffer, not a scene node. - /** \param buffer Meshbuffer on which the operation is performed. + /** Note: When your scale are not uniform then + prefer the transform function to have correct normals. + \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 { @@ -146,9 +150,12 @@ namespace scene /** \param mesh Mesh on which the operation is performed. \param m transformation matrix. \param normalsUpdate When 0 - don't update normals. - When 1 - update normals with inverse transposed of the transformation matrix + When 1 - update normals with inner 3x3 matrix of the inverse transposed of the transformation matrix + should be set when the matrix has some non-uniform scaling + \param normalizeNormals When true it normalizes all normals again. + Usually makes sense to set this as well when normalsUpdate is 1 */ - void transform(IMesh* mesh, const core::matrix4& m, u32 normalsUpdate = 0) const + void transform(IMesh* mesh, const core::matrix4& m, u32 normalsUpdate = 0, bool normalizeNormals=false) const { apply(SVertexPositionTransformManipulator(m), mesh, true); @@ -158,18 +165,25 @@ namespace scene if ( m.getInverse(invT) ) { invT = invT.getTransposed(); - apply(SVertexNormalTransformManipulator(invT), mesh, false); + apply(SVertexNormalRotateScaleManipulator(invT), mesh, false); } } + if ( normalizeNormals ) + { + apply(SVertexNormalizeNormalManipulator(), mesh, false); + } } //! Applies a transformation to a meshbuffer /** \param buffer Meshbuffer on which the operation is performed. \param m transformation matrix. \param normalsUpdate When 0 - don't update normals. - When 1 - update normals with inverse transposed of the transformation matrix + When 1 - update normals with inner 3x3 matrix of the inverse transposed of the transformation matrix + should be set when the matrix has some non-uniform scaling + \param normalizeNormals When true it normalizes all normals again. + Usually makes sense to set this as well when normalsUpdate is 1 */ - void transform(IMeshBuffer* buffer, const core::matrix4& m, u32 normalsUpdate = 0) const + void transform(IMeshBuffer* buffer, const core::matrix4& m, u32 normalsUpdate = 0, bool normalizeNormals=false) const { apply(SVertexPositionTransformManipulator(m), buffer, true); @@ -179,9 +193,13 @@ namespace scene if ( m.getInverse(invT) ) { invT = invT.getTransposed(); - apply(SVertexNormalTransformManipulator(invT), buffer, false); + apply(SVertexNormalRotateScaleManipulator(invT), buffer, false); } } + if ( normalizeNormals ) + { + apply(SVertexNormalizeNormalManipulator(), buffer, false); + } } //! Applies a transformation to a mesh diff --git a/include/SVertexManipulator.h b/include/SVertexManipulator.h index 1c32d4c9..0fcc31db 100644 --- a/include/SVertexManipulator.h +++ b/include/SVertexManipulator.h @@ -277,6 +277,32 @@ namespace scene core::matrix4 Transformation; }; + //! Vertex manipulator which transforms the normal of the vertex with the rotate/scale part of the given matrix (inner 3x3) + class SVertexNormalRotateScaleManipulator : public IVertexManipulator + { + public: + SVertexNormalRotateScaleManipulator(const core::matrix4& m) : Transformation(m) {} + template + void operator()(VType& vertex) const + { + Transformation.rotateVect(vertex.Normal); + } + private: + core::matrix4 Transformation; + }; + + //! Vertex manipulator which normalizes the normal of the vertex + class SVertexNormalizeNormalManipulator : public IVertexManipulator + { + public: + SVertexNormalizeNormalManipulator() {} + template + void operator()(VType& vertex) const + { + vertex.Normal.normalize(); + } + }; + //! Vertex manipulator which scales the TCoords of the vertex class SVertexTCoordsScaleManipulator : public IVertexManipulator { diff --git a/include/matrix4.h b/include/matrix4.h index 26a3306b..b561fdcd 100644 --- a/include/matrix4.h +++ b/include/matrix4.h @@ -221,10 +221,10 @@ namespace core //! 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. + //! Tranform (rotate/scale) a vector by the inverse of the rotation part this matrix void inverseRotateVect( vector3df& vect ) const; - //! Rotate a vector by the rotation part of this matrix. + //! Transform (rotate/scale) a vector by the rotation part of this matrix. void rotateVect( vector3df& vect ) const; //! An alternate transform vector method, writing into a second vector