mnode_t *node;
Mod_CheckLoaded(model);
-// if (!model || !model->nodes)
-// Sys_Error ("Mod_PointInLeaf: bad model");
// LordHavoc: modified to start at first clip node,
// in other words: first node of the (sub)model
pos[2]-=1;
}
-/*
-mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
-{
- mnode_t *node;
- float d;
- mplane_t *plane;
-
- if (!model || !model->nodes)
- Sys_Error ("Mod_PointInLeaf: bad model");
-
- node = model->nodes;
- while (1)
- {
- if (node->contents < 0)
- return (mleaf_t *)node;
- plane = node->plane;
- d = DotProduct (p,plane->normal) - plane->dist;
- if (d > 0)
- node = node->children[0];
- else
- node = node->children[1];
- }
-
- return NULL; // never reached
-}
-*/
/*
===================
row = (model->numleafs+7)>>3;
out = decompressed;
- /*
- if (!in)
- { // no vis info, so make all visible
- while (row)
- {
- *out++ = 0xff;
- row--;
- }
- return decompressed;
- }
- */
-
do
{
if (*in)
}
}
+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 *)((qbyte *) 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++)
- {
for (j = 0;j < 3;j++)
- {
mesh->index[i*3+j] = subdivpolyindex[i][j];
- //if (mesh->index[i] < 0 || mesh->index[i] >= mesh->numverts)
- // Host_Error("Mod_GenerateWarpMesh: invalid index generated\n");
- }
- }
for (i = 0, v = mesh->vertex;i < subdivpolyverts;i++, v++)
{
surfvertex_t *out;
surfmesh_t *mesh;
- //surf->flags |= SURF_LIGHTMAP;
smax = surf->extents[0] >> 4;
tmax = surf->extents[1] >> 4;
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 *)((qbyte *) 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 = R_CompatibleFragmentWidth((surf->extents[0]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0);
surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE, NULL, NULL, 0);
}
-// surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE);
-// surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_PRECACHE);
R_FragmentLocation(surf->lightmaptexture, NULL, NULL, &xbase, &ybase, &xscale, &yscale);
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 *)((qbyte *) 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 *)((qbyte *) 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)
- {
- out->shader = &Cshader_water;
- /*
- for (i=0 ; i<2 ; i++)
- {
- out->extents[i] = 16384*1024;
- out->texturemins[i] = -8192*1024;
- }
- */
- out->samples = NULL;
- Mod_GenerateWarpMesh (out);
- continue;
}
-
- if (!R_TextureHasAlpha(out->texinfo->texture->texture))
- out->flags |= SURF_CLIPSOLID;
- if (out->texinfo->flags & TEX_SPECIAL)
+ else if (out->texinfo->texture->flags & SURF_DRAWTURB)
{
- // 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))
- {
- 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)
{
- out->shader = &Cshader_wall_vertex;
- Mod_GenerateVertexLitMesh(out);
+ // 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))
+ {
+ 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);
}
}
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
- // gl underwater warp
- // LordHavoc: disabled underwater warping
- /*
- if (out->contents != CONTENTS_EMPTY)
- {
- for (j=0 ; j<out->nummarksurfaces ; j++)
- out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
- }
- */
+ // FIXME: Insert caustics here
}
}
out->normal[2] = LittleFloat (in->normal[2]);
out->dist = LittleFloat (in->dist);
- // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal?
-// out->type = LittleLong (in->type);
PlaneClassify(out);
}
}
// free the original winding
FreeWinding (in);
- // debugging
- //Mem_CheckSentinels(neww);
-
return neww;
}
VectorCopy (mid, b->points[b->numpoints]);
b->numpoints++;
}
-
- // debugging
- //Mem_CheckSentinels(f);
- //Mem_CheckSentinels(b);
}
typedef struct portal_s
{
portal_t *p;
p = Mem_Alloc(loadmodel->mempool, sizeof(portal_t));
- //memset(p, 0, sizeof(portal_t));
p->chain = portalchain;
portalchain = p;
return p;
mleaf_t *leaf, *endleaf;
winding_t *w;
- //Mem_CheckSentinelsGlobal();
-
// recalculate bounding boxes for all leafs (because qbsp is very sloppy)
leaf = loadmodel->leafs;
endleaf = leaf + loadmodel->numleafs;
Mod_RecursiveRecalcNodeBBox(loadmodel->nodes);
- //Mem_CheckSentinelsGlobal();
-
// tally up portal and point counts
p = portalchain;
numportals = 0;
FreePortal(p);
p = pnext;
}
-
- //Mem_CheckSentinelsGlobal();
}
/*
portal_t *portal, *nextportal, *nodeportal, *splitportal, *temp;
winding_t *nodeportalwinding, *frontwinding, *backwinding;
- // CheckLeafPortalConsistancy (node);
-
// if a leaf, we're done
if (node->contents)
return;
nodeportal->plane = *node->plane;
nodeportalwinding = BaseWindingForPlane (node->plane);
- //Mem_CheckSentinels(nodeportalwinding);
side = 0; // shut up compiler warning
for (portal = (portal_t *)node->portals;portal;portal = portal->next[side])
{
Mod_RecursiveNodePortals(back);
}
-/*
-void Mod_MakeOutsidePortals(mnode_t *node)
-{
- int i, j;
- portal_t *p, *portals[6];
- mnode_t *outside_node;
-
- outside_node = Mem_Alloc(loadmodel->mempool, sizeof(mnode_t));
- outside_node->contents = CONTENTS_SOLID;
- outside_node->portals = NULL;
-
- for (i = 0;i < 3;i++)
- {
- for (j = 0;j < 2;j++)
- {
- portals[j*3 + i] = p = AllocPortal ();
- memset (&p->plane, 0, sizeof(mplane_t));
- p->plane.normal[i] = j ? -1 : 1;
- p->plane.dist = -65536;
- p->winding = BaseWindingForPlane (&p->plane);
- if (j)
- AddPortalToNodes (p, outside_node, node);
- else
- AddPortalToNodes (p, node, outside_node);
- }
- }
-
- // clip the basewindings by all the other planes
- for (i = 0;i < 6;i++)
- {
- for (j = 0;j < 6;j++)
- {
- if (j == i)
- continue;
- portals[i]->winding = ClipWinding (portals[i]->winding, &portals[j]->plane, true);
- }
- }
-}
-*/
static void Mod_MakePortals(void)
{
-// Con_Printf("building portals for %s\n", loadmodel->name);
-
portalchain = NULL;
-// Mod_MakeOutsidePortals (loadmodel->nodes);
Mod_RecursiveNodePortals (loadmodel->nodes);
Mod_FinalizePortals();
}
// store which lightmap format to use
mod->lightmaprgba = r_lightmaprgba.integer;
-// Mem_CheckSentinelsGlobal();
- // LordHavoc: had to move entity loading above everything to allow parsing various settings from worldspawn
Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadFaces (&header->lumps[LUMP_FACES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadNodes (&header->lumps[LUMP_NODES]);
-// Mem_CheckSentinelsGlobal();
Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
-// Mem_CheckSentinelsGlobal();
-// Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
-// Mem_CheckSentinelsGlobal();
Mod_MakeHull0 ();
-// Mem_CheckSentinelsGlobal();
Mod_MakePortals();
-// Mem_CheckSentinelsGlobal();
mod->numframes = 2; // regular and alternate animation
mainmempool = mod->mempool;
loadname = mod->name;
+ Mod_LoadLightList ();
+
//
// set up the submodels (FIXME: this is confusing)
//
mod->yawmaxs[2] = mod->normalmaxs[2];
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])
{
VectorClear(mod->yawmaxs);
VectorClear(mod->rotatedmins);
VectorClear(mod->rotatedmaxs);
- //mod->modelradius = 0;
}
-// VectorCopy (bm->maxs, mod->maxs);
-// VectorCopy (bm->mins, mod->mins);
-
-// mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
-
mod->numleafs = bm->visleafs;
mod->SERAddEntity = Mod_Brush_SERAddEntity;
mod = loadmodel;
}
}
-// Mem_CheckSentinelsGlobal();
}
+