Forum

Problems with MD3 loader

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Problems with MD3 loader

Postby drm_wayne » 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?

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

User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Problems with MD3 loader

Postby Baker » Thu Feb 26, 2015 4:59 pm

drm_wayne wrote:Its just crashing when it comes to dump the md3 normalfile.
1) What line is it crashing on?
2) Offtopic: Is this C or C++ ? I would assume C++. Was that your intent? i.e. "static_cast<md3header_t*>" instead of C "(md3header_t *)"
3) A raw write of a buffer to disk? Not really good practice, although maybe not related to your problem. And a different topic.
4) Ok ...

short* normalBuffer, ptr;
normalBuffer = (short*)malloc(sizeof(short)*size*5 + 1);
ptr = *normalBuffer; <---------------------- WHAT?

normalBuffer is a pointer to short. ptr is a pointer to short. I take it normalBuffer is supposed to be an array of shorts.

Any time you see *normalBuffer think of it as normalBuffer[0] or the first element of your array. Normal buffer holds shorts, right? A value of -32768 to + 32767

So ptr = *normalBuffer is going to assign ptr to memory address of -32768 to + 32767. Certainly invalid.

You need ptr=normalBuffer; for starters. You aren't trying to assign ptr to the value of the first member of normalBuffer (*normalBuffer or normalBuffer[0]), but the address of the first member of normalBuffer (which is simply ptr = normalBuffer or as I think of it in my head ... &normalBuffer[0] ).
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Problems with MD3 loader

Postby drm_wayne » Thu Feb 26, 2015 5:36 pm

hmm i see i tried to make something that is way above my poor coding skills..
The original code is from Qrack, and it takes too long to load MD3 models when its on to calculate the normals
(In time, you can get married, buy a house, get 2 children and choose a grave stone.) :lol:

I wodner if theres an faster way to load MD3 models?
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Problems with MD3 loader

Postby r00k » Tue Mar 03, 2015 5:56 am

The md3 loader is legacy from JoeQuake, I think it was just really for demos.
It does work for me but i really never use it.
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Re: Problems with MD3 loader

Postby dimman » Tue Mar 03, 2015 11:57 am

Even if its not pretty, ptr is _not_ a pointer to short but a regular short.

'short *a, b'. Only a is a pointer to short, b is just a short.
dimman
 
Posts: 7
Joined: Wed Jan 29, 2014 1:58 pm


Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 2 guests