Sign in to follow this  
Canvas

C++ OpenGL md3 loader help

Recommended Posts

Hey guys, ive been asked to code a MD3 loader in C++ /openGL, I cant seem to find that much information on actually coding a MD3 loader, I have some basic code at the moment which i "feel" is correct,

Here is the header file

[CODE]
#include <GL/glew.h>
#include <GL/gl.h>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vectormath/scalar/cpp/vectormath_aos.h>
#include "GameAsset.h"
using namespace std;
using namespace Vectormath::Aos;
#ifndef MD3ASSET_H_
#define MD3ASSET_H_
class Md3Asset : public GameAsset{
public:
Md3Asset();
Md3Asset(const string &filename);
virtual ~Md3Asset();
virtual void update();
private:
void import_md3_asset(const string &filename);
struct md3_header
{
int ident;
int version;
char name[64];
int flags;
int num_frames;
int num_tags;
int num_surfaces;
int num_skins;
int ofs_frames;
int ofs_tags;
int ofs_surfaces;
int ofs_eof;
struct md3_frame
{
Vector3 min_bounds;
Vector3 max_bounds;
Vector3 local_origin;
float radius;
char name[16];
};
struct md3_tag
{
char name[64];
Vector3 origin;
Vector3 axis[3];
};
struct md3_surface
{
int ident;
char name[64];
int flags;
int num_frames;
int num_shaders;
int num_verts;
int num_triangles;
int ofs_triangles;
int ofs_shaders;
int ofs_ST;
int ofs_xyzNormal;
int ofs_end;
struct md3_shader
{
char name[64];
int shader_index;
};
struct md3_triangle
{
int indexes[3];
};
struct md3_st
{
float st[3];
};
struct md3_vertex
{
short coord[3];
short normal;
};
};
};
//Not sure about this
typedef float vec3[3];
//Not sure about this
md3_header::md3_surface::md3_triangle * triangles;
md3_header::md3_surface * surfaces;
};
#endif /* MD3ASSET_H_ */
[/CODE]

And here is the C++ file so far
[CODE]
#include "Md3Asset.h"
Md3Asset::Md3Asset(const string &filename) {
import_md3_asset(filename);
// make the objects to display
if(0 == make_resources()) {
cout << "Can't make the required OpenGL resources for Md3Asset." << endl;
// TODO: exit nicely here
}
}
Md3Asset::Md3Asset(){}
Md3Asset::~Md3Asset() {
// TODO: clean up
}
void Md3Asset::update() {
}
void Md3Asset::import_md3_asset(const string &filename) {
ifstream md3file;
md3file.open(filename.c_str(), ios::in|ios::binary);
// C stuff
md3_header * md3header = (struct md3_header *)
malloc(sizeof(struct md3_header));
md3file.read((char*) md3header, sizeof(struct md3_header));
if((md3header->ident != 860898377)||(md3header->version !=15))
{
cout << md3header->version << endl;
cout << md3header->ident << endl;
cerr<<"Bad Version or identifier"<<endl;
}
// Get the triange data
this->triangles = (md3_header::md3_surface::md3_triangle*)
calloc(this->surfaces->num_triangles, sizeof(struct md3_header::md3_surface));
cout<<triangles<<endl;
}
[/CODE]

Im basing my code on a old MD2 loader using calloc and malloc, I have read i could use a vector instead... If anyone has any source code on how to load a MD3 in C++ that would be amazing. I have read the file format specs and got the header but there isn't really any information on actually coding the C++ file.

Cheers for the help
Canvas

Share this post


Link to post
Share on other sites
You could have a look at the Quake 3 source code, particularly the tr_model.c file here: https://github.com/id-Software/Quake-III-Arena/blob/master/code/renderer/tr_model.c

Yes, it's C instead of nice modern C++, and yes, there will be hacky game code here. I'm not suggesting that you emulate it, just that you use it as the authoritative source for an MD3 loader.

Share this post


Link to post
Share on other sites
mhagain I have found this inside the .c file

[CODE]
static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) {
int i, j;
md3Header_t *pinmodel;
md3Frame_t *frame;
md3Surface_t *surf;
md3Shader_t *shader;
md3Triangle_t *tri;
md3St_t *st;
md3XyzNormal_t *xyz;
md3Tag_t *tag;
int version;
int size;
pinmodel = (md3Header_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != MD3_VERSION) {
ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n",
mod_name, version, MD3_VERSION);
return qfalse;
}
mod->type = MOD_MESH;
size = LittleLong(pinmodel->ofsEnd);
mod->dataSize += size;
mod->md3[lod] = ri.Hunk_Alloc( size, h_low );
Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) );
LL(mod->md3[lod]->ident);
LL(mod->md3[lod]->version);
LL(mod->md3[lod]->numFrames);
LL(mod->md3[lod]->numTags);
LL(mod->md3[lod]->numSurfaces);
LL(mod->md3[lod]->ofsFrames);
LL(mod->md3[lod]->ofsTags);
LL(mod->md3[lod]->ofsSurfaces);
LL(mod->md3[lod]->ofsEnd);
if ( mod->md3[lod]->numFrames < 1 ) {
ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name );
return qfalse;
}
// swap all the frames
frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames );
for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) {
frame->radius = LittleFloat( frame->radius );
for ( j = 0 ; j < 3 ; j++ ) {
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
}
}
// swap all the tags
tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags );
for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) {
for ( j = 0 ; j < 3 ; j++ ) {
tag->origin[j] = LittleFloat( tag->origin[j] );
tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
}
}
// swap all the surfaces
surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces );
for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) {
LL(surf->ident);
LL(surf->flags);
LL(surf->numFrames);
LL(surf->numShaders);
LL(surf->numTriangles);
LL(surf->ofsTriangles);
LL(surf->numVerts);
LL(surf->ofsShaders);
LL(surf->ofsSt);
LL(surf->ofsXyzNormals);
LL(surf->ofsEnd);
if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
}
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
}
// change to surface identifier
surf->ident = SF_MD3;
// lowercase the surface name so skin compares are faster
Q_strlwr( surf->name );
// strip off a trailing _1 or _2
// this is a crutch for q3data being a mess
j = strlen( surf->name );
if ( j > 2 && surf->name[j-2] == '_' ) {
surf->name[j-2] = 0;
}
// register the shaders
shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
shader_t *sh;
sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue );
if ( sh->defaultShader ) {
shader->shaderIndex = 0;
} else {
shader->shaderIndex = sh->index;
}
}
// swap all the triangles
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
LL(tri->indexes[0]);
LL(tri->indexes[1]);
LL(tri->indexes[2]);
}
// swap all the ST
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
st->st[0] = LittleFloat( st->st[0] );
st->st[1] = LittleFloat( st->st[1] );
}
// swap all the XyzNormals
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
{
xyz->xyz[0] = LittleShort( xyz->xyz[0] );
xyz->xyz[1] = LittleShort( xyz->xyz[1] );
xyz->xyz[2] = LittleShort( xyz->xyz[2] );
xyz->normal = LittleShort( xyz->normal );
}

// find the next surface
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
}
return qtrue;
}
[/CODE]

is that the code im looking for?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this