From 2cf45b50c97ad7f1662a540f09fb24425c13466c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 4 Jun 2004 08:24:13 +0000 Subject: [PATCH] From Terry Welsh, added checks to incoming Geometry for existance of normals, and if they are present use these to compute the tanget and binormals vectors perpendicular to existing normals. --- include/osgUtil/TangentSpaceGenerator | 2 +- src/osgUtil/TangentSpaceGenerator.cpp | 191 +++++++++++++++++++------- 2 files changed, 144 insertions(+), 49 deletions(-) diff --git a/include/osgUtil/TangentSpaceGenerator b/include/osgUtil/TangentSpaceGenerator index 5c2e4b044..39d5b0559 100644 --- a/include/osgUtil/TangentSpaceGenerator +++ b/include/osgUtil/TangentSpaceGenerator @@ -58,7 +58,7 @@ namespace osgUtil virtual ~TangentSpaceGenerator() {} TangentSpaceGenerator &operator=(const TangentSpaceGenerator &) { return *this; } - void compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *tx, int iA, int iB, int iC); + void compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *nx, const osg::Array *tx, int iA, int iB, int iC); private: osg::ref_ptr T_; diff --git a/src/osgUtil/TangentSpaceGenerator.cpp b/src/osgUtil/TangentSpaceGenerator.cpp index 3f55eca4d..18a9a4315 100644 --- a/src/osgUtil/TangentSpaceGenerator.cpp +++ b/src/osgUtil/TangentSpaceGenerator.cpp @@ -23,6 +23,7 @@ TangentSpaceGenerator::TangentSpaceGenerator(const TangentSpaceGenerator ©, void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit) { const osg::Array *vx = geo->getVertexArray(); + const osg::Array *nx = geo->getNormalArray(); const osg::Array *tx = geo->getTexCoordArray(normal_map_tex_unit); if (!vx || !tx) return; @@ -44,14 +45,14 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit case osg::PrimitiveSet::TRIANGLES: for (i=0; i(*pi-2); for (i=0; ibegin(); pi!=dal->end(); ++pi) { unsigned iN = static_cast(*pi-2); for (i=0; iindex(iA); iB = pset->index(iB); @@ -171,6 +172,41 @@ void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: vertex array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; } + osg::Vec3 N1; + osg::Vec3 N2; + osg::Vec3 N3; + + if(nx) + { + switch (nx->getType()) + { + case osg::Array::Vec2ArrayType: + for (i=0; i<2; ++i) { + N1.ptr()[i] = static_cast(*nx)[iA].ptr()[i]; + N2.ptr()[i] = static_cast(*nx)[iB].ptr()[i]; + N3.ptr()[i] = static_cast(*nx)[iC].ptr()[i]; + } + break; + + case osg::Array::Vec3ArrayType: + N1 = static_cast(*nx)[iA]; + N2 = static_cast(*nx)[iB]; + N3 = static_cast(*nx)[iC]; + break; + + case osg::Array::Vec4ArrayType: + for (i=0; i<3; ++i) { + N1.ptr()[i] = static_cast(*nx)[iA].ptr()[i]; + N2.ptr()[i] = static_cast(*nx)[iB].ptr()[i]; + N3.ptr()[i] = static_cast(*nx)[iC].ptr()[i]; + } + break; + + default: + osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: normal array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; + } + } + osg::Vec2 uv1; osg::Vec2 uv2; osg::Vec2 uv3; @@ -203,47 +239,106 @@ void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: texture coord array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; } - osg::Vec3 face_normal = (P2 - P1) ^ (P3 - P1); + if(nx){ + osg::Vec3 V, T1, T2, T3, B1, B2, B3; - osg::Vec3 V; + V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + T1.x() += -V.y() / V.x(); + B1.x() += -V.z() / V.x(); + T2.x() += -V.y() / V.x(); + B2.x() += -V.z() / V.x(); + T3.x() += -V.y() / V.x(); + B3.x() += -V.z() / V.x(); + } - V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ - osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); - if (V.x() != 0) { - V.normalize(); - (*T_)[iA].x() += -V.y() / V.x(); - (*B_)[iA].x() += -V.z() / V.x(); - (*T_)[iB].x() += -V.y() / V.x(); - (*B_)[iB].x() += -V.z() / V.x(); - (*T_)[iC].x() += -V.y() / V.x(); - (*B_)[iC].x() += -V.z() / V.x(); + V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + T1.y() += -V.y() / V.x(); + B1.y() += -V.z() / V.x(); + T2.y() += -V.y() / V.x(); + B2.y() += -V.z() / V.x(); + T3.y() += -V.y() / V.x(); + B3.y() += -V.z() / V.x(); + } + + V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + T1.z() += -V.y() / V.x(); + B1.z() += -V.z() / V.x(); + T2.z() += -V.y() / V.x(); + B2.z() += -V.z() / V.x(); + T3.z() += -V.y() / V.x(); + B3.z() += -V.z() / V.x(); + } + + osg::Vec3 tempvec; + tempvec = N1 ^ T1; + (*T_)[iA] = osg::Vec4(tempvec ^ N1, 0); + tempvec = B1 ^ N1; + (*B_)[iA] = osg::Vec4(N1 ^ tempvec, 0); + tempvec = N2 ^ T2; + (*T_)[iB] = osg::Vec4(tempvec ^ N2, 0); + tempvec = B2 ^ N2; + (*B_)[iB] = osg::Vec4(N2 ^ tempvec, 0); + tempvec = N3 ^ T3; + (*T_)[iC] = osg::Vec4(tempvec ^ N3, 0); + tempvec = B3 ^ N3; + (*B_)[iC] = osg::Vec4(N3 ^ tempvec, 0); + + (*N_)[iA] += osg::Vec4(N1, 0); + (*N_)[iB] += osg::Vec4(N2, 0); + (*N_)[iC] += osg::Vec4(N3, 0); } + else{ + osg::Vec3 face_normal = (P2 - P1) ^ (P3 - P1); - V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ - osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); - if (V.x() != 0) { - V.normalize(); - (*T_)[iA].y() += -V.y() / V.x(); - (*B_)[iA].y() += -V.z() / V.x(); - (*T_)[iB].y() += -V.y() / V.x(); - (*B_)[iB].y() += -V.z() / V.x(); - (*T_)[iC].y() += -V.y() / V.x(); - (*B_)[iC].y() += -V.z() / V.x(); + osg::Vec3 V; + + V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + (*T_)[iA].x() += -V.y() / V.x(); + (*B_)[iA].x() += -V.z() / V.x(); + (*T_)[iB].x() += -V.y() / V.x(); + (*B_)[iB].x() += -V.z() / V.x(); + (*T_)[iC].x() += -V.y() / V.x(); + (*B_)[iC].x() += -V.z() / V.x(); + } + + V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + (*T_)[iA].y() += -V.y() / V.x(); + (*B_)[iA].y() += -V.z() / V.x(); + (*T_)[iB].y() += -V.y() / V.x(); + (*B_)[iB].y() += -V.z() / V.x(); + (*T_)[iC].y() += -V.y() / V.x(); + (*B_)[iC].y() += -V.z() / V.x(); + } + + V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ + osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); + if (V.x() != 0) { + V.normalize(); + (*T_)[iA].z() += -V.y() / V.x(); + (*B_)[iA].z() += -V.z() / V.x(); + (*T_)[iB].z() += -V.y() / V.x(); + (*B_)[iB].z() += -V.z() / V.x(); + (*T_)[iC].z() += -V.y() / V.x(); + (*B_)[iC].z() += -V.z() / V.x(); + } + + (*N_)[iA] += osg::Vec4(face_normal, 0); + (*N_)[iB] += osg::Vec4(face_normal, 0); + (*N_)[iC] += osg::Vec4(face_normal, 0); } - - V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^ - osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y()); - if (V.x() != 0) { - V.normalize(); - (*T_)[iA].z() += -V.y() / V.x(); - (*B_)[iA].z() += -V.z() / V.x(); - (*T_)[iB].z() += -V.y() / V.x(); - (*B_)[iB].z() += -V.z() / V.x(); - (*T_)[iC].z() += -V.y() / V.x(); - (*B_)[iC].z() += -V.z() / V.x(); - } - - (*N_)[iA] += osg::Vec4(face_normal, 0); - (*N_)[iB] += osg::Vec4(face_normal, 0); - (*N_)[iC] += osg::Vec4(face_normal, 0); }