From d1f6169889914c169d0a3fc19f589d43231a3cc7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 Mar 2016 16:48:41 +0100 Subject: [PATCH] Add special handling of RigGeometry tangents in ShaderVisitor --- components/sceneutil/riggeometry.cpp | 30 ++++++++++++++++++++++++++++ components/sceneutil/riggeometry.hpp | 2 ++ components/shader/shadervisitor.cpp | 17 ++++++++++++---- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index 87afce034..895ff7e34 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -99,6 +99,13 @@ void RigGeometry::setSourceGeometry(osg::ref_ptr sourceGeometry) setColorArray(from.getColorArray()); setSecondaryColorArray(from.getSecondaryColorArray()); setFogCoordArray(from.getFogCoordArray()); + + // need to copy over texcoord list manually due to a missing null pointer check in setTexCoordArrayList(), this has been fixed in OSG 3.5 + osg::Geometry::ArrayList& texCoordList = from.getTexCoordArrayList(); + for (unsigned int i=0; i sourceGeometry) normalArray->setVertexBufferObject(vbo); setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX); } + + if (from.getTexCoordArray(7) && dynamic_cast(from.getTexCoordArray(7))) + { + // tangents + osg::ref_ptr tangentArray = osg::clone(from.getTexCoordArray(7), osg::CopyOp::DEEP_COPY_ALL); + tangentArray->setVertexBufferObject(vbo); + setTexCoordArray(7, tangentArray, osg::Array::BIND_PER_VERTEX); + } +} + +osg::ref_ptr RigGeometry::getSourceGeometry() +{ + return mSourceGeometry; } bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv) @@ -225,9 +245,11 @@ void RigGeometry::update(osg::NodeVisitor* nv) // skinning osg::Vec3Array* positionSrc = static_cast(mSourceGeometry->getVertexArray()); osg::Vec3Array* normalSrc = static_cast(mSourceGeometry->getNormalArray()); + osg::Vec4Array* tangentSrc = static_cast(mSourceGeometry->getTexCoordArray(7)); osg::Vec3Array* positionDst = static_cast(getVertexArray()); osg::Vec3Array* normalDst = static_cast(getNormalArray()); + osg::Vec4Array* tangentDst = static_cast(getTexCoordArray(7)); for (Bone2VertexMap::const_iterator it = mBone2VertexMap.begin(); it != mBone2VertexMap.end(); ++it) { @@ -251,11 +273,19 @@ void RigGeometry::update(osg::NodeVisitor* nv) unsigned short vertex = *vertexIt; (*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]); (*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat); + if (tangentDst) + { + osg::Vec4f srcTangent = (*tangentSrc)[vertex]; + osg::Vec3f transformedTangent = osg::Matrix::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat); + (*tangentDst)[vertex] = osg::Vec4f(transformedTangent, srcTangent.w()); + } } } positionDst->dirty(); normalDst->dirty(); + if (tangentDst) + tangentDst->dirty(); } void RigGeometry::updateBounds(osg::NodeVisitor *nv) diff --git a/components/sceneutil/riggeometry.hpp b/components/sceneutil/riggeometry.hpp index 90d4c1156..8ce753402 100644 --- a/components/sceneutil/riggeometry.hpp +++ b/components/sceneutil/riggeometry.hpp @@ -43,6 +43,8 @@ namespace SceneUtil /// @note The source geometry will not be modified. void setSourceGeometry(osg::ref_ptr sourceGeom); + osg::ref_ptr getSourceGeometry(); + // Called automatically by our CullCallback void update(osg::NodeVisitor* nv); diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index ea9cb11ac..dbba721c2 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "shadermanager.hpp" @@ -313,24 +314,32 @@ namespace Shader { const ShaderRequirements& reqs = mRequirements.back(); + osg::ref_ptr sourceGeometry = &geometry; + SceneUtil::RigGeometry* rig = dynamic_cast(&geometry); + if (rig) + sourceGeometry = rig->getSourceGeometry(); + if (mAllowedToModifyStateSets) { // make sure that all UV sets are there for (std::map::const_iterator it = reqs.mTextures.begin(); it != reqs.mTextures.end(); ++it) { - if (geometry.getTexCoordArray(it->first) == NULL) - geometry.setTexCoordArray(it->first, geometry.getTexCoordArray(0)); + if (sourceGeometry->getTexCoordArray(it->first) == NULL) + sourceGeometry->setTexCoordArray(it->first, sourceGeometry->getTexCoordArray(0)); } } if (reqs.mTexStageRequiringTangents != -1 && mAllowedToModifyStateSets) { osg::ref_ptr generator (new osgUtil::TangentSpaceGenerator); - generator->generate(&geometry, reqs.mTexStageRequiringTangents); + generator->generate(sourceGeometry, reqs.mTexStageRequiringTangents); - geometry.setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX); + sourceGeometry->setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX); } + if (rig) + rig->setSourceGeometry(sourceGeometry); + // TODO: find a better place for the stateset if (reqs.mShaderRequired || mForceShaders) createProgram(reqs, geometry);