Page 2 of 2

Posted: Thu Dec 27, 2007 9:41 am
by frustum
I have successfully loaded md5b files with animation.
There are many unused and repeated records in the structures.

md5b format is:

Code: Select all

int version (1)
int unused

int number of joints
each joint is:
  string name
  int parent
  float[8] unused
  float[4] row_0 of bind pose matrix
  float[4] row_1 of bind pose matrix
  float[4] row_2 of bind pose matrix

int number of meshes
each mesh is:
  string name
  int[3] unused
  int number of shadow vertices
  uchar vertex buffer index (0 or 1)
  uchar vertex buffer shared flag (1 means mesh without vertex)
  uchar vertex rigid flag (0 means 4 bones per vertex, 1 means 1 bone)
  string shader
  int[2] unused
  int number of triangles
  ushort[num_of_triangles * 3] array of indices
  int number of shadow indices unused
  short[num_of_shadow_indices * 4] unused
  uchar[num_of_shadow_vertices * 2] unused
  int number of vertex
  int number of extended vertices unused
  int[num_of_extended_vertices] unused
  int[2] unused
  int number of joints
  uchar[num_of_joints] joints indices
  vertex[num_of_vertex]
  each vertex is:
     float[3] coordinate
     float[2] texcoord
     float[3] normal
     float[3] tangent
     float binormal direction (cross(normal,tangnet) * binormal)
     int unused
  if rigid is 1
     uchar[num_of_vertex] each uchar is joint index * 3
  else
     uchar[num_of_vertex * 8] each pair of uchars are joint undex * 3 and joint weight
   uchar[5] unused
animb format is:

Code: Select all

int id (ANMB)
int version (1)

int number of frames
int[4] unused

int number of frames
bounds[num_of_frames]
each bound is:
  short[3] min
  short[3] max

int number of joints
joint[num_of_joints]
each joint is:
   string name
   int parent
   int flags
   int offset

int number of joints
baseframe[num_of_joints]
each baseframe is:
  short[3] rotation
  short[3] position

int number of components
short[components]
i don't want to describe algorithms
piece of code will be better:

components to frames:

Code: Select all

int offset = 0;
for(int j = 0; j < joints.size(); j++) {
	int flags = joints[j].flags;
	if(flags & 0x01) offset++;
	if(flags & 0x02) offset++;
	if(flags & 0x04) offset++;
	if(flags & 0x08) offset++;
	if(flags & 0x10) offset++;
	if(flags & 0x20) offset++;
}

for(int i = 0; i < frames.size(); i++) {
	Vector<Frame> &frame = frames[i];
	frame.resize(joints.size());
	
	for(int j = 0; j < joints.size(); j++) {
		int parent = joints[j].parent;
		int flags = joints[j].flags;
		int index = joints[j].index + offset * i;
		vec3 xyz = joints[j].xyz;
		quat rot = joints[j].rot;
		
		if(flags & 0x01) xyz.x = components[index++] * 256.0f / 32767.0f;
		if(flags & 0x02) xyz.y = components[index++] * 256.0f / 32767.0f;
		if(flags & 0x04) xyz.z = components[index++] * 256.0f / 32767.0f;
		if(flags & 0x08) rot.x = components[index++] / 32767.0f;
		if(flags & 0x10) rot.y = components[index++] / 32767.0f;
		if(flags & 0x20) rot.z = components[index++] / 32767.0f;
	
		rot.w = -sqrtf(max(1.0f - length2(vec3(rot)),0.0f));
		
		if(parent == -1) {
			frame[j].xyz = xyz;
			frame[j].rot = rot;
		} else {
			frame[j].xyz = frame[parent].rot * xyz + frame[parent].xyz;
			frame[j].rot = normalize(frame[parent].rot * rot);
		}
	}
}
mesh vertex buffer:

Code: Select all

Vertex *vertex = mesh->vertex.get();
if(mesh->shared) {
	for(int i = 0; i < meshes.size(); i++) {
		if(meshes[i].shared == 0 && meshes[i].index == mesh->index && meshes[i].shader == mesh->shader) {
			vertex = meshes[i].vertex.get();
			break;
		}
	}
}

