#include "std.hpp" #include "md2rep.hpp" #include "md2norms.hpp" extern gxRuntime *gx_runtime; extern gxGraphics *gx_graphics; static Vector *normals = 0; static float tex_coords[2][2] = { {0,0},{0,0} }; #pragma pack( push,1 ) struct md2_header { int magic; int version; int skinWidth; int skinHeight; int frameSize; int numSkins; int numVertices; int numTexCoords; int numTriangles; int numGlCommands; int numFrames; int offsetSkins; int offsetTexCoords; int offsetTriangles; int offsetFrames; int offsetGlCommands; int offsetEnd; }; struct md2_uv { short u, v; }; struct md2_vert { unsigned char x, y, z, n; }; struct md2_tri { unsigned short verts[3], uvs[3]; }; #pragma pack( pop ) struct t_vert { unsigned short i, uv; bool operator<(const t_vert &t)const { return memcmp(&i, &t.i, 4) < 0; } }; struct t_tri { unsigned short verts[3]; }; MD2Rep::MD2Rep(const string &f) : mesh(0), n_verts(0), n_tris(0), n_frames(0) { filebuf in; md2_header header; if (!in.open(f.c_str(), ios_base::in | ios_base::binary)) return; if (in.sgetn((char*)&header, sizeof(header)) != sizeof(header)) return; if (header.magic != '2PDI' || header.version != 8) return; n_frames = header.numFrames; n_tris = header.numTriangles; //read in tex coords vector md2_uvs; md2_uvs.resize(header.numTexCoords); in.pubseekpos(header.offsetTexCoords); in.sgetn((char*)(&md2_uvs.begin()[0]), header.numTexCoords * sizeof(md2_uv)); //read in triangles vector md2_tris; md2_tris.resize(n_tris); in.pubseekpos(header.offsetTriangles); in.sgetn((char*)(&md2_tris.begin()[0]), n_tris * sizeof(md2_tri)); vector t_tris; vector t_verts; map t_map; int k; for (k = 0; k < n_tris; ++k) { t_tri tr; for (int j = 0; j < 3; ++j) { t_vert t; t.i = md2_tris[k].verts[j]; t.uv = md2_tris[k].uvs[j]; map::iterator it = t_map.find(t); if (it == t_map.end()) { //create new vert tr.verts[j] = t_map[t] = t_verts.size(); t_verts.push_back(t); //add UVs VertexUV uv; uv.u = md2_uvs[t.uv].u / (float)(header.skinWidth); uv.v = md2_uvs[t.uv].v / (float)(header.skinHeight); uvs.push_back(uv); } else { //reuse vert tr.verts[j] = it->second; } } t_tris.push_back(tr); } n_verts = t_verts.size(); frames.resize(n_frames); in.pubseekpos(header.offsetFrames); vector md2_verts; md2_verts.resize(header.numVertices); //read in frames for (k = 0; k < n_frames; ++k) { char t_buff[16]; Frame *fr = &frames[k]; in.sgetn((char*)&fr->scale, 12); in.sgetn((char*)&fr->trans, 12); in.sgetn(t_buff, 16); fr->scale = Vector(fr->scale.y, fr->scale.z, fr->scale.x); fr->trans = Vector(fr->trans.y, fr->trans.z, fr->trans.x); //read vertices in.sgetn((char*)&md2_verts.begin()[0], header.numVertices * sizeof(md2_vert)); fr->verts.resize(n_verts); for (int j = 0; j < n_verts; ++j) { Vertex *v = &fr->verts[j]; const t_vert &tv = t_verts[j]; const md2_vert &mv = md2_verts[tv.i]; v->x = mv.y; v->y = mv.z; v->z = mv.x; v->n = mv.n; box.update(Vector(v->x, v->y, v->z) * fr->scale + fr->trans); } } //create mesh and setup tris mesh = gx_graphics->createMesh(n_verts, n_tris, 0); mesh->lock(true); for (k = 0; k < n_tris; ++k) { const t_tri &t = t_tris[k]; mesh->setTriangle(k, t.verts[0], t.verts[2], t.verts[1]); } mesh->unlock(); //build normals if (!normals) { normals = (Vector*)md2norms; for (int k = 0; k < sizeof(md2norms) / 12; ++k) { normals[k] = Vector(normals[k].y, normals[k].z, normals[k].x); } } } MD2Rep::~MD2Rep() { if (mesh) gx_graphics->freeMesh(mesh); } /* void MD2Rep::render( Vert *v,int frame ){ const Frame &frame_a=frames[frame]; const Vertex *v_a=frame_a.verts.begin(); const Vector scale_a=frame_a.scale,trans_a=frame_a.trans; for( int k=0;kcoords=Vector( v_a->x*scale_a.x+trans_a.x,v_a->y*scale_a.y+trans_a.y,v_a->z*scale_a.z+trans_a.z ); v->normal=normals[ v_a->n ]; } } */ void MD2Rep::render(Vert *v, int frame, float time) { const Frame &frame_b = frames[frame]; const Vertex *v_b = (Vertex*)(&frame_b.verts.begin()[0]); const Vector scale_b = frame_b.scale, trans_b = frame_b.trans; for (int k = 0; k < n_verts; ++v, ++v_b, ++k) { const Vector t_b(v_b->x*scale_b.x + trans_b.x, v_b->y*scale_b.y + trans_b.y, v_b->z*scale_b.z + trans_b.z); const Vector &n_b = normals[v_b->n]; v->coords += (t_b - v->coords)*time; v->normal += (n_b - v->normal)*time; } } void MD2Rep::render(Vert *v, int render_a, int render_b, float render_t) { const Frame &frame_a = frames[render_a]; const Vector scale_a = frame_a.scale, trans_a = frame_a.trans; const Frame &frame_b = frames[render_b]; const Vector scale_b = frame_b.scale, trans_b = frame_b.trans; const Vertex *v_a = (Vertex*)(&frame_a.verts.begin()[0]); const Vertex *v_b = (Vertex*)(&frame_b.verts.begin()[0]); for (int k = 0; k < n_verts; ++v, ++v_a, ++v_b, ++k) { const Vector t_a(v_a->x*scale_a.x + trans_a.x, v_a->y*scale_a.y + trans_a.y, v_a->z*scale_a.z + trans_a.z); const Vector t_b(v_b->x*scale_b.x + trans_b.x, v_b->y*scale_b.y + trans_b.y, v_b->z*scale_b.z + trans_b.z); v->coords = (t_b - t_a)*render_t + t_a; const Vector &n_a = normals[v_a->n]; const Vector &n_b = normals[v_b->n]; v->normal = (n_b - n_a)*render_t + n_a; } } /* void MD2Rep::render( Vert *v,const Vert *v_a,const Vert *v_b,float render_t ){ for( int k=0;kcoords=(v_b->coords-v_a->coords)*render_t+v_a->coords; v->normal=(v_b->normal-v_a->normal)*render_t+v_a->normal; } } */ void MD2Rep::render(Model *model, int render_a, int render_b, float render_t) { const Frame &frame_a = frames[render_a]; const Vector scale_a = frame_a.scale, trans_a = frame_a.trans; const Frame &frame_b = frames[render_b]; const Vector scale_b = frame_b.scale, trans_b = frame_b.trans; const VertexUV *uv = (VertexUV*)&uvs.begin()[0]; const Vertex *v_a = (Vertex*)(&frame_a.verts.begin()[0]); const Vertex *v_b = (Vertex*)(&frame_b.verts.begin()[0]); mesh->lock(true); for (int k = 0; k < n_verts; ++uv, ++v_a, ++v_b, ++k) { const Vector t_a(v_a->x*scale_a.x + trans_a.x, v_a->y*scale_a.y + trans_a.y, v_a->z*scale_a.z + trans_a.z); const Vector t_b(v_b->x*scale_b.x + trans_b.x, v_b->y*scale_b.y + trans_b.y, v_b->z*scale_b.z + trans_b.z); const Vector t((t_b - t_a)*render_t + t_a); const Vector &n_a = normals[v_a->n]; const Vector &n_b = normals[v_b->n]; const Vector n((n_b - n_a)*render_t + n_a); tex_coords[0][0] = uv->u; tex_coords[0][1] = uv->v; mesh->setVertex(k, &t.x, &n.x, tex_coords); } mesh->unlock(); model->enqueue(mesh, 0, n_verts, 0, n_tris); } /* void MD2Rep::render( Model *model,const Vert *v_a,const Vert *v_b,float render_t ){ const VertexUV *uv=uvs.begin(); mesh->lock(); for( int k=0;kcoords-v_a->coords)*render_t+v_a->coords ); const Vector n( ( v_b->normal-v_a->normal)*render_t+v_a->normal ); tex_coords[0]=uv->u; tex_coords[1]=uv->v; mesh->setVertex( k,&t.x,&n.x,tex_coords ); } mesh->unlock(); model->enqueue( mesh,0,n_verts,0,n_tris ); } */ void MD2Rep::render(Model *model, const Vert *v_a, int render_b, float render_t) { const Frame &frame_b = frames[render_b]; const Vector scale_b = frame_b.scale, trans_b = frame_b.trans; const VertexUV *uv = (VertexUV*)&uvs.begin()[0]; const Vertex *v_b = (Vertex*)&frame_b.verts.begin()[0]; mesh->lock(true); for (int k = 0; k < n_verts; ++uv, ++v_a, ++v_b, ++k) { const Vector t_b(v_b->x*scale_b.x + trans_b.x, v_b->y*scale_b.y + trans_b.y, v_b->z*scale_b.z + trans_b.z); const Vector t((t_b - v_a->coords)*render_t + v_a->coords); const Vector &n_b = normals[v_b->n]; const Vector n((n_b - v_a->normal)*render_t + v_a->normal); tex_coords[0][0] = uv->u; tex_coords[0][1] = uv->v; mesh->setVertex(k, &t.x, &n.x, tex_coords); } mesh->unlock(); model->enqueue(mesh, 0, n_verts, 0, n_tris); }