invradius = 1.0f / radius;
loc0:
- if (node->contents < 0)
+ if (!node->plane)
return;
ndist = PlaneDiff(origin, node->plane);
if (ndist > radius)
}
}
- if (node->children[0]->contents >= 0)
+ if (node->children[0]->plane)
{
- if (node->children[1]->contents >= 0)
+ if (node->children[1]->plane)
{
R_StainNode(node->children[0], model, origin, radius, fcolor);
node = node->children[1];
goto loc0;
}
}
- else if (node->children[1]->contents >= 0)
+ else if (node->children[1]->plane)
{
node = node->children[1];
goto loc0;
void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
{
- int i, j, f, *surfacevisframes, flagsmask;
+ int i, j, f, flagsmask;
msurface_t *surface, **surfacechain;
texture_t *t, *texture;
model_t *model = ent->model;
if (ent != r_refdef.worldentity)
{
- // because bmodels can be reused, we have to decide which things to render
- // from scratch every time
- int *mark = model->brushq1.surfacevisframes + model->firstmodelsurface;
+ // because bmodels can be reused, we have to clear dlightframe every time
surface = model->brushq1.surfaces + model->firstmodelsurface;
- for (i = 0;i < model->nummodelsurfaces;i++, mark++, surface++)
- {
- *mark = r_framecount;
+ for (i = 0;i < model->nummodelsurfaces;i++, surface++)
surface->dlightframe = -1;
- }
}
// update light styles
}
R_UpdateTextureInfo(ent);
- surfacevisframes = model->brushq1.surfacevisframes;
flagsmask = skysurfaces ? SURF_DRAWSKY : (SURF_DRAWTURB | SURF_LIGHTMAP);
f = 0;
t = NULL;
numsurfacelist = 0;
for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
{
- if (surfacevisframes[j] == r_framecount)
+ if (ent != r_refdef.worldentity || r_worldsurfacevisible[j])
{
surface = model->brushq1.surfaces + j;
if (t != surface->texinfo->texture)
}
if (f)
{
- // mark any backface surfaces as not visible
- if (PlaneDist(modelorg, surface->plane) < surface->plane->dist)
- {
- if (!(surface->flags & SURF_PLANEBACK))
- {
- surfacevisframes[j] = -1;
- continue;
- }
- }
- else
- {
- if ((surface->flags & SURF_PLANEBACK))
- {
- surfacevisframes[j] = -1;
- continue;
- }
- }
// add face to draw list and update lightmap if necessary
c_faces++;
if (surface->cached_dlight && surface->lightmaptexture != NULL)
mleaf_t *leaf;
mleaf_t *viewleaf;
model_t *model = r_refdef.worldmodel;
- int *surfacevisframes = model->brushq1.surfacevisframes;
int leafstackpos;
mportal_t *p;
mleaf_t *leafstack[8192];
+ qbyte leafvisited[32768];
if (!model || !model->brushq1.PointInLeaf)
return;
if (!viewleaf)
return;
- if (viewleaf->contents == CONTENTS_SOLID || r_surfaceworldnode.integer)
+ memset(r_worldsurfacevisible, 0, r_refdef.worldmodel->brushq1.numsurfaces);
+ if (viewleaf->clusterindex < 0 || r_surfaceworldnode.integer)
{
// equivilant to quake's RecursiveWorldNode but faster and more effective
for (j = 0, leaf = model->brushq1.data_leafs;j < model->brushq1.num_leafs;j++, leaf++)
if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox (leaf->mins, leaf->maxs))
{
c_leafs++;
- leaf->visframe = r_framecount;
if (leaf->nummarksurfaces)
for (i = 0, mark = leaf->firstmarksurface;i < leaf->nummarksurfaces;i++, mark++)
- surfacevisframes[*mark] = r_framecount;
+ r_worldsurfacevisible[*mark] = true;
}
}
}
// RecursiveWorldNode
leafstack[0] = viewleaf;
leafstackpos = 1;
+ memset(leafvisited, 0, r_refdef.worldmodel->brushq1.num_leafs);
while (leafstackpos)
{
c_leafs++;
leaf = leafstack[--leafstackpos];
- leaf->visframe = r_framecount;
+ leafvisited[leaf - r_refdef.worldmodel->brushq1.data_leafs] = 1;
// draw any surfaces bounding this leaf
if (leaf->nummarksurfaces)
for (i = 0, mark = leaf->firstmarksurface;i < leaf->nummarksurfaces;i++, mark++)
- surfacevisframes[*mark] = r_framecount;
+ r_worldsurfacevisible[*mark] = true;
// follow portals into other leafs
for (p = leaf->portals;p;p = p->next)
- if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && p->past->visframe != r_framecount && CHECKPVSBIT(r_pvsbits, p->past->clusterindex) && !R_CullBox(p->mins, p->maxs))
+ if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !leafvisited[p->past - r_refdef.worldmodel->brushq1.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex) && !R_CullBox(p->mins, p->maxs))
leafstack[leafstackpos++] = p->past;
}
}
if (t->flags & SURF_LIGHTMAP && t->skin.fog == NULL)
Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texinfo->texture->skin.base, surface->texinfo->texture->skin.gloss, surface->texinfo->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i);
}
- else if (ent != r_refdef.worldentity || ent->model->brushq1.surfacevisframes[surface - ent->model->brushq1.surfaces] == r_framecount)
+ else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surface - ent->model->brushq1.surfaces])
{
t = surface->texinfo->texture->currentframe;
// FIXME: transparent surfaces need to be lit later
// LordHavoc: modified to start at first clip node,
// in other words: first node of the (sub)model
node = model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode;
- while (node->contents == 0)
+ while (node->plane)
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
return (mleaf_t *)node;
return false;
}
-/*
-static int Mod_Q1BSP_PointContents(model_t *model, const vec3_t p)
-{
- mnode_t *node;
-
- if (model == NULL)
- return CONTENTS_EMPTY;
-
- Mod_CheckLoaded(model);
-
- // LordHavoc: modified to start at first clip node,
- // in other words: first node of the (sub)model
- node = model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode;
- while (node->contents == 0)
- node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
-
- return ((mleaf_t *)node)->contents;
-}
-*/
-
typedef struct findnonsolidlocationinfo_s
{
vec3_t center;
static void Mod_Q1BSP_FindNonSolidLocation_r(findnonsolidlocationinfo_t *info, mnode_t *node)
{
- if (node->contents)
- {
- if (((mleaf_t *)node)->nummarksurfaces)
- Mod_Q1BSP_FindNonSolidLocation_r_Leaf(info, (mleaf_t *)node);
- }
- else
+ if (node->plane)
{
float f = PlaneDiff(info->center, node->plane);
if (f >= -info->bestdist)
if (f <= info->bestdist)
Mod_Q1BSP_FindNonSolidLocation_r(info, node->children[1]);
}
+ else
+ {
+ if (((mleaf_t *)node)->nummarksurfaces)
+ Mod_Q1BSP_FindNonSolidLocation_r_Leaf(info, (mleaf_t *)node);
+ }
}
static void Mod_Q1BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, float radius)
float mid;
loc0:
- if (node->contents < 0)
+ if (!node->plane)
return false; // didn't hit anything
switch (node->plane->type)
}
// go down front side
- if (node->children[side]->contents >= 0 && Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, node->children[side], x, y, startz, mid))
+ if (node->children[side]->plane && Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, node->children[side], x, y, startz, mid))
return true; // hit something
else
{
loadmodel->brushq1.surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t));
loadmodel->brushq1.numsurfaces = count;
- loadmodel->brushq1.surfacevisframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
for (surfnum = 0, surf = loadmodel->brushq1.surfaces, totalverts = 0, totaltris = 0, totalmeshes = 0;surfnum < count;surfnum++, totalverts += surf->poly_numverts, totaltris += surf->poly_numverts - 2, totalmeshes++, in++, surf++)
{
static void Mod_Q1BSP_SetParent(mnode_t *node, mnode_t *parent)
{
node->parent = parent;
- if (node->contents < 0)
- return;
- Mod_Q1BSP_SetParent(node->children[0], node);
- Mod_Q1BSP_SetParent(node->children[1], node);
+ if (node->plane)
+ {
+ Mod_Q1BSP_SetParent(node->children[0], node);
+ Mod_Q1BSP_SetParent(node->children[1], node);
+ }
}
static void Mod_Q1BSP_LoadNodes(lump_t *l)
for (i = 0;i < loadmodel->brushq1.numnodes;i++, out++, in++)
{
out->planenum = in->plane - loadmodel->brushq1.planes;
- out->children[0] = in->children[0]->contents < 0 ? in->children[0]->contents : in->children[0] - loadmodel->brushq1.nodes;
- out->children[1] = in->children[1]->contents < 0 ? in->children[1]->contents : in->children[1] - loadmodel->brushq1.nodes;
+ out->children[0] = in->children[0]->plane ? in->children[0] - loadmodel->brushq1.nodes : ((mleaf_t *)in->children[0])->contents;
+ out->children[1] = in->children[1]->plane ? in->children[1] - loadmodel->brushq1.nodes : ((mleaf_t *)in->children[1])->contents;
}
}
static void Mod_Q1BSP_RecursiveRecalcNodeBBox(mnode_t *node)
{
+ // process only nodes (leafs already had their box calculated)
+ if (!node->plane)
+ return;
+
// calculate children first
- if (node->children[0]->contents >= 0)
- Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[0]);
- if (node->children[1]->contents >= 0)
- Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[1]);
+ Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[0]);
+ Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[1]);
// make combined bounding box from children
node->mins[0] = min(node->children[0]->mins[0], node->children[1]->mins[0]);
{
// note: this check must match the one below or it will usually corrupt memory
// the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
- if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1]
- && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
- && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
+ if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
{
numportals += 2;
numpoints += p->numpoints * 2;
{
pnext = p->chain;
- if (p->numpoints >= 3)
+ // note: this check must match the one above or it will usually corrupt memory
+ // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
+ if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
{
- // note: this check must match the one above or it will usually corrupt memory
- // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
- if (p->nodes[0] != p->nodes[1]
- && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
- && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
+ // first make the back to front portal(forward portal)
+ portal->points = point;
+ portal->numpoints = p->numpoints;
+ portal->plane.dist = p->plane.dist;
+ VectorCopy(p->plane.normal, portal->plane.normal);
+ portal->here = (mleaf_t *)p->nodes[1];
+ portal->past = (mleaf_t *)p->nodes[0];
+ // copy points
+ for (j = 0;j < portal->numpoints;j++)
{
- // first make the back to front portal(forward portal)
- portal->points = point;
- portal->numpoints = p->numpoints;
- portal->plane.dist = p->plane.dist;
- VectorCopy(p->plane.normal, portal->plane.normal);
- portal->here = (mleaf_t *)p->nodes[1];
- portal->past = (mleaf_t *)p->nodes[0];
- // copy points
- for (j = 0;j < portal->numpoints;j++)
- {
- VectorCopy(p->points + j*3, point->position);
- point++;
- }
- BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
- PlaneClassify(&portal->plane);
-
- // link into leaf's portal chain
- portal->next = portal->here->portals;
- portal->here->portals = portal;
-
- // advance to next portal
- portal++;
-
- // then make the front to back portal(backward portal)
- portal->points = point;
- portal->numpoints = p->numpoints;
- portal->plane.dist = -p->plane.dist;
- VectorNegate(p->plane.normal, portal->plane.normal);
- portal->here = (mleaf_t *)p->nodes[0];
- portal->past = (mleaf_t *)p->nodes[1];
- // copy points
- for (j = portal->numpoints - 1;j >= 0;j--)
- {
- VectorCopy(p->points + j*3, point->position);
- point++;
- }
- BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
- PlaneClassify(&portal->plane);
+ VectorCopy(p->points + j*3, point->position);
+ point++;
+ }
+ BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+ PlaneClassify(&portal->plane);
+
+ // link into leaf's portal chain
+ portal->next = portal->here->portals;
+ portal->here->portals = portal;
+
+ // advance to next portal
+ portal++;
+
+ // then make the front to back portal(backward portal)
+ portal->points = point;
+ portal->numpoints = p->numpoints;
+ portal->plane.dist = -p->plane.dist;
+ VectorNegate(p->plane.normal, portal->plane.normal);
+ portal->here = (mleaf_t *)p->nodes[0];
+ portal->past = (mleaf_t *)p->nodes[1];
+ // copy points
+ for (j = portal->numpoints - 1;j >= 0;j--)
+ {
+ VectorCopy(p->points + j*3, point->position);
+ point++;
+ }
+ BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+ PlaneClassify(&portal->plane);
- // link into leaf's portal chain
- portal->next = portal->here->portals;
- portal->here->portals = portal;
+ // link into leaf's portal chain
+ portal->next = portal->here->portals;
+ portal->here->portals = portal;
- // advance to next portal
- portal++;
- }
+ // advance to next portal
+ portal++;
}
FreePortal(p);
p = pnext;
double frontpoints[3*MAX_PORTALPOINTS], backpoints[3*MAX_PORTALPOINTS];
// if a leaf, we're done
- if (node->contents)
+ if (!node->plane)
return;
plane = node->plane;
out->number = i;
strlcpy (out->name, in->name, sizeof (out->name));
out->surfaceflags = LittleLong(in->surfaceflags);
- out->nativecontents = LittleLong(in->contents);
- out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents);
+ out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in->contents));
out->surfaceparms = -1;
}
invalidelements++;
if (invalidelements)
{
- Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, texture->nativecontents = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, out->texture->nativecontents, firstvertex, out->mesh.num_vertices, firstelement, out->mesh.num_triangles * 3);
+ Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, firstvertex, out->mesh.num_vertices, firstelement, out->mesh.num_triangles * 3);
for (j = 0;j < out->mesh.num_triangles * 3;j++)
{
Con_Printf(" %i", out->mesh.data_element3i[j]);
static int Mod_Q3BSP_SuperContentsFromNativeContents(model_t *model, int nativecontents)
{
int supercontents = 0;
- if (nativecontents & Q2CONTENTS_SOLID)
+ if (nativecontents & CONTENTSQ3_SOLID)
supercontents |= SUPERCONTENTS_SOLID;
- if (nativecontents & Q2CONTENTS_WATER)
+ if (nativecontents & CONTENTSQ3_WATER)
supercontents |= SUPERCONTENTS_WATER;
- if (nativecontents & Q2CONTENTS_SLIME)
+ if (nativecontents & CONTENTSQ3_SLIME)
supercontents |= SUPERCONTENTS_SLIME;
- if (nativecontents & Q2CONTENTS_LAVA)
+ if (nativecontents & CONTENTSQ3_LAVA)
supercontents |= SUPERCONTENTS_LAVA;
+ if (nativecontents & CONTENTSQ3_BODY)
+ supercontents |= SUPERCONTENTS_BODY;
+ if (nativecontents & CONTENTSQ3_CORPSE)
+ supercontents |= SUPERCONTENTS_CORPSE;
+ if (nativecontents & CONTENTSQ3_NODROP)
+ supercontents |= SUPERCONTENTS_NODROP;
return supercontents;
}
{
int nativecontents = 0;
if (supercontents & SUPERCONTENTS_SOLID)
- nativecontents |= Q2CONTENTS_SOLID;
+ nativecontents |= CONTENTSQ3_SOLID;
if (supercontents & SUPERCONTENTS_WATER)
- nativecontents |= Q2CONTENTS_WATER;
+ nativecontents |= CONTENTSQ3_WATER;
if (supercontents & SUPERCONTENTS_SLIME)
- nativecontents |= Q2CONTENTS_SLIME;
+ nativecontents |= CONTENTSQ3_SLIME;
if (supercontents & SUPERCONTENTS_LAVA)
- nativecontents |= Q2CONTENTS_LAVA;
+ nativecontents |= CONTENTSQ3_LAVA;
+ if (supercontents & SUPERCONTENTS_BODY)
+ nativecontents |= CONTENTSQ3_BODY;
+ if (supercontents & SUPERCONTENTS_CORPSE)
+ nativecontents |= CONTENTSQ3_CORPSE;
+ if (supercontents & SUPERCONTENTS_NODROP)
+ nativecontents |= CONTENTSQ3_NODROP;
return nativecontents;
}