Posted: Sun Dec 30, 2007 1:54 am
by Wobble
[out]

Posted: Sun Dec 30, 2007 7:07 am
by frustum
Character meshes has vertex buffer in each mesh.
But other meshes can share vertex buffer with others.
For example vehicles.

Posted: Sun Dec 30, 2007 8:52 am
by Karpati
Fustrum,

I think I did find 2 bugs in your great description:

uchar[num_of_shadow_vertices * 2] unused
int numVPart1 (for the third time =\)
'missed line from the namshub's doc'

int number of vertex


int number of triangles -----> (number of triangles)/3
ushort[num_of_triangles * 3] array of indices



I uploaded the latest 3d converter package (v4.025) to my web page now (today, 8:30 am). It has two ETQW related loader modules:
Enemy Territory: QUAKE Wars *.MD5B
Enemy Territory: QUAKE Wars *.MD5MESH

http://web.t-online.hu/karpo

You can update your installed application (version>=4.0) quickly and easily using the auto-update function (Help/Check for updates…).

Posted: Sun Dec 30, 2007 9:02 am
by frustum
Karpati,

yeah two misprints

Code: Select all

int number of meshes
each mesh is:
  string name
  int[3] unused
  int number of shadow vertices
  uchar vertex buffer index (0 or 1)
  uchar vertex buffer shared flag (1 means mesh without vertex)
  uchar vertex rigid flag (0 means 4 bones per vertex, 1 means 1 bone)
  string shader
  int[2] unused
  int number of indices
  ushort[num_of_indices] array of indices
  int number of shadow indices unused
  short[num_of_shadow_indices * 4] unused
  uchar[num_of_shadow_vertices * 2] unused
  int number of vertex unused
  int number of vertex
  int number of extended vertices unused
  int[num_of_extended_vertices] unused
  int[2] unused
  int number of joints
  uchar[num_of_joints] joints indices
  vertex[num_of_vertex]
  each vertex is:
     float[3] coordinate
     float[2] texcoord
     float[3] normal
     float[3] tangent
     float binormal direction (cross(normal,tangnet) * binormal)
     int unused
  if rigid is 1
     uchar[num_of_vertex] each uchar is joint index * 3
  else
     uchar[num_of_vertex * 8] each pair of uchars are joint undex * 3 and joint weight
   uchar[5] unused 

Posted: Mon Dec 31, 2007 12:05 am
by Wobble
[out]

Posted: Mon Dec 31, 2007 7:02 am
by frustum
Probably index is boolean flag because i didn't see values different from 0 and 1.

I posted code to select vertex buffer above.
I'm not sure in this code, but it works for all models from quakeWars.

Code: Select all

Loading /home/frustum/husky.md5b
-- | num_vertex: 1003 | index:  0 | shared:  0 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
-- | num_vertex: 1001 | index:  1 | shared:  0 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  1 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1
-- | num_vertex:  400 | index:  0 | shared:  0 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
-- | num_vertex:  387 | index:  1 | shared:  0 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  1 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  1 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  1 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  0 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  1 | shared:  1 | shader: textures/common/shadow_vehicle
   | num_vertex:    0 | index:  1 | shared:  1 | shader: textures/common/shadow_vehicle
-- | num_vertex:    8 | index:  0 | shared:  0 | shader: models/vehicles/edf_badger/brakelight
   | num_vertex:    0 | index:  0 | shared:  1 | shader: dummy/metal/shader1

Posted: Tue Jan 01, 2008 2:32 am
by Wobble
[out]

Posted: Tue Jan 01, 2008 5:30 am
by Wobble
[out]

Posted: Tue Jan 01, 2008 7:34 am
by frustum
Wobble wrote: Look at Mesh[37]. The max vertex index is 1955. The only VB buffer that is a logical match
is found at Mesh[0] with 1956 vertices. It can't use the VB buffer at Mesh[36], since there's
only 527 vertices there.
Append shader name into the table.

Probably bone index multiplied by 3 for direct loading bone matrices in shader (3 rows per bone).
And engine must pass some vectors into shader for rendering in additional to bones.
Direct3d9 level hardware has only 255 shader parameters.
Therefore uchar is the reasonable format for bones.