Displaying A Quake Ii Model


el_pango

Member
Joined
May 31, 2006
Messages
145
Location
California
Good evening all,

I'm trying to load and display a .MD2 file[sup]1[/sup] like so:

load:
Code:
MD2_MODEL_PTR MD2MODEL_load(const char * filename)
{
	FILE 					*fin;
	MD2_HEADER_STRUCT	header;
	int					index;
	int					element_index;
	int					dest;
	int					tmp;
	MD2_MODEL			*output;

	fin	= fopen(filename,"rb");

	if(fin == NULL)
	{
		DUH_WHERE_AM_I("file couldn't be opened");
		return NULL;
	}

	rewind(fin);

	output = (MD2_MODEL *)malloc(sizeof(MD2_MODEL));

	if(output == NULL)
	{
		DUH_WHERE_AM_I("malloc failed, couldn't create space for model");
		fclose(fin);
		return NULL;
	}

	/* read header, populate fields */
	fread(&header.ident,				4,1,fin);
	fread(&header.version,			4,1,fin);
	fread(&header.skin_width,		4,1,fin);
	fread(&header.skin_height,		4,1,fin);
	fread(&header.frame_size,		4,1,fin);
	fread(&header.num_skins,		4,1,fin);
	fread(&header.num_vertices,	4,1,fin);
	fread(&header.num_texture_coords,4,1,fin);
	fread(&header.num_triangles,	4,1,fin);
	fread(&header.num_gl_commands,4,1,fin);
	fread(&header.num_frames,		4,1,fin);
	fread(&header.offset_skins,	4,1,fin);
	fread(&header.offset_texture_coords,4,1,fin);
	fread(&header.offset_triangles,4,1,fin);
	fread(&header.offset_frames,	4,1,fin);
	fread(&header.offset_gl_commands,4,1,fin);
	fread(&header.offset_end,		4,1,fin);

	output->num_frames 		= header.num_frames;
	output->frames				= malloc(sizeof(MD2_ANIM_FRAME_STRUCT) * output->num_frames);

	output->num_tris			= header.num_triangles;
	output->tri_list			= malloc(sizeof(MD2_TRIANGLE) * output->num_tris);

	output->num_tex_coords 	= header.num_texture_coords;
	output->tex_coords		= malloc(sizeof(MD2_TEX_COORD) * output->num_tex_coords);

	output->tmp_verts			= malloc(sizeof(VERTEX )		* output->num_tris * 3);
	output->tmp_norms			= malloc(sizeof(NORMAL)			* output->num_tris * 3);
	output->tmp_coords		= malloc(sizeof(TEX_COORD)		* output->num_tris * 3);

	fseek(fin,header.offset_texture_coords,0L);

	/* load u,v coordinates */
	for(index = 0; index < header.num_texture_coords; index++)
	{
		fread(&output->tex_coords[index].u,2,1,fin);
		fread(&output->tex_coords[index].v,2,1,fin);
	}

	fseek(fin,header.offset_triangles,0L);

	/* load triangle vertex indexes */
	for(index = 0; index < header.num_triangles; index++)
	{
		fread(&output->tri_list[index].vertex_indices[0],2,1,fin);
		fread(&output->tri_list[index].vertex_indices[1],2,1,fin);
		fread(&output->tri_list[index].vertex_indices[2],2,1,fin);

		fread(&output->tri_list[index].texture_indices[0],2,1,fin);
		fread(&output->tri_list[index].texture_indices[1],2,1,fin);
		fread(&output->tri_list[index].texture_indices[2],2,1,fin);
	}

	fseek(fin,header.offset_frames,0L);

	for(index = 0; index < output->num_frames; index++)
	{
		DUH_WHERE_AM_I("reading next frame");

		element_index 	= 0;

		fread(&output->frames[index].scale_x,		4,1,fin);
		fread(&output->frames[index].scale_y,		4,1,fin);
		fread(&output->frames[index].scale_z,		4,1,fin);
		fread(&output->frames[index].translate_x,	4,1,fin);
		fread(&output->frames[index].translate_y,	4,1,fin);
		fread(&output->frames[index].translate_z,	4,1,fin);

		fseek(fin,16,ftell(fin)); // skip the name

		do
		{
			fread(&output->frames[index].vertices[element_index].unscaled_x,1,1,fin);
			fread(&output->frames[index].vertices[element_index].unscaled_y,1,1,fin);
			fread(&output->frames[index].vertices[element_index].unscaled_z,1,1,fin);
			fread(&output->frames[index].vertices[element_index].normal_list_index,1,1,fin);

			element_index++;
		}
		while(element_index < header.num_vertices);
	}

	fclose(fin);

	return output;
}

