r698 - trunk

lordhavoc at icculus.org lordhavoc at icculus.org
Sat Apr 8 23:55:57 EDT 2006


Author: lordhavoc
Date: 2006-04-08 23:55:57 -0400 (Sat, 08 Apr 2006)
New Revision: 698

Modified:
   trunk/model.c
   trunk/model.h
Log:
no longer stores skeletal data about md5mesh files that contain only one
bone, this saves a bit of memory


Modified: trunk/model.c
===================================================================
--- trunk/model.c	2006-04-09 03:10:04 UTC (rev 697)
+++ trunk/model.c	2006-04-09 03:55:57 UTC (rev 698)
@@ -215,11 +215,12 @@
 void Model_Load(ResourceEntry *r)
 {
 	Util_ParseC_Thread thread;
-	NUint32 meshnum, version;
+	NUint32 meshnum, version, numjoints = 0;
 	Nbool error;
 	Nsize filesize;
 	Model *model;
 	char *filedata;
+	Nbool isskeletal = false;
 
 	model = Mem_Alloc(r->memzone, sizeof(Model));
 
@@ -275,14 +276,19 @@
 		//numJoints 3
 		else if (Util_ParseC_MatchKeyword(&thread, "numJoints"))
 		{
-			LoadInt(model->num_transforms, "after 'numJoints'");
-			if (model->num_transforms < 1)
+			LoadInt(numjoints, "after 'numJoints'");
+			if (numjoints < 1)
 			{
-				Console_Printf("Model_Load: numJoints %i < 1\n", model->num_transforms);
+				Console_Printf("Model_Load: numJoints %i < 1\n", numjoints);
 				Abort();
 			}
-			model->max_transforms = model->num_transforms;
-			model->data_transforminfo = Mem_Alloc(r->memzone, model->max_transforms * sizeof(*model->data_transforminfo));
+			if (numjoints > 1)
+			{
+				isskeletal = true;
+				model->num_transforms = numjoints;
+				model->max_transforms = model->num_transforms;
+				model->data_transforminfo = Mem_Alloc(r->memzone, model->max_transforms * sizeof(*model->data_transforminfo));
+			}
 		}
 		//numMeshes 1
 		else if (Util_ParseC_MatchKeyword(&thread, "numMeshes"))
@@ -303,35 +309,44 @@
 		//}
 		else if (Util_ParseC_MatchKeyword(&thread, "joints"))
 		{
+			char *name = NULL;
 			NUint32 jointnum;
 			ExpectKeyword("{", "after 'joints'");
 			for (jointnum = 0; !Util_ParseC_MatchKeyword(&thread, "}");jointnum++)
 			{
 				NSint32 parent;
+				Nfloat pose[6];
 				//	"root"	-1 ( 0.000000 0.000000 0.000000 ) ( -0.707107 -0.000000 -0.000000 )
-				LoadString(model->data_transforminfo[jointnum].name, "for joint name");
+				LoadString(name, "for joint name");
 				LoadInt(parent, "as parent");
 				ExpectKeyword("(", "before first joint data list");
-				LoadValue(model->data_transforminfo[jointnum].basepose[0], "(joint 0)");
-				LoadValue(model->data_transforminfo[jointnum].basepose[1], "(joint 1)");
-				LoadValue(model->data_transforminfo[jointnum].basepose[2], "(joint 2)");
+				LoadValue(pose[0], "(joint 0)");
+				LoadValue(pose[1], "(joint 1)");
+				LoadValue(pose[2], "(joint 2)");
 				ExpectKeyword(")", "after first joint data list");
 				ExpectKeyword("(", "before second joint data list");
-				LoadValue(model->data_transforminfo[jointnum].basepose[3], "(joint 3)");
-				LoadValue(model->data_transforminfo[jointnum].basepose[4], "(joint 4)");
-				LoadValue(model->data_transforminfo[jointnum].basepose[5], "(joint 5)");
+				LoadValue(pose[3], "(joint 3)");
+				LoadValue(pose[4], "(joint 4)");
+				LoadValue(pose[5], "(joint 5)");
 				ExpectKeyword(")", "after second joint data list");
-				Matrix4x4_CreateFromDoom3Joint(&model->data_transforminfo[jointnum].basematrix, model->data_transforminfo[jointnum].basepose[0], model->data_transforminfo[jointnum].basepose[1], model->data_transforminfo[jointnum].basepose[2], model->data_transforminfo[jointnum].basepose[3], model->data_transforminfo[jointnum].basepose[4], model->data_transforminfo[jointnum].basepose[5]);
-				Matrix4x4_Invert_Simple(&model->data_transforminfo[jointnum].baseinversematrix, &model->data_transforminfo[jointnum].basematrix);
 				if (parent >= (NSint32)jointnum)
 				{
+					String_Free(&name);
 					Console_Printf("Model_Load: joint.parent (%i) >= joint (%i)\n", parent, jointnum);
 					Abort();
 				}
+				if (isskeletal)
+				{
+					Matrix4x4_CreateFromDoom3Joint(&model->data_transforminfo[jointnum].basematrix, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5]);
+					Matrix4x4_Invert_Simple(&model->data_transforminfo[jointnum].baseinversematrix, &model->data_transforminfo[jointnum].basematrix);
+					model->data_transforminfo[jointnum].name = name;
+					name = NULL;
+				}
 			}
-			if (jointnum != model->num_transforms)
+			String_Free(&name);
+			if (jointnum != numjoints)
 			{
-				Console_Printf("Model_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, model->num_transforms);
+				Console_Printf("Model_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, numjoints);
 				Abort();
 			}
 		}
@@ -377,8 +392,11 @@
 					mesh->data_normal3f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[3]));
 					mesh->data_texcoord2f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[2]));
 					mesh->data_lightmaptexcoord2f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[2]));
