crc = 0;
buf = NULL;
- if (!mod->needload)
+ if (mod->isworldmodel != isworldmodel)
+ mod->needload = true;
+ if (mod->needload || checkdisk)
{
- if (checkdisk)
+ if (checkdisk && !mod->needload)
+ Con_DPrintf("checking model %s\n", mod->name);
+ buf = FS_LoadFile (mod->name, tempmempool, false);
+ if (buf)
{
- buf = FS_LoadFile (mod->name, tempmempool, false);
- if (!buf)
- {
- if (crash)
- Host_Error ("Mod_LoadModel: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING*
- return NULL;
- }
-
crc = CRC_Block(buf, fs_filesize);
- }
- else
- crc = mod->crc;
-
- if (mod->crc == crc && mod->isworldmodel == isworldmodel)
- {
- if (buf)
- Mem_Free(buf);
- return mod; // already loaded
+ if (mod->crc != crc)
+ mod->needload = true;
}
}
+ if (!mod->needload)
+ return mod; // already loaded
Con_DPrintf("loading model %s\n", mod->name);
-
- if (!buf)
- {
- buf = FS_LoadFile (mod->name, tempmempool, false);
- if (!buf)
- {
- if (crash)
- Host_Error ("Mod_LoadModel: %s not found", mod->name);
- return NULL;
- }
- crc = CRC_Block(buf, fs_filesize);
- }
-
- // allocate a new model
- loadmodel = mod;
-
// LordHavoc: unload the existing model in this slot (if there is one)
Mod_UnloadModel(mod);
+ // load the model
mod->isworldmodel = isworldmodel;
mod->used = true;
mod->crc = crc;
// errors can prevent the corresponding mod->needload = false;
mod->needload = true;
+ // default model radius and bounding box (mainly for missing models)
+ mod->radius = 16;
+ VectorSet(mod->normalmins, -mod->radius, -mod->radius, -mod->radius);
+ VectorSet(mod->normalmaxs, mod->radius, mod->radius, mod->radius);
+ VectorSet(mod->yawmins, -mod->radius, -mod->radius, -mod->radius);
+ VectorSet(mod->yawmaxs, mod->radius, mod->radius, mod->radius);
+ VectorSet(mod->rotatedmins, -mod->radius, -mod->radius, -mod->radius);
+ VectorSet(mod->rotatedmaxs, mod->radius, mod->radius, mod->radius);
+
// all models use memory, so allocate a memory pool
- mod->mempool = Mem_AllocPool(mod->name);
+ mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
// all models load textures, so allocate a texture pool
if (cls.state != ca_dedicated)
mod->texturepool = R_AllocTexturePool();
- // call the apropriate loader
- num = LittleLong(*((int *)buf));
- if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf);
- else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf);
- else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf);
- else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf);
- else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf);
- else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf);
- else if (strlen(mod->name) >= 4 && !strcmp(mod->name - 4, ".map")) Mod_MAP_Load(mod, buf);
- else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf);
- else Host_Error("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
-
- Mem_Free(buf);
+ if (buf)
+ {
+ num = LittleLong(*((int *)buf));
+ // call the apropriate loader
+ loadmodel = mod;
+ if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf);
+ else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf);
+ else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf);
+ else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf);
+ else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf);
+ else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf);
+ else if (strlen(mod->name) >= 4 && !strcmp(mod->name - 4, ".map")) Mod_MAP_Load(mod, buf);
+ else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf);
+ else Host_Error("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
+ Mem_Free(buf);
+ }
+ else if (crash)
+ {
+ // LordHavoc: Sys_Error was *ANNOYING*
+ Con_Printf ("Mod_LoadModel: %s not found", mod->name);
+ }
// no errors occurred
mod->needload = false;
Mod_LoadModel(mod, true, true, mod->isworldmodel);
else
{
- if (mod->type == mod_invalid)
- Host_Error("Mod_CheckLoaded: invalid model\n");
+ //if (mod->type == mod_invalid)
+ // Host_Error("Mod_CheckLoaded: invalid model\n");
mod->used = true;
return;
}
Con_Print("usage: modelprecache <filename>\n");
}
+int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices)
+{
+ int i, count;
+ qbyte *used;
+ used = Mem_Alloc(tempmempool, numvertices);
+ memset(used, 0, numvertices);
+ for (i = 0;i < numelements;i++)
+ used[elements[i]] = 1;
+ for (i = 0, count = 0;i < numvertices;i++)
+ remapvertices[i] = used[i] ? count++ : -1;
+ Mem_Free(used);
+ return count;
+}
+
#if 1
// fast way, using an edge hash
#define TRIANGLEEDGEHASH 1024
void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
{
- float f;
+ float f, tangentcross[3];
normal3f[0] = (v1[1] - v0[1]) * (v2[2] - v0[2]) - (v1[2] - v0[2]) * (v2[1] - v0[1]);
normal3f[1] = (v1[2] - v0[2]) * (v2[0] - v0[0]) - (v1[0] - v0[0]) * (v2[2] - v0[2]);
normal3f[2] = (v1[0] - v0[0]) * (v2[1] - v0[1]) - (v1[1] - v0[1]) * (v2[0] - v0[0]);
f = -DotProduct(svector3f, normal3f);
VectorMA(svector3f, f, normal3f, svector3f);
VectorNormalize(svector3f);
+ CrossProduct(tvector3f, svector3f, tangentcross);
+ // if texture is mapped the wrong way (counterclockwise), the tangents have to be flipped, this is detected by calculating a normal from the two tangents, and seeing if it is opposite the surface normal
+ if (DotProduct(tangentcross, normal3f) < 0)
+ {
+ VectorNegate(svector3f, svector3f);
+ VectorNegate(tvector3f, tvector3f);
+ }
}
// warning: this is an expensive function!
int i, words, numtags, line, tagsetsused = false, wordsoverflow;
char *text;
const char *data;
- skinfile_t *skinfile, *first = NULL;
+ skinfile_t *skinfile = NULL, *first = NULL;
skinfileitem_t *skinfileitem;
char word[10][MAX_QPATH];
overridetagnameset_t tagsets[MAX_SKINS];
for (i = 0;i < MAX_SKINS && (data = text = FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true));i++)
{
numtags = 0;
- skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t));
- skinfile->next = first;
- first = skinfile;
+
+ // If it's the first file we parse
+ if (skinfile == NULL)
+ {
+ skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+ first = skinfile;
+ }
+ else
+ {
+ skinfile->next = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+ skinfile = skinfile->next;
+ }
+ skinfile->next = NULL;
+
for(line = 0;;line++)
{
// parse line