Problems with MD3 loader
Posted: Thu Feb 26, 2015 3:15 pm
I have some trouble with my MD3 loader (based on Qracks MD3 loader)..
I added a code to dump the normals to a external file (because they take kinda long to load), but it looks like theres something wrong.
Its just crashing when it comes to dump the md3 normalfile.
Can anybody see whats wrong?
I added a code to dump the normals to a external file (because they take kinda long to load), but it looks like theres something wrong.
Its just crashing when it comes to dump the md3 normalfile.
Can anybody see whats wrong?
Code: Select all
/*
=================
Mod_LoadQ3Model
=================
*/
void Mod_LoadQ3AliasModel (model_t *mod, void *buffer)
{
int i, j, size, base, texture_flag, version, gl_texnum;
char basename[MAX_QPATH];
float radiusmax;
md3header_t *header;
md3frame_t *frame;
md3tag_t *tag;
md3surface_t *surf;
md3shader_t *shader;
md3triangle_t *tris;
md3tc_t *tc;
md3vert_t *vert;
char md3name[128];
COM_StripExtension(mod->name, &md3name[0]);
if (!strcmp (md3name, "progs/g_shot") ||
!strcmp (md3name, "progs/g_nail") ||
!strcmp (md3name, "progs/g_nail2") ||
!strcmp (md3name, "progs/g_rock") ||
!strcmp (md3name, "progs/g_rock2") ||
!strcmp (md3name, "progs/g_light") ||
!strcmp (md3name, "progs/armor") ||
!strcmp (md3name, "progs/backpack") ||
!strcmp (md3name, "progs/w_g_key") ||
!strcmp (md3name, "progs/w_s_key") ||
!strcmp (md3name, "progs/m_g_key") ||
!strcmp (md3name, "progs/m_s_key") ||
!strcmp (md3name, "progs/b_g_key") ||
!strcmp (md3name, "progs/b_s_key") ||
!strcmp (md3name, "progs/quaddama") ||
!strcmp (md3name, "progs/invisibl") ||
!strcmp (md3name, "progs/invulner") ||
!strcmp (md3name, "progs/jetpack") ||
!strcmp (md3name, "progs/cube") ||
!strcmp (md3name, "progs/suit") ||
!strcmp (md3name, "progs/boots") ||
!strcmp (md3name, "progs/end1") ||
!strcmp (md3name, "progs/end2") ||
!strcmp (md3name, "progs/end3") ||
!strcmp (md3name, "progs/end4")) {
mod->flags |= EF_ROTATE;
}
else if (!strcmp (md3name, "progs/missile"))
{
mod->flags |= EF_ROCKET;
}
else if (!strcmp (md3name, "progs/gib1") || //EF_GIB
!strcmp (md3name, "progs/gib2") ||
!strcmp (md3name, "progs/gib3") ||
!strcmp (md3name, "progs/h_player") ||
!strcmp (md3name, "progs/h_dog") ||
!strcmp (md3name, "progs/h_mega") ||
!strcmp (md3name, "progs/h_guard") ||
!strcmp (md3name, "progs/h_wizard") ||
!strcmp (md3name, "progs/h_knight") ||
!strcmp (md3name, "progs/h_hellkn") ||
!strcmp (md3name, "progs/h_zombie") ||
!strcmp (md3name, "progs/h_shams") ||
!strcmp (md3name, "progs/h_shal") ||
!strcmp (md3name, "progs/h_ogre") ||
!strcmp (md3name, "progs/armor") ||
!strcmp (md3name, "progs/h_demon")) {
mod->flags |= EF_GIB;
}
else if (!strcmp (md3name, "progs/grenade"))
{
mod->flags |= EF_GRENADE;
}
else if (!strcmp (md3name, "progs/w_spike"))
{
mod->flags |= EF_TRACER;
}
else if (!strcmp (md3name, "progs/k_spike"))
{
mod->flags |= EF_TRACER2;
}
else if (!strcmp (md3name, "progs/v_spike"))
{
mod->flags |= EF_TRACER3;
}
else if (!strcmp (md3name, "progs/zom_gib"))
{
mod->flags |= EF_ZOMGIB;
}
else if (!strcmp(md3name, "progs/v_shot") ||
!strcmp(md3name, "progs/v_shot2") ||
!strcmp(md3name, "progs/v_nail") ||
!strcmp(md3name, "progs/v_nail2") ||
!strcmp(md3name, "progs/v_rock") ||
!strcmp(md3name, "progs/v_rock2"))
{
mod->modhint = MOD_WEAPON;
}
else if (!strcmp (md3name, "progs/lavaball"))
{
mod->modhint = MOD_LAVABALL;
}
header = (md3header_t *)buffer;
version = LittleLong (header->version);
if (version != MD3_VERSION)
Sys_Error ("Mod_LoadQ3Model: %s has wrong version number (%i should be %i)", md3name, version, MD3_VERSION);
Con_Printf ("Loading md3 model...%s \n", md3name);
// endian-adjust all data
header->numframes = LittleLong (header->numframes);
if (header->numframes < 1)
Sys_Error ("Mod_LoadQ3Model: model %s has no frames", md3name);
else if (header->numframes > MAXMD3FRAMES)
Sys_Error ("Mod_LoadQ3Model: model %s has too many frames", md3name);
header->numtags = LittleLong (header->numtags);
if (header->numtags > MAXMD3TAGS)
Sys_Error ("Mod_LoadQ3Model: model %s has too many tags", md3name);
header->numsurfs = LittleLong (header->numsurfs);
if (header->numsurfs < 1)
Sys_Error ("Mod_LoadQ3Model: model %s has no surfaces", md3name);
else if (header->numsurfs > MAXMD3SURFS)
Sys_Error ("Mod_LoadQ3Model: model %s has too many surfaces", md3name);
header->numskins = LittleLong (header->numskins);
header->ofsframes = LittleLong (header->ofsframes);
header->ofstags = LittleLong (header->ofstags);
header->ofssurfs = LittleLong (header->ofssurfs);
header->ofsend = LittleLong (header->ofsend);
// swap all the frames
frame = (md3frame_t *)((byte *)header + header->ofsframes);
for (i=0 ; i<header->numframes ; i++)
{
frame[i].radius = LittleFloat (frame->radius);
for (j=0 ; j<3 ; j++)
{
frame[i].mins[j] = LittleFloat (frame[i].mins[j]);
frame[i].maxs[j] = LittleFloat (frame[i].maxs[j]);
frame[i].pos[j] = LittleFloat (frame[i].pos[j]);
}
}
// swap all the tags
tag = (md3tag_t *)((byte *)header + header->ofstags);
for (i=0 ; i<header->numtags ; i++)
{
for (j=0 ; j<3 ; j++)
{
tag[i].pos[j] = LittleFloat (tag[i].pos[j]);
tag[i].rot[0][j] = LittleFloat (tag[i].rot[0][j]);
tag[i].rot[1][j] = LittleFloat (tag[i].rot[1][j]);
tag[i].rot[2][j] = LittleFloat (tag[i].rot[2][j]);
}
}
// swap all the surfaces
surf = (md3surface_t *)((byte *)header + header->ofssurfs);
for (i=0 ; i<header->numsurfs ; i++)
{
surf->ident = LittleLong (surf->ident);
surf->flags = LittleLong (surf->flags);
surf->numframes = LittleLong (surf->numframes);
if (surf->numframes != header->numframes)
Sys_Error ("Mod_LoadQ3Model: number of frames don't match in %s", md3name);
surf->numshaders = LittleLong (surf->numshaders);
if (surf->numshaders <= 0)
Sys_Error ("Mod_LoadQ3Model: model %s has no shaders", md3name);
else if (surf->numshaders > MAXMD3SHADERS)
Sys_Error ("Mod_LoadQ3Model: model %s has too many shaders", md3name);
surf->numverts = LittleLong (surf->numverts);
if (surf->numverts <= 0)
Sys_Error ("Mod_LoadQ3Model: model %s has no vertices", md3name);
else if (surf->numverts > MAXMD3VERTS)
Sys_Error ("Mod_LoadQ3Model: model %s has too many vertices", md3name);
surf->numtris = LittleLong (surf->numtris);
if (surf->numtris <= 0)
Sys_Error ("Mod_LoadQ3Model: model %s has no triangles", md3name);
else if (surf->numtris > MAXMD3TRIS)
Sys_Error ("Mod_LoadQ3Model: model %s has too many triangles", md3name);
surf->ofstris = LittleLong (surf->ofstris);
surf->ofsshaders = LittleLong (surf->ofsshaders);
surf->ofstc = LittleLong (surf->ofstc);
surf->ofsverts = LittleLong (surf->ofsverts);
surf->ofsend = LittleLong (surf->ofsend);
// swap all the shaders
shader = (md3shader_t *)((byte *)surf + surf->ofsshaders);
for (j=0 ; j<surf->numshaders ; j++)
shader[j].index = LittleLong (shader[j].index);
// swap all the triangles
tris = (md3triangle_t *)((byte *)surf + surf->ofstris);
for (j=0 ; j<surf->numtris ; j++)
{
tris[j].indexes[0] = LittleLong (tris[j].indexes[0]);
tris[j].indexes[1] = LittleLong (tris[j].indexes[1]);
tris[j].indexes[2] = LittleLong (tris[j].indexes[2]);
}
// swap all the texture coords
tc = (md3tc_t *)((byte *)surf + surf->ofstc);
for (j=0 ; j<surf->numverts ; j++)
{
tc[j].s = LittleFloat (tc[j].s);
tc[j].t = LittleFloat (tc[j].t);
}
// swap all the vertices
vert = (md3vert_t *)((byte *)surf + surf->ofsverts);
for (j=0 ; j < surf->numverts * surf->numframes ; j++)
{
vert[j].vec[0] = LittleShort (vert[j].vec[0]);
vert[j].vec[1] = LittleShort (vert[j].vec[1]);
vert[j].vec[2] = LittleShort (vert[j].vec[2]);
vert[j].normal = LittleShort (vert[j].normal);
}
// find the next surface
surf = (md3surface_t *)((byte *)surf + surf->ofsend);
}
// allocate extra size for structures different in memory
surf = (md3surface_t *)((byte *)header + header->ofssurfs);
for (size = 0, i = 0 ; i < header->numsurfs ; i++)
{
size += surf->numshaders * sizeof(md3shader_mem_t); // shader containing texnum
size += surf->numverts * surf->numframes * sizeof(md3vert_mem_t); // floating point vertices
surf = (md3surface_t *)((byte *)surf + surf->ofsend);
}
header = static_cast<md3header_t*>(Cache_Alloc (&mod->cache, com_filesize + size, loadname));
if (!mod->cache.data)
return;
memcpy (header, buffer, com_filesize);
base = com_filesize;
mod->type = mod_md3;
mod->numframes = header->numframes;
md3bboxmins[0] = md3bboxmins[1] = md3bboxmins[2] = 99999;
md3bboxmaxs[0] = md3bboxmaxs[1] = md3bboxmaxs[2] = -99999;
radiusmax = 0;
frame = (md3frame_t *)((byte *)header + header->ofsframes);
for (i=0 ; i<header->numframes ; i++)
{
for (j=0 ; j<3 ; j++)
{
md3bboxmins[j] = min(md3bboxmins[j], frame[i].mins[j]);
md3bboxmaxs[j] = max(md3bboxmaxs[j], frame[i].maxs[j]);
}
radiusmax = max(radiusmax, frame[i].radius);
}
VectorCopy (md3bboxmins, mod->mins);
VectorCopy (md3bboxmaxs, mod->maxs);
mod->radius = radiusmax;
// load the skins
Mod_LoadAllQ3Skins (mod->name, header);
// load the animation frames if loading the player model
if (!strcmp(mod->name, "progs/player/lower.md3"))
Mod_LoadQ3Animation ();
surf = (md3surface_t *)((byte *)header + header->ofssurfs);
for (i=0 ; i<header->numsurfs; i++)
{
shader = (md3shader_t *)((byte *)surf + surf->ofsshaders);
surf->ofsshaders = base;
size = surf->numshaders;
for (j=0 ; j<size ; j++)
{
md3shader_mem_t *memshader = (md3shader_mem_t *)((byte *)header + surf->ofsshaders);
Q_strncpyz (memshader[j].name, shader->name, sizeof(memshader[j].name));
memshader[j].index = shader->index;
COM_StripExtension (COM_SkipPath(shader->name), basename);
gl_texnum = 0;
texture_flag = 0;
Mod_LoadQ3ModelTexture (basename, texture_flag, &gl_texnum);
memshader[j].gl_texnum = gl_texnum;
shader++;
}
base += size * sizeof(md3shader_mem_t);
vert = (md3vert_t *)((byte *)surf + surf->ofsverts);
surf->ofsverts = base;
size = surf->numverts * surf->numframes;
//It takes a fucking _YEAR_ to calculate normals.
//We'll store them in a cache file for future use if it's not already available.
FILE* md3normalfile;
md3normalfile = fopen(va("%s_%d.nrm", md3name, i), "rb");
Con_DPrintf ("Looking for MD3 normalfile\n");
if (!md3normalfile)
{
//Output 'em.
md3normalfile = fopen(va("%s_%d.nrm", md3name, i), "wb");
short* normalBuffer, ptr;
normalBuffer = (short*)malloc(sizeof(short)*size*5 + 1);
ptr = *normalBuffer;
for (j=0 ; j<size ; j++)
{
float lat, lng;
vec3_t ang;
md3vert_mem_t *vertexes = (md3vert_mem_t *)((byte *)header + surf->ofsverts);
vertexes[j].oldnormal = vert->normal;
vertexes[j].vec[0] = (float)vert->vec[0] * MD3_XYZ_SCALE;
vertexes[j].vec[1] = (float)vert->vec[1] * MD3_XYZ_SCALE;
vertexes[j].vec[2] = (float)vert->vec[2] * MD3_XYZ_SCALE;
lat = ((vert->normal >> 8) & 0xff) * M_PI / 128.0f;
lng = (vert->normal & 0xff) * M_PI / 128.0f;
vertexes[j].normal[0] = cos(lat) * sin(lng);
vertexes[j].normal[1] = sin(lat) * sin(lng);
vertexes[j].normal[2] = cos(lng);
vectoangles (vertexes[j].normal, ang);
vertexes[j].anorm_pitch = ang[0] * 256 / 360;
vertexes[j].anorm_yaw = ang[1] * 256 / 360;
ptr = (short) vertexes[j].normal[0];
ptr++;
ptr = (short) vertexes[j].normal[1];
ptr++;
ptr = (short) vertexes[j].normal[2];
ptr++;
ptr = (short) vertexes[j].anorm_pitch;
ptr++;
ptr = (short) vertexes[j].anorm_yaw;
ptr++;
vert++;
}
fwrite(normalBuffer, 2, size*5, md3normalfile);
Con_DPrintf ("Writing MD3 Normal File.\n");
fclose(md3normalfile);
free(normalBuffer);
ptr = NULL;
}
base += size * sizeof(md3vert_mem_t);
surf = (md3surface_t *)((byte *)surf + surf->ofsend);
}
}