Jump to content
  • Advertisement


This topic is now archived and is closed to further replies.


Loading an MD2 without DrawPrimitiveUP

This topic is 5862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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! ¬_¬

Share this post

Link to post
Share on other sites

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:

Stay Casual,

Drunken Hyena

Share this post

Link to post
Share on other sites
Hi there!

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


Share this post

Link to post
Share on other sites
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

Share this post

Link to post
Share on other sites
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.


Share this post

Link to post
Share on other sites
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:


Share this post

Link to post
Share on other sites
Guest Anonymous Poster
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...

Share this post

Link to post
Share on other sites

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 structs

struct 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 below

struct 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 D3D

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)


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 mesh

HRESULT 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];


LogInfo("<li>Mesh %s created", Filename);
return S_OK;

// Init

HRESULT D3D_mesh::Init(){

int i, j = 0;

// For each animation we use a SMesh

for(i = 0; i < GetNumFrames(); i++){

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;

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;

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_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));

return S_OK;

And here is the render function:

// Render :D

HRESULT D3D_mesh::Render(int frame){

// Check for invalid frame number

if(frame >= GetNumFrames()-1)
return E_FAIL;

// Set vertex shader

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!



Share this post

Link to post
Share on other sites
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;

_nxt : cardinal;

// Clear the back buffer to a black color.

$FF000080, 1.0, 0);

// Begin the scene.


// Lighting ?

D3DDEV8.SetRenderState(D3DRS_LIGHTING, Ord(CheckBox1.Checked));

// Set texture (skin)

D3DDEV8.SetTexture(0, G_Text0);

// Render MD2

if G_Mesh0.ok then
// animation

while (G_Anim > (G_TIM_FREQ div G_Speed)) do
if G_Frame > G_LastFrame then G_Frame := G_FirstFrame;
dec(G_Anim, (G_TIM_FREQ div G_Speed));

_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 the scene.


// Display scene.

D3DDEV8.Present(NIL, NIL, 0, NIL);

"Change mesh" code:

procedure TForm1.ChangeMesh(_fn: string);

// Load MD2

_i : longint;

// free previous mesh


// 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);
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


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.



Share this post

Link to post
Share on other sites

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!