X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_alias.c;h=b095d9bf8fc56f454a9857d4606abf2b602819a6;hb=4b08159c59c67950fccf0fc9a1d038d53ecb0203;hp=517975fd0d338b1e14e6e51845100f2fded19e64;hpb=f5a4b82533115030947726519e70b51d64f573da;p=xonotic%2Fdarkplaces.git diff --git a/model_alias.c b/model_alias.c index 517975fd..b095d9bf 100644 --- a/model_alias.c +++ b/model_alias.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "image.h" +#include "r_shadow.h" static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"}; @@ -28,42 +29,57 @@ void Mod_AliasInit (void) Cvar_RegisterVariable(&r_mipskins); } -// LordHavoc: proper bounding box considerations -static float aliasbboxmin[3], aliasbboxmax[3], modelyawradius, modelradius; - -static float vertst[MAXALIASVERTS][2]; -static int vertusage[MAXALIASVERTS]; -static int vertonseam[MAXALIASVERTS]; -static int vertremap[MAXALIASVERTS]; -static int temptris[MAXALIASTRIS][3]; +static void Mod_CalcAliasModelBBoxes (void) +{ + int vnum, meshnum; + float dist, yawradius, radius; + aliasmesh_t *mesh; + aliasvertex_t *v; + VectorClear(loadmodel->normalmins); + VectorClear(loadmodel->normalmaxs); + yawradius = 0; + radius = 0; + for (meshnum = 0, mesh = loadmodel->aliasdata_meshes;meshnum < loadmodel->aliasnum_meshes;meshnum++, mesh++) + { + for (vnum = 0, v = mesh->data_aliasvertex;vnum < mesh->num_vertices * mesh->num_frames;vnum++, v++) + { + if (loadmodel->normalmins[0] > v->origin[0]) loadmodel->normalmins[0] = v->origin[0]; + if (loadmodel->normalmins[1] > v->origin[1]) loadmodel->normalmins[1] = v->origin[1]; + if (loadmodel->normalmins[2] > v->origin[2]) loadmodel->normalmins[2] = v->origin[2]; + if (loadmodel->normalmaxs[0] < v->origin[0]) loadmodel->normalmaxs[0] = v->origin[0]; + if (loadmodel->normalmaxs[1] < v->origin[1]) loadmodel->normalmaxs[1] = v->origin[1]; + if (loadmodel->normalmaxs[2] < v->origin[2]) loadmodel->normalmaxs[2] = v->origin[2]; + dist = v->origin[0] * v->origin[0] + v->origin[1] * v->origin[1]; + if (yawradius < dist) + yawradius = dist; + dist += v->origin[2] * v->origin[2]; + if (radius < dist) + radius = dist; + } + } + radius = sqrt(radius); + yawradius = sqrt(yawradius); + loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius; + loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius; + loadmodel->yawmins[2] = loadmodel->normalmins[2]; + loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; + loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius; + loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius; + loadmodel->radius = radius; + loadmodel->radius2 = radius * radius; +} -static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out) +static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int *vertremap) { int i, j; - float dist; vec3_t temp; for (i = 0;i < inverts;i++) { if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply... continue; - 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]; - // update bounding box - if (temp[0] < aliasbboxmin[0]) aliasbboxmin[0] = temp[0]; - if (temp[1] < aliasbboxmin[1]) aliasbboxmin[1] = temp[1]; - if (temp[2] < aliasbboxmin[2]) aliasbboxmin[2] = temp[2]; - if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0]; - if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1]; - if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2]; - dist = temp[0]*temp[0]+temp[1]*temp[1]; - if (modelyawradius < dist) - modelyawradius = dist; - dist += temp[2]*temp[2]; - if (modelradius < dist) - modelradius = dist; - j = vertremap[i]; // not onseam if (j >= 0) VectorCopy(temp, out[j].origin); @@ -73,25 +89,24 @@ static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, } } -static void Mod_BuildAliasVertexTextureVectors(int numtriangles, const int *elements, int numverts, aliasvertex_t *vertices, const float *texcoords, float *vertexbuffer, float *svectorsbuffer, float *tvectorsbuffer, float *normalsbuffer) +static void Mod_BuildAliasVertexTextureVectors(int numverts, aliasvertex_t *vertices, const float *texcoords, float *vertexbuffer, float *svectorsbuffer, float *tvectorsbuffer, float *normalsbuffer, int numtriangles, const int *elements) { int i; for (i = 0;i < numverts;i++) - VectorCopy(vertices[i].origin, &vertexbuffer[i * 4]); + VectorCopy(vertices[i].origin, &vertexbuffer[i * 3]); Mod_BuildTextureVectorsAndNormals(numverts, numtriangles, vertexbuffer, texcoords, elements, svectorsbuffer, tvectorsbuffer, normalsbuffer); for (i = 0;i < numverts;i++) { - // LordHavoc: alias models are backwards, apparently - vertices[i].normal[0] = normalsbuffer[i * 4 + 0]; - vertices[i].normal[1] = normalsbuffer[i * 4 + 1]; - vertices[i].normal[2] = normalsbuffer[i * 4 + 2]; - vertices[i].svector[0] = svectorsbuffer[i * 4 + 0]; - vertices[i].svector[1] = svectorsbuffer[i * 4 + 1]; - vertices[i].svector[2] = svectorsbuffer[i * 4 + 2]; + vertices[i].normal[0] = normalsbuffer[i * 3 + 0]; + vertices[i].normal[1] = normalsbuffer[i * 3 + 1]; + vertices[i].normal[2] = normalsbuffer[i * 3 + 2]; + vertices[i].svector[0] = svectorsbuffer[i * 3 + 0]; + vertices[i].svector[1] = svectorsbuffer[i * 3 + 1]; + vertices[i].svector[2] = svectorsbuffer[i * 3 + 2]; } } -static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, vec3_t translate, int *elements, float *texcoords, aliasvertex_t *posedata) +static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, int outverts, vec3_t scale, vec3_t translate, float *texcoords, aliasvertex_t *posedata, int numtris, int *elements, int *vertremap) { int i, f, pose, groupframes; float interval, *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer; @@ -102,10 +117,10 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v animscene_t *scene; pose = 0; scene = loadmodel->animscenes; - vertexbuffer = Mem_Alloc(tempmempool, loadmodel->numverts * sizeof(float[4]) * 4); - svectorsbuffer = vertexbuffer + loadmodel->numverts * 4; - tvectorsbuffer = svectorsbuffer + loadmodel->numverts * 4; - normalsbuffer = tvectorsbuffer + loadmodel->numverts * 4; + vertexbuffer = Mem_Alloc(tempmempool, outverts * sizeof(float[3+3+3+3])); + svectorsbuffer = vertexbuffer + outverts * 3; + tvectorsbuffer = svectorsbuffer + outverts * 3; + normalsbuffer = tvectorsbuffer + outverts * 3; for (f = 0;f < loadmodel->numframes;f++) { pframetype = (daliasframetype_t *)datapointer; @@ -129,7 +144,7 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups if (interval < 0.01f) - Host_Error("Mod_LoadAliasGroup: invalid interval"); + Host_Error("Mod_MDL_LoadFrames: invalid interval"); } // get scene name from first frame @@ -147,8 +162,8 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v { pinframe = (daliasframe_t *)datapointer; datapointer += sizeof(daliasframe_t); - Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, posedata + pose * loadmodel->numverts); - Mod_BuildAliasVertexTextureVectors(loadmodel->numtris, elements, loadmodel->numverts, posedata + pose * loadmodel->numverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer); + Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, posedata + pose * outverts, vertremap); + Mod_BuildAliasVertexTextureVectors(outverts, posedata + pose * outverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements); datapointer += sizeof(trivertx_t) * inverts; pose++; } @@ -156,64 +171,109 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v Mem_Free(vertexbuffer); } -static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int precache) -{ - int i; - for (i = 0;i < width*height;i++) - if (((qbyte *)&palette[in[i]])[3] > 0) - return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), palette); - return NULL; -} - -static int Mod_LoadExternalSkin (char *basename, skinframe_t *skinframe, int precache) -{ - skinframe->base = loadtextureimagewithmaskandnmap(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1); - if (!skinframe->base) - skinframe->base = loadtextureimagewithmaskandnmap(loadmodel->texturepool, basename, 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1); - skinframe->fog = image_masktex; - skinframe->nmap = image_nmaptex; - skinframe->gloss = loadtextureimage(loadmodel->texturepool, va("%s_gloss" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->pants = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->shirt = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->glow = loadtextureimage(loadmodel->texturepool, va("%s_glow" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->merged = NULL; - return skinframe->base != NULL || skinframe->pants != NULL || skinframe->shirt != NULL || skinframe->glow != NULL; -} - -static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int height, skinframe_t *skinframe, int precache) +void Mod_BuildAliasSkinFromSkinFrame(aliasskin_t *skin, skinframe_t *skinframe) { - qbyte *temp1, *temp2; - if (!skindata) - return false; - temp1 = Mem_Alloc(loadmodel->mempool, width * height * 8); - temp2 = temp1 + width * height * 4; - Image_Copy8bitRGBA(skindata, temp1, width * height, palette_nofullbrights); - Image_HeightmapToNormalmap(temp1, temp2, width, height, false, 1); - skinframe->nmap = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), NULL); - Mem_Free(temp1); - skinframe->gloss = NULL; - skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, false); // pants - skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, false); // shirt - skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, precache); // glow - if (skinframe->pants || skinframe->shirt) + aliaslayer_t *layer; + skin->flags = 0; + // fog texture only exists if some pixels are transparent... + if (skinframe->fog != NULL) + skin->flags |= ALIASSKIN_TRANSPARENT; + // fog and gloss layers always exist + skin->num_layers = 2; + if (skinframe->glow != NULL) + skin->num_layers++; + if (skinframe->merged != NULL) + skin->num_layers += 2; + if (skinframe->base != NULL) + skin->num_layers += 2; + if (skinframe->pants != NULL) + skin->num_layers += 2; + if (skinframe->shirt != NULL) + skin->num_layers += 2; + layer = skin->data_layers = Mem_Alloc(loadmodel->mempool, skin->num_layers * sizeof(aliaslayer_t)); + if (skinframe->glow != NULL) + { + layer->flags = 0; + layer->texture = skinframe->glow; + layer++; + } + if (skinframe->merged != NULL) + { + layer->flags = ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE; + if (skinframe->glow != NULL) + layer->flags |= ALIASLAYER_ADD; + layer->texture = skinframe->merged; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->base != NULL) + { + layer->flags = (skinframe->merged != NULL ? ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED : 0) | ALIASLAYER_DIFFUSE; + if (skinframe->glow != NULL) + layer->flags |= ALIASLAYER_ADD; + layer->texture = skinframe->base; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->pants != NULL) + { + layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; + if (skinframe->glow != NULL || skinframe->base != NULL) + layer->flags |= ALIASLAYER_ADD; + layer->texture = skinframe->pants; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->shirt != NULL) + { + layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; + if (skinframe->glow != NULL || skinframe->base != NULL || skinframe->pants != NULL) + layer->flags |= ALIASLAYER_ADD; + layer->texture = skinframe->shirt; + layer->nmap = skinframe->nmap; + layer++; + } + layer->flags = ALIASLAYER_FOG; + layer->texture = skinframe->fog; + layer++; + layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_SPECULAR; + layer->texture = skinframe->gloss; + layer->nmap = skinframe->nmap; + layer++; + if (skinframe->merged != NULL) + { + layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE; + layer->texture = skinframe->merged; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->base != NULL) + { + layer->flags = ALIASLAYER_DRAW_PER_LIGHT | (skinframe->merged != NULL ? ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED : 0) | ALIASLAYER_DIFFUSE; + layer->texture = skinframe->base; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->pants != NULL) + { + layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_PANTS; + layer->texture = skinframe->pants; + layer->nmap = skinframe->nmap; + layer++; + } + if (skinframe->shirt != NULL) { - skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_normal", basename), palette_nocolormapnofullbrights, false); // normal (no special colors) - skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_body", basename), palette_nofullbrights, precache); // body (normal + pants + shirt, but not glow) + layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; + layer->texture = skinframe->shirt; + layer->nmap = skinframe->nmap; + layer++; } - else - skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_base", basename), palette_nofullbrights, precache); // no special colors - // quake model skins don't have alpha - skinframe->fog = NULL; - return true; } -void Mod_BuildMDLMD2MeshInfo(int *elements, float *texcoords, aliasvertex_t *posedata) +void Mod_BuildMDLMD2MeshInfo(int numverts, int numtris, int *elements, float *texcoord2f, aliasvertex_t *posedata) { int i; aliasmesh_t *mesh; - aliasskin_t *skin; - aliaslayer_t *layer; - skinframe_t *skinframe; loadmodel->aliasnum_meshes = 1; mesh = loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t)); @@ -223,112 +283,18 @@ void Mod_BuildMDLMD2MeshInfo(int *elements, float *texcoords, aliasvertex_t *pos mesh->num_frames += loadmodel->animscenes[i].framecount; for (i = 0;i < loadmodel->numskins;i++) mesh->num_skins += loadmodel->skinscenes[i].framecount; - mesh->num_triangles = loadmodel->numtris; - mesh->num_vertices = loadmodel->numverts; + mesh->num_triangles = numtris; + mesh->num_vertices = numverts; mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t)); - mesh->data_elements = elements; - mesh->data_neighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); - Mod_ValidateElements(mesh->data_elements, loadmodel->numtris, loadmodel->numverts, __FILE__, __LINE__); - Mod_BuildTriangleNeighbors(mesh->data_neighbors, elements, loadmodel->numtris); - mesh->data_texcoords = texcoords; - mesh->data_vertices = posedata; - for (i = 0, skin = mesh->data_skins, skinframe = loadmodel->skinframes;i < mesh->num_skins;i++, skin++, skinframe++) - { - skin->flags = 0; - // fog texture only exists if some pixels are transparent... - if (skinframe->fog != NULL) - skin->flags |= ALIASSKIN_TRANSPARENT; - // fog and gloss layers always exist - skin->num_layers = 2; - if (skinframe->glow != NULL) - skin->num_layers++; - if (skinframe->merged != NULL) - skin->num_layers += 2; - if (skinframe->base != NULL) - skin->num_layers += 2; - if (skinframe->pants != NULL) - skin->num_layers += 2; - if (skinframe->shirt != NULL) - skin->num_layers += 2; - layer = skin->data_layers = Mem_Alloc(loadmodel->mempool, skin->num_layers * sizeof(aliaslayer_t)); - if (skinframe->glow != NULL) - { - layer->flags = 0; - layer->texture = skinframe->glow; - layer++; - } - if (skinframe->merged != NULL) - { - layer->flags = ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE; - if (skinframe->glow != NULL) - layer->flags |= ALIASLAYER_ADD; - layer->texture = skinframe->merged; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->base != NULL) - { - layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE; - if (skinframe->glow != NULL) - layer->flags |= ALIASLAYER_ADD; - layer->texture = skinframe->base; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->pants != NULL) - { - layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; - if (skinframe->glow != NULL || skinframe->base != NULL) - layer->flags |= ALIASLAYER_ADD; - layer->texture = skinframe->pants; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->shirt != NULL) - { - layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; - if (skinframe->glow != NULL || skinframe->base != NULL || skinframe->pants != NULL) - layer->flags |= ALIASLAYER_ADD; - layer->texture = skinframe->shirt; - layer->nmap = skinframe->nmap; - layer++; - } - layer->flags = ALIASLAYER_FOG; - layer->texture = skinframe->fog; - layer++; - layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_SPECULAR; - layer->texture = skinframe->gloss; - layer->nmap = skinframe->nmap; - layer++; - if (skinframe->merged != NULL) - { - layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE; - layer->texture = skinframe->merged; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->base != NULL) - { - layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE; - layer->texture = skinframe->base; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->pants != NULL) - { - layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_PANTS; - layer->texture = skinframe->pants; - layer->nmap = skinframe->nmap; - layer++; - } - if (skinframe->shirt != NULL) - { - layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT; - layer->texture = skinframe->shirt; - layer->nmap = skinframe->nmap; - layer++; - } - } + mesh->data_element3i = elements; + mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3])); + Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__); + Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles); + mesh->data_texcoord2f = texcoord2f; + mesh->data_aliasvertex = posedata; + for (i = 0;i < mesh->num_skins;i++) + Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + i, loadmodel->skinframes + i); + Mod_CalcAliasModelBBoxes(); } #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); @@ -336,10 +302,10 @@ void Mod_BuildMDLMD2MeshInfo(int *elements, float *texcoords, aliasvertex_t *pos extern void R_Model_Alias_Draw(entity_render_t *ent); extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent); extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor); -void Mod_LoadAliasModel (model_t *mod, void *buffer) +extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); +void Mod_LoadQ1AliasModel (model_t *mod, void *buffer) { - int i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins, *elements; + int i, j, version, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins, *elements, numverts, numtris; float scales, scalet, scale[3], translate[3], interval, *texcoords; mdl_t *pinmodel; stvert_t *pinstverts; @@ -355,8 +321,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) skinframe_t tempskinframe; animscene_t *tempskinscenes; skinframe_t *tempskinframes; - modelyawradius = 0; - modelradius = 0; + float *vertst; + int *vertonseam, *vertusage, *vertremap, *temptris; datapointer = buffer; pinmodel = (mdl_t *)datapointer; @@ -381,10 +347,10 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) BOUNDI(skinwidth,0,4096); skinheight = LittleLong (pinmodel->skinheight); BOUNDI(skinheight,0,4096); - loadmodel->numverts = numverts = LittleLong(pinmodel->numverts); - BOUNDI(loadmodel->numverts,0,MAXALIASVERTS); - loadmodel->numtris = LittleLong(pinmodel->numtris); - BOUNDI(loadmodel->numtris,0,MAXALIASTRIS); + numverts = LittleLong(pinmodel->numverts); + BOUNDI(numverts,0,65536); + numtris = LittleLong(pinmodel->numtris); + BOUNDI(numtris,0,65536 / 3); // max elements limit, rather than max triangles limit loadmodel->numframes = LittleLong(pinmodel->numframes); BOUNDI(loadmodel->numframes,0,65536); loadmodel->synctype = LittleLong (pinmodel->synctype); @@ -424,7 +390,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) datapointer += sizeof(stvert_t) * numverts; pintriangles = (dtriangle_t *)datapointer; - datapointer += sizeof(dtriangle_t) * loadmodel->numtris; + datapointer += sizeof(dtriangle_t) * numtris; startframes = datapointer; totalposes = 0; @@ -477,7 +443,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) interval = LittleFloat(pinskinintervals[0].interval); if (interval < 0.01f) - Host_Error("Mod_LoadAliasModel: invalid interval\n"); + Host_Error("Mod_LoadQ1AliasModel: invalid interval\n"); } sprintf(loadmodel->skinscenes[i].name, "skin %i", i); @@ -492,8 +458,8 @@ 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); - if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0)) - Mod_LoadInternalSkin(name, (qbyte *)datapointer, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0); + if (!Mod_LoadSkinFrame(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true)) + Mod_LoadSkinFrame_Internal(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true, (qbyte *)datapointer, skinwidth, skinheight); datapointer += skinwidth * skinheight; totalskins++; } @@ -503,7 +469,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) for (;;) { sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins); - if (Mod_LoadExternalSkin(name, &tempskinframe, loadmodel->numskins == 0)) + if (Mod_LoadSkinFrame (&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true)) { // expand the arrays to make room tempskinscenes = loadmodel->skinscenes; @@ -529,39 +495,45 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) } // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data) + vertst = Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2])); + vertonseam = Mem_Alloc(tempmempool, numverts * sizeof(int)); + vertusage = Mem_Alloc(tempmempool, numverts * 2 * sizeof(int)); + vertremap = Mem_Alloc(tempmempool, numverts * 2 * sizeof(int)); + temptris = Mem_Alloc(tempmempool, numtris * sizeof(int[3])); + scales = 1.0 / skinwidth; scalet = 1.0 / skinheight; for (i = 0;i < numverts;i++) { vertonseam[i] = LittleLong(pinstverts[i].onseam); - vertst[i][0] = (LittleLong(pinstverts[i].s) + 0.5) * scales; - vertst[i][1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet; - vertst[i+numverts][0] = vertst[i][0] + 0.5; - vertst[i+numverts][1] = vertst[i][1]; + vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales; + vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet; + vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5; + vertst[(i+numverts)*2+1] = vertst[i*2+1]; vertusage[i] = 0; vertusage[i+numverts] = 0; } // load triangle data - elements = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris); + elements = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * numtris); // count the vertices used for (i = 0;i < numverts*2;i++) vertusage[i] = 0; - for (i = 0;i < loadmodel->numtris;i++) + for (i = 0;i < numtris;i++) { - temptris[i][0] = LittleLong(pintriangles[i].vertindex[0]); - temptris[i][1] = LittleLong(pintriangles[i].vertindex[1]); - temptris[i][2] = LittleLong(pintriangles[i].vertindex[2]); + temptris[i*3+0] = LittleLong(pintriangles[i].vertindex[0]); + temptris[i*3+1] = LittleLong(pintriangles[i].vertindex[1]); + temptris[i*3+2] = LittleLong(pintriangles[i].vertindex[2]); if (!LittleLong(pintriangles[i].facesfront)) // backface { - if (vertonseam[temptris[i][0]]) temptris[i][0] += numverts; - if (vertonseam[temptris[i][1]]) temptris[i][1] += numverts; - if (vertonseam[temptris[i][2]]) temptris[i][2] += numverts; + if (vertonseam[temptris[i*3+0]]) temptris[i*3+0] += numverts; + if (vertonseam[temptris[i*3+1]]) temptris[i*3+1] += numverts; + if (vertonseam[temptris[i*3+2]]) temptris[i*3+2] += numverts; } - vertusage[temptris[i][0]]++; - vertusage[temptris[i][1]]++; - vertusage[temptris[i][2]]++; + vertusage[temptris[i*3+0]]++; + vertusage[temptris[i*3+1]]++; + vertusage[temptris[i*3+2]]++; } // build remapping table and compact array totalverts = 0; @@ -570,89 +542,53 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) if (vertusage[i]) { vertremap[i] = totalverts; - vertst[totalverts][0] = vertst[i][0]; - vertst[totalverts][1] = vertst[i][1]; + vertst[totalverts*2+0] = vertst[i*2+0]; + vertst[totalverts*2+1] = vertst[i*2+1]; totalverts++; } else vertremap[i] = -1; // not used at all } - loadmodel->numverts = totalverts; // remap the triangle references - for (i = 0;i < loadmodel->numtris;i++) - { - elements[i*3+0] = vertremap[temptris[i][0]]; - elements[i*3+1] = vertremap[temptris[i][1]]; - elements[i*3+2] = vertremap[temptris[i][2]]; - } + for (i = 0;i < numtris * 3;i++) + elements[i] = vertremap[temptris[i]]; // store the texture coordinates - texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * totalverts); + texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts); for (i = 0;i < totalverts;i++) { - texcoords[i*4+0] = vertst[i][0]; - texcoords[i*4+1] = vertst[i][1]; + texcoords[i*2+0] = vertst[i*2+0]; + texcoords[i*2+1] = vertst[i*2+1]; } // load the frames loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes); posedata = Mem_Alloc(loadmodel->mempool, sizeof(aliasvertex_t) * totalposes * totalverts); + Mod_MDL_LoadFrames (startframes, numverts, totalverts, scale, translate, texcoords, posedata, numtris, elements, vertremap); + Mod_BuildMDLMD2MeshInfo(totalverts, numtris, elements, texcoords, posedata); - // LordHavoc: doing proper bbox for model - aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000; - aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000000000; - - Mod_MDL_LoadFrames (startframes, numverts, scale, translate, elements, texcoords, posedata); - - modelyawradius = sqrt(modelyawradius); - modelradius = sqrt(modelradius); - for (j = 0;j < 3;j++) - { - loadmodel->normalmins[j] = aliasbboxmin[j]; - loadmodel->normalmaxs[j] = aliasbboxmax[j]; - loadmodel->rotatedmins[j] = -modelradius; - loadmodel->rotatedmaxs[j] = modelradius; - } - loadmodel->yawmins[0] = loadmodel->yawmins[1] = -(loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelyawradius); - loadmodel->yawmins[2] = loadmodel->normalmins[2]; - loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; - loadmodel->radius = modelradius; - loadmodel->radius2 = modelradius * modelradius; - - Mod_BuildMDLMD2MeshInfo(elements, texcoords, posedata); + Mem_Free(vertst); + Mem_Free(vertonseam); + Mem_Free(vertusage); + Mem_Free(vertremap); + Mem_Free(temptris); } -static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int *vertremap) +static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int numverts, int *vertremap) { int i; - float dist; trivertx_t *in; - vec3_t temp; - for (i = 0;i < loadmodel->numverts;i++) + for (i = 0;i < numverts;i++) { in = v + vertremap[i]; - 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]; - if (temp[2] < aliasbboxmin[2]) aliasbboxmin[2] = temp[2]; - if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0]; - if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1]; - if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2]; - dist = temp[0]*temp[0]+temp[1]*temp[1]; - if (modelyawradius < dist) - modelyawradius = dist; - dist += temp[2]*temp[2]; - if (modelradius < dist) - modelradius = dist; - VectorCopy(temp, out[i].origin); + out[i].origin[0] = in->v[0] * scale[0] + translate[0]; + out[i].origin[1] = in->v[1] * scale[1] + translate[1]; + out[i].origin[2] = in->v[2] * scale[2] + translate[2]; } } void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) { - int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, *elements; + int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, *elements, numverts, numtris; float *stverts, s, t, scale[3], translate[3], *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer, *texcoords; aliasvertex_t *posedata; md2_t *pinmodel; @@ -685,13 +621,13 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume; loadmodel->DrawLight = R_Model_Alias_DrawLight; - if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES) + if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > (65536 / 3)) 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) + if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > 65536) 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) + if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > 65536) 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) + if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > 256) Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins)); end = LittleLong(pinmodel->ofs_end); @@ -709,7 +645,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->numskins = LittleLong(pinmodel->num_skins); numxyz = LittleLong(pinmodel->num_xyz); numst = LittleLong(pinmodel->num_st); - loadmodel->numtris = LittleLong(pinmodel->num_tris); + numtris = LittleLong(pinmodel->num_tris); loadmodel->numframes = LittleLong(pinmodel->num_frames); loadmodel->flags = 0; // there are no MD2 flags @@ -727,15 +663,8 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->skinscenes[i].framecount = 1; loadmodel->skinscenes[i].loop = true; loadmodel->skinscenes[i].framerate = 10; - loadmodel->skinframes[i].base = loadtextureimagewithmaskandnmap (loadmodel->texturepool, inskin, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1); - loadmodel->skinframes[i].fog = image_masktex; - loadmodel->skinframes[i].nmap = image_nmaptex; - loadmodel->skinframes[i].gloss = NULL; - loadmodel->skinframes[i].pants = NULL; - loadmodel->skinframes[i].shirt = NULL; - loadmodel->skinframes[i].glow = NULL; - loadmodel->skinframes[i].merged = NULL; - inskin += MD2MAX_SKINNAME; + Mod_LoadSkinFrame (loadmodel->skinframes + i, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true); + inskin += MD2_SKINNAME; } } @@ -762,11 +691,11 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) } md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash)); - md2verthashdata = Mem_Alloc(tempmempool, loadmodel->numtris * 3 * sizeof(*hash)); + md2verthashdata = Mem_Alloc(tempmempool, numtris * 3 * sizeof(*hash)); // swap the triangle list num = 0; - elements = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); - for (i = 0;i < loadmodel->numtris;i++) + elements = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3])); + for (i = 0;i < numtris;i++) { for (j = 0;j < 3;j++) { @@ -803,36 +732,29 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) Mem_Free(stverts); - loadmodel->numverts = num; + numverts = num; vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int)); - texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[4])); + texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2])); for (i = 0;i < num;i++) { hash = md2verthashdata + i; vertremap[i] = hash->xyz; - texcoords[i*4+0] = hash->st[0]; - texcoords[i*4+1] = hash->st[1]; + texcoords[i*2+0] = hash->st[0]; + 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 = (base + LittleLong(pinmodel->ofs_frames)); // load the frames + datapointer = (base + LittleLong(pinmodel->ofs_frames)); loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); - posedata = Mem_Alloc(loadmodel->mempool, loadmodel->numverts * loadmodel->numframes * sizeof(trivertx_t)); + posedata = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->numframes * sizeof(trivertx_t)); - vertexbuffer = Mem_Alloc(tempmempool, loadmodel->numverts * sizeof(float[4]) * 4); - svectorsbuffer = vertexbuffer + loadmodel->numverts * 4; - tvectorsbuffer = svectorsbuffer + loadmodel->numverts * 4; - normalsbuffer = tvectorsbuffer + loadmodel->numverts * 4; + vertexbuffer = Mem_Alloc(tempmempool, numverts * sizeof(float[3+3+3+3])); + svectorsbuffer = vertexbuffer + numverts * 3; + tvectorsbuffer = svectorsbuffer + numverts * 3; + normalsbuffer = tvectorsbuffer + numverts * 3; for (i = 0;i < loadmodel->numframes;i++) { pinframe = (md2frame_t *)datapointer; @@ -842,8 +764,8 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) scale[j] = LittleFloat(pinframe->scale[j]); translate[j] = LittleFloat(pinframe->translate[j]); } - Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, posedata + i * loadmodel->numverts, vertremap); - Mod_BuildAliasVertexTextureVectors(loadmodel->numtris, elements, loadmodel->numverts, posedata + i * loadmodel->numverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer); + Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, posedata + i * numverts, numverts, vertremap); + Mod_BuildAliasVertexTextureVectors(numverts, posedata + i * numverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements); datapointer += numxyz * sizeof(trivertx_t); strcpy(loadmodel->animscenes[i].name, pinframe->name); @@ -856,30 +778,113 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) Mem_Free(vertremap); - // LordHavoc: model bbox - modelyawradius = sqrt(modelyawradius); - modelradius = sqrt(modelradius); - for (j = 0;j < 3;j++) + Mod_BuildMDLMD2MeshInfo(numverts, numtris, elements, texcoords, posedata); +} + +void Mod_LoadQ3AliasModel(model_t *mod, void *buffer) +{ + int i, j, version; + float *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer; + md3modelheader_t *pinmodel; + md3frameinfo_t *pinframe; + md3mesh_t *pinmesh; + aliasmesh_t *mesh; + skinframe_t tempskinframe; + + pinmodel = buffer; + + if (memcmp(pinmodel->identifier, "IDP3", 4)) + Host_Error ("%s is not a MD3 (IDP3) file\n", loadmodel->name); + version = LittleLong (pinmodel->version); + if (version != MD3VERSION) + Host_Error ("%s has wrong version number (%i should be %i)", + loadmodel->name, version, MD3VERSION); + + loadmodel->type = mod_alias; + loadmodel->aliastype = ALIASTYPE_ALIAS; + loadmodel->DrawSky = NULL; + loadmodel->Draw = R_Model_Alias_Draw; + loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow; + loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume; + loadmodel->DrawLight = R_Model_Alias_DrawLight; + loadmodel->flags = 0; + loadmodel->synctype = ST_RAND; + + // set up some global info about the model + loadmodel->numframes = LittleLong(pinmodel->num_frames); + loadmodel->numskins = 1; + loadmodel->aliasnum_meshes = LittleLong(pinmodel->num_meshes); + loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t)); + loadmodel->skinscenes[0].firstframe = 0; + loadmodel->skinscenes[0].framecount = 1; + loadmodel->skinscenes[0].loop = true; + loadmodel->skinscenes[0].framerate = 10; + + // load frameinfo + loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); + for (i = 0, pinframe = (md3frameinfo_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++) { - loadmodel->normalmins[j] = aliasbboxmin[j]; - loadmodel->normalmaxs[j] = aliasbboxmax[j]; - loadmodel->rotatedmins[j] = -modelradius; - loadmodel->rotatedmaxs[j] = modelradius; + strcpy(loadmodel->animscenes[i].name, pinframe->name); + loadmodel->animscenes[i].firstframe = i; + loadmodel->animscenes[i].framecount = 1; + loadmodel->animscenes[i].framerate = 10; + loadmodel->animscenes[i].loop = true; } - loadmodel->yawmins[0] = loadmodel->yawmins[1] = -(loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelyawradius); - loadmodel->yawmins[2] = loadmodel->normalmins[2]; - loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; - loadmodel->radius = modelradius; - loadmodel->radius2 = modelradius * modelradius; - Mod_BuildMDLMD2MeshInfo(elements, texcoords, posedata); + // tags are not loaded yet + + // load meshes + loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t)); + for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->aliasnum_meshes;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end))) + { + if (memcmp(pinmesh->identifier, "IDP3", 4)) + Host_Error("Mod_LoadQ3AliasModel: invalid mesh identifier (not IDP3)\n"); + mesh = loadmodel->aliasdata_meshes + i; + mesh->num_skins = loadmodel->numskins; + mesh->num_frames = LittleLong(pinmesh->num_frames); + mesh->num_vertices = LittleLong(pinmesh->num_vertices); + mesh->num_triangles = LittleLong(pinmesh->num_triangles); + mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t)); + mesh->data_element3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3])); + mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3])); + mesh->data_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2])); + mesh->data_aliasvertex = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_frames * sizeof(aliasvertex_t)); + for (j = 0;j < mesh->num_triangles * 3;j++) + mesh->data_element3i[j] = LittleLong(((int *)((qbyte *)pinmesh + pinmesh->lump_elements))[j]); + for (j = 0;j < mesh->num_vertices;j++) + { + mesh->data_texcoord2f[j * 2 + 0] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 0]); + mesh->data_texcoord2f[j * 2 + 1] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 1]); + } + for (j = 0;j < mesh->num_vertices * mesh->num_frames;j++) + { + mesh->data_aliasvertex[j].origin[0] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 0]) * (1.0f / 64.0f); + mesh->data_aliasvertex[j].origin[1] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 1]) * (1.0f / 64.0f); + mesh->data_aliasvertex[j].origin[2] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 2]) * (1.0f / 64.0f); + } + vertexbuffer = Mem_Alloc(tempmempool, mesh->num_vertices * sizeof(float[3+3+3+3])); + svectorsbuffer = vertexbuffer + mesh->num_vertices * 3; + tvectorsbuffer = svectorsbuffer + mesh->num_vertices * 3; + normalsbuffer = tvectorsbuffer + mesh->num_vertices * 3; + for (j = 0;j < mesh->num_frames;j++) + Mod_BuildAliasVertexTextureVectors(mesh->num_vertices, mesh->data_aliasvertex + j * mesh->num_vertices, mesh->data_texcoord2f, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, mesh->num_triangles, mesh->data_element3i); + Mem_Free(vertexbuffer); + + memset(&tempskinframe, 0, sizeof(tempskinframe)); + if (LittleLong(pinmesh->num_shaders) >= 1 && ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name[0]) + Mod_LoadSkinFrame (&tempskinframe, ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true); + Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__); + Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles); + Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins, &tempskinframe); + } + Mod_CalcAliasModelBBoxes(); } extern void R_Model_Zymotic_DrawSky(entity_render_t *ent); extern void R_Model_Zymotic_Draw(entity_render_t *ent); extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent); extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor); +extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); void Mod_LoadZymoticModel(model_t *mod, void *buffer) { zymtype1header_t *pinmodel, *pheader; @@ -938,8 +943,8 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->flags = 0; // there are no flags loadmodel->numframes = pheader->numscenes; loadmodel->synctype = ST_SYNC; - loadmodel->numtris = pheader->numtris; - loadmodel->numverts = 0; + //loadmodel->numtris = pheader->numtris; + //loadmodel->numverts = 0; { unsigned int i; @@ -973,12 +978,6 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->skinscenes[0].loop = true; loadmodel->skinscenes[0].framerate = 10; loadmodel->skinframes = (void *)(loadmodel->skinscenes + 1); - loadmodel->skinframes->base = NULL; - loadmodel->skinframes->fog = NULL; - loadmodel->skinframes->pants = NULL; - loadmodel->skinframes->shirt = NULL; - loadmodel->skinframes->glow = NULL; - loadmodel->skinframes->merged = NULL; loadmodel->numskins = 1; } @@ -1064,15 +1063,15 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) { int i; - float *intexcoord, *outtexcoord; + float *intexcoord2f, *outtexcoord2f; // zymlump_t lump_texcoords; // float texcoords[numvertices][2]; - loadmodel->zymdata_texcoords = outtexcoord = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[4])); - intexcoord = (void *) (pheader->lump_texcoords.start + pbase); + loadmodel->zymdata_texcoords = outtexcoord2f = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[2])); + intexcoord2f = (void *) (pheader->lump_texcoords.start + pbase); for (i = 0;i < pheader->numverts;i++) { - outtexcoord[i*4+0] = BigFloat(intexcoord[i*2+0]); + outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]); // flip T coordinate for OpenGL - outtexcoord[i*4+1] = 1 - BigFloat(intexcoord[i*2+1]); + outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]); } }