From 3408f2ce6af3deffd654bf0ac40ebacfff33c213 Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Sun, 25 Jun 2006 17:55:38 +0000 Subject: [PATCH] Removed automatic attempt to find natural bind pose. Added ability to retrieve skin influenced vertex positions from NiTriBasedGeom. --- niflib.cpp | 14 +++++----- obj/NiTriBasedGeom.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++ obj/NiTriBasedGeom.h | 4 +-- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/niflib.cpp b/niflib.cpp index 927b8808..0bca8729 100644 --- a/niflib.cpp +++ b/niflib.cpp @@ -274,13 +274,13 @@ vector<NiObjectRef> ReadNifList( istream & in ) { } //TODO: Make this an optional step? - //Send all skeleton roots to bind position - for (uint i = 0; i < blocks.size(); ++i) { - NiNodeRef node = DynamicCast<NiNode>(blocks[i]); - if ( node != NULL && node->IsSkeletonRoot() ) { - node->GoToSkeletonBindPosition(); - } - } + ////Send all skeleton roots to bind position + //for (uint i = 0; i < blocks.size(); ++i) { + // NiNodeRef node = DynamicCast<NiNode>(blocks[i]); + // if ( node != NULL && node->IsSkeletonRoot() ) { + // node->GoToSkeletonBindPosition(); + // } + //} //Return completed block list return blocks; diff --git a/obj/NiTriBasedGeom.cpp b/obj/NiTriBasedGeom.cpp index 50db534b..ed34038c 100644 --- a/obj/NiTriBasedGeom.cpp +++ b/obj/NiTriBasedGeom.cpp @@ -89,4 +89,67 @@ void NiTriBasedGeom::BindSkin( Ref<NiNode> skeleton_root, vector< Ref<NiNode> > void NiTriBasedGeom::UnbindSkin() { //Clear skin instance skinInstance = NULL; +} + +vector<Vector3> NiTriBasedGeom::GetSkinInfluencedVertices() const { + //--Get required data & insure validity--// + + NiTriBasedGeomDataRef geom_data = GetData(); + + if ( geom_data == NULL ) { + throw runtime_error("This NiTriBasedGeom has no NiTriBasedGeomData so there are no vertices to get."); + } + + NiSkinInstanceRef skin_inst = GetSkinInstance(); + + + if ( skin_inst == NULL ) { + throw runtime_error("This NiTriBasedGeom is not influenced by a skin."); + } + + NiSkinDataRef skin_data = skin_inst->GetSkinData(); + + if ( skin_data == NULL ) { + throw runtime_error("Skin Data is missing, cannot calculate skin influenced vertex position."); + } + + //Ensure that skin instance bone count & skin data bone count match + if ( skin_inst->GetBoneCount() != skin_data->GetBoneCount() ) { + throw runtime_error("Skin Instance and Skin Data bone count do not match."); + } + + //Get skeleton root + NiNodeRef skel_root = skin_inst->GetSkeletonRoot(); + if ( skel_root == NULL ) { + throw runtime_error("Skin Instance is not bound to a skeleton root."); + } + + //Get the vertices & bone nodes + vector<Vector3> vertices = geom_data->GetVertices(); + vector<NiNodeRef> bone_nodes = skin_inst->GetBones(); + + //Set up an aray to hold the transformed vertices + vector<Vector3> skin_verts( vertices.size()); + + //Transform vertices into position based on skin data + Matrix44 root_world = skel_root->GetWorldTransform(); + Matrix44 geom_world = GetWorldTransform(); + for ( uint i = 0; i < skin_data->GetBoneCount(); ++i ) { + Matrix44 bone_world = bone_nodes[i]->GetWorldTransform(); + Matrix44 bone_offset = skin_data->GetBoneTransform(i); + vector<SkinWeight> weights = skin_data->GetBoneWeights(i); + Matrix44 vert_trans = bone_offset * bone_world; + for ( uint j = 0; j < weights.size(); ++j ) { + uint index = weights[j].index; + float weight = weights[j].weight; + skin_verts[index] += (vert_trans * vertices[index] ) * weight; + } + } + + //Transform all vertices to final position + for ( uint i = 0; i < skin_verts.size(); ++i ) { + skin_verts[i] = geom_world.Inverse() * skin_verts[i]; + } + + return skin_verts; } \ No newline at end of file diff --git a/obj/NiTriBasedGeom.h b/obj/NiTriBasedGeom.h index 360d1512..b12c5be5 100644 --- a/obj/NiTriBasedGeom.h +++ b/obj/NiTriBasedGeom.h @@ -59,8 +59,8 @@ public: string GetShader() const; void SetShader( const string & n ); - - + vector<Vector3> GetSkinInfluencedVertices() const; + protected: NI_TRI_BASED_GEOM_MEMBERS STANDARD_INTERNAL_METHODS -- GitLab