From 6da17e04b62fd9a0c7b4105875ad99013eafa614 Mon Sep 17 00:00:00 2001 From: hybrid Date: Fri, 20 Jun 2008 12:45:05 +0000 Subject: [PATCH] Added generation of tangent space which can keep the original normals, by ryanclark. Note that inaccuracies of the tangent space may arise if you keep the original tangents. Angle weighted smoothing seems to be bogus, maybe indices are wrong. git-svn-id: http://svn.code.sf.net/p/irrlicht/code/trunk@1392 dfc29bdd-3216-0410-991c-e03cc46cb475 --- include/IMeshManipulator.h | 9 ++++-- source/Irrlicht/CMeshManipulator.cpp | 48 ++++++++++++++++++---------- source/Irrlicht/CMeshManipulator.h | 2 +- 3 files changed, 39 insertions(+), 20 deletions(-) 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