X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_alias.c;h=c62cb9c98d47324777a0b8a6320a463a306e0077;hp=7f2d0132cafb9be783779bbf90bdfaf363e02adc;hb=66a136af999cd76551bd56e3c3096fff0d42f613;hpb=83982c1b3388e3a56cca7b82c23ede7d3155af9d diff --git a/model_alias.c b/model_alias.c index 7f2d0132..c62cb9c9 100644 --- a/model_alias.c +++ b/model_alias.c @@ -27,11 +27,6 @@ void Mod_AliasInit (void) Cvar_RegisterVariable(&r_mipskins); } -static void Mod_Alias_SERAddEntity(void) -{ - R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); -} - // LordHavoc: proper bounding box considerations static float aliasbboxmin[3], aliasbboxmax[3], modelyawradius, modelradius; @@ -95,7 +90,7 @@ static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, Con_Printf("Mod_ConvertAliasVerts: \"%s\", %i invalid normal indices found\n", loadmodel->name, invalidnormals); } -static void Mod_MDL_LoadFrames (long datapointer, int inverts, int outverts, vec3_t scale, vec3_t translate) +static void Mod_MDL_LoadFrames (qbyte * datapointer, int inverts, int outverts, vec3_t scale, vec3_t translate) { daliasframetype_t *pframetype; daliasframe_t *pinframe; @@ -160,10 +155,10 @@ static void Mod_MDL_LoadFrames (long datapointer, int inverts, int outverts, vec } } -static rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, int bits, char *name, int precache) +static rtexture_t *GL_SkinSplitShirt(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache) { int i, pixels, passed; - byte pixeltest[16]; + qbyte pixeltest[16]; for (i = 0;i < 16;i++) pixeltest[i] = (bits & (1 << i)) != 0; pixels = width*height; @@ -190,10 +185,10 @@ static rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, return NULL; } -static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, int bits, char *name, int precache) +static rtexture_t *GL_SkinSplit(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache) { int i, pixels, passed; - byte pixeltest[16]; + qbyte pixeltest[16]; for (i = 0;i < 16;i++) pixeltest[i] = (bits & (1 << i)) != 0; pixels = width*height; @@ -216,39 +211,39 @@ static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, int return NULL; } -static void Mod_LoadSkin (char *basename, byte *skindata, byte *skintemp, int width, int height, skinframe_t *skinframe, int precache) +static int Mod_LoadExternalSkin (char *basename, skinframe_t *skinframe, int precache) { skinframe->base = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, r_mipskins.integer, precache); skinframe->fog = image_masktex; - skinframe->pants = NULL; - skinframe->shirt = NULL; + if (!skinframe->base) + { + skinframe->base = loadtextureimagewithmask(loadmodel->texturepool, basename, 0, 0, false, r_mipskins.integer, precache); + skinframe->fog = image_masktex; + } + skinframe->pants = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, r_mipskins.integer, precache); + skinframe->shirt = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, r_mipskins.integer, precache); skinframe->glow = loadtextureimage(loadmodel->texturepool, va("%s_glow" , basename), 0, 0, false, r_mipskins.integer, precache); skinframe->merged = NULL; - if (skinframe->base) + return skinframe->base != NULL || skinframe->pants != NULL || skinframe->shirt != NULL || skinframe->glow != NULL; +} + +static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, qbyte *skintemp, int width, int height, skinframe_t *skinframe, int precache) +{ + if (!skindata || !skintemp) + return false; + skinframe->pants = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants + skinframe->shirt = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt + skinframe->glow = GL_SkinSplit (skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), precache); // glow + if (skinframe->pants || skinframe->shirt) { - skinframe->pants = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, r_mipskins.integer, precache); - skinframe->shirt = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, r_mipskins.integer, precache); + skinframe->base = GL_SkinSplit (skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors) + skinframe->merged = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), precache); // body (normal + pants + shirt, but not glow) } else - { - skinframe->base = loadtextureimagewithmask(loadmodel->texturepool, basename, 0, 0, false, true, true); - skinframe->fog = image_masktex; - if (!skinframe->base) - { - skinframe->pants = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants - skinframe->shirt = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt - skinframe->glow = GL_SkinSplit (skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), precache); // glow - if (skinframe->pants || skinframe->shirt) - { - skinframe->base = GL_SkinSplit (skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors) - skinframe->merged = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), precache); // body (normal + pants + shirt, but not glow) - } - else - skinframe->base = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), precache); // no special colors - // quake model skins don't have alpha - skinframe->fog = NULL; - } - } + skinframe->base = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), precache); // no special colors + // quake model skins don't have alpha + skinframe->fog = NULL; + return true; } #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", loadmodel->name, VALUE, MIN, MAX); @@ -265,13 +260,16 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) daliasframetype_t *pinframetype; daliasgroup_t *pinframegroup; float scales, scalet, scale[3], translate[3], interval; - long datapointer, startframes, startskins; + qbyte *datapointer, *startframes, *startskins; char name[MAX_QPATH]; - byte *skintemp = NULL; + qbyte *skintemp = NULL; + skinframe_t tempskinframe; + animscene_t *tempskinscenes; + skinframe_t *tempskinframes; modelyawradius = 0; modelradius = 0; - datapointer = (long) buffer; + datapointer = buffer; pinmodel = (mdl_t *)datapointer; datapointer += sizeof(mdl_t); @@ -281,7 +279,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->name, version, ALIAS_VERSION); loadmodel->type = mod_alias; - loadmodel->aliastype = ALIASTYPE_MDL; + loadmodel->aliastype = ALIASTYPE_MDLMD2; loadmodel->numskins = LittleLong(pinmodel->numskins); BOUNDI(loadmodel->numskins,0,256); @@ -401,12 +399,42 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) sprintf (name, "%s_%i_%i", loadmodel->name, i, j); else sprintf (name, "%s_%i", loadmodel->name, i); - Mod_LoadSkin(name, (byte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0); + if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0)) + Mod_LoadInternalSkin(name, (qbyte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0); datapointer += skinwidth * skinheight; totalskins++; } } Mem_Free(skintemp); + // check for skins that don't exist in the model, but do exist as external images + // (this was added because yummyluv kept pestering me about support for it) + for (;;) + { + sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins); + if (Mod_LoadExternalSkin(name, &tempskinframe, loadmodel->numskins == 0)) + { + // expand the arrays to make room + tempskinscenes = loadmodel->skinscenes; + tempskinframes = loadmodel->skinframes; + loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t)); + loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(skinframe_t)); + memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t)); + memcpy(loadmodel->skinframes, tempskinframes, totalskins * sizeof(skinframe_t)); + Mem_Free(tempskinscenes); + Mem_Free(tempskinframes); + // store the info about the new skin + strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name); + loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins; + loadmodel->skinscenes[loadmodel->numskins].framecount = 1; + loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f; + loadmodel->skinscenes[loadmodel->numskins].loop = true; + loadmodel->skinframes[totalskins] = tempskinframe; + loadmodel->numskins++; + totalskins++; + } + else + break; + } // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data) scales = 1.0 / skinwidth; @@ -423,7 +451,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) } // load triangle data - loadmodel->mdldata_indices = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris); + loadmodel->mdlmd2data_indices = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris); // count the vertices used for (i = 0;i < numverts*2;i++) @@ -461,16 +489,16 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // remap the triangle references for (i = 0;i < loadmodel->numtris;i++) { - loadmodel->mdldata_indices[i*3+0] = vertremap[temptris[i][0]]; - loadmodel->mdldata_indices[i*3+1] = vertremap[temptris[i][1]]; - loadmodel->mdldata_indices[i*3+2] = vertremap[temptris[i][2]]; + loadmodel->mdlmd2data_indices[i*3+0] = vertremap[temptris[i][0]]; + loadmodel->mdlmd2data_indices[i*3+1] = vertremap[temptris[i][1]]; + loadmodel->mdlmd2data_indices[i*3+2] = vertremap[temptris[i][2]]; } // store the texture coordinates - loadmodel->mdldata_texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts); + loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts); for (i = 0;i < totalverts;i++) { - loadmodel->mdldata_texcoords[i*2+0] = vertst[i][0]; - loadmodel->mdldata_texcoords[i*2+1] = vertst[i][1]; + loadmodel->mdlmd2data_texcoords[i*2+0] = vertst[i][0]; + loadmodel->mdlmd2data_texcoords[i*2+1] = vertst[i][1]; } // load the frames @@ -484,12 +512,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) Mod_MDL_LoadFrames (startframes, numverts, totalverts, scale, translate); - // LordHavoc: fixed model bbox - was //FIXME: do this right - //loadmodel->mins[0] = loadmodel->mins[1] = loadmodel->mins[2] = -16; - //loadmodel->maxs[0] = loadmodel->maxs[1] = loadmodel->maxs[2] = 16; modelyawradius = sqrt(modelyawradius); modelradius = sqrt(modelradius); -// loadmodel->modelradius = modelradius; for (j = 0;j < 3;j++) { loadmodel->normalmins[j] = aliasbboxmin[j]; @@ -501,23 +525,24 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->yawmins[2] = loadmodel->normalmins[2]; loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; - loadmodel->SERAddEntity = Mod_Alias_SERAddEntity; - loadmodel->Draw = R_DrawAliasModel; + loadmodel->Draw = R_DrawQ1Q2AliasModel; loadmodel->DrawSky = NULL; loadmodel->DrawShadow = NULL; } -static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) +static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out, int *vertremap) { int i, invalidnormals = 0; float dist; + trivertx_t *in; vec3_t temp; - for (i = 0;i < numverts;i++) + for (i = 0;i < loadmodel->numverts;i++) { - VectorCopy(v[i].v, out[i].v); - temp[0] = v[i].v[0] * scale[0] + translate[0]; - temp[1] = v[i].v[1] * scale[1] + translate[1]; - temp[2] = v[i].v[2] * scale[2] + translate[2]; + in = v + vertremap[i]; + VectorCopy(in->v, out[i].v); + temp[0] = in->v[0] * scale[0] + translate[0]; + temp[1] = in->v[1] * scale[1] + translate[1]; + temp[2] = in->v[2] * scale[2] + translate[2]; // update bounding box if (temp[0] < aliasbboxmin[0]) aliasbboxmin[0] = temp[0]; if (temp[1] < aliasbboxmin[1]) aliasbboxmin[1] = temp[1]; @@ -531,7 +556,7 @@ static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, dist += temp[2]*temp[2]; if (modelradius < dist) modelradius = dist; - out[i].lightnormalindex = v[i].lightnormalindex; + out[i].lightnormalindex = in->lightnormalindex; if (out[i].lightnormalindex >= NUMVERTEXNORMALS) { invalidnormals++; @@ -542,58 +567,74 @@ static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, Con_Printf("Mod_MD2_ConvertVerts: \"%s\", %i invalid normal indices found\n", loadmodel->name, invalidnormals); } -void Mod_MD2_ReadHeader(md2_t *in, int *numglcmds) +void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) { + int *vertremap; + md2_t *pinmodel; + qbyte *base; int version, end; + int i, j, k, hashindex, num, numxyz, numst, xyz, st; + float *stverts, s, t; + struct md2verthash_s + { + struct md2verthash_s *next; + int xyz; + float st[2]; + } + *hash, **md2verthash, *md2verthashdata; + qbyte *datapointer; + md2frame_t *pinframe; + char *inskin; + md2triangle_t *intri; + unsigned short *inst; + int skinwidth, skinheight; - version = LittleLong (in->version); + pinmodel = buffer; + base = buffer; + + version = LittleLong (pinmodel->version); if (version != MD2ALIAS_VERSION) Host_Error ("%s has wrong version number (%i should be %i)", loadmodel->name, version, MD2ALIAS_VERSION); loadmodel->type = mod_alias; - loadmodel->aliastype = ALIASTYPE_MD2; - loadmodel->SERAddEntity = Mod_Alias_SERAddEntity; - loadmodel->Draw = R_DrawAliasModel; + loadmodel->aliastype = ALIASTYPE_MDLMD2; + loadmodel->Draw = R_DrawQ1Q2AliasModel; loadmodel->DrawSky = NULL; loadmodel->DrawShadow = NULL; - if (LittleLong(in->num_tris < 1) || LittleLong(in->num_tris) > MD2MAX_TRIANGLES) - Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(in->num_tris)); - if (LittleLong(in->num_xyz < 1) || LittleLong(in->num_xyz) > MD2MAX_VERTS) - Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(in->num_xyz)); - if (LittleLong(in->num_frames < 1) || LittleLong(in->num_frames) > MD2MAX_FRAMES) - Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(in->num_frames)); - if (LittleLong(in->num_skins < 0) || LittleLong(in->num_skins) > MAX_SKINS) - Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(in->num_skins)); - - end = LittleLong(in->ofs_end); - if (LittleLong(in->num_skins) >= 1 && (LittleLong(in->ofs_skins <= 0) || LittleLong(in->ofs_skins) >= end)) + if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES) + Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris)); + if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > MD2MAX_VERTS) + Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz)); + if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES) + Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames)); + if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MAX_SKINS) + Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins)); + + end = LittleLong(pinmodel->ofs_end); + if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= end)) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_st <= 0) || LittleLong(in->ofs_st) >= end) + if (LittleLong(pinmodel->ofs_st <= 0) || LittleLong(pinmodel->ofs_st) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_tris <= 0) || LittleLong(in->ofs_tris) >= end) + if (LittleLong(pinmodel->ofs_tris <= 0) || LittleLong(pinmodel->ofs_tris) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_frames <= 0) || LittleLong(in->ofs_frames) >= end) + if (LittleLong(pinmodel->ofs_frames <= 0) || LittleLong(pinmodel->ofs_frames) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_glcmds <= 0) || LittleLong(in->ofs_glcmds) >= end) + if (LittleLong(pinmodel->ofs_glcmds <= 0) || LittleLong(pinmodel->ofs_glcmds) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - loadmodel->numskins = LittleLong(in->num_skins); - loadmodel->numverts = LittleLong(in->num_xyz); -// loadmodel->md2num_st = LittleLong(in->num_st); - loadmodel->numtris = LittleLong(in->num_tris); - loadmodel->numframes = LittleLong(in->num_frames); - *numglcmds = LittleLong(in->num_glcmds); + loadmodel->numskins = LittleLong(pinmodel->num_skins); + numxyz = LittleLong(pinmodel->num_xyz); + numst = LittleLong(pinmodel->num_st); + loadmodel->numtris = LittleLong(pinmodel->num_tris); + loadmodel->numframes = LittleLong(pinmodel->num_frames); loadmodel->flags = 0; // there are no MD2 flags loadmodel->synctype = ST_RAND; -} -void Mod_MD2_LoadSkins(char *in) -{ - int i; -// load the skins + // load the skins + inskin = (void*)(base + LittleLong(pinmodel->ofs_skins)); if (loadmodel->numskins) { loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); @@ -604,51 +645,103 @@ void Mod_MD2_LoadSkins(char *in) loadmodel->skinscenes[i].framecount = 1; loadmodel->skinscenes[i].loop = true; loadmodel->skinscenes[i].framerate = 10; - loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, in, 0, 0, true, r_mipskins.integer, true); + loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, inskin, 0, 0, true, r_mipskins.integer, true); loadmodel->skinframes[i].fog = image_masktex; loadmodel->skinframes[i].pants = NULL; loadmodel->skinframes[i].shirt = NULL; loadmodel->skinframes[i].glow = NULL; loadmodel->skinframes[i].merged = NULL; - in += MD2MAX_SKINNAME; + inskin += MD2MAX_SKINNAME; } } -} -/* -void Mod_MD2_LoadTriangles(md2triangle_t *in) -{ - int i, j; - loadmodel->md2data_tris = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(md2triangle_t)); + // load the triangles and stvert data + inst = (void*)(base + LittleLong(pinmodel->ofs_st)); + intri = (void*)(base + LittleLong(pinmodel->ofs_tris)); + skinwidth = LittleLong(pinmodel->skinwidth); + skinheight = LittleLong(pinmodel->skinheight); + + stverts = Mem_Alloc(tempmempool, numst * sizeof(float[2])); + s = 1.0f / skinwidth; + t = 1.0f / skinheight; + for (i = 0;i < numst;i++) + { + j = (unsigned short) LittleShort(inst[i*2+0]); + k = (unsigned short) LittleShort(inst[i*2+1]); + if (j >= skinwidth || k >= skinheight) + { + Mem_Free(stverts); + Host_Error("Mod_MD2_LoadGeometry: invalid skin coordinate (%i %i) on vert %i of model %s\n", j, k, i, loadmodel->name); + } + stverts[i*2+0] = j * s; + stverts[i*2+1] = k * t; + } + + md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash)); + md2verthashdata = Mem_Alloc(tempmempool, loadmodel->numtris * 3 * sizeof(*hash)); // swap the triangle list + num = 0; + loadmodel->mdlmd2data_indices = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); for (i = 0;i < loadmodel->numtris;i++) { for (j = 0;j < 3;j++) { - loadmodel->md2data_tris[i].index_xyz[j] = LittleShort (in[i].index_xyz[j]); - loadmodel->md2data_tris[i].index_st[j] = LittleShort (in[i].index_st[j]); - if (loadmodel->md2data_tris[i].index_xyz[j] >= loadmodel->md2num_xyz) - Host_Error ("%s has invalid vertex indices", loadmodel->name); - if (loadmodel->md2data_tris[i].index_st[j] >= loadmodel->md2num_st) - Host_Error ("%s has invalid vertex indices", loadmodel->name); + xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]); + st = (unsigned short) LittleShort (intri[i].index_st[j]); + if (xyz >= numxyz || st >= numst) + { + Mem_Free(md2verthash); + Mem_Free(md2verthashdata); + Mem_Free(stverts); + if (xyz >= numxyz) + Host_Error("Mod_MD2_LoadGeometry: invalid xyz index (%i) on triangle %i of model %s\n", xyz, i, loadmodel->name); + if (st >= numst) + Host_Error("Mod_MD2_LoadGeometry: invalid st index (%i) on triangle %i of model %s\n", st, i, loadmodel->name); + } + s = stverts[st*2+0]; + t = stverts[st*2+1]; + hashindex = (xyz * 17 + st) & 255; + for (hash = md2verthash[hashindex];hash;hash = hash->next) + if (hash->xyz == xyz && hash->st[0] == s && hash->st[1] == t) + break; + if (hash == NULL) + { + hash = md2verthashdata + num++; + hash->xyz = xyz; + hash->st[0] = s; + hash->st[1] = t; + hash->next = md2verthash[hashindex]; + md2verthash[hashindex] = hash; + } + loadmodel->mdlmd2data_indices[i*3+j] = (hash - md2verthashdata); } } -} -*/ -void Mod_MD2_LoadFrames(void *start) -{ - int i, j; - long datapointer; - md2frame_t *pinframe; + Mem_Free(stverts); + + loadmodel->numverts = num; + vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int)); + loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2])); + for (i = 0;i < num;i++) + { + hash = md2verthashdata + i; + vertremap[i] = hash->xyz; + loadmodel->mdlmd2data_texcoords[i*2+0] = hash->st[0]; + loadmodel->mdlmd2data_texcoords[i*2+1] = hash->st[1]; + } + + Mem_Free(md2verthash); + Mem_Free(md2verthashdata); + + // load frames // LordHavoc: doing proper bbox for model aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000; aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000000000; modelyawradius = 0; modelradius = 0; - datapointer = (long) start; -// load the frames + datapointer = (base + LittleLong(pinmodel->ofs_frames)); + // load the frames loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); loadmodel->mdlmd2data_frames = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(md2frame_t)); loadmodel->mdlmd2data_pose = Mem_Alloc(loadmodel->mempool, loadmodel->numverts * loadmodel->numframes * sizeof(trivertx_t)); @@ -663,8 +756,8 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->mdlmd2data_frames[i].scale[j] = LittleFloat(pinframe->scale[j]); loadmodel->mdlmd2data_frames[i].translate[j] = LittleFloat(pinframe->translate[j]); } - Mod_MD2_ConvertVerts (loadmodel->numverts, loadmodel->mdlmd2data_frames[i].scale, loadmodel->mdlmd2data_frames[i].translate, (void *)datapointer, &loadmodel->mdlmd2data_pose[i * loadmodel->numverts]); - datapointer += loadmodel->numverts * sizeof(trivertx_t); + Mod_MD2_ConvertVerts (loadmodel->mdlmd2data_frames[i].scale, loadmodel->mdlmd2data_frames[i].translate, (void *)datapointer, &loadmodel->mdlmd2data_pose[i * loadmodel->numverts], vertremap); + datapointer += numxyz * sizeof(trivertx_t); strcpy(loadmodel->animscenes[i].name, loadmodel->mdlmd2data_frames[i].name); loadmodel->animscenes[i].firstframe = i; @@ -673,10 +766,11 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->animscenes[i].loop = true; } + Mem_Free(vertremap); + // LordHavoc: model bbox modelyawradius = sqrt(modelyawradius); modelradius = sqrt(modelradius); -// loadmodel->modelradius = modelradius; for (j = 0;j < 3;j++) { loadmodel->normalmins[j] = aliasbboxmin[j]; @@ -689,29 +783,6 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; } -void Mod_MD2_LoadGLCmds(int *in, int numglcmds) -{ - int i; - // load the draw list - loadmodel->md2data_glcmds = Mem_Alloc(loadmodel->mempool, numglcmds * sizeof(int)); - for (i = 0;i < numglcmds;i++) - loadmodel->md2data_glcmds[i] = LittleLong(in[i]); -} - -void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) -{ - md2_t *pinmodel; - int numglcmds; - long base; - pinmodel = buffer; - base = (long) buffer; - Mod_MD2_ReadHeader(pinmodel, &numglcmds); - Mod_MD2_LoadSkins((void*)(base + LittleLong(pinmodel->ofs_skins))); -// Mod_MD2_LoadTriangles((void*)(base + LittleLong(pinmodel->ofs_tris))); - Mod_MD2_LoadFrames((void*)(base + LittleLong(pinmodel->ofs_frames))); - Mod_MD2_LoadGLCmds((void*)(base + LittleLong(pinmodel->ofs_glcmds)), numglcmds); -} - static void zymswapintblock(int *m, int size) { size /= 4; @@ -724,7 +795,7 @@ static void zymswapintblock(int *m, int size) void Mod_LoadZymoticModel(model_t *mod, void *buffer) { - int i, pbase, *bonecount; + int i, pbase, *bonecount, numposes; unsigned int count, a, b, c, *renderlist, *renderlistend; rtexture_t **texture; char *shadername; @@ -795,6 +866,7 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->skinframes->glow = NULL; loadmodel->skinframes->merged = NULL; loadmodel->numskins = 1; + numposes = pheader->lump_poses.length / sizeof(float[3][4]) / pheader->numbones; // go through the lumps, swapping things @@ -817,6 +889,12 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->animscenes[i].framerate = scene->framerate; loadmodel->animscenes[i].loop = (scene->flags & ZYMSCENEFLAG_NOLOOP) == 0; + if ((unsigned int) loadmodel->animscenes[i].firstframe >= numposes) + Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, numposes); + if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > numposes) + Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) + framecount (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes); + if (loadmodel->animscenes[i].framerate < 0) + Host_Error("Mod_LoadZymoticModel: scene framerate (%f) < 0\n", loadmodel->animscenes[i].framerate); scene++; } @@ -850,7 +928,7 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) zymswapintblock((void *) (pheader->lump_render.start + pbase), pheader->lump_render.length); // validate renderlist and swap winding order of tris renderlist = (void *) (pheader->lump_render.start + pbase); - renderlistend = (void *) ((byte *) renderlist + pheader->lump_render.length); + renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length); i = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]); if (pheader->lump_render.length != i) Host_Error("Mod_LoadZymoticModel: renderlist is wrong size in %s (is %i bytes, should be %i bytes)\n", loadmodel->name, pheader->lump_render.length, i); @@ -891,7 +969,6 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) // model bbox modelradius = pheader->radius; -// loadmodel->modelradius = pheader->radius; for (i = 0;i < 3;i++) { loadmodel->normalmins[i] = pheader->mins[i]; @@ -908,8 +985,8 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->yawmins[2] = loadmodel->normalmins[2]; loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; - loadmodel->SERAddEntity = Mod_Alias_SERAddEntity; - loadmodel->Draw = R_DrawAliasModel; + loadmodel->Draw = R_DrawZymoticModel; loadmodel->DrawSky = NULL; loadmodel->DrawShadow = NULL; } +