Loading an MD2 without DrawPrimitiveUP

Started by
11 comments, last by Fuzztrek 21 years, 5 months ago
Hello All, I''ve been following the tutorial on gamedev for loading a MD2 file, but it is very slow, and I think this may be attributed to the fact that it uses DrawPrimitiveUP (I know for sure that I shouldn''t be using drawPrimitiveUP). Is there another tutorial or way of render MD2 files that is better? I am too clueless to figure out how to get the data into a vertex buffer :''( Thanks in advance! ¬_¬
Advertisement
G''day!

All you do is create an appropriately sized VB, lock it, copy, unlock and you''re done.

A very simple example of copying a vertex array into a VB can be found here:
http://www.drunkenhyena.com/docs/d3d_tutorial.phtml#Lesson2b

Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena
Hi there!


Thanks for replying, but I think i''m going to need a bit more direction than that :*( Thanks again tho!

¬_¬
bump.

¬_¬
actually you could use an vertex-buffer like an real vertex-array. You could also check out the DX SDK, I''m sure you will also find something interesting there.

I currently have no code about this topic, but the link to the tutorial above should explain all you need
I know how to use a vertex buffer, and use it with simple vertices, but not with the data i have. I''m not sure what type of vertex buffer i need to make, etc.

¬_¬
You can look at this tutorial of mine ... I think it''s a pretty decent explanation of the most basic functionality of vertex buffers, maybe it will help? (Excuse the website that accompanies it ... I''m just using the site as filespace, that content was all done when I was in 7th grade)
Anyway, here''s the link:

http://www.geocities.com/jimzaphos/Vertexbuf.htm
The question is not "why a talking monkey," but rather, "why not a talking monkey." -Monkey Island 4
I think you guys are missing the point...correct me if I''m wrong, but he knows how to use a vertex buffer, he just has some structures filled with vertices (the md2''s), and he doesn''t know exactly what FVF to use, etc for them?

p.s. Fuzztrek i sent you an email at hotmail asking if you need anyone to help w/ your engine...
Hey,

Yeah the AP is pretty much right. I know how to use VertexBuffers (to some extent.. I dont'' know everything about them but I know how to do the basics. As always, i could learn more) and I do know what FVF to use. Maybe it would help if I posted some code:

These are all of the structures.

  //These are some restriction for MD2//You can alter the values if you like to...const int MAX_TRIANGLES = 4096; const int MAX_VERTS = 2048; const int MAX_FRAMES = 512; const int MAX_MD2SKINS = 32; const int MAX_SKINNAME = 64;// The 13 structsstruct make_index_list {   int a, b, c;  float a_s, a_t, b_s, b_t, c_s, c_t;};struct make_vertex_list {  float x, y, z;};struct make_frame_list{  make_vertex_list *vertex;};struct vec3_t{  float v[3];};struct dstvert_t {  short s, t;};struct dtriangle_t {   short index_xyz[3];  short index_st[3];};struct dtrivertx_t{   BYTE v[3];   BYTE lightnormalindex;};//We use that to identify one animation//The only variably which is important for us is "name", it is filled with the names//of the animation frames, p.ex. "run1", or "attack2". More belowstruct daliasframe_t{   float scale[3];  float translate[3];   char name[16];   dtrivertx_t verts[1]; };//Here all information for the model is saved. Most is unimportant, the important//stuff is commented..//This struct is read first from file...struct SMD2Header{  int ident;   int version;   int skinwidth;   int skinheight;   int framesize;   int num_skins;   int num_xyz;     //Vertex count   int num_st;   int num_tris;    //Triangle count  int num_glcmds;   int num_frames;  //Numer of frames/animations within the file  int ofs_skins;   int ofs_st;   int ofs_tris;   int ofs_frames;   int ofs_glcmds;   int ofs_end; };struct trivert_t{   vec3_t v;   int lightnormalindex; };struct frame_t{   vec3_t mins, maxs;   char name[16];   trivert_t v[MAX_VERTS];};// The vertex we use for D3Dstruct MODELVERTEX {    D3DXVECTOR3 m_vecPos; //Position   D3DCOLOR m_dwDiffuse; //Color   D3DXVECTOR2 m_vecTex; //texturecoordinates};//This is the definition for the vertex declared above (FVF=flexible vertex format)#define D3DFVF_MODELVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0) )struct SMesh {  //std::vector is declared in "vector" and it is a comfortable wrapper for dynamic arrays  std::vector<MODELVERTEX> vertex;};  


And here is the loading function:

  // Load the meshHRESULT D3D_mesh::Load(char * Filename){	FILE * model = NULL;	char g_skins[MAX_MD2SKINS][64];	dstvert_t base_st[MAX_VERTS];	BYTE buffer[MAX_VERTS * 4 + 128];	SMD2Header modelHeader;	dtriangle_t tri;	daliasframe_t * out;	int i = 0;	// Load mesh in binary mode	if((model = fopen(Filename, "rb")) == NULL){		LogError("<li>Mesh failed opening mesh");		return E_FAIL;	}	// Read header	fread(&modelHeader, 1, sizeof(SMD2Header), model);	modelHeader.framesize = (int)&((daliasframe_t *)0)->verts[modelHeader.num_xyz];	// Create some variables according to the header	pro_Frames = modelHeader.num_frames;	pro_Vertices = modelHeader.num_xyz;	pro_Triangles = modelHeader.num_tris;	pro_index_list = new make_index_list[modelHeader.num_tris];	pro_frame_list = new make_frame_list[modelHeader.num_frames];	for(i = 0; i < modelHeader.num_frames; i++)		pro_frame_list[i].vertex = new make_vertex_list[modelHeader.num_xyz];	// Read skin (texture) info	fread(g_skins, 1, modelHeader.num_skins * MAX_SKINNAME, model);	// Read index for model	fread(base_st, 1, modelHeader.num_st * sizeof(base_st[0]), model);	int max_tex_u = 0, max_tex_v = 0;	for(i = 0; i < modelHeader.num_tris; i++){		// Read vertices		fread(&tri, 1, sizeof(dtriangle_t), model);		(pro_index_list)[i].a = tri.index_xyz[2];		(pro_index_list)[i].b = tri.index_xyz[1];		(pro_index_list)[i].c = tri.index_xyz[0];		// Read texture coordinates		(pro_index_list)[i].a_s = base_st[tri.index_st[2]].s;		(pro_index_list)[i].a_t = base_st[tri.index_st[2]].t;		(pro_index_list)[i].b_s = base_st[tri.index_st[1]].s;		(pro_index_list)[i].b_t = base_st[tri.index_st[1]].t;		(pro_index_list)[i].c_s = base_st[tri.index_st[0]].s;		(pro_index_list)[i].c_t = base_st[tri.index_st[0]].t;		max_tex_u = max(max_tex_u, base_st[tri.index_st[0]].s);		max_tex_u = max(max_tex_u, base_st[tri.index_st[1]].s);		max_tex_u = max(max_tex_u, base_st[tri.index_st[2]].s);		max_tex_v = max(max_tex_v, base_st[tri.index_st[0]].t);		max_tex_v = max(max_tex_v, base_st[tri.index_st[1]].t);		max_tex_v = max(max_tex_v, base_st[tri.index_st[2]].t);	}	// Recalculate texture coords	for(i = 0; i < modelHeader.num_tris; i++){		pro_index_list[i].a_s /= max_tex_u;		pro_index_list[i].b_s /= max_tex_u;		pro_index_list[i].c_s /= max_tex_u;		pro_index_list[i].a_t /= max_tex_v;		pro_index_list[i].b_t /= max_tex_v;		pro_index_list[i].c_t /= max_tex_v;	}	int j;	// Read vertex data of all animation frames	for(i = 0; i < modelHeader.num_frames; i++){		out = (daliasframe_t *)buffer;		fread(out, 1, modelHeader.framesize, model);		for(j = 0; j < modelHeader.num_xyz; j++){			(pro_frame_list)[i].vertex[j].x = out->verts[j].v[0] * out->scale[0] + out->translate[0];			(pro_frame_list)[i].vertex[j].y = out->verts[j].v[1] * out->scale[1] + out->translate[1];			(pro_frame_list)[i].vertex[j].z = out->verts[j].v[2] * out->scale[2] + out->translate[2];		}	}	fclose(model);	Init();	LogInfo("<li>Mesh %s created", Filename);	return S_OK;}// InitHRESULT D3D_mesh::Init(){	int i, j = 0;	// For each animation we use a SMesh	for(i = 0; i < GetNumFrames(); i++){		MODELVERTEX pVertex;		D3DXCOLOR LightColor(1.0f, 1.0f, 1.0f, 1.0f);		// Now we copy the vertex data to pro_data		for(j = 0; j < GetNumTriangles(); j++){			pVertex.m_vecPos.x = pro_frame_list[i].vertex[pro_index_list[j].a].x;			pVertex.m_vecPos.y = pro_frame_list[i].vertex[pro_index_list[j].a].z;			pVertex.m_vecPos.z = pro_frame_list[i].vertex[pro_index_list[j].a].y;			pVertex.m_vecTex.x = pro_index_list[j].a_s;			pVertex.m_vecTex.y = pro_index_list[j].a_t;			pVertex.m_dwDiffuse = LightColor;			pro_data[i].vertex.push_back(pVertex);			pVertex.m_vecPos.x = pro_frame_list[i].vertex[pro_index_list[j].b].x;			pVertex.m_vecPos.y = pro_frame_list[i].vertex[pro_index_list[j].b].z;			pVertex.m_vecPos.z = pro_frame_list[i].vertex[pro_index_list[j].b].y;			pVertex.m_vecTex.x = pro_index_list[j].b_s;			pVertex.m_vecTex.y = pro_index_list[j].b_t;			pVertex.m_dwDiffuse = LightColor;			pro_data[i].vertex.push_back(pVertex);			pVertex.m_vecPos.x = pro_frame_list[i].vertex[pro_index_list[j].c].x;			pVertex.m_vecPos.y = pro_frame_list[i].vertex[pro_index_list[j].c].z;			pVertex.m_vecPos.z = pro_frame_list[i].vertex[pro_index_list[j].c].y;			pVertex.m_vecTex.x = pro_index_list[j].c_s;			pVertex.m_vecTex.y = pro_index_list[j].c_t;			pVertex.m_dwDiffuse = LightColor;			pro_data[i].vertex.push_back(pVertex);		}	}		pro_lpGMain->GetDevice()->CreateVertexBuffer(sizeof(SMesh), D3DUSAGE_WRITEONLY, D3DFVF_MODELVERTEX, D3DPOOL_MANAGED, &pro_VB);	unsigned char *vb_verts;	pro_VB->Lock(0, 0, &vb_verts, 0);	memcpy(vb_verts, pro_data, sizeof(pro_data));	pro_VB->Unlock();	return S_OK;}  


And here is the render function:

  // Render :DHRESULT D3D_mesh::Render(int frame){	// Check for invalid frame number	if(frame >= GetNumFrames()-1)		return E_FAIL;	// Set vertex shader	pro_lpGMain->GetDevice()->SetVertexShader(D3DFVF_MODELVERTEX);	pro_lpGMain->GetDevice()->SetStreamSource(0, pro_VB, sizeof(SMesh));	pro_lpGMain->GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, GetNumTriangles());	return S_OK;}  


Note that I''ve edited the code so that it uses a vertex buffer. This does not work at all.. I''m probably loading it with the wrong thing or something. It was just an attempt and I''ve probably fried some memory in my graphics card, but oh well

Anyway.. Thanks for replying, and no I do not need any help AP, though thanks for asking. I didn''t recieve an e-mail in my hotmail account.. very odd eh?

Thanks again!

fuzztrek

¬_¬
Alright! I found some delphi code that I *think* loads the mesh into a vertex buffer. Unfortunatly I do not know exactly what''s going on, but I''m going to post the code and see if its what I think it is.

Render code:

  procedure TForm1.RenderFrame;var  _nxt : cardinal;begin  // Clear the back buffer to a black color.  D3DDEV8.Clear(0, NIL, D3DCLEAR_ZBUFFER or D3DCLEAR_TARGET,                $FF000080, 1.0, 0);  // Begin the scene.  D3DDEV8.BeginScene;  // Lighting ?  D3DDEV8.SetRenderState(D3DRS_LIGHTING, Ord(CheckBox1.Checked));  // Set texture (skin)  D3DDEV8.SetTexture(0, G_Text0);  // Render MD2  if G_Mesh0.ok then  begin    // animation    inc(G_Anim, G_FPS_FRAMETIME);    while (G_Anim > (G_TIM_FREQ div G_Speed)) do    begin      inc(G_Frame);      if G_Frame > G_LastFrame then G_Frame := G_FirstFrame;      dec(G_Anim, (G_TIM_FREQ div G_Speed));    end;    _nxt := G_Frame + 1;    if _nxt > G_LastFrame then _nxt := G_FirstFrame;    // Fill VertexBuffer with current frame data    MD2_SetFrameInt(G_Mesh0, G_Mesh0VB, G_Frame, _nxt,                    G_Anim / (G_TIM_FREQ div G_Speed));    // Render current frame    MD2_RenderCurrentFrame(G_Mesh0, G_Mesh0VB);  end;  // End the scene.  D3DDEV8.EndScene;  // Display scene.  D3DDEV8.Present(NIL, NIL, 0, NIL);end;  


"Change mesh" code:


  procedure TForm1.ChangeMesh(_fn: string);// Load MD2var  _i : longint;begin  // free previous mesh  MD2_Free(G_Mesh0);  MD2_FreeVB(G_Mesh0VB);  // Load new one  G_Mesh0 := MD2_Load(_fn);  if not G_Mesh0.ok then hHalt(Format(ERR01, [_fn]));  G_Mesh0VB := MD2_CreateVB(G_Mesh0);  if not G_Mesh0VB.ok then hHalt(ERR02);  // Retrieve animation data  G_Anims := MD2_GetAnimData(G_Mesh0);  ComboBox1.Clear;  for _i := 0 to G_Anims.count -1 do ComboBox1.Items.Add(g_Anims.anim[_i].name);  ComboBox1.ItemIndex := 0;  G_FirstFrame := 0;  G_LastFrame  := G_Mesh0.header.numFrames - 1;  G_Frame := G_FirstFrame;  // Reset camera  G_CDistance := C_DEFAULT_CAM_DISTANCE;  G_CHeight   := C_DEFAULT_CAM_HEIGHT;end;  


Hmm... unfortunatly this doesn''t actually have any loading code in it. It seems that you must update the vertex buffer every time you render, which means i''ll need a dynamic one right?

I can''t believe how many MD2 loaders there are for openGL, and hardly any for directX (ones that includes source). I mean, there are hardly any (skinned) x-file tutorials out there.

Sigh. Anyway.. maybe it will give people some ideas? I find it very interesting, but I might have to start learning about the MD2 file format more so I can figure out what to load into the vertex buffer and what not to.

Fuzztrek

¬_¬

This topic is closed to new replies.

Advertisement