diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index 0b459ba9..79ed068d 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -93,13 +93,18 @@ namespace scene mapped geometry because it calculates the tangent and binormal data which is needed there. \param mesh Input mesh - \param smooth The normals are smoothed across the meshbuffer's faces if this flag is set. + \param recalculateNormals The normals are recalculated if set, + otherwise the original ones are kept. Note that keeping the + normals may introduce inaccurate tangents if the normals are + very different to those calculated from the faces. + \param smooth The normals/tangents are smoothed across the + meshbuffer's faces if this flag is set. \param angleWeighted Improved smoothing calculation used \return Mesh consisting only of S3DVertexTangents vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ - virtual IMesh* createMeshWithTangents(IMesh* mesh, bool smooth=false, bool angleWeighted=false) const = 0; + virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const = 0; //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. /** \param mesh Input mesh diff --git a/source/Irrlicht/CMeshManipulator.cpp b/source/Irrlicht/CMeshManipulator.cpp index db133f0e..d9a97a01 100644 --- a/source/Irrlicht/CMeshManipulator.cpp +++ b/source/Irrlicht/CMeshManipulator.cpp @@ -751,7 +751,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. -IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool angleWeighted) const +IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const { if (!mesh) return 0; @@ -764,7 +764,7 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a for (b=0; bgetMeshBuffer(b)->getIndexCount(); + const u32 idxCnt = mesh->getMeshBuffer(b)->getIndexCount(); const u16* idx = mesh->getMeshBuffer(b)->getIndices(); SMeshBufferTangents* buffer = new SMeshBufferTangents(); @@ -780,10 +780,10 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a video::S3DVertex* v = (video::S3DVertex*)mesh->getMeshBuffer(b)->getVertices(); - for (s32 i=0; iVertices.push_back( video::S3DVertexTangents( - v[idx[i]].Pos, v[idx[i]].Color, v[idx[i]].TCoords)); + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords)); } break; case video::EVT_2TCOORDS: @@ -791,9 +791,9 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a video::S3DVertex2TCoords* v = (video::S3DVertex2TCoords*)mesh->getMeshBuffer(b)->getVertices(); - for (s32 i=0; iVertices.push_back(video::S3DVertexTangents( - v[idx[i]].Pos, v[idx[i]].Color, v[idx[i]].TCoords)); + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords)); } break; case video::EVT_TANGENTS: @@ -801,7 +801,7 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a video::S3DVertexTangents* v = (video::S3DVertexTangents*)mesh->getMeshBuffer(b)->getVertices(); - for (s32 i=0; iVertices.push_back(v[idx[i]]); } break; @@ -810,7 +810,7 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a // create new indices buffer->Indices.set_used(idxCnt); - for (s32 i=0; iIndices[i] = i; buffer->setBoundingBox(mesh->getMeshBuffer(b)->getBoundingBox()); @@ -837,7 +837,8 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a for ( i = 0; i!= vtxCnt; ++i ) { - v[i].Normal.set( 0.f, 0.f, 0.f ); + if (recalculateNormals) + v[i].Normal.set( 0.f, 0.f, 0.f ); v[i].Tangent.set( 0.f, 0.f, 0.f ); v[i].Binormal.set( 0.f, 0.f, 0.f ); } @@ -875,7 +876,8 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a v[idx[i+1]].TCoords, v[idx[i+2]].TCoords); - v[idx[i+0]].Tangent += localTangent * weight.X; + if (recalculateNormals) + v[idx[i+0]].Tangent += localTangent * weight.X; v[idx[i+0]].Binormal += localBinormal * weight.X; v[idx[i+0]].Normal += localNormal * weight.X; @@ -890,7 +892,8 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a v[idx[i+2]].TCoords, v[idx[i+0]].TCoords); - v[idx[i+1]].Tangent += localTangent * weight.Y; + if (recalculateNormals) + v[idx[i+1]].Tangent += localTangent * weight.Y; v[idx[i+1]].Binormal += localBinormal * weight.Y; v[idx[i+1]].Normal += localNormal * weight.Y; @@ -905,25 +908,31 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool smooth, bool a v[idx[i+0]].TCoords, v[idx[i+1]].TCoords); - v[idx[i+2]].Tangent += localTangent * weight.Z; + if (recalculateNormals) + v[idx[i+2]].Tangent += localTangent * weight.Z; v[idx[i+2]].Binormal += localBinormal * weight.Z; v[idx[i+2]].Normal += localNormal * weight.Z; } // Normalize the tangents and binormals + if (recalculateNormals) + { + for ( i = 0; i!= vtxCnt; ++i ) + v[i].Normal.normalize(); + } for ( i = 0; i!= vtxCnt; ++i ) { v[i].Tangent.normalize(); v[i].Binormal.normalize(); - v[i].Normal.normalize(); } } else { + core::vector3df localNormal; for (u32 i=0; i