diff --git a/include/osgUtil/TangentSpaceGenerator b/include/osgUtil/TangentSpaceGenerator index b08d7b6b3..9dc1afbab 100644 --- a/include/osgUtil/TangentSpaceGenerator +++ b/include/osgUtil/TangentSpaceGenerator @@ -54,16 +54,25 @@ public: inline const osg::Vec4Array *getBinormalArray() const { return B_.get(); } inline void setBinormalArray(osg::Vec4Array *array) { B_ = array; } + inline osg::IndexArray *getIndices() { return indices_.get(); } protected: virtual ~TangentSpaceGenerator() {} TangentSpaceGenerator &operator=(const TangentSpaceGenerator &) { return *this; } - 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); + void compute_basis_vectors(osg::PrimitiveSet *pset, + const osg::Array *vx, + const osg::Array *nx, + const osg::Array *tx, + const osg::IndexArray *vix, + const osg::IndexArray *nix, + const osg::IndexArray *tix, + int iA, int iB, int iC); private: osg::ref_ptr T_; osg::ref_ptr B_; osg::ref_ptr N_; + osg::ref_ptr indices_; }; } diff --git a/src/osgUtil/TangentSpaceGenerator.cpp b/src/osgUtil/TangentSpaceGenerator.cpp index cdab50c37..264283d3d 100644 --- a/src/osgUtil/TangentSpaceGenerator.cpp +++ b/src/osgUtil/TangentSpaceGenerator.cpp @@ -23,16 +23,30 @@ TangentSpaceGenerator::TangentSpaceGenerator(const TangentSpaceGenerator ©, void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit) { const osg::Array *vx = geo->getVertexArray(); + const osg::IndexArray *vix = geo->getVertexIndices(); + const osg::IndexArray *nix = geo->getNormalIndices(); + const osg::IndexArray *tix = geo->getTexCoordIndices(normal_map_tex_unit); const osg::Array *nx = geo->getNormalArray(); const osg::Array *tx = geo->getTexCoordArray(normal_map_tex_unit); if (!vx || !tx) return; unsigned int vertex_count = vx->getNumElements(); - - T_->assign(vertex_count, osg::Vec4()); - B_->assign(vertex_count, osg::Vec4()); - N_->assign(vertex_count, osg::Vec4()); + if (geo->getVertexIndices() == NULL) { + T_->assign(vertex_count, osg::Vec4()); + B_->assign(vertex_count, osg::Vec4()); + N_->assign(vertex_count, osg::Vec4()); + } else { + unsigned int index_count = geo->getVertexIndices()->getNumElements(); + T_->assign(index_count, osg::Vec4()); + B_->assign(index_count, osg::Vec4()); + N_->assign(index_count, osg::Vec4()); + indices_ = new osg::UIntArray(); + unsigned int i; + for (i=0;ipush_back(i); + } + } unsigned i; // VC6 doesn't like for-scoped variables @@ -45,14 +59,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; igetNumElements(); + if (geo->getVertexIndices() != NULL) { + attrib_count = geo->getVertexIndices()->getNumElements(); + } + for (i=0; iindex(iA); - iB = pset->index(iB); - iC = pset->index(iC); - - osg::Vec3 P1; - osg::Vec3 P2; - osg::Vec3 P3; - - int i; // VC6 doesn't like for-scoped variables - - switch (vx->getType()) +#if 1 +// Original compute_basis_vectors implementation + void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet* pset, + const osg::Array* vx, + const osg::Array* nx, + const osg::Array* tx, + const osg::IndexArray* /*vix*/, + const osg::IndexArray* /*nix*/, + const osg::IndexArray* /*tix*/, + int iA, int iB, int iC) { - case osg::Array::Vec2ArrayType: - for (i=0; i<2; ++i) { - P1.ptr()[i] = static_cast(*vx)[iA].ptr()[i]; - P2.ptr()[i] = static_cast(*vx)[iB].ptr()[i]; - P3.ptr()[i] = static_cast(*vx)[iC].ptr()[i]; - } - break; + iA = pset->index(iA); + iB = pset->index(iB); + iC = pset->index(iC); - case osg::Array::Vec3ArrayType: - P1 = static_cast(*vx)[iA]; - P2 = static_cast(*vx)[iB]; - P3 = static_cast(*vx)[iC]; - break; + osg::Vec3 P1; + osg::Vec3 P2; + osg::Vec3 P3; - case osg::Array::Vec4ArrayType: - for (i=0; i<3; ++i) { - P1.ptr()[i] = static_cast(*vx)[iA].ptr()[i]; - P2.ptr()[i] = static_cast(*vx)[iB].ptr()[i]; - P3.ptr()[i] = static_cast(*vx)[iC].ptr()[i]; - } - break; + int i; // VC6 doesn't like for-scoped variables - default: - 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()) + switch (vx->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]; + P1.ptr()[i] = static_cast(*vx)[iA].ptr()[i]; + P2.ptr()[i] = static_cast(*vx)[iB].ptr()[i]; + P3.ptr()[i] = static_cast(*vx)[iC].ptr()[i]; } break; case osg::Array::Vec3ArrayType: - N1 = static_cast(*nx)[iA]; - N2 = static_cast(*nx)[iB]; - N3 = static_cast(*nx)[iC]; + P1 = static_cast(*vx)[iA]; + P2 = static_cast(*vx)[iB]; + P3 = static_cast(*vx)[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]; + P1.ptr()[i] = static_cast(*vx)[iA].ptr()[i]; + P2.ptr()[i] = static_cast(*vx)[iB].ptr()[i]; + P3.ptr()[i] = static_cast(*vx)[iC].ptr()[i]; } break; default: - osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: normal array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; + 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; + + switch (tx->getType()) + { + case osg::Array::Vec2ArrayType: + uv1 = static_cast(*tx)[iA]; + uv2 = static_cast(*tx)[iB]; + uv3 = static_cast(*tx)[iC]; + break; + + case osg::Array::Vec3ArrayType: + for (i=0; i<2; ++i) { + uv1.ptr()[i] = static_cast(*tx)[iA].ptr()[i]; + uv2.ptr()[i] = static_cast(*tx)[iB].ptr()[i]; + uv3.ptr()[i] = static_cast(*tx)[iC].ptr()[i]; + } + break; + + case osg::Array::Vec4ArrayType: + for (i=0; i<2; ++i) { + uv1.ptr()[i] = static_cast(*tx)[iA].ptr()[i]; + uv2.ptr()[i] = static_cast(*tx)[iB].ptr()[i]; + uv3.ptr()[i] = static_cast(*tx)[iC].ptr()[i]; + } + break; + + default: + osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: texture coord array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; + } + + if(nx){ + osg::Vec3 V, T1, T2, T3, B1, B2, B3; + + 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.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); + + 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); } } - osg::Vec2 uv1; - osg::Vec2 uv2; - osg::Vec2 uv3; +#else - switch (tx->getType()) + // Ruben's new code, supporting index arrays + void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, + const osg::Array *vx, + const osg::Array *nx, + const osg::Array *tx, + const osg::IndexArray *vix, + const osg::IndexArray *nix, + const osg::IndexArray *tix, + int iA, int iB, int iC) { - case osg::Array::Vec2ArrayType: - uv1 = static_cast(*tx)[iA]; - uv2 = static_cast(*tx)[iB]; - uv3 = static_cast(*tx)[iC]; - break; + int v1 = pset->index(iA); + int v2 = pset->index(iB); + int v3 = pset->index(iC); + int viA = v1; + int viB = v2; + int viC = v3; - case osg::Array::Vec3ArrayType: - for (i=0; i<2; ++i) { - uv1.ptr()[i] = static_cast(*tx)[iA].ptr()[i]; - uv2.ptr()[i] = static_cast(*tx)[iB].ptr()[i]; - uv3.ptr()[i] = static_cast(*tx)[iC].ptr()[i]; + if (vix != NULL) { + viA = vix->index(v1); + viB = vix->index(v2); + viC = vix->index(v3); + } + int niA = viA; + int niB = viA; + int niC = viA; + int tiA = viA; + int tiB = viA; + int tiC = viA; + if (nix != NULL) { + niA = nix->index(v1); + niB = nix->index(v2); + niC = nix->index(v3); + } + if (tix != NULL) { + tiA = tix->index(v1); + tiB = tix->index(v2); + tiC = tix->index(v3); + } + + osg::Vec3 P1; + osg::Vec3 P2; + osg::Vec3 P3; + + int i; // VC6 doesn't like for-scoped variables + + switch (vx->getType()) + { + case osg::Array::Vec2ArrayType: + for (i=0; i<2; ++i) { + P1.ptr()[i] = static_cast(*vx)[viA].ptr()[i]; + P2.ptr()[i] = static_cast(*vx)[viB].ptr()[i]; + P3.ptr()[i] = static_cast(*vx)[viC].ptr()[i]; + } + break; + + case osg::Array::Vec3ArrayType: + P1 = static_cast(*vx)[viA]; + P2 = static_cast(*vx)[viB]; + P3 = static_cast(*vx)[viC]; + break; + + case osg::Array::Vec4ArrayType: + for (i=0; i<3; ++i) { + P1.ptr()[i] = static_cast(*vx)[viA].ptr()[i]; + P2.ptr()[i] = static_cast(*vx)[viB].ptr()[i]; + P3.ptr()[i] = static_cast(*vx)[viC].ptr()[i]; + } + break; + + default: + 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)[niA].ptr()[i]; + N2.ptr()[i] = static_cast(*nx)[niB].ptr()[i]; + N3.ptr()[i] = static_cast(*nx)[niC].ptr()[i]; + } + break; + + case osg::Array::Vec3ArrayType: + N1 = static_cast(*nx)[niA]; + N2 = static_cast(*nx)[niB]; + N3 = static_cast(*nx)[niC]; + break; + + case osg::Array::Vec4ArrayType: + for (i=0; i<3; ++i) { + N1.ptr()[i] = static_cast(*nx)[niA].ptr()[i]; + N2.ptr()[i] = static_cast(*nx)[niB].ptr()[i]; + N3.ptr()[i] = static_cast(*nx)[niC].ptr()[i]; + } + break; + + default: + osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: normal array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; } - break; + } - case osg::Array::Vec4ArrayType: - for (i=0; i<2; ++i) { - uv1.ptr()[i] = static_cast(*tx)[iA].ptr()[i]; - uv2.ptr()[i] = static_cast(*tx)[iB].ptr()[i]; - uv3.ptr()[i] = static_cast(*tx)[iC].ptr()[i]; + osg::Vec2 uv1; + osg::Vec2 uv2; + osg::Vec2 uv3; + + switch (tx->getType()) + { + case osg::Array::Vec2ArrayType: + uv1 = static_cast(*tx)[tiA]; + uv2 = static_cast(*tx)[tiB]; + uv3 = static_cast(*tx)[tiC]; + break; + + case osg::Array::Vec3ArrayType: + for (i=0; i<2; ++i) { + uv1.ptr()[i] = static_cast(*tx)[tiA].ptr()[i]; + uv2.ptr()[i] = static_cast(*tx)[tiB].ptr()[i]; + uv3.ptr()[i] = static_cast(*tx)[tiC].ptr()[i]; + } + break; + + case osg::Array::Vec4ArrayType: + for (i=0; i<2; ++i) { + uv1.ptr()[i] = static_cast(*tx)[tiA].ptr()[i]; + uv2.ptr()[i] = static_cast(*tx)[tiB].ptr()[i]; + uv3.ptr()[i] = static_cast(*tx)[tiC].ptr()[i]; + } + break; + + default: + osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator::compute_basis_vectors(,,,) texture coord array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; + } + + if (nx) + { + osg::Vec3 V, T1, T2, T3, B1, B2, B3; + + 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(); + } else { + osg::notify(osg::NOTICE)<<"Bu!" << uv1 << " || " << uv2 << " || " << uv3 << std::endl; } - break; - default: - osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: texture coord array must be Vec2Array, Vec3Array or Vec4Array" << std::endl; + 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(); + } + + (*T_)[v1] = osg::Vec4(T1, 0); + (*B_)[v1] = osg::Vec4(B1, 0); + (*T_)[v2] = osg::Vec4(T2, 0); + (*B_)[v2] = osg::Vec4(B2, 0); + (*T_)[v3] = osg::Vec4(T3, 0); + (*B_)[v3] = osg::Vec4(B3, 0); + + (*N_)[v1] += osg::Vec4(N1, 0); + (*N_)[v2] += osg::Vec4(N2, 0); + (*N_)[v3] += osg::Vec4(N3, 0); + + } + else{ + osg::Vec3 face_normal = (P2 - P1) ^ (P3 - P1); + + 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_)[v1].x() += -V.y() / V.x(); + (*B_)[v1].x() += -V.z() / V.x(); + (*T_)[v2].x() += -V.y() / V.x(); + (*B_)[v2].x() += -V.z() / V.x(); + (*T_)[v3].x() += -V.y() / V.x(); + (*B_)[v3].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_)[v1].y() += -V.y() / V.x(); + (*B_)[v1].y() += -V.z() / V.x(); + (*T_)[v2].y() += -V.y() / V.x(); + (*B_)[v2].y() += -V.z() / V.x(); + (*T_)[v3].y() += -V.y() / V.x(); + (*B_)[v3].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_)[v1].z() += -V.y() / V.x(); + (*B_)[v1].z() += -V.z() / V.x(); + (*T_)[v2].z() += -V.y() / V.x(); + (*B_)[v2].z() += -V.z() / V.x(); + (*T_)[v3].z() += -V.y() / V.x(); + (*B_)[v3].z() += -V.z() / V.x(); + } + + (*N_)[v1] += osg::Vec4(face_normal, 0); + (*N_)[v2] += osg::Vec4(face_normal, 0); + (*N_)[v3] += osg::Vec4(face_normal, 0); + } + if ( (*B_)[v1].length() == 0 || (*B_)[v2].length() == 0 || (*B_)[v3].length() == 0) { + osg::notify(osg::WARN) << "WARNING: zero binormal/s!" << std::endl; + osg::notify(osg::WARN) << " " << P1 << "|" << P2 << "|" << P3 << std::endl; + osg::notify(osg::WARN) << " " << iA << "|" << iB << "|" << iC << std::endl; + } } - - if(nx){ - osg::Vec3 V, T1, T2, T3, B1, B2, B3; - - 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.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); - - 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); - } -} +#endif