-					mesh->data_weightindex4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
-					mesh->data_weightvalue4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
+					if (isskeletal)
+					{
+						mesh->data_weightindex4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
+						mesh->data_weightvalue4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
+					}
 					md5weightrange = Mem_Alloc(Global_Zone, mesh->max_vertices * sizeof(NUint32[2]));
 				}
 				//	vert 0 ( 0.142532 0.983877 ) 0 1
@@ -469,9 +487,9 @@
 					md5weight = md5weights + weightnum;
 					// 2
 					LoadInt(md5weight->jointnum, "(weight jointnum)");
-					if (md5weight->jointnum >= model->num_transforms)
+					if (md5weight->jointnum >= numjoints)
 					{
-						Console_Printf("Model_Load: joint (%i) >= num_transforms (%i)\n", md5weight->jointnum, model->num_transforms);
+						Console_Printf("Model_Load: joint (%i) >= numjoints (%i)\n", md5weight->jointnum, numjoints);
 						Abort();
 					}
 					// 1.000000
@@ -497,57 +515,68 @@
 				}
 			}
 			memset(mesh->data_vertex3f, 0, mesh->num_vertices * sizeof(float[3]));
-			for (i = 0;i < mesh->num_vertices;i++)
+			if (isskeletal)
 			{
-				Ndouble sum = 0;
-				NUint32 k;
-				NUint32 wi[4];
-				Nfloat wf[4];
-				Vector4Clear(wi);
-				Vector4Clear(wf);
-				for (j = 0, md5weight = md5weights + md5weightrange[i*2+0];j < md5weightrange[i*2+1];j++, md5weight++)
+				// convert the skeletal data from doom3 vertex weights to
+				// matrix palette weights (usable by a vertex shader)
+				for (i = 0;i < mesh->num_vertices;i++)
 				{
-					matrix = &model->data_transforminfo[md5weight->jointnum].basematrix;
-					mesh->data_vertex3f[i*3+0] += DotProduct4(md5weight->vertex, matrix->m[0]);
-					mesh->data_vertex3f[i*3+1] += DotProduct4(md5weight->vertex, matrix->m[1]);
-					mesh->data_vertex3f[i*3+2] += DotProduct4(md5weight->vertex, matrix->m[2]);
-					// store the best weights in the vertex's limited number of blend weights
-					for (k = 4;k >= 1 && mesh->data_weightvalue4b[i*4+k-1] < md5weight->vertex[3];k--)
+					Ndouble sum = 0;
+					NUint32 k;
+					NUint32 wi[4];
+					Nfloat wf[4];
+					Vector4Clear(wi);
+					Vector4Clear(wf);
+					for (j = 0, md5weight = md5weights + md5weightrange[i*2+0];j < md5weightrange[i*2+1];j++, md5weight++)
 					{
+						matrix = &model->data_transforminfo[md5weight->jointnum].basematrix;
+						mesh->data_vertex3f[i*3+0] += DotProduct4(md5weight->vertex, matrix->m[0]);
+						mesh->data_vertex3f[i*3+1] += DotProduct4(md5weight->vertex, matrix->m[1]);
+						mesh->data_vertex3f[i*3+2] += DotProduct4(md5weight->vertex, matrix->m[2]);
+						// store the best weights in the vertex's limited number of blend weights
+						for (k = 4;k >= 1 && mesh->data_weightvalue4b[i*4+k-1] < md5weight->vertex[3];k--)
+						{
+							if (k < 4)
+							{
+								wi[k] = wi[k-1];
+								wf[k] = wf[k-1];
+							}
+						}
 						if (k < 4)
 						{
-							wi[k] = wi[k-1];
-							wf[k] = wf[k-1];
+							wi[k] = md5weight->jointnum;
+							wf[k] = md5weight->vertex[3];
 						}
+						sum += md5weight->vertex[3];
 					}
-					if (k < 4)
+					if (fabs(sum - 1) > 0.001)
+						Console_Printf("vertex #%i (weights %i-%i) does not sum to 1! (sum = %f)\n", i, md5weightrange[i*2+0], md5weightrange[i*2+0]+md5weightrange[i*2+1], sum);
+					if (wf[3] > wf[2] || wf[2] > wf[1] || wf[1] > wf[0])
+						Console_Printf("vertex sorting error!  vertex #%i has weights %i:%f %i:%f %i:%f %i:%f\n", i, wi[0], wf[0], wi[1], wf[1], wi[2], wf[2], wi[3], wf[3]);
+					// renormalize the array of strongest weights on this vertex
+					sum = 0;
+					for (k = 0;k < 4;k++)
+						sum += wf[k];
+					if (sum)
 					{
-						wi[k] = md5weight->jointnum;
-						wf[k] = md5weight->vertex[3];
+						sum = 1.0f / sum;
+						for (k = 0;k < 4;k++)
+							wf[k] *= sum;
 					}
-					sum += md5weight->vertex[3];
-				}
-				if (fabs(sum - 1) > 0.001)
-					Console_Printf("vertex #%i (weights %i-%i) does not sum to 1! (sum = %f)\n", i, md5weightrange[i*2+0], md5weightrange[i*2+0]+md5weightrange[i*2+1], sum);
-				if (wf[3] > wf[2] || wf[2] > wf[1] || wf[1] > wf[0])
-					Console_Printf("vertex sorting error!  vertex #%i has weights %i:%f %i:%f %i:%f %i:%f\n", i, wi[0], wf[0], wi[1], wf[1], wi[2], wf[2], wi[3], wf[3]);
-				// renormalize the array of strongest weights on this vertex
-				sum = 0;
-				for (k = 0;k < 4;k++)
-					sum += wf[k];
-				if (sum)
-				{
-					sum = 1.0f / sum;
+					// now convert to the compact format used for longterm storage
 					for (k = 0;k < 4;k++)
-						wf[k] *= sum;
+					{
+						mesh->data_weightindex4b[i*4+k] = (NUint8)wi[k];
+						mesh->data_weightvalue4b[i*4+k] = (NUint8)(wf[k] * 255.0f);
+					}
 				}
-				// now convert to the compact format used for longterm storage
-				for (k = 0;k < 4;k++)
-				{
-					mesh->data_weightindex4b[i*4+k] = (NUint8)wi[k];
-					mesh->data_weightvalue4b[i*4+k] = (NUint8)(wf[k] * 255.0f);
-				}
 			}