put into array and draw:
Code:
MD2MODEL_render(const MD2_MODEL *model, GLfloat x, GLfloat y, GLfloat z,
					GLfloat y_rotation, GLuint texture, int tex_size, int curr_frame,
	            int next_frame, float tween_value)
{
	float 	scaled_x0, scaled_y0, scaled_z0;
	float 	scaled_x1, scaled_y1, scaled_z1;
	float 	scaled_x, scaled_y, scaled_z;

	int		tri_index;

	for(tri_index = 0; tri_index < model->num_tris; tri_index++)
	{
		scaled_x = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].unscaled_x * model->frames[curr_frame].scale_x + model->frames[curr_frame].translate_x;
		scaled_y = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].unscaled_y * model->frames[curr_frame].scale_y + model->frames[curr_frame].translate_y;
		scaled_z = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].unscaled_z * model->frames[curr_frame].scale_z + model->frames[curr_frame].translate_z;

		model->tmp_verts[tri_index * 3 + 0].x = scaled_x;
		model->tmp_verts[tri_index * 3 + 0].y = scaled_y;
		model->tmp_verts[tri_index * 3 + 0].z = scaled_z;

		scaled_x = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].normal_list_index][0];
		scaled_y = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].normal_list_index][ 1];
		scaled_z = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[0]].normal_list_index][ 2];

		model->tmp_norms[tri_index * 3 + 0].x = scaled_x;
		model->tmp_norms[tri_index * 3 + 0].y = scaled_y;
		model->tmp_norms[tri_index * 3 + 0].z = scaled_z;

		model->tmp_coords[tri_index * 3 + 0].u = model->tex_coords[model->tri_list[tri_index].texture_indices[0]].u / tex_size;
		model->tmp_coords[tri_index * 3 + 0].v = model->tex_coords[model->tri_list[tri_index].texture_indices[0]].v / tex_size;

		///////////////////////////////////////

		scaled_x = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].unscaled_x * model->frames[curr_frame].scale_x + model->frames[curr_frame].translate_x;
		scaled_y = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].unscaled_y * model->frames[curr_frame].scale_y + model->frames[curr_frame].translate_y;
		scaled_z = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].unscaled_z * model->frames[curr_frame].scale_z + model->frames[curr_frame].translate_z;

		model->tmp_verts[tri_index * 3 + 1].x = scaled_x;
		model->tmp_verts[tri_index * 3 + 1].y = scaled_y;
		model->tmp_verts[tri_index * 3 + 1].z = scaled_z;

		scaled_x = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].normal_list_index][0];
		scaled_y = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].normal_list_index][ 1];
		scaled_z = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[1]].normal_list_index][2];

		model->tmp_norms[tri_index * 3 + 1].x = scaled_x;
		model->tmp_norms[tri_index * 3 + 1].y = scaled_y;
		model->tmp_norms[tri_index * 3 + 1].z = scaled_z;

		model->tmp_coords[tri_index * 3 + 1].u = model->tex_coords[model->tri_list[tri_index].texture_indices[1]].u / tex_size;
		model->tmp_coords[tri_index * 3 + 1].u = model->tex_coords[model->tri_list[tri_index].texture_indices[1]].v / tex_size;

		///////////////////////////////////////

		scaled_x = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].unscaled_x * model->frames[curr_frame].scale_x + model->frames[curr_frame].translate_x;
		scaled_y = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].unscaled_y * model->frames[curr_frame].scale_y + model->frames[curr_frame].translate_y;
		scaled_z = model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].unscaled_z * model->frames[curr_frame].scale_z + model->frames[curr_frame].translate_z;

		model->tmp_verts[tri_index * 3 + 2].x = scaled_x;
		model->tmp_verts[tri_index * 3 + 2].y = scaled_y;
		model->tmp_verts[tri_index * 3 + 2].z = scaled_z;

		scaled_x = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].normal_list_index][ 0];
		scaled_y = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].normal_list_index ][1];
		scaled_z = normal_list[ model->frames[curr_frame].vertices[model->tri_list[tri_index].vertex_indices[2]].normal_list_index][2];

		model->tmp_norms[tri_index * 3 + 2].x = scaled_x;
		model->tmp_norms[tri_index * 3 + 2].y = scaled_y;
		model->tmp_norms[tri_index * 3 + 2].z = scaled_z;

		model->tmp_coords[tri_index * 3 + 2].u = model->tex_coords[model->tri_list[tri_index].texture_indices[2]].u / tex_size;
		model->tmp_coords[tri_index * 3 + 2].u = model->tex_coords[model->tri_list[tri_index].texture_indices[2]].v / tex_size;
	}

	// world_pos	=	  Matrix.CreateRotationZ(MathHelper.ToRadians(y_rotation)) * Matrix.CreateRotationX(MathHelper.ToRadians(x_rotation))  * Matrix.CreateTranslation(x,y,z) ;
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(x,y,z);
	glRotatef(y_rotation,0,1,0);

