[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44228] trunk/blender/source/blender/ collada: Collada export: changes to joints/weights in skincontroller

Juha Mäki-Kanto kiskosika at gmail.com
Sat Feb 18 17:20:25 CET 2012


Revision: 44228
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44228
Author:   kanttori
Date:     2012-02-18 16:20:24 +0000 (Sat, 18 Feb 2012)
Log Message:
-----------
Collada export: changes to joints/weights in skincontroller

- Collecting joints/weights in one place, it's easier to exclude zero weights or vertexgroups with no matching bone than trying to match same logic in multiple places.
- Still not exporting -1 joints for vertices without weights, but also not outputting -1 joint + weight for each vertexgroup without a matching bone.
- The exported weights are now normalized.

Last I tested this patch stopped 3ds Max crashing on import of file from #29465 (opencollada / internal .dae).

Modified Paths:
--------------
    trunk/blender/source/blender/collada/ArmatureExporter.cpp
    trunk/blender/source/blender/collada/ArmatureExporter.h

Modified: trunk/blender/source/blender/collada/ArmatureExporter.cpp
===================================================================
--- trunk/blender/source/blender/collada/ArmatureExporter.cpp	2012-02-18 16:12:22 UTC (rev 44227)
+++ trunk/blender/source/blender/collada/ArmatureExporter.cpp	2012-02-18 16:20:24 UTC (rev 44228)
@@ -296,10 +296,64 @@
 
 	std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
 	std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
-	std::string weights_source_id = add_weights_source(me, controller_id);
 
+	std::list<int> vcounts;
+	std::list<int> joints;
+	std::list<float> weights;
+
+	{
+		int i, j;
+
+		// def group index -> joint index
+		std::vector<int> joint_index_by_def_index;
+		bDeformGroup *def;
+
+		for (def = (bDeformGroup*)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
+			if (is_bone_defgroup(ob_arm, def))
+				joint_index_by_def_index.push_back(j++);
+			else
+				joint_index_by_def_index.push_back(-1);
+		}
+
+		for (i = 0; i < me->totvert; i++) {
+			MDeformVert *vert = &me->dvert[i];
+			std::map<int, float> jw;
+
+			// We're normalizing the weights later
+			float sumw = 0.0f;
+
+			for (j = 0; j < vert->totweight; j++) {
+				int joint_index = joint_index_by_def_index[vert->dw[j].def_nr];
+				if(joint_index != -1 && vert->dw[j].weight > 0.0f)
+				{
+					jw[joint_index] += vert->dw[j].weight;
+					sumw += vert->dw[j].weight;
+				}
+			}
+
+			if(sumw > 0.0f)
+			{
+				float invsumw = 1.0f/sumw;
+				vcounts.push_back(jw.size());
+				for(std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m)
+				{
+					joints.push_back((*m).first);
+					weights.push_back(invsumw*(*m).second);
+				}
+			}
+			else
+			{
+				vcounts.push_back(0);
+				/*vcounts.push_back(1);
+				joints.push_back(-1);
+				weights.push_back(1.0f);*/
+			}
+		}
+	}
+
+	std::string weights_source_id = add_weights_source(me, controller_id, weights);
 	add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
-	add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase);
+	add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
 
 	closeSkin();
 	closeController();
@@ -445,21 +499,14 @@
 	return get_bone_from_defgroup(ob_arm, def) != NULL;
 }
 
-std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id)
+std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
 {
 	std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
 
-	int i;
-	int totweight = 0;
-
-	for (i = 0; i < me->totvert; i++) {
-		totweight += me->dvert[i].totweight;
-	}
-
 	COLLADASW::FloatSourceF source(mSW);
 	source.setId(source_id);
 	source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-	source.setAccessorCount(totweight);
+	source.setAccessorCount(weights.size());
 	source.setAccessorStride(1);
 	
 	COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
@@ -467,13 +514,8 @@
 
 	source.prepareToAppendValues();
 
-	// NOTE: COLLADA spec says weights should be normalized
-
-	for (i = 0; i < me->totvert; i++) {
-		MDeformVert *vert = &me->dvert[i];
-		for (int j = 0; j < vert->totweight; j++) {
-			source.appendValues(vert->dw[j].weight);
-		}
+	for(std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
+		source.appendValues(*i);
 	}
 
 	source.finish();
@@ -481,11 +523,12 @@
 	return source_id;
 }
 
-void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
-								Object *ob_arm, ListBase *defbase)
+void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+												  const std::list<int>& vcounts,
+												  const std::list<int>& joints)
 {
-	COLLADASW::VertexWeightsElement weights(mSW);
-	COLLADASW::InputList &input = weights.getInputList();
+	COLLADASW::VertexWeightsElement weightselem(mSW);
+	COLLADASW::InputList &input = weightselem.getInputList();
 
 	int offset = 0;
 	input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
@@ -493,40 +536,25 @@
 	input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
 									 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
 
-	weights.setCount(me->totvert);
+	weightselem.setCount(vcounts.size());
 
 	// write number of deformers per vertex
-	COLLADASW::PrimitivesBase::VCountList vcount;
-	int i;
-	for (i = 0; i < me->totvert; i++) {
-		vcount.push_back(me->dvert[i].totweight);
-	}
+	COLLADASW::PrimitivesBase::VCountList vcountlist;
 
-	weights.prepareToAppendVCountValues();
-	weights.appendVertexCount(vcount);
+	vcountlist.resize(vcounts.size());
+	std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
 
-	// def group index -> joint index
-	std::map<int, int> joint_index_by_def_index;
-	bDeformGroup *def;
-	int j;
-	for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
-		if (is_bone_defgroup(ob_arm, def))
-			joint_index_by_def_index[i] = j++;
-		else
-			joint_index_by_def_index[i] = -1;
-	}
+	weightselem.prepareToAppendVCountValues();
+	weightselem.appendVertexCount(vcountlist);
 
-	weights.CloseVCountAndOpenVElement();
+	weightselem.CloseVCountAndOpenVElement();
 
 	// write deformer index - weight index pairs
 	int weight_index = 0;
-	for (i = 0; i < me->totvert; i++) {
-		MDeformVert *dvert = &me->dvert[i];
-		for (int j = 0; j < dvert->totweight; j++) {
-			weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]);
-			weights.appendValues(weight_index++);
-		}
+	for(std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i)
+	{
+		weightselem.appendValues(*i, weight_index++);
 	}
 
-	weights.finish();
+	weightselem.finish();
 }

Modified: trunk/blender/source/blender/collada/ArmatureExporter.h
===================================================================
--- trunk/blender/source/blender/collada/ArmatureExporter.h	2012-02-18 16:12:22 UTC (rev 44227)
+++ trunk/blender/source/blender/collada/ArmatureExporter.h	2012-02-18 16:20:24 UTC (rev 44228)
@@ -111,10 +111,11 @@
 
 	bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def);
 
-	std::string add_weights_source(Mesh *me, const std::string& controller_id);
+	std::string add_weights_source(Mesh *me, const std::string& controller_id,
+								   const std::list<float>& weights);
 
-	void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
-									Object *ob_arm, ListBase *defbase);
+	void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+									const std::list<int>& vcount, const std::list<int>& joints);
 };
 
 #endif




More information about the Bf-blender-cvs mailing list