+			else
+			{
+				// non-skeletal
+				for (i = 0;i < mesh->num_vertices;i++)
+					VectorCopy(md5weights[md5weightrange[i*2+0]].vertex, mesh->data_vertex3f + i*3);
+			}
 			// compile the base frame of the mesh for static uses
 			Model_MeshVectors(mesh->num_triangles, mesh->data_element3i, mesh->num_vertices, mesh->data_vertex3f, mesh->data_texcoord2f, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f);
 			Model_MeshNeighbors(mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, mesh->num_vertices);
@@ -590,15 +619,18 @@
 					mesh->basecullmaxs[1] = Max(mesh->basecullmaxs[1], mesh->data_vertex3f[i * 3 + 1]);
 					mesh->basecullmaxs[2] = Max(mesh->basecullmaxs[2], mesh->data_vertex3f[i * 3 + 2]);
 				}
-				for (k = 0;k < 4 && mesh->data_weightvalue4b[i*4+k] > 0;k++)
+				if (isskeletal)
 				{
-					NUint32 index = mesh->data_weightindex4b[i*4+k];
-					Nvec3 v1, v;
-					Nvec r;
-					VectorCopy(mesh->data_vertex3f + i * 3, v1);
-					Matrix4x4_Transform(&model->data_transforminfo[index].baseinversematrix, v1, v);
-					r = VectorLength(v);
-					model->data_transforminfo[index].radius = Max(model->data_transforminfo[index].radius, r);
+					for (k = 0;k < 4 && mesh->data_weightvalue4b[i*4+k] > 0;k++)
+					{
+						NUint32 index = mesh->data_weightindex4b[i*4+k];
+						Nvec3 v1, v;
+						Nvec r;
+						VectorCopy(mesh->data_vertex3f + i * 3, v1);
+						Matrix4x4_Transform(&model->data_transforminfo[index].baseinversematrix, v1, v);
+						r = VectorLength(v);
+						model->data_transforminfo[index].radius = Max(model->data_transforminfo[index].radius, r);
+					}
 				}
 			}
 			Mem_Free(&md5weights);
