X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=tools%2Fquake2%2Fqdata_heretic2%2Fmodels.c;h=5ae30a15f6bf6530f8dd5936416c3be5b2b312e1;hp=d594cafe135589d1ac7a208aea89319a2461d794;hb=99980506540d9546dad31223a6eadf126ba68121;hpb=287cde2548fe80cf16fb523fc3993d3dd2f40500;ds=sidebyside diff --git a/tools/quake2/qdata_heretic2/models.c b/tools/quake2/qdata_heretic2/models.c index d594cafe..5ae30a15 100644 --- a/tools/quake2/qdata_heretic2/models.c +++ b/tools/quake2/qdata_heretic2/models.c @@ -1,2050 +1,2050 @@ -/* -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. - -This file is part of GtkRadiant. - -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - - -#include "qdata.h" -#include -#include "jointed.h" -#include "fmodel.h" - -//================================================================= - -typedef struct -{ - int numnormals; - vec3_t normalsum; -} vertexnormals_t; - -typedef struct -{ - vec3_t v; - int lightnormalindex; -} trivert_t; - -typedef struct -{ - vec3_t mins, maxs; - char name[16]; - trivert_t v[MAX_VERTS]; - QDataJoint_t joints[NUM_CLUSTERS]; // ,this -} frame_t; - -// ,and all of this should get out of here, need to use new stuff in fmodels instead - -typedef struct IntListNode_s -{ - int data; - struct IntListNode_s *next; -} IntListNode_t; // gaak - -typedef struct -{ - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this -} PartialAliasFrame_t; - -int jointed; -int clustered; - -int *clusters[NUM_CLUSTERS]; -IntListNode_t *vertLists[NUM_CLUSTERS]; -int num_verts[NUM_CLUSTERS + 1]; -int new_num_verts[NUM_CLUSTERS + 1]; - -// end that - -//================================================================ - -frame_t g_frames[MAX_FRAMES]; -//frame_t *g_frames; - -static dmdl_t model; - - -float scale_up; // set by $scale -vec3_t adjust; // set by $origin -int g_fixedwidth, g_fixedheight; // set by $skinsize - - -// -// base frame info -// -dstvert_t base_st[MAX_VERTS]; -dtriangle_t triangles[MAX_TRIANGLES]; - -static int triangle_st[MAX_TRIANGLES][3][2]; - -// the command list holds counts, s/t values, and xyz indexes -// that are valid for every frame -int commands[16384]; -int numcommands; -int numglverts; -int used[MAX_TRIANGLES]; - -char g_skins[MAX_MD2SKINS][64]; - -char cdarchive[1024]; -char cdpartial[1024]; -char cddir[1024]; - -char modelname[64]; // empty unless $modelname issued (players) - -extern char *g_outputDir; - -#define NUMVERTEXNORMALS 162 - -float avertexnormals[NUMVERTEXNORMALS][3] = -{ - #include "anorms.h" -}; - -unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768]; - -FILE *headerouthandle = NULL; - -//============================================================== - -/* -=============== -ClearModel -=============== -*/ -static void ClearModel (void) -{ - memset (&model, 0, sizeof(model)); - - modelname[0] = 0; - jointed = NOT_JOINTED; - clustered = 0; - scale_up = 1.0; - VectorCopy (vec3_origin, adjust); - g_fixedwidth = g_fixedheight = 0; - g_skipmodel = false; -} - - -void H_printf(char *fmt, ...) -{ - va_list argptr; - char name[1024]; - - if (!headerouthandle) - { - sprintf (name, "%s/tris.h", cddir); - headerouthandle = SafeOpenWrite (name); - fprintf(headerouthandle, "// %s\n\n", cddir); - fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n"); - } - - va_start (argptr, fmt); - vfprintf (headerouthandle, fmt, argptr); - va_end (argptr); -} - -#if 1 -/* -============ -WriteModelFile -============ -*/ -void WriteCommonModelFile (FILE *modelouthandle, PartialAliasFrame_t *outFrames) -{ - int i; - dmdl_t modeltemp; - int j, k; - frame_t *in; - daliasframe_t *out; - byte buffer[MAX_VERTS*4+128]; - float v; - int c_on, c_off; - - model.version = ALIAS_VERSION; - model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz]; - model.num_glcmds = numcommands; - model.ofs_skins = sizeof(dmdl_t); - model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; - model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t); - model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t); - model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize; - model.ofs_end = model.ofs_glcmds + model.num_glcmds*sizeof(int); - // - // write out the model header - // - for (i=0 ; iname, in->name); - for (j=0 ; j<3 ; j++) - { - out->scale[j] = (in->maxs[j] - in->mins[j])/255; - out->translate[j] = in->mins[j]; - - if(outFrames) - { - outFrames[i].scale[j] = out->scale[j]; - outFrames[i].translate[j] = out->translate[j]; - } - } - - for (j=0 ; jverts[j].lightnormalindex = in->v[j].lightnormalindex; - - for (k=0 ; k<3 ; k++) - { - // scale to byte values & min/max check - v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if (v > 255.0) - v = 255.0; - if (v < 0) - v = 0; - out->verts[j].v[k] = v; - } - } - - for (j=0 ; j<3 ; j++) - { - out->scale[j] = LittleFloat (out->scale[j]); - out->translate[j] = LittleFloat (out->translate[j]); - } - - SafeWrite (modelouthandle, out, model.framesize); - } - - // - // write out glcmds - // - SafeWrite (modelouthandle, commands, numcommands*4); -} - -/* -============ -WriteModelFile -============ -*/ -void WriteModelFile (FILE *modelouthandle) -{ - model.ident = IDALIASHEADER; - - WriteCommonModelFile(modelouthandle, NULL); -} - -/* -============ -WriteJointedModelFile -============ -*/ -void WriteJointedModelFile (FILE *modelouthandle) -{ - int i; - int j, k; - frame_t *in; - float v; - IntListNode_t *current, *toFree; - PartialAliasFrame_t outFrames[MAX_FRAMES]; - - model.ident = IDJOINTEDALIASHEADER; - - WriteCommonModelFile(modelouthandle, outFrames); - - // Skeletal Type - SafeWrite(modelouthandle, &jointed, sizeof(int)); - - // number of joints - SafeWrite(modelouthandle, &numJointsForSkeleton[jointed], sizeof(int)); - - // number of verts in each cluster - SafeWrite(modelouthandle, &new_num_verts[1], sizeof(int)*numJointsForSkeleton[jointed]); - - // cluster verts - for(i = 0; i < new_num_verts[0]; ++i) - { - current = vertLists[i]; - while(current) - { - SafeWrite (modelouthandle, ¤t->data, sizeof(int)); - toFree = current; - current = current->next; - free(toFree); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base - } - } - - for (i=0 ; ijoints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if (v > 255.0) - { - v = 255.0; - } - - if (v < 0) - { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite (modelouthandle, &v, sizeof(float)); - } - - for (k=0 ; k<3 ; k++) - { - v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if (v > 255.0) - { - v = 255.0; - } - - if (v < 0) - { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite (modelouthandle, &v, sizeof(float)); - } - - for (k=0 ; k<3 ; k++) - { - v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if (v > 255.0) - { - v = 255.0; - } - - if (v < 0) - { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite (modelouthandle, &v, sizeof(float)); - } - } - } -} -#else -/* -============ -WriteModelFile -============ -*/ -static void WriteModelFile (FILE *modelouthandle) -{ - int i; - dmdl_t modeltemp; - int j, k; - frame_t *in; - daliasframe_t *out; - byte buffer[MAX_VERTS*4+128]; - float v; - int c_on, c_off; - - model.ident = IDALIASHEADER; - model.version = ALIAS_VERSION; - model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz]; - model.num_glcmds = numcommands; - model.ofs_skins = sizeof(dmdl_t); - model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; - model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t); - model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t); - model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize; - model.ofs_end = model.ofs_glcmds + model.num_glcmds*4; - - // - // write out the model header - // - for (i=0 ; iname, in->name); - for (j=0 ; j<3 ; j++) - { - out->scale[j] = (in->maxs[j] - in->mins[j])/255; - out->translate[j] = in->mins[j]; - } - - for (j=0 ; jverts[j].lightnormalindex = in->v[j].lightnormalindex; - - for (k=0 ; k<3 ; k++) - { - // scale to byte values & min/max check - v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if (v > 255.0) - v = 255.0; - if (v < 0) - v = 0; - out->verts[j].v[k] = v; - } - } - - for (j=0 ; j<3 ; j++) - { - out->scale[j] = LittleFloat (out->scale[j]); - out->translate[j] = LittleFloat (out->translate[j]); - } - - SafeWrite (modelouthandle, out, model.framesize); - } - - // - // write out glcmds - // - SafeWrite (modelouthandle, commands, numcommands*4); -} -#endif - -/* -=============== -FinishModel -=============== -*/ -void FinishModel (void) -{ - FILE *modelouthandle; - int i; - char name[1024]; - - if (!model.num_frames) - return; - -// -// copy to release directory tree if doing a release build -// - if (g_release) - { - if (modelname[0]) - sprintf (name, "%s", modelname); - else - sprintf (name, "%s/tris.md2", cdpartial); - ReleaseFile (name); - - for (i=0 ; iindex_xyz[(startv)%3]; - strip_xyz[1] = last->index_xyz[(startv+1)%3]; - strip_xyz[2] = last->index_xyz[(startv+2)%3]; - strip_st[0] = last->index_st[(startv)%3]; - strip_st[1] = last->index_st[(startv+1)%3]; - strip_st[2] = last->index_st[(startv+2)%3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[(startv+2)%3]; - st1 = last->index_st[(startv+2)%3]; - m2 = last->index_xyz[(startv+1)%3]; - st2 = last->index_st[(startv+1)%3]; - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] - ; jindex_xyz[k] != m1) - continue; - if (check->index_st[k] != st1) - continue; - if (check->index_xyz[ (k+1)%3 ] != m2) - continue; - if (check->index_st[ (k+1)%3 ] != st2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - if (stripcount & 1) - { - m2 = check->index_xyz[ (k+2)%3 ]; - st2 = check->index_st[ (k+2)%3 ]; - } - else - { - m1 = check->index_xyz[ (k+2)%3 ]; - st1 = check->index_st[ (k+2)%3 ]; - } - - strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ]; - strip_st[stripcount+2] = check->index_st[ (k+2)%3 ]; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; jindex_xyz[(startv)%3]; - strip_xyz[1] = last->index_xyz[(startv+1)%3]; - strip_xyz[2] = last->index_xyz[(startv+2)%3]; - strip_st[0] = last->index_st[(startv)%3]; - strip_st[1] = last->index_st[(startv+1)%3]; - strip_st[2] = last->index_st[(startv+2)%3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[(startv+0)%3]; - st1 = last->index_st[(startv+0)%3]; - m2 = last->index_xyz[(startv+2)%3]; - st2 = last->index_st[(startv+2)%3]; - - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] - ; jindex_xyz[k] != m1) - continue; - if (check->index_st[k] != st1) - continue; - if (check->index_xyz[ (k+1)%3 ] != m2) - continue; - if (check->index_st[ (k+1)%3 ] != st2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - m2 = check->index_xyz[ (k+2)%3 ]; - st2 = check->index_st[ (k+2)%3 ]; - - strip_xyz[stripcount+2] = m2; - strip_st[stripcount+2] = st2; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; j bestlen) - { - besttype = type; - bestlen = len; - for (j=0 ; j= 150) - scale = 150.0 / width; - if (height*scale >= 190) - scale = 190.0 / height; - - s_scale = t_scale = scale; - - iwidth = ceil(width*s_scale); - iheight = ceil(height*t_scale); - - iwidth += 4; - iheight += 4; - } - else - { // new style - iwidth = g_fixedwidth / 2; - iheight = g_fixedheight; - - s_scale = (float)(iwidth-4) / width; - t_scale = (float)(iheight-4) / height; - } - -// -// determine which side of each triangle to map the texture to -// - for (i=0 ; i 0) - { - basex = iwidth + 2; - } - else - { - basex = 2; - } - basey = 2; - - for (j=0 ; j<3 ; j++) - { - pbasevert = ptri[i].verts[j]; - - triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex); - triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey); - } - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - swidth = iwidth*2; - model.skinwidth = (swidth + 3) & ~3; - model.skinheight = iheight; -} -#endif - -//========================================================================== -// -// DrawScreen -// -//========================================================================== - -void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight) -{ - int i; - byte *scrpos; - char buffer[256]; - - // Divider - scrpos = &pic[(INFO_Y-2)*SKINPAGE_WIDTH]; - for(i = 0; i < SKINPAGE_WIDTH; i++) - { - *scrpos++ = 255; - } - - sprintf(buffer, "GENSKIN: "); - DrawTextChar(16, INFO_Y, buffer); - - sprintf(buffer, "( %03d * %03d ) SCALE %f %f, SKINWIDTH %d," - " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth*2, (int)iheight); - DrawTextChar(80, INFO_Y, buffer); -} - -/* -============ -BuildST - -Builds the triangle_st array for the base frame and -model.skinwidth / model.skinheight - - FIXME: allow this to be loaded from a file for - arbitrary mappings -============ -*/ -void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin) -{ - int i, j; - int width, height, iwidth, iheight, swidth; - float basex, basey; - float scale; - vec3_t mins, maxs; - float *pbasevert; - vec3_t vtemp1, vtemp2, normal; - float s_scale, t_scale; - float scWidth; - float scHeight; - - // - // find bounds of all the verts on the base frame - // - ClearBounds (mins, maxs); - - for (i=0 ; i= scHeight) - { - scale = scHeight/height; - } - - iwidth = ceil(width*scale)+4; - iheight = ceil(height*scale)+4; - - s_scale = (float)(iwidth-4) / width; - t_scale = (float)(iheight-4) / height; - t_scale = s_scale; - - if (DrawSkin) - DrawScreen(s_scale, t_scale, iwidth, iheight); - - -/* if (!g_fixedwidth) - { // old style - scale = 8; - if (width*scale >= 150) - scale = 150.0 / width; - if (height*scale >= 190) - scale = 190.0 / height; - - s_scale = t_scale = scale; - - iwidth = ceil(width*s_scale); - iheight = ceil(height*t_scale); - - iwidth += 4; - iheight += 4; - } - else - { // new style - iwidth = g_fixedwidth / 2; - iheight = g_fixedheight; - - s_scale = (float)(iwidth-4) / width; - t_scale = (float)(iheight-4) / height; - }*/ - -// -// determine which side of each triangle to map the texture to -// - for (i=0 ; i 0) - { - basex = iwidth + 2; - } - else - { - basex = 2; - } - basey = 2; - - for (j=0 ; j<3 ; j++) - { - pbasevert = ptri[i].verts[j]; - - triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex); - triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey); - } - } - - DrawLine(triangle_st[i][0][0], triangle_st[i][0][1], - triangle_st[i][1][0], triangle_st[i][1][1]); - DrawLine(triangle_st[i][1][0], triangle_st[i][1][1], - triangle_st[i][2][0], triangle_st[i][2][1]); - DrawLine(triangle_st[i][2][0], triangle_st[i][2][1], - triangle_st[i][0][0], triangle_st[i][0][1]); - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - - swidth = iwidth*2; - model.skinwidth = (swidth + 3) & ~3; - model.skinheight = iheight; -} - - -static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, - IntListNode_t **vertLists, int *num_verts, int *new_num_verts) -{ - int i, j; - IntListNode_t *next; - - for(j = 0; j < num_verts[0]; ++j) - { - for(i = 0; i < num_verts[j+1]; ++i) - { - if(clusters[j][i] == oldindex) - { - ++new_num_verts[j+1]; - - next = vertLists[j]; - - vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex"); - // Currently freed in WriteJointedModelFile only - - vertLists[j]->data = newIndex; - vertLists[j]->next = next; - } - } - } -} - -/* -================= -Cmd_Base -================= -*/ -void Cmd_Base (void) -{ - vec3_t base_xyz[MAX_VERTS]; - triangle_t *ptri; - int i, j, k; -#if 1 -#else - int time1; -#endif - char file1[1024]; - char file2[1024]; - - GetScriptToken (false); - - if (g_skipmodel || g_release || g_archive) - return; - - printf ("---------------------\n"); -#if 1 - sprintf (file1, "%s/%s", cdpartial, token); - printf ("%s ", file1); - - ExpandPathAndArchive (file1); - - sprintf (file1, "%s/%s", cddir, token); -#else - sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext); - printf ("%s\n", file1); - - ExpandPathAndArchive (file1); - - sprintf (file1, "%s/%s.%s", cddir, token, trifileext); - - time1 = FileTime (file1); - if (time1 == -1) - Error ("%s doesn't exist", file1); -#endif -// -// load the base triangles -// - if (do3ds) - Load3DSTriangleList (file1, &ptri, &model.num_tris, NULL, NULL); - else - LoadTriangleList (file1, &ptri, &model.num_tris, NULL, NULL); - - - GetScriptToken (false); - sprintf (file2, "%s/%s.pcx", cddir, token); -// sprintf (trans_file, "%s/!%s_a.pcx", cddir, token); - - printf ("skin: %s\n", file2); - Load256Image (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight); - - if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT) - { - if (g_allow_newskin) - { - ScaleWidth = BaseWidth; - ScaleHeight = BaseHeight; - } - else - { - Error("Invalid skin page size: (%d,%d) should be (%d,%d)", - BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT); - } - } - else - { - ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X, - ENCODED_WIDTH_Y); - ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X, - ENCODED_HEIGHT_Y); - } - -// -// get the ST values -// - BuildST (ptri, model.num_tris,false); - -// -// run through all the base triangles, storing each unique vertex in the -// base vertex list and setting the indirect triangles to point to the base -// vertices -// - for (i=0 ; i= '0' && *s <= '9') - s--; - - strcpy (suffix, s+1); - strcpy (base, frame); - base[s-frame+1] = 0; - - sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "hrc"); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s%s.%s", base, suffix, "hrc"); - return retname; - } - - sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "asc"); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s%s.%s", base, suffix, "asc"); - return retname; - } - - sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "tri"); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s%s.%s", base, suffix, "tri"); - return retname; - } - - sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "3ds"); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s%s.%s", base, suffix, "3ds"); - return retname; - } - - sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "htr"); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s%s.%s", base, suffix, "htr"); - return retname; - } - - // check for 'run.1' - sprintf (file1, "%s/%s.%s",cddir, base, suffix); - time1 = FileTime (file1); - if (time1 != -1) - { - sprintf (retname, "%s.%s", base, suffix); - return retname; - } - - Error ("frame %s could not be found",frame); - return NULL; -} - -/* -=============== -GrabFrame -=============== -*/ -static void GrabFrame (char *frame) -{ - triangle_t *ptri; - int i, j; - trivert_t *ptrivert; - int num_tris; - char file1[1024]; - frame_t *fr; - vertexnormals_t vnorms[MAX_VERTS]; - int index_xyz; - char *framefile; - - // the frame 'run1' will be looked for as either - // run.1 or run1.tri, so the new alias sequence save - // feature an be used - framefile = FindFrameFile (frame); - - sprintf (file1, "%s/%s", cdarchive, framefile); - ExpandPathAndArchive (file1); - - sprintf (file1, "%s/%s",cddir, framefile); - - printf ("grabbing %s ", file1); - - if (model.num_frames >= MAX_FRAMES) - Error ("model.num_frames >= MAX_FRAMES"); - fr = &g_frames[model.num_frames]; - model.num_frames++; - - strcpy (fr->name, frame); - -// -// load the frame -// - if (do3ds) - Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL); - else - LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL); - - if (num_tris != model.num_tris) - Error ("%s: number of triangles doesn't match base frame\n", file1); - -// -// allocate storage for the frame's vertices -// - ptrivert = fr->v; - - for (i=0 ; imins, fr->maxs); - -// -// store the frame's vertices in the same order as the base. This assumes the -// triangles and vertices in this frame are in exactly the same order as in the -// base -// - for (i=0 ; imins, fr->maxs); - - VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum); - vnorms[index_xyz].numnormals++; - } - } - -// -// calculate the vertex normals, match them to the template list, and store the -// index of the best match -// - for (i=0 ; i maxdot) - { - maxdot = dot; - maxdotindex = j; - } - } - - ptrivert[i].lightnormalindex = maxdotindex; - } - - free (ptri); -} - -/* -=============== -GrabJointedFrame -=============== -*/ -void GrabJointedFrame(char *frame) -{ - char file1[1024]; - char *framefile; - frame_t *fr; - - framefile = FindFrameFile (frame); - - sprintf (file1, "%s/%s", cdarchive, framefile); - ExpandPathAndArchive (file1); - - sprintf (file1, "%s/%s",cddir, framefile); - - printf ("grabbing %s\n", file1); - - fr = &g_frames[model.num_frames - 1]; // last frame read in - - LoadJointList(file1, fr->joints, jointed); -} - -/* -=============== -GrabGlobals -=============== -*/ -void GrabGlobals(char *frame) -{ - char file1[1024]; - char *framefile; - frame_t *fr; - - framefile = FindFrameFile (frame); - - sprintf (file1, "%s/%s", cdarchive, framefile); - ExpandPathAndArchive (file1); - - sprintf (file1, "%s/%s",cddir, framefile); - - printf ("grabbing %s\n", file1); - - fr = &g_frames[model.num_frames - 1]; // last frame read in - - LoadGlobals(file1); -} - -/* -=============== -Cmd_Frame -=============== -*/ -void Cmd_Frame (void) -{ - while (ScriptTokenAvailable()) - { - GetScriptToken (false); - if (g_skipmodel) - continue; - if (g_release || g_archive) - { - model.num_frames = 1; // don't skip the writeout - continue; - } - - H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames); - - GrabFrame (token); - } -} - -/* -=============== -Cmd_Skin - -Skins aren't actually stored in the file, only a reference -is saved out to the header file. -=============== -*/ -void Cmd_Skin (void) -{ - byte *palette; - byte *pixels; - int width, height; - byte *cropped; - int y; - char name[1024], savename[1024]; - - GetScriptToken (false); - - if (model.num_skins == MAX_MD2SKINS) - Error ("model.num_skins == MAX_MD2SKINS"); - - if (g_skipmodel) - return; - -#if 1 - sprintf (name, "%s/%s.pcx", cddir, token); - sprintf (savename, "%s/!%s.pcx", g_outputDir, token); - sprintf (g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token); -#else - sprintf (name, "%s/%s.lbm", cdarchive, token); - strcpy (name, ExpandPathAndArchive( name ) ); -// sprintf (name, "%s/%s.lbm", cddir, token); - - if (ScriptTokenAvailable()) - { - GetScriptToken (false); - sprintf (g_skins[model.num_skins], "%s.pcx", token); - sprintf (savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins]); - } - else - { - sprintf (savename, "%s/%s.pcx", g_outputDir, token); - sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token); - } -#endif - - model.num_skins++; - - if (g_skipmodel || g_release || g_archive) - return; - - // load the image - printf ("loading %s\n", name); - Load256Image (name, &pixels, &palette, &width, &height); -// RemapZero (pixels, palette, width, height); - - // crop it to the proper size - cropped = (byte *) SafeMalloc (model.skinwidth*model.skinheight, "Cmd_Skin"); - for (y=0 ; y +#include "jointed.h" +#include "fmodel.h" + +//================================================================= + +typedef struct +{ + int numnormals; + vec3_t normalsum; +} vertexnormals_t; + +typedef struct +{ + vec3_t v; + int lightnormalindex; +} trivert_t; + +typedef struct +{ + vec3_t mins, maxs; + char name[16]; + trivert_t v[MAX_VERTS]; + QDataJoint_t joints[NUM_CLUSTERS]; // ,this +} frame_t; + +// ,and all of this should get out of here, need to use new stuff in fmodels instead + +typedef struct IntListNode_s +{ + int data; + struct IntListNode_s *next; +} IntListNode_t; // gaak + +typedef struct +{ + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this +} PartialAliasFrame_t; + +int jointed; +int clustered; + +int *clusters[NUM_CLUSTERS]; +IntListNode_t *vertLists[NUM_CLUSTERS]; +int num_verts[NUM_CLUSTERS + 1]; +int new_num_verts[NUM_CLUSTERS + 1]; + +// end that + +//================================================================ + +frame_t g_frames[MAX_FRAMES]; +//frame_t *g_frames; + +static dmdl_t model; + + +float scale_up; // set by $scale +vec3_t adjust; // set by $origin +int g_fixedwidth, g_fixedheight; // set by $skinsize + + +// +// base frame info +// +dstvert_t base_st[MAX_VERTS]; +dtriangle_t triangles[MAX_TRIANGLES]; + +static int triangle_st[MAX_TRIANGLES][3][2]; + +// the command list holds counts, s/t values, and xyz indexes +// that are valid for every frame +int commands[16384]; +int numcommands; +int numglverts; +int used[MAX_TRIANGLES]; + +char g_skins[MAX_MD2SKINS][64]; + +char cdarchive[1024]; +char cdpartial[1024]; +char cddir[1024]; + +char modelname[64]; // empty unless $modelname issued (players) + +extern char *g_outputDir; + +#define NUMVERTEXNORMALS 162 + +float avertexnormals[NUMVERTEXNORMALS][3] = +{ + #include "anorms.h" +}; + +unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768]; + +FILE *headerouthandle = NULL; + +//============================================================== + +/* +=============== +ClearModel +=============== +*/ +static void ClearModel (void) +{ + memset (&model, 0, sizeof(model)); + + modelname[0] = 0; + jointed = NOT_JOINTED; + clustered = 0; + scale_up = 1.0; + VectorCopy (vec3_origin, adjust); + g_fixedwidth = g_fixedheight = 0; + g_skipmodel = false; +} + + +void H_printf(char *fmt, ...) +{ + va_list argptr; + char name[1024]; + + if (!headerouthandle) + { + sprintf (name, "%s/tris.h", cddir); + headerouthandle = SafeOpenWrite (name); + fprintf(headerouthandle, "// %s\n\n", cddir); + fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n"); + } + + va_start (argptr, fmt); + vfprintf (headerouthandle, fmt, argptr); + va_end (argptr); +} + +#if 1 +/* +============ +WriteModelFile +============ +*/ +void WriteCommonModelFile (FILE *modelouthandle, PartialAliasFrame_t *outFrames) +{ + int i; + dmdl_t modeltemp; + int j, k; + frame_t *in; + daliasframe_t *out; + byte buffer[MAX_VERTS*4+128]; + float v; + int c_on, c_off; + + model.version = ALIAS_VERSION; + model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz]; + model.num_glcmds = numcommands; + model.ofs_skins = sizeof(dmdl_t); + model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; + model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t); + model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t); + model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize; + model.ofs_end = model.ofs_glcmds + model.num_glcmds*sizeof(int); + // + // write out the model header + // + for (i=0 ; iname, in->name); + for (j=0 ; j<3 ; j++) + { + out->scale[j] = (in->maxs[j] - in->mins[j])/255; + out->translate[j] = in->mins[j]; + + if(outFrames) + { + outFrames[i].scale[j] = out->scale[j]; + outFrames[i].translate[j] = out->translate[j]; + } + } + + for (j=0 ; jverts[j].lightnormalindex = in->v[j].lightnormalindex; + + for (k=0 ; k<3 ; k++) + { + // scale to byte values & min/max check + v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + v = 255.0; + if (v < 0) + v = 0; + out->verts[j].v[k] = v; + } + } + + for (j=0 ; j<3 ; j++) + { + out->scale[j] = LittleFloat (out->scale[j]); + out->translate[j] = LittleFloat (out->translate[j]); + } + + SafeWrite (modelouthandle, out, model.framesize); + } + + // + // write out glcmds + // + SafeWrite (modelouthandle, commands, numcommands*4); +} + +/* +============ +WriteModelFile +============ +*/ +void WriteModelFile (FILE *modelouthandle) +{ + model.ident = IDALIASHEADER; + + WriteCommonModelFile(modelouthandle, NULL); +} + +/* +============ +WriteJointedModelFile +============ +*/ +void WriteJointedModelFile (FILE *modelouthandle) +{ + int i; + int j, k; + frame_t *in; + float v; + IntListNode_t *current, *toFree; + PartialAliasFrame_t outFrames[MAX_FRAMES]; + + model.ident = IDJOINTEDALIASHEADER; + + WriteCommonModelFile(modelouthandle, outFrames); + + // Skeletal Type + SafeWrite(modelouthandle, &jointed, sizeof(int)); + + // number of joints + SafeWrite(modelouthandle, &numJointsForSkeleton[jointed], sizeof(int)); + + // number of verts in each cluster + SafeWrite(modelouthandle, &new_num_verts[1], sizeof(int)*numJointsForSkeleton[jointed]); + + // cluster verts + for(i = 0; i < new_num_verts[0]; ++i) + { + current = vertLists[i]; + while(current) + { + SafeWrite (modelouthandle, ¤t->data, sizeof(int)); + toFree = current; + current = current->next; + free(toFree); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base + } + } + + for (i=0 ; ijoints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + { + v = 255.0; + } + + if (v < 0) + { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite (modelouthandle, &v, sizeof(float)); + } + + for (k=0 ; k<3 ; k++) + { + v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + { + v = 255.0; + } + + if (v < 0) + { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite (modelouthandle, &v, sizeof(float)); + } + + for (k=0 ; k<3 ; k++) + { + v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + { + v = 255.0; + } + + if (v < 0) + { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite (modelouthandle, &v, sizeof(float)); + } + } + } +} +#else +/* +============ +WriteModelFile +============ +*/ +static void WriteModelFile (FILE *modelouthandle) +{ + int i; + dmdl_t modeltemp; + int j, k; + frame_t *in; + daliasframe_t *out; + byte buffer[MAX_VERTS*4+128]; + float v; + int c_on, c_off; + + model.ident = IDALIASHEADER; + model.version = ALIAS_VERSION; + model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz]; + model.num_glcmds = numcommands; + model.ofs_skins = sizeof(dmdl_t); + model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; + model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t); + model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t); + model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize; + model.ofs_end = model.ofs_glcmds + model.num_glcmds*4; + + // + // write out the model header + // + for (i=0 ; iname, in->name); + for (j=0 ; j<3 ; j++) + { + out->scale[j] = (in->maxs[j] - in->mins[j])/255; + out->translate[j] = in->mins[j]; + } + + for (j=0 ; jverts[j].lightnormalindex = in->v[j].lightnormalindex; + + for (k=0 ; k<3 ; k++) + { + // scale to byte values & min/max check + v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + v = 255.0; + if (v < 0) + v = 0; + out->verts[j].v[k] = v; + } + } + + for (j=0 ; j<3 ; j++) + { + out->scale[j] = LittleFloat (out->scale[j]); + out->translate[j] = LittleFloat (out->translate[j]); + } + + SafeWrite (modelouthandle, out, model.framesize); + } + + // + // write out glcmds + // + SafeWrite (modelouthandle, commands, numcommands*4); +} +#endif + +/* +=============== +FinishModel +=============== +*/ +void FinishModel (void) +{ + FILE *modelouthandle; + int i; + char name[1024]; + + if (!model.num_frames) + return; + +// +// copy to release directory tree if doing a release build +// + if (g_release) + { + if (modelname[0]) + sprintf (name, "%s", modelname); + else + sprintf (name, "%s/tris.md2", cdpartial); + ReleaseFile (name); + + for (i=0 ; iindex_xyz[(startv)%3]; + strip_xyz[1] = last->index_xyz[(startv+1)%3]; + strip_xyz[2] = last->index_xyz[(startv+2)%3]; + strip_st[0] = last->index_st[(startv)%3]; + strip_st[1] = last->index_st[(startv+1)%3]; + strip_st[2] = last->index_st[(startv+2)%3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[(startv+2)%3]; + st1 = last->index_st[(startv+2)%3]; + m2 = last->index_xyz[(startv+1)%3]; + st2 = last->index_st[(startv+1)%3]; + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] + ; jindex_xyz[k] != m1) + continue; + if (check->index_st[k] != st1) + continue; + if (check->index_xyz[ (k+1)%3 ] != m2) + continue; + if (check->index_st[ (k+1)%3 ] != st2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + if (stripcount & 1) + { + m2 = check->index_xyz[ (k+2)%3 ]; + st2 = check->index_st[ (k+2)%3 ]; + } + else + { + m1 = check->index_xyz[ (k+2)%3 ]; + st1 = check->index_st[ (k+2)%3 ]; + } + + strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ]; + strip_st[stripcount+2] = check->index_st[ (k+2)%3 ]; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jindex_xyz[(startv)%3]; + strip_xyz[1] = last->index_xyz[(startv+1)%3]; + strip_xyz[2] = last->index_xyz[(startv+2)%3]; + strip_st[0] = last->index_st[(startv)%3]; + strip_st[1] = last->index_st[(startv+1)%3]; + strip_st[2] = last->index_st[(startv+2)%3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[(startv+0)%3]; + st1 = last->index_st[(startv+0)%3]; + m2 = last->index_xyz[(startv+2)%3]; + st2 = last->index_st[(startv+2)%3]; + + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] + ; jindex_xyz[k] != m1) + continue; + if (check->index_st[k] != st1) + continue; + if (check->index_xyz[ (k+1)%3 ] != m2) + continue; + if (check->index_st[ (k+1)%3 ] != st2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + m2 = check->index_xyz[ (k+2)%3 ]; + st2 = check->index_st[ (k+2)%3 ]; + + strip_xyz[stripcount+2] = m2; + strip_st[stripcount+2] = st2; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; j bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; j= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + + s_scale = t_scale = scale; + + iwidth = ceil(width*s_scale); + iheight = ceil(height*t_scale); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + } + +// +// determine which side of each triangle to map the texture to +// + for (i=0 ; i 0) + { + basex = iwidth + 2; + } + else + { + basex = 2; + } + basey = 2; + + for (j=0 ; j<3 ; j++) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex); + triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey); + } + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + swidth = iwidth*2; + model.skinwidth = (swidth + 3) & ~3; + model.skinheight = iheight; +} +#endif + +//========================================================================== +// +// DrawScreen +// +//========================================================================== + +void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight) +{ + int i; + byte *scrpos; + char buffer[256]; + + // Divider + scrpos = &pic[(INFO_Y-2)*SKINPAGE_WIDTH]; + for(i = 0; i < SKINPAGE_WIDTH; i++) + { + *scrpos++ = 255; + } + + sprintf(buffer, "GENSKIN: "); + DrawTextChar(16, INFO_Y, buffer); + + sprintf(buffer, "( %03d * %03d ) SCALE %f %f, SKINWIDTH %d," + " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth*2, (int)iheight); + DrawTextChar(80, INFO_Y, buffer); +} + +/* +============ +BuildST + +Builds the triangle_st array for the base frame and +model.skinwidth / model.skinheight + + FIXME: allow this to be loaded from a file for + arbitrary mappings +============ +*/ +void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin) +{ + int i, j; + int width, height, iwidth, iheight, swidth; + float basex, basey; + float scale; + vec3_t mins, maxs; + float *pbasevert; + vec3_t vtemp1, vtemp2, normal; + float s_scale, t_scale; + float scWidth; + float scHeight; + + // + // find bounds of all the verts on the base frame + // + ClearBounds (mins, maxs); + + for (i=0 ; i= scHeight) + { + scale = scHeight/height; + } + + iwidth = ceil(width*scale)+4; + iheight = ceil(height*scale)+4; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + t_scale = s_scale; + + if (DrawSkin) + DrawScreen(s_scale, t_scale, iwidth, iheight); + + +/* if (!g_fixedwidth) + { // old style + scale = 8; + if (width*scale >= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + + s_scale = t_scale = scale; + + iwidth = ceil(width*s_scale); + iheight = ceil(height*t_scale); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + }*/ + +// +// determine which side of each triangle to map the texture to +// + for (i=0 ; i 0) + { + basex = iwidth + 2; + } + else + { + basex = 2; + } + basey = 2; + + for (j=0 ; j<3 ; j++) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex); + triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey); + } + } + + DrawLine(triangle_st[i][0][0], triangle_st[i][0][1], + triangle_st[i][1][0], triangle_st[i][1][1]); + DrawLine(triangle_st[i][1][0], triangle_st[i][1][1], + triangle_st[i][2][0], triangle_st[i][2][1]); + DrawLine(triangle_st[i][2][0], triangle_st[i][2][1], + triangle_st[i][0][0], triangle_st[i][0][1]); + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + + swidth = iwidth*2; + model.skinwidth = (swidth + 3) & ~3; + model.skinheight = iheight; +} + + +static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, + IntListNode_t **vertLists, int *num_verts, int *new_num_verts) +{ + int i, j; + IntListNode_t *next; + + for(j = 0; j < num_verts[0]; ++j) + { + for(i = 0; i < num_verts[j+1]; ++i) + { + if(clusters[j][i] == oldindex) + { + ++new_num_verts[j+1]; + + next = vertLists[j]; + + vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex"); + // Currently freed in WriteJointedModelFile only + + vertLists[j]->data = newIndex; + vertLists[j]->next = next; + } + } + } +} + +/* +================= +Cmd_Base +================= +*/ +void Cmd_Base (void) +{ + vec3_t base_xyz[MAX_VERTS]; + triangle_t *ptri; + int i, j, k; +#if 1 +#else + int time1; +#endif + char file1[1024]; + char file2[1024]; + + GetScriptToken (false); + + if (g_skipmodel || g_release || g_archive) + return; + + printf ("---------------------\n"); +#if 1 + sprintf (file1, "%s/%s", cdpartial, token); + printf ("%s ", file1); + + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s", cddir, token); +#else + sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext); + printf ("%s\n", file1); + + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s.%s", cddir, token, trifileext); + + time1 = FileTime (file1); + if (time1 == -1) + Error ("%s doesn't exist", file1); +#endif +// +// load the base triangles +// + if (do3ds) + Load3DSTriangleList (file1, &ptri, &model.num_tris, NULL, NULL); + else + LoadTriangleList (file1, &ptri, &model.num_tris, NULL, NULL); + + + GetScriptToken (false); + sprintf (file2, "%s/%s.pcx", cddir, token); +// sprintf (trans_file, "%s/!%s_a.pcx", cddir, token); + + printf ("skin: %s\n", file2); + Load256Image (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight); + + if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT) + { + if (g_allow_newskin) + { + ScaleWidth = BaseWidth; + ScaleHeight = BaseHeight; + } + else + { + Error("Invalid skin page size: (%d,%d) should be (%d,%d)", + BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT); + } + } + else + { + ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X, + ENCODED_WIDTH_Y); + ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X, + ENCODED_HEIGHT_Y); + } + +// +// get the ST values +// + BuildST (ptri, model.num_tris,false); + +// +// run through all the base triangles, storing each unique vertex in the +// base vertex list and setting the indirect triangles to point to the base +// vertices +// + for (i=0 ; i= '0' && *s <= '9') + s--; + + strcpy (suffix, s+1); + strcpy (base, frame); + base[s-frame+1] = 0; + + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "hrc"); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, "hrc"); + return retname; + } + + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "asc"); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, "asc"); + return retname; + } + + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "tri"); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, "tri"); + return retname; + } + + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "3ds"); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, "3ds"); + return retname; + } + + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "htr"); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, "htr"); + return retname; + } + + // check for 'run.1' + sprintf (file1, "%s/%s.%s",cddir, base, suffix); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s.%s", base, suffix); + return retname; + } + + Error ("frame %s could not be found",frame); + return NULL; +} + +/* +=============== +GrabFrame +=============== +*/ +static void GrabFrame (char *frame) +{ + triangle_t *ptri; + int i, j; + trivert_t *ptrivert; + int num_tris; + char file1[1024]; + frame_t *fr; + vertexnormals_t vnorms[MAX_VERTS]; + int index_xyz; + char *framefile; + + // the frame 'run1' will be looked for as either + // run.1 or run1.tri, so the new alias sequence save + // feature an be used + framefile = FindFrameFile (frame); + + sprintf (file1, "%s/%s", cdarchive, framefile); + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s",cddir, framefile); + + printf ("grabbing %s ", file1); + + if (model.num_frames >= MAX_FRAMES) + Error ("model.num_frames >= MAX_FRAMES"); + fr = &g_frames[model.num_frames]; + model.num_frames++; + + strcpy (fr->name, frame); + +// +// load the frame +// + if (do3ds) + Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL); + else + LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL); + + if (num_tris != model.num_tris) + Error ("%s: number of triangles doesn't match base frame\n", file1); + +// +// allocate storage for the frame's vertices +// + ptrivert = fr->v; + + for (i=0 ; imins, fr->maxs); + +// +// store the frame's vertices in the same order as the base. This assumes the +// triangles and vertices in this frame are in exactly the same order as in the +// base +// + for (i=0 ; imins, fr->maxs); + + VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum); + vnorms[index_xyz].numnormals++; + } + } + +// +// calculate the vertex normals, match them to the template list, and store the +// index of the best match +// + for (i=0 ; i maxdot) + { + maxdot = dot; + maxdotindex = j; + } + } + + ptrivert[i].lightnormalindex = maxdotindex; + } + + free (ptri); +} + +/* +=============== +GrabJointedFrame +=============== +*/ +void GrabJointedFrame(char *frame) +{ + char file1[1024]; + char *framefile; + frame_t *fr; + + framefile = FindFrameFile (frame); + + sprintf (file1, "%s/%s", cdarchive, framefile); + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s",cddir, framefile); + + printf ("grabbing %s\n", file1); + + fr = &g_frames[model.num_frames - 1]; // last frame read in + + LoadJointList(file1, fr->joints, jointed); +} + +/* +=============== +GrabGlobals +=============== +*/ +void GrabGlobals(char *frame) +{ + char file1[1024]; + char *framefile; + frame_t *fr; + + framefile = FindFrameFile (frame); + + sprintf (file1, "%s/%s", cdarchive, framefile); + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s",cddir, framefile); + + printf ("grabbing %s\n", file1); + + fr = &g_frames[model.num_frames - 1]; // last frame read in + + LoadGlobals(file1); +} + +/* +=============== +Cmd_Frame +=============== +*/ +void Cmd_Frame (void) +{ + while (ScriptTokenAvailable()) + { + GetScriptToken (false); + if (g_skipmodel) + continue; + if (g_release || g_archive) + { + model.num_frames = 1; // don't skip the writeout + continue; + } + + H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames); + + GrabFrame (token); + } +} + +/* +=============== +Cmd_Skin + +Skins aren't actually stored in the file, only a reference +is saved out to the header file. +=============== +*/ +void Cmd_Skin (void) +{ + byte *palette; + byte *pixels; + int width, height; + byte *cropped; + int y; + char name[1024], savename[1024]; + + GetScriptToken (false); + + if (model.num_skins == MAX_MD2SKINS) + Error ("model.num_skins == MAX_MD2SKINS"); + + if (g_skipmodel) + return; + +#if 1 + sprintf (name, "%s/%s.pcx", cddir, token); + sprintf (savename, "%s/!%s.pcx", g_outputDir, token); + sprintf (g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token); +#else + sprintf (name, "%s/%s.lbm", cdarchive, token); + strcpy (name, ExpandPathAndArchive( name ) ); +// sprintf (name, "%s/%s.lbm", cddir, token); + + if (ScriptTokenAvailable()) + { + GetScriptToken (false); + sprintf (g_skins[model.num_skins], "%s.pcx", token); + sprintf (savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins]); + } + else + { + sprintf (savename, "%s/%s.pcx", g_outputDir, token); + sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token); + } +#endif + + model.num_skins++; + + if (g_skipmodel || g_release || g_archive) + return; + + // load the image + printf ("loading %s\n", name); + Load256Image (name, &pixels, &palette, &width, &height); +// RemapZero (pixels, palette, width, height); + + // crop it to the proper size + cropped = (byte *) SafeMalloc (model.skinwidth*model.skinheight, "Cmd_Skin"); + for (y=0 ; y