}
}
+void Mod_LoadLightList(void)
+{
+ int a, n, numlights;
+ char lightsfilename[1024], *s, *t, *lightsstring;
+ mlight_t *e;
+
+ strcpy(lightsfilename, loadmodel->name);
+ COM_StripExtension(lightsfilename, lightsfilename);
+ strcat(lightsfilename, ".lights");
+ s = lightsstring = (char *) COM_LoadFile (lightsfilename, false);
+ if (s)
+ {
+ numlights = 0;
+ while (*s)
+ {
+ while (*s && *s != '\n')
+ s++;
+ if (!*s)
+ {
+ Mem_Free(lightsstring);
+ Host_Error("lights file must end with a newline\n");
+ }
+ s++;
+ numlights++;
+ }
+ loadmodel->lights = Mem_Alloc(loadmodel->mempool, numlights * sizeof(mlight_t));
+ s = lightsstring;
+ n = 0;
+ while (*s && n < numlights)
+ {
+ t = s;
+ while (*s && *s != '\n')
+ s++;
+ if (!*s)
+ {
+ Mem_Free(lightsstring);
+ Host_Error("misparsed lights file!\n");
+ }
+ e = loadmodel->lights + n;
+ *s = 0;
+ a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style);
+ *s = '\n';
+ if (a != 14)
+ {
+ Mem_Free(lightsstring);
+ Host_Error("invalid lights file, found %d parameters on line %i, should be 13 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone style)\n", a, n + 1);
+ }
+ s++;
+ n++;
+ }
+ if (*s)
+ {
+ Mem_Free(lightsstring);
+ Host_Error("misparsed lights file!\n");
+ }
+ loadmodel->numlights = numlights;
+ Mem_Free(lightsstring);
+ }
+}
+
/*
=================
subdivpolytriangles = 0;
subdivpolyverts = 0;
SubdividePolygon (surf->poly_numverts, surf->poly_verts);
+ if (subdivpolytriangles < 1)
+ Host_Error("Mod_GenerateWarpMesh: no triangles?\n");
- mesh = &surf->mesh;
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + subdivpolytriangles * sizeof(int[3]) + subdivpolyverts * sizeof(surfvertex_t));
mesh->numverts = subdivpolyverts;
mesh->numtriangles = subdivpolytriangles;
- if (mesh->numtriangles < 1)
- Host_Error("Mod_GenerateWarpMesh: no triangles?\n");
- mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
- mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+ mesh->vertex = (surfvertex_t *)(mesh + 1);
+ mesh->index = (int *)(mesh->vertex + mesh->numverts);
memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
for (i = 0;i < mesh->numtriangles;i++)
surf->lightmaptexturestride = 0;
surf->lightmaptexture = NULL;
- mesh = &surf->mesh;
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
mesh->numverts = surf->poly_numverts;
mesh->numtriangles = surf->poly_numverts - 2;
- mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
- mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+ mesh->vertex = (surfvertex_t *)(mesh + 1);
+ mesh->index = (int *)(mesh->vertex + mesh->numverts);
memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
index = mesh->index;
xscale = (xscale - xbase) * 16.0 / ((surf->extents[0] & ~15) + 16);
yscale = (yscale - ybase) * 16.0 / ((surf->extents[1] & ~15) + 16);
- mesh = &surf->mesh;
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
mesh->numverts = surf->poly_numverts;
mesh->numtriangles = surf->poly_numverts - 2;
- mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
- mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+ mesh->vertex = (surfvertex_t *)(mesh + 1);
+ mesh->index = (int *)(mesh->vertex + mesh->numverts);
memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
index = mesh->index;
surf->lightmaptexturestride = 0;
surf->lightmaptexture = NULL;
- mesh = &surf->mesh;
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
mesh->numverts = surf->poly_numverts;
mesh->numtriangles = surf->poly_numverts - 2;
- mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
- mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+ mesh->vertex = (surfvertex_t *)(mesh + 1);
+ mesh->index = (int *)(mesh->vertex + mesh->numverts);
memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
index = mesh->index;
}
}
+static void Mod_SplitSurfMeshIfTooBig(msurface_t *s)
+{
+ int j, base, tricount, newvertexcount, *index, *vertexremap;
+ surfmesh_t *newmesh, *oldmesh, *firstmesh;
+ if (s->mesh->numtriangles > 1000)
+ {
+ vertexremap = Mem_Alloc(tempmempool, s->mesh->numverts * sizeof(int));
+ base = 0;
+ oldmesh = NULL;
+ firstmesh = NULL;
+ newmesh = NULL;
+ while (base < s->mesh->numtriangles)
+ {
+ tricount = s->mesh->numtriangles - base;
+ if (tricount > 1000)
+ tricount = 1000;
+ index = s->mesh->index + base * 3;
+ base += tricount;
+
+ newvertexcount = 0;
+ memset(vertexremap, -1, s->mesh->numverts * sizeof(int));
+ for (j = 0;j < tricount * 3;j++)
+ if (vertexremap[index[j]] < 0)
+ vertexremap[index[j]] = newvertexcount++;
+
+ newmesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + newvertexcount * sizeof(surfvertex_t) + tricount * sizeof(int[3]));
+ newmesh->chain = NULL;
+ newmesh->numverts = newvertexcount;
+ newmesh->numtriangles = tricount;
+ newmesh->vertex = (surfvertex_t *)(newmesh + 1);
+ newmesh->index = (int *)(newmesh->vertex + newvertexcount);
+ for (j = 0;j < tricount * 3;j++)
+ {
+ newmesh->index[j] = vertexremap[index[j]];
+ // yes this copies the same vertex multiple times in many cases... but that's ok...
+ memcpy(&newmesh->vertex[newmesh->index[j]], &s->mesh->vertex[index[j]], sizeof(surfvertex_t));
+ }
+ if (oldmesh)
+ oldmesh->chain = newmesh;
+ else
+ firstmesh = newmesh;
+ oldmesh = newmesh;
+ }
+ Mem_Free(vertexremap);
+ Mem_Free(s->mesh);
+ s->mesh = firstmesh;
+ }
+}
+
/*
=================
Mod_LoadFaces
out->shader = &Cshader_sky;
out->samples = NULL;
Mod_GenerateWarpMesh (out);
- continue;
}
-
- if (out->texinfo->texture->flags & SURF_DRAWTURB)
+ else if (out->texinfo->texture->flags & SURF_DRAWTURB)
{
out->shader = &Cshader_water;
/*
*/
out->samples = NULL;
Mod_GenerateWarpMesh (out);
- continue;
- }
-
- if (!R_TextureHasAlpha(out->texinfo->texture->texture))
- out->flags |= SURF_CLIPSOLID;
- if (out->texinfo->flags & TEX_SPECIAL)
- {
- // qbsp couldn't find the texture for this surface, but it was either turb or sky... assume turb
- out->shader = &Cshader_water;
- out->samples = NULL;
- Mod_GenerateWarpMesh (out);
- }
- else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16))
- {
- Con_Printf ("Bad surface extents, converting to fullbright polygon");
- out->shader = &Cshader_wall_fullbright;
- out->samples = NULL;
- Mod_GenerateVertexMesh(out);
}
else
{
- // stainmap for permanent marks on walls
- out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
- // clear to white
- memset(out->stainsamples, 255, ssize * tsize * 3);
- if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
+ if (!R_TextureHasAlpha(out->texinfo->texture->texture))
+ out->flags |= SURF_CLIPSOLID;
+ if (out->texinfo->flags & TEX_SPECIAL)
+ {
+ // qbsp couldn't find the texture for this surface, but it was either turb or sky... assume turb
+ out->shader = &Cshader_water;
+ out->shader = &Cshader_water;
+ out->samples = NULL;
+ Mod_GenerateWarpMesh (out);
+ }
+ else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16))
{
- out->shader = &Cshader_wall_vertex;
- Mod_GenerateVertexLitMesh(out);
+ Con_Printf ("Bad surface extents, converting to fullbright polygon");
+ out->shader = &Cshader_wall_fullbright;
+ out->samples = NULL;
+ Mod_GenerateVertexMesh(out);
}
else
{
- out->shader = &Cshader_wall_lightmap;
- Mod_GenerateLightmappedMesh(out);
+ // stainmap for permanent marks on walls
+ out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
+ // clear to white
+ memset(out->stainsamples, 255, ssize * tsize * 3);
+ if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
+ {
+ out->shader = &Cshader_wall_vertex;
+ Mod_GenerateVertexLitMesh(out);
+ }
+ else
+ {
+ out->shader = &Cshader_wall_lightmap;
+ Mod_GenerateLightmappedMesh(out);
+ }
}
}
+ Mod_SplitSurfMeshIfTooBig(out);
}
}
a = *((const msurface_t **)voida);
b = *((const msurface_t **)voidb);
if (a->shader != b->shader)
- return (long) a->shader - (long) b->shader;
+ return (qbyte *) a->shader - (qbyte *) b->shader;
if (a->texinfo->texture != b->texinfo->texture);
return a->texinfo->texture - b->texinfo->texture;
return 0;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 36;
+ VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->clip_maxs[0] = 32;
hull->clip_maxs[1] = 32;
hull->clip_maxs[2] = 32;
+ VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
hull = &loadmodel->hulls[3];
hull->clipnodes = out;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 18;
+ VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
}
else
{
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 32;
+ VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->clip_maxs[0] = 32;
hull->clip_maxs[1] = 32;
hull->clip_maxs[2] = 64;
+ VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
}
for (i=0 ; i<count ; i++, out++, in++)
}
loadmodel->portals = Mem_Alloc(loadmodel->mempool, numportals * sizeof(mportal_t) + numpoints * sizeof(mvertex_t));
loadmodel->numportals = numportals;
- loadmodel->portalpoints = (void *) ((long) loadmodel->portals + numportals * sizeof(mportal_t));
+ loadmodel->portalpoints = (void *) ((qbyte *) loadmodel->portals + numportals * sizeof(mportal_t));
loadmodel->numportalpoints = numpoints;
// clear all leaf portal chains
for (i = 0;i < loadmodel->numleafs;i++)
dheader_t *header;
dmodel_t *bm;
mempool_t *mainmempool;
+ char *loadname;
mod->type = mod_brush;
mod->numframes = 2; // regular and alternate animation
mainmempool = mod->mempool;
+ loadname = mod->name;
+
+ Mod_LoadLightList ();
//
// set up the submodels (FIXME: this is confusing)
mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
// mod->modelradius = modelradius;
+ // LordHavoc: check for empty submodels (lacrima.bsp has such a glitch)
+ if (mod->normalmins[0] > mod->normalmaxs[0] || mod->normalmins[1] > mod->normalmaxs[1] || mod->normalmins[2] > mod->normalmaxs[2])
+ {
+ Con_Printf("warning: empty submodel *%i in %s\n", i+1, loadname);
+ VectorClear(mod->normalmins);
+ VectorClear(mod->normalmaxs);
+ VectorClear(mod->yawmins);
+ VectorClear(mod->yawmaxs);
+ VectorClear(mod->rotatedmins);
+ VectorClear(mod->rotatedmaxs);
+ //mod->modelradius = 0;
+ }
// VectorCopy (bm->maxs, mod->maxs);
// VectorCopy (bm->mins, mod->mins);