//	//be.End();
//	be.TextureEnabled		= true;
//	be.LightingEnabled	= false;
//	be.Texture				= tex;
//	be.World					= world_pos;
//	be.CommitChanges();

//	foreach (EffectPass pass in be.CurrentTechnique.Passes)
//	{
//		pass.Begin();
//		COMMON.gfx_device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, tmp_verts, 0,model->num_tris);
//		pass.End();
//	}
	glBindTexture(GL_TEXTURE_2D, texture);

	glVertexPointer(3,GL_FLOAT,0,model->tmp_verts);
	glNormalPointer(GL_FLOAT,0,model->tmp_norms);
	glTexCoordPointer(2,GL_FLOAT,0,model->tmp_coords);
	glDrawArrays(GL_TRIANGLES,0,model->num_tris * 3);
	glPopMatrix();

}

But nothing appears.

I've verified that the correct arrays (vertex, tex coord and normal) are enabled and the pointers to them are set, that I can draw something else (a simple textured cube works) and that the model is inside the frustum (rendering with same coordinates as cube) and that backface culling is off, so even if the camera were stuck inside the model, I'd see something, but no luck.

Sorry for the wall of code, but can anyone figure out what I've done wrong here?

1. File format as described in this page on icculus.org.
 

crow_riot

Well-Known Member
Joined
Sep 21, 2009
Messages
1,763
Location
.at
one copy paste bug here

Code:
model->tmp_coords[tri_index * 3 + 1].u = model->tex_coords[model->tri_list[tri_index].texture_indices[1]].u / tex_size;
model->tmp_coords[tri_index * 3 + 1].u = model->tex_coords[model->tri_list[tri_index].texture_indices[1]].v / tex_size;

i assume u want to set tmp_coords[].v on the seconds line ...

and probably you are missing a glLoadIdentity() call after glPushMatrix();
 

Spirit

Member
Joined
Aug 17, 2008
Messages
411
Hi, check out http://www.icculus.org/qshed/qwalk/
It includes a modelviewer.
 

darkblu

Member
Joined
Oct 6, 2008
Messages
640
crow_riot said:
and probably you are missing a glLoadIdentity() call after glPushMatrix();
my guess is el_pango actually has a view matrix on the modelview stack at that moment (ergo the push/pop pair).

el_pango, two things:

1. make sure the vertex attributes you specify pointers to are actually enabled (glEnableClientState)
2. the fact the model is at known coordinates and culling is off does not guarantee you'd see something - the entire camera frustum might be inside the model. try playing with the camera frustum and/or model's scale.
 
Last edited by a moderator:
Top