*/
#include "quakedef.h"
+#include "image.h"
static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
static int vertremap[MAXALIASVERTS];
static int temptris[MAXALIASTRIS][3];
-static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
+static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out)
{
- int i, j, invalidnormals = 0;
+ int i, j;
float dist;
vec3_t temp;
for (i = 0;i < inverts;i++)
j = vertremap[i]; // not onseam
if (j >= 0)
- {
- VectorCopy(v[i].v, out[j].v);
- out[j].lightnormalindex = v[i].lightnormalindex;
- if (out[j].lightnormalindex >= NUMVERTEXNORMALS)
- {
- invalidnormals++;
- out[j].lightnormalindex = 0;
- }
- }
+ VectorCopy(temp, out[j].origin);
j = vertremap[i+inverts]; // onseam
if (j >= 0)
- {
- VectorCopy(v[i].v, out[j].v);
- out[j].lightnormalindex = v[i].lightnormalindex;
- if (out[j].lightnormalindex >= NUMVERTEXNORMALS)
- {
- invalidnormals++;
- out[j].lightnormalindex = 0;
- }
- }
+ VectorCopy(temp, out[j].origin);
+ }
+}
+
+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)
+{
+ int i;
+ for (i = 0;i < numverts;i++)
+ VectorCopy(vertices[i].origin, &vertexbuffer[i * 4]);
+ 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];
}
- if (invalidnormals)
- Con_Printf("Mod_ConvertAliasVerts: \"%s\", %i invalid normal indices found\n", loadmodel->name, invalidnormals);
}
-static void Mod_MDL_LoadFrames (qbyte * datapointer, int inverts, int outverts, vec3_t scale, vec3_t translate)
+static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, vec3_t translate, int *elements, float *texcoords, aliasvertex_t *posedata)
{
- daliasframetype_t *pframetype;
- daliasframe_t *pinframe;
- daliasgroup_t *group;
- daliasinterval_t *intervals;
- int i, f, pose, groupframes;
- float interval;
- animscene_t *scene;
+ int i, f, pose, groupframes;
+ float interval, *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer;
+ daliasframetype_t *pframetype;
+ daliasframe_t *pinframe;
+ daliasgroup_t *group;
+ daliasinterval_t *intervals;
+ 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;
for (f = 0;f < loadmodel->numframes;f++)
{
pframetype = (daliasframetype_t *)datapointer;
{
pinframe = (daliasframe_t *)datapointer;
datapointer += sizeof(daliasframe_t);
-
- // convert to MD2 frame headers
- strcpy(loadmodel->mdlmd2data_frames[pose].name, pinframe->name);
- VectorCopy(scale, loadmodel->mdlmd2data_frames[pose].scale);
- VectorCopy(translate, loadmodel->mdlmd2data_frames[pose].translate);
-
- Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, loadmodel->mdlmd2data_pose + pose * outverts);
+ 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);
datapointer += sizeof(trivertx_t) * inverts;
pose++;
}
}
+ Mem_Free(vertexbuffer);
}
-static rtexture_t *GL_SkinSplitShirt(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache)
+static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int precache)
{
- int i, pixels, passed;
- qbyte pixeltest[16];
- for (i = 0;i < 16;i++)
- pixeltest[i] = (bits & (1 << i)) != 0;
- pixels = width*height;
- passed = 0;
- while(pixels--)
- {
- if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
- {
- passed++;
- // turn to white while copying
- if (*in >= 128 && *in < 224) // backwards ranges
- *out = (*in & 15) ^ 15;
- else
- *out = *in & 15;
- }
- else
- *out = 0;
- in++;
- out++;
- }
- if (passed)
- return R_LoadTexture (loadmodel->texturepool, name, width, height, out - width*height, TEXTYPE_QPALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
- else
- return NULL;
-}
-
-static rtexture_t *GL_SkinSplit(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache)
-{
- int i, pixels, passed;
- qbyte pixeltest[16];
- for (i = 0;i < 16;i++)
- pixeltest[i] = (bits & (1 << i)) != 0;
- pixels = width*height;
- passed = 0;
- while(pixels--)
- {
- if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
- {
- passed++;
- *out = *in;
- }
- else
- *out = 0;
- in++;
- out++;
- }
- if (passed)
- return R_LoadTexture (loadmodel->texturepool, name, width, height, out - width*height, TEXTYPE_QPALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
- else
- return NULL;
+ 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 = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, r_mipskins.integer, precache);
- skinframe->fog = image_masktex;
+ 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 = 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->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, qbyte *skintemp, int width, int height, skinframe_t *skinframe, int precache)
+static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int height, skinframe_t *skinframe, int precache)
{
- if (!skindata || !skintemp)
+ qbyte *temp1, *temp2;
+ if (!skindata)
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
+ 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)
{
- 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)
+ 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)
}
else
- skinframe->base = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), precache); // no special colors
+ 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)
+{
+ 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));
+ mesh->num_skins = 0;
+ mesh->num_frames = 0;
+ for (i = 0;i < loadmodel->numframes;i++)
+ 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->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++;
+ }
+ }
+}
+
#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);
#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
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_DrawDepth(entity_render_t *ent);
-extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Alias_DrawOntoLight(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)
{
- int i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins;
- mdl_t *pinmodel;
- stvert_t *pinstverts;
- dtriangle_t *pintriangles;
- daliasskintype_t *pinskintype;
- daliasskingroup_t *pinskingroup;
- daliasskininterval_t *pinskinintervals;
- daliasframetype_t *pinframetype;
- daliasgroup_t *pinframegroup;
- float scales, scalet, scale[3], translate[3], interval;
- qbyte *datapointer, *startframes, *startskins;
- char name[MAX_QPATH];
- qbyte *skintemp = NULL;
- skinframe_t tempskinframe;
- animscene_t *tempskinscenes;
- skinframe_t *tempskinframes;
+ int i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins, *elements;
+ float scales, scalet, scale[3], translate[3], interval, *texcoords;
+ mdl_t *pinmodel;
+ stvert_t *pinstverts;
+ dtriangle_t *pintriangles;
+ daliasskintype_t *pinskintype;
+ daliasskingroup_t *pinskingroup;
+ daliasskininterval_t *pinskinintervals;
+ daliasframetype_t *pinframetype;
+ daliasgroup_t *pinframegroup;
+ aliasvertex_t *posedata;
+ qbyte *datapointer, *startframes, *startskins;
+ char name[MAX_QPATH];
+ skinframe_t tempskinframe;
+ animscene_t *tempskinscenes;
+ skinframe_t *tempskinframes;
modelyawradius = 0;
modelradius = 0;
loadmodel->name, version, ALIAS_VERSION);
loadmodel->type = mod_alias;
- loadmodel->aliastype = ALIASTYPE_MDLMD2;
+ loadmodel->aliastype = ALIASTYPE_ALIAS;
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Alias_Draw;
loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
- loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
loadmodel->DrawLight = R_Model_Alias_DrawLight;
- loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
loadmodel->numskins = LittleLong(pinmodel->numskins);
BOUNDI(loadmodel->numskins,0,256);
}
// load the skins
- skintemp = Mem_Alloc(tempmempool, skinwidth * skinheight);
loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, totalskins * sizeof(skinframe_t));
totalskins = 0;
else
sprintf (name, "%s_%i", loadmodel->name, i);
if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0))
- Mod_LoadInternalSkin(name, (qbyte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0);
+ Mod_LoadInternalSkin(name, (qbyte *)datapointer, 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 (;;)
for (i = 0;i < numverts;i++)
{
vertonseam[i] = LittleLong(pinstverts[i].onseam);
- vertst[i][0] = LittleLong(pinstverts[i].s) * scales;
- vertst[i][1] = LittleLong(pinstverts[i].t) * scalet;
+ 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];
vertusage[i] = 0;
}
// load triangle data
- loadmodel->mdlmd2data_indices = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris);
+ elements = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris);
// count the vertices used
for (i = 0;i < numverts*2;i++)
// remap the triangle references
for (i = 0;i < loadmodel->numtris;i++)
{
- 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]];
+ elements[i*3+0] = vertremap[temptris[i][0]];
+ elements[i*3+1] = vertremap[temptris[i][1]];
+ elements[i*3+2] = vertremap[temptris[i][2]];
}
// store the texture coordinates
- loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * totalverts);
+ texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * totalverts);
for (i = 0;i < totalverts;i++)
{
- loadmodel->mdlmd2data_texcoords[i*4+0] = vertst[i][0];
- loadmodel->mdlmd2data_texcoords[i*4+1] = vertst[i][1];
+ texcoords[i*4+0] = vertst[i][0];
+ texcoords[i*4+1] = vertst[i][1];
}
// load the frames
loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
- loadmodel->mdlmd2data_frames = Mem_Alloc(loadmodel->mempool, sizeof(md2frame_t) * totalposes);
- loadmodel->mdlmd2data_pose = Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * totalposes * totalverts);
+ posedata = Mem_Alloc(loadmodel->mempool, sizeof(aliasvertex_t) * totalposes * totalverts);
// 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, totalverts, scale, translate);
+ Mod_MDL_LoadFrames (startframes, numverts, scale, translate, elements, texcoords, posedata);
modelyawradius = sqrt(modelyawradius);
modelradius = sqrt(modelradius);
loadmodel->radius = modelradius;
loadmodel->radius2 = modelradius * modelradius;
- loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
- Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
+ Mod_BuildMDLMD2MeshInfo(elements, texcoords, posedata);
}
-static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out, int *vertremap)
+static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int *vertremap)
{
- int i, invalidnormals = 0;
+ int i;
float dist;
trivertx_t *in;
vec3_t temp;
for (i = 0;i < loadmodel->numverts;i++)
{
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];
dist += temp[2]*temp[2];
if (modelradius < dist)
modelradius = dist;
- out[i].lightnormalindex = in->lightnormalindex;
- if (out[i].lightnormalindex >= NUMVERTEXNORMALS)
- {
- invalidnormals++;
- out[i].lightnormalindex = 0;
- }
+ VectorCopy(temp, out[i].origin);
}
- if (invalidnormals)
- Con_Printf("Mod_MD2_ConvertVerts: \"%s\", %i invalid normal indices found\n", loadmodel->name, invalidnormals);
}
void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
{
- int *vertremap;
+ int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, *elements;
+ float *stverts, s, t, scale[3], translate[3], *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer, *texcoords;
+ aliasvertex_t *posedata;
md2_t *pinmodel;
- qbyte *base;
- int version, end;
- int i, j, k, hashindex, num, numxyz, numst, xyz, st;
- float *stverts, s, t;
+ qbyte *base, *datapointer;
+ md2frame_t *pinframe;
+ char *inskin;
+ md2triangle_t *intri;
+ unsigned short *inst;
struct md2verthash_s
{
struct md2verthash_s *next;
float st[2];
}
*hash, **md2verthash, *md2verthashdata;
- qbyte *datapointer;
- md2frame_t *pinframe;
- char *inskin;
- md2triangle_t *intri;
- unsigned short *inst;
- int skinwidth, skinheight;
pinmodel = buffer;
base = buffer;
loadmodel->name, version, MD2ALIAS_VERSION);
loadmodel->type = mod_alias;
- loadmodel->aliastype = ALIASTYPE_MDLMD2;
+ loadmodel->aliastype = ALIASTYPE_ALIAS;
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Alias_Draw;
loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
- loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
loadmodel->DrawLight = R_Model_Alias_DrawLight;
- loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
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));
inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
if (loadmodel->numskins)
{
- loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
- loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, sizeof(skinframe_t) * loadmodel->numskins);
+ loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins + sizeof(skinframe_t) * loadmodel->numskins);
+ loadmodel->skinframes = (void *)(loadmodel->skinscenes + loadmodel->numskins);
for (i = 0;i < loadmodel->numskins;i++)
{
loadmodel->skinscenes[i].firstframe = i;
loadmodel->skinscenes[i].framecount = 1;
loadmodel->skinscenes[i].loop = true;
loadmodel->skinscenes[i].framerate = 10;
- loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, inskin, 0, 0, true, r_mipskins.integer, true);
+ 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;
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]));
+ elements = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
for (i = 0;i < loadmodel->numtris;i++)
{
for (j = 0;j < 3;j++)
hash->next = md2verthash[hashindex];
md2verthash[hashindex] = hash;
}
- loadmodel->mdlmd2data_indices[i*3+j] = (hash - md2verthashdata);
+ elements[i*3+j] = (hash - md2verthashdata);
}
}
loadmodel->numverts = num;
vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int));
- loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[4]));
+ texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[4]));
for (i = 0;i < num;i++)
{
hash = md2verthashdata + i;
vertremap[i] = hash->xyz;
- loadmodel->mdlmd2data_texcoords[i*4+0] = hash->st[0];
- loadmodel->mdlmd2data_texcoords[i*4+1] = hash->st[1];
+ texcoords[i*4+0] = hash->st[0];
+ texcoords[i*4+1] = hash->st[1];
}
Mem_Free(md2verthash);
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));
+ posedata = Mem_Alloc(loadmodel->mempool, loadmodel->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;
for (i = 0;i < loadmodel->numframes;i++)
{
pinframe = (md2frame_t *)datapointer;
datapointer += sizeof(md2frame_t);
- strcpy(loadmodel->mdlmd2data_frames[i].name, pinframe->name);
for (j = 0;j < 3;j++)
{
- loadmodel->mdlmd2data_frames[i].scale[j] = LittleFloat(pinframe->scale[j]);
- loadmodel->mdlmd2data_frames[i].translate[j] = LittleFloat(pinframe->translate[j]);
+ scale[j] = LittleFloat(pinframe->scale[j]);
+ translate[j] = LittleFloat(pinframe->translate[j]);
}
- Mod_MD2_ConvertVerts (loadmodel->mdlmd2data_frames[i].scale, loadmodel->mdlmd2data_frames[i].translate, (void *)datapointer, &loadmodel->mdlmd2data_pose[i * loadmodel->numverts], vertremap);
+ 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);
datapointer += numxyz * sizeof(trivertx_t);
- strcpy(loadmodel->animscenes[i].name, loadmodel->mdlmd2data_frames[i].name);
+ 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;
}
+ Mem_Free(vertexbuffer);
Mem_Free(vertremap);
loadmodel->radius = modelradius;
loadmodel->radius2 = modelradius * modelradius;
- loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
- Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
-}
-
-static void zymswapintblock(int *m, int size)
-{
- size /= 4;
- while(size--)
- {
- *m = BigLong(*m);
- m++;
- }
+ Mod_BuildMDLMD2MeshInfo(elements, texcoords, posedata);
}
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_DrawDepth(entity_render_t *ent);
-extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Zymotic_DrawOntoLight(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);
void Mod_LoadZymoticModel(model_t *mod, void *buffer)
{
zymtype1header_t *pinmodel, *pheader;
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Zymotic_Draw;
loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
- loadmodel->DrawDepth = NULL;//R_Model_Zymotic_DrawDepth;
loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
- loadmodel->DrawOntoLight = NULL;//R_Model_Zymotic_DrawOntoLight;
// byteswap header
pheader = pinmodel;
// go through the lumps, swapping things
{
- unsigned int i, numposes;
+ int i, numposes;
zymscene_t *scene;
// zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
loadmodel->animscenes[i].framecount = BigLong(scene->length);
loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
- if ((unsigned int) loadmodel->animscenes[i].firstframe >= numposes)
+ if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) 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)
+ if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) 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);
}
{
- unsigned int i;
+ int i;
float *poses;
// zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
loadmodel->zymdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
}
{
- unsigned int i;
+ int i;
zymbone_t *bone;
// zymlump_t lump_bones; // zymbone_t bone[numbones];
loadmodel->zymdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(zymbone_t));
memcpy(loadmodel->zymdata_bones[i].name, bone[i].name, sizeof(bone[i].name));
loadmodel->zymdata_bones[i].flags = BigLong(bone[i].flags);
loadmodel->zymdata_bones[i].parent = BigLong(bone[i].parent);
- if (bone[i].parent >= i)
- Host_Error("Mod_LoadZymoticModel: bone[i].parent >= i in %s\n", loadmodel->name);
+ if (loadmodel->zymdata_bones[i].parent >= i)
+ Host_Error("Mod_LoadZymoticModel: bone[%i].parent >= %i in %s\n", i, i, loadmodel->name);
}
}
{
- unsigned int i, *bonecount;
+ int i, *bonecount;
// zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
- loadmodel->zymdata_vertbonecounts = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(int));
+ loadmodel->zymdata_vertbonecounts = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
bonecount = (void *) (pheader->lump_vertbonecounts.start + pbase);
- for (i = 0;i < pheader->numbones;i++)
+ for (i = 0;i < pheader->numverts;i++)
{
loadmodel->zymdata_vertbonecounts[i] = BigLong(bonecount[i]);
if (loadmodel->zymdata_vertbonecounts[i] < 1)
}
{
- unsigned int i;
+ int i;
zymvertex_t *vertdata;
// zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
loadmodel->zymdata_verts = Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
vertdata = (void *) (pheader->lump_verts.start + pbase);
- for (i = 0;i < pheader->lump_verts.length / 4;i++)
+ for (i = 0;i < pheader->lump_verts.length / (int) sizeof(zymvertex_t);i++)
{
loadmodel->zymdata_verts[i].bonenum = BigLong(vertdata[i].bonenum);
- loadmodel->zymdata_verts[i].origin[0] = BigLong(vertdata[i].origin[0]);
- loadmodel->zymdata_verts[i].origin[1] = BigLong(vertdata[i].origin[1]);
- loadmodel->zymdata_verts[i].origin[2] = BigLong(vertdata[i].origin[2]);
+ loadmodel->zymdata_verts[i].origin[0] = BigFloat(vertdata[i].origin[0]);
+ loadmodel->zymdata_verts[i].origin[1] = BigFloat(vertdata[i].origin[1]);
+ loadmodel->zymdata_verts[i].origin[2] = BigFloat(vertdata[i].origin[2]);
}
}
{
- unsigned int i;
+ int i;
float *intexcoord, *outtexcoord;
// 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);
- for (i = 0;i < pheader->numverts;i++);
+ for (i = 0;i < pheader->numverts;i++)
{
outtexcoord[i*4+0] = BigFloat(intexcoord[i*2+0]);
// flip T coordinate for OpenGL
}
{
- unsigned int i, count, a, b, c, *renderlist, *renderlistend, *outrenderlist;
+ int i, count, *renderlist, *renderlistend, *outrenderlist;
// zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, pheader->lump_render.length);
// byteswap, validate, and swap winding order of tris
*outrenderlist++ = count;
while (count--)
{
- a = BigLong(renderlist[0]);
- b = BigLong(renderlist[1]);
- c = BigLong(renderlist[2]);
- renderlist += 3;
- if (a >= pheader->numverts || b >= pheader->numverts || c >= pheader->numverts)
+ outrenderlist[2] = BigLong(renderlist[0]);
+ outrenderlist[1] = BigLong(renderlist[1]);
+ outrenderlist[0] = BigLong(renderlist[2]);
+ if ((unsigned int)outrenderlist[0] >= (unsigned int)pheader->numverts
+ || (unsigned int)outrenderlist[1] >= (unsigned int)pheader->numverts
+ || (unsigned int)outrenderlist[2] >= (unsigned int)pheader->numverts)
Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (out of bounds index)\n", loadmodel->name);
- *outrenderlist++ = c;
- *outrenderlist++ = b;
- *outrenderlist++ = a;
+ renderlist += 3;
+ outrenderlist += 3;
}
}
}
{
- unsigned int i;
+ int i;
char *shadername;
// zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
+ loadmodel->zymdata_textures = Mem_Alloc(loadmodel->mempool, pheader->numshaders * sizeof(rtexture_t *));
shadername = (void *) (pheader->lump_shaders.start + pbase);
for (i = 0;i < pheader->numshaders;i++)
- loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, r_mipskins.integer, true);
+ loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0));
}
{