@@ -653,7 +685,9 @@
 	if (meshindex >= model->num_meshes)
 		return; // invalid mesh index
 	mesh = model->data_meshes + meshindex;
-	if (!transforms)
+	// if the caller is not requesting skeletal animation or if the model
+	// doesn't even support animation, just return the undeformed arrays
+	if (!transforms || !mesh->data_weightvalue4b)
 	{
 		if (outvertex3f)
 		{

Modified: trunk/model.h
===================================================================
--- trunk/model.h	2006-04-09 03:10:04 UTC (rev 697)
+++ trunk/model.h	2006-04-09 03:55:57 UTC (rev 698)
@@ -47,6 +47,8 @@
 	// (aka bumpmapped) lighting.
 	// location of vertex
 	float *data_vertex3f;
+	// TODO: these should be used only in the vertex shader
+	// TODO: when vertex shader is used, replace svector tvector normal with a 4 byte quaternion to save memory
 	// direction of S texcoord
 	float *data_svector3f;
 	// direction of T texcoord
@@ -57,6 +59,7 @@
 	float *data_texcoord2f;
 	// lightmap texture coordinates for vertices in this mesh
 	float *data_lightmaptexcoord2f;
+	// NOTE: on non-skeletal models all weight stuff is NULL!
 	// indices of up to 4 transforms per vertex
 	NUint8 *data_weightindex4b;
 	// blending influence values of up to 4 transforms per vertex
@@ -81,6 +84,7 @@
 	NUint32 max_meshes;
 	Model_Mesh *data_meshes;
 
+	// NOTE: on non-skeletal models all transform stuff is 0 or NULL!
 	NUint32 num_transforms;
 	NUint32 max_transforms;
 	Model_TransformInfo *data_transforminfo;




More information about the neither-commits mailing list