// fill out all slots with notexture
for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
{
+ tx->number = i;
tx->width = 16;
tx->height = 16;
tx->texture = r_notexture;
tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES;
tx->shader = &Cshader_water;
}
+ tx->currentframe = tx;
}
// just to work around bounds checking when debugging with it (array index out of bounds error thing)
dist = -dist;
if (dist > 0 && dist < e->cullradius)
{
- VectorSubtract(e->origin, surf->poly_center, temp);
- if (DotProduct(temp, temp) - surf->poly_radius2 < e->cullradius2)
+ temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
+ temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
+ temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
+ if (DotProduct(temp, temp) < lightradius2)
loadmodel->surfacevisframes[*mark] = -2;
}
}
}
}
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-static void CalcSurfaceExtents (msurface_t *s)
-{
- float mins[2], maxs[2], val;
- int i,j, e;
- mvertex_t *v;
- mtexinfo_t *tex;
- int bmins[2], bmaxs[2];
-
- mins[0] = mins[1] = 999999999;
- maxs[0] = maxs[1] = -999999999;
-
- tex = s->texinfo;
-
- for (i=0 ; i<s->numedges ; i++)
- {
- e = loadmodel->surfedges[s->firstedge+i];
- if (e >= 0)
- v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
- else
- v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
- for (j=0 ; j<2 ; j++)
- {
- val = v->position[0] * tex->vecs[j][0] +
- v->position[1] * tex->vecs[j][1] +
- v->position[2] * tex->vecs[j][2] +
- tex->vecs[j][3];
- if (val < mins[j])
- mins[j] = val;
- if (val > maxs[j])
- maxs[j] = val;
- }
- }
-
- for (i=0 ; i<2 ; i++)
- {
- bmins[i] = floor(mins[i]/16);
- bmaxs[i] = ceil(maxs[i]/16);
-
- s->texturemins[i] = bmins[i] * 16;
- s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
- }
-}
-
-
void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
{
int i, j;
Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
}
-void Mod_GenerateSurfacePolygon (msurface_t *surf)
+void Mod_GenerateSurfacePolygon (msurface_t *surf, int firstedge, int numedges)
{
- int i, lindex;
- float *vec, *vert, mins[3], maxs[3], temp[3], dist;
+ int i, lindex, j;
+ float *vec, *vert, mins[3], maxs[3], val, *v;
+ mtexinfo_t *tex;
// convert edges back to a normal polygon
- surf->poly_numverts = surf->numedges;
- vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * surf->numedges);
- for (i = 0;i < surf->numedges;i++)
+ surf->poly_numverts = numedges;
+ vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * numedges);
+ for (i = 0;i < numedges;i++)
{
- lindex = loadmodel->surfedges[surf->firstedge + i];
+ lindex = loadmodel->surfedges[firstedge + i];
if (lindex > 0)
vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
else
VectorCopy (vec, vert);
vert += 3;
}
+
+ // calculate polygon bounding box and center
vert = surf->poly_verts;
VectorCopy(vert, mins);
VectorCopy(vert, maxs);
vert += 3;
- for (i = 1;i < surf->poly_numverts;i++)
+ for (i = 1;i < surf->poly_numverts;i++, vert += 3)
{
if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0];
if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1];
if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2];
- vert += 3;
}
VectorCopy(mins, surf->poly_mins);
VectorCopy(maxs, surf->poly_maxs);
surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
- surf->poly_radius2 = 0;
- vert = surf->poly_verts;
- for (i = 0;i < surf->poly_numverts;i++)
+
+ // generate surface extents information
+ tex = surf->texinfo;
+ mins[0] = maxs[0] = DotProduct(surf->poly_verts, tex->vecs[0]) + tex->vecs[0][3];
+ mins[1] = maxs[1] = DotProduct(surf->poly_verts, tex->vecs[1]) + tex->vecs[1][3];
+ for (i = 1, v = surf->poly_verts + 3;i < surf->poly_numverts;i++, v += 3)
{
- VectorSubtract(vert, surf->poly_center, temp);
- dist = DotProduct(temp, temp);
- if (surf->poly_radius2 < dist)
- surf->poly_radius2 = dist;
- vert += 3;
+ for (j = 0;j < 2;j++)
+ {
+ val = DotProduct(v, tex->vecs[j]) + tex->vecs[j][3];
+ if (mins[j] > val)
+ mins[j] = val;
+ if (maxs[j] < val)
+ maxs[j] = val;
+ }
+ }
+ for (i = 0;i < 2;i++)
+ {
+ surf->texturemins[i] = (int) floor(mins[i] / 16) * 16;
+ surf->extents[i] = (int) ceil(maxs[i] / 16) * 16 - surf->texturemins[i];
}
- surf->poly_radius = sqrt(surf->poly_radius2);
}
/*
{
dface_t *in;
msurface_t *out;
- int i, count, surfnum, planenum, ssize, tsize;
+ int i, count, surfnum, planenum, ssize, tsize, firstedge, numedges;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
out->number = surfnum;
// FIXME: validate edges, texinfo, etc?
- out->firstedge = LittleLong(in->firstedge);
- out->numedges = LittleShort(in->numedges);
- if ((unsigned int) out->firstedge + (unsigned int) out->numedges > (unsigned int) loadmodel->numsurfedges)
- Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", out->firstedge, out->numedges, loadmodel->numsurfedges);
+ firstedge = LittleLong(in->firstedge);
+ numedges = LittleShort(in->numedges);
+ if ((unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->numsurfedges)
+ Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", firstedge, numedges, loadmodel->numsurfedges);
i = LittleShort (in->texinfo);
if ((unsigned int) i >= (unsigned int) loadmodel->numtexinfo)
// force lightmap upload on first time seeing the surface
out->cached_dlight = true;
- CalcSurfaceExtents (out);
+ Mod_GenerateSurfacePolygon(out, firstedge, numedges);
ssize = (out->extents[0] >> 4) + 1;
tsize = (out->extents[1] >> 4) + 1;
else // LordHavoc: white lighting (bsp version 29)
out->samples = loadmodel->lightdata + (i * 3);
- Mod_GenerateSurfacePolygon(out);
if (out->texinfo->texture->shader == &Cshader_wall_lightmap)
{
if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256))
#endif
}
+void Mod_BuildLightmapUpdateChains(mempool_t *mempool, model_t *model)
+{
+ int i, j, stylecounts[256], totalcount, remapstyles[256];
+ msurface_t *surf;
+ memset(stylecounts, 0, sizeof(stylecounts));
+ for (i = 0;i < model->nummodelsurfaces;i++)
+ {
+ surf = model->surfaces + model->firstmodelsurface + i;
+ for (j = 0;j < MAXLIGHTMAPS;j++)
+ stylecounts[surf->styles[j]]++;
+ }
+ totalcount = 0;
+ model->light_styles = 0;
+ for (i = 0;i < 255;i++)
+ {
+ if (stylecounts[i])
+ {
+ remapstyles[i] = model->light_styles++;
+ totalcount += stylecounts[i] + 1;
+ }
+ }
+ if (!totalcount)
+ return;
+ model->light_style = Mem_Alloc(mempool, model->light_styles * sizeof(qbyte));
+ model->light_stylevalue = Mem_Alloc(mempool, model->light_styles * sizeof(int));
+ model->light_styleupdatechains = Mem_Alloc(mempool, model->light_styles * sizeof(msurface_t **));
+ model->light_styleupdatechainsbuffer = Mem_Alloc(mempool, totalcount * sizeof(msurface_t *));
+ model->light_styles = 0;
+ for (i = 0;i < 255;i++)
+ if (stylecounts[i])
+ model->light_style[model->light_styles++] = i;
+ j = 0;
+ for (i = 0;i < model->light_styles;i++)
+ {
+ model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j;
+ j += stylecounts[model->light_style[i]] + 1;
+ }
+ for (i = 0;i < model->nummodelsurfaces;i++)
+ {
+ surf = model->surfaces + model->firstmodelsurface + i;
+ for (j = 0;j < MAXLIGHTMAPS;j++)
+ if (surf->styles[j] != 255)
+ *model->light_styleupdatechains[remapstyles[surf->styles[j]]]++ = surf;
+ }
+ j = 0;
+ for (i = 0;i < model->light_styles;i++)
+ {
+ *model->light_styleupdatechains[i] = NULL;
+ model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j;
+ j += stylecounts[model->light_style[i]] + 1;
+ }
+}
+
+void Mod_BuildPVSTextureChains(model_t *model)
+{
+ int i, j;
+ for (i = 0;i < model->numtextures;i++)
+ model->pvstexturechainslength[i] = 0;
+ for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+ {
+ if (model->surfacepvsframes[j] == model->pvsframecount)
+ {
+ model->pvssurflist[model->pvssurflistlength++] = j;
+ model->pvstexturechainslength[model->surfaces[j].texinfo->texture->number]++;
+ }
+ }
+ for (i = 0, j = 0;i < model->numtextures;i++)
+ {
+ if (model->pvstexturechainslength[i])
+ {
+ model->pvstexturechains[i] = model->pvstexturechainsbuffer + j;
+ j += model->pvstexturechainslength[i] + 1;
+ }
+ else
+ model->pvstexturechains[i] = NULL;
+ }
+ for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+ if (model->surfacepvsframes[j] == model->pvsframecount)
+ *model->pvstexturechains[model->surfaces[j].texinfo->texture->number]++ = model->surfaces + j;
+ for (i = 0;i < model->numtextures;i++)
+ {
+ if (model->pvstexturechainslength[i])
+ {
+ *model->pvstexturechains[i] = NULL;
+ model->pvstexturechains[i] -= model->pvstexturechainslength[i];
+ }
+ }
+}
+
/*
=================
Mod_LoadBrushModel
extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor);
void Mod_LoadBrushModel (model_t *mod, void *buffer)
{
- int i, j;
- dheader_t *header;
- dmodel_t *bm;
- mempool_t *mainmempool;
- char *loadname;
- model_t *originalloadmodel;
+ int i, j, k;
+ dheader_t *header;
+ dmodel_t *bm;
+ mempool_t *mainmempool;
+ char *loadname;
+ model_t *originalloadmodel;
+ float dist, modelyawradius, modelradius, *vec;
+ msurface_t *surf;
+ surfmesh_t *mesh;
mod->type = mod_brush;
//
for (i = 0;i < mod->numsubmodels;i++)
{
- int k, l;
- float dist, modelyawradius, modelradius, *vec;
- msurface_t *surf;
-
- mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
- mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
- modelyawradius = 0;
- modelradius = 0;
-
bm = &mod->submodels[i];
mod->hulls[0].firstclipnode = bm->headnode[0];
mod->DrawFakeShadow = NULL;
mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
mod->DrawLight = R_Model_Brush_DrawLight;
- mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
+ mod->pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t **));
+ mod->pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool, (mod->nummodelsurfaces + mod->numtextures) * sizeof(msurface_t *));
+ mod->pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(int));
+ Mod_BuildPVSTextureChains(mod);
+ Mod_BuildLightmapUpdateChains(originalloadmodel->mempool, mod);
if (mod->nummodelsurfaces)
{
// LordHavoc: calculate bmodel bounding box rather than trusting what it says
+ mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+ mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+ modelyawradius = 0;
+ modelradius = 0;
for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
{
// we only need to have a drawsky function if it is used (usually only on world model)
if (surf->texinfo->texture->shader == &Cshader_sky)
mod->DrawSky = R_Model_Brush_DrawSky;
- // link into texture chain
- surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
- mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
// calculate bounding shapes
- for (k = 0;k < surf->numedges;k++)
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
{
- l = mod->surfedges[k + surf->firstedge];
- if (l > 0)
- vec = mod->vertexes[mod->edges[l].v[0]].position;
- else
- vec = mod->vertexes[mod->edges[-l].v[1]].position;
- if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
- if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
- if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
- if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
- if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
- if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
- dist = vec[0]*vec[0]+vec[1]*vec[1];
- if (modelyawradius < dist)
- modelyawradius = dist;
- dist += vec[2]*vec[2];
- if (modelradius < dist)
- modelradius = dist;
+ for (k = 0, vec = mesh->verts;k < mesh->numverts;k++, vec += 4)
+ {
+ if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
+ if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
+ if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
+ if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
+ if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
+ if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
+ dist = vec[0]*vec[0]+vec[1]*vec[1];
+ if (modelyawradius < dist)
+ modelyawradius = dist;
+ dist += vec[2]*vec[2];
+ if (modelradius < dist)
+ modelradius = dist;
+ }
}
}
modelyawradius = sqrt(modelyawradius);
mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
- // LordHavoc: build triangle meshs for entire model's geometry
- // (only used for shadow volumes)
- mod->shadowmesh = Mod_ShadowMesh_Begin(originalloadmodel->mempool, 1024);
- for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
- if (surf->flags & SURF_SHADOWCAST)
- Mod_ShadowMesh_AddPolygon(originalloadmodel->mempool, mod->shadowmesh, surf->poly_numverts, surf->poly_verts);
- mod->shadowmesh = Mod_ShadowMesh_Finish(originalloadmodel->mempool, mod->shadowmesh);
- Mod_ShadowMesh_CalcBBox(mod->shadowmesh, mod->shadowmesh_mins, mod->shadowmesh_maxs, mod->shadowmesh_center, &mod->shadowmesh_radius);
}
else
{
// LordHavoc: empty submodel (lacrima.bsp has such a glitch)
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->radius = 0;
- mod->radius2 = 0;
- mod->shadowmesh = NULL;
}
Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);