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