Merge pull request #12 from shpuld/feat/broad-phase-clipping-checks

Port broad phase clipping checks from interstice
This commit is contained in:
cypress 2023-09-05 09:50:00 -04:00 committed by GitHub
commit cf3c2a65ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 18 deletions

View file

@ -332,6 +332,8 @@ void EmitBothSkyLayers (msurface_t *fa);
void EmitUnderWaterPolys (void); void EmitUnderWaterPolys (void);
void EmitDetailPolys (void); void EmitDetailPolys (void);
void R_DrawSkyChain (msurface_t *s); void R_DrawSkyChain (msurface_t *s);
int R_FrustumCheckBox (vec3_t mins, vec3_t maxs);
int R_FrustumCheckSphere (vec3_t centre, float radius);
int R_CullBox (vec3_t emins, vec3_t emaxs); int R_CullBox (vec3_t emins, vec3_t emaxs);
qboolean R_CullSphere (vec3_t centre, float radius); qboolean R_CullSphere (vec3_t centre, float radius);
void R_MarkLights (dlight_t *light, int bit, mnode_t *node); void R_MarkLights (dlight_t *light, int bit, mnode_t *node);

View file

@ -309,6 +309,50 @@ void R_RotateForViewEntity (entity_t *ent)
sceGumRotateZYX(&rotation); sceGumRotateZYX(&rotation);
} }
/*
=================
R_FrustumCheckBox
Returns 0 if box completely inside frustum
Returns +N with intersected planes count as N
Returns -1 when completely outside frustum
=================
*/
int R_FrustumCheckBox (vec3_t mins, vec3_t maxs)
{
int i, res;
int intersections = 0;
for (i=0 ; i<4 ; i++)
{
res = BoxOnPlaneSide (mins, maxs, &frustum[i]);
if (res == 2) return -1;
if (res == 3) ++intersections;
}
return intersections;
}
/*
=================
R_FrustumCheckSphere
=================
*/
int R_FrustumCheckSphere (vec3_t centre, float radius)
{
int i, res;
mplane_t *p;
int intersections = 0;
for (i=0, p=frustum ; i<4 ; i++, p++)
{
res = PlaneDiff(centre, p);
if (res <= -radius) return -1;
if (res < radius) ++intersections;
}
return intersections;
}
/* /*
================= =================
R_CullBox R_CullBox

View file

@ -120,6 +120,8 @@ typedef struct texture_s
#define TEXFLAG_REFLECT 512 #define TEXFLAG_REFLECT 512
#define TEXFLAG_NORMAL 1024 #define TEXFLAG_NORMAL 1024
#define SURF_NEEDSCLIPPING 2048 // see texflags below
// !!! if this is changed, it must be changed in asm_draw.h too !!! // !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct typedef struct
{ {

View file

@ -832,6 +832,14 @@ static void R_BlendLightmaps (void)
int ClipFace (msurface_t * fa) int ClipFace (msurface_t * fa)
{ {
// skip maths if broad phase tells us we don't need clipping
if (!(fa->flags & SURF_NEEDSCLIPPING))
{
fa->polys->numclippedverts = fa->polys->numverts;
fa->polys->display_list_verts = fa->polys->verts;
return fa->polys->numverts;
}
// shpuld: moved clipping here to have it in one place only // shpuld: moved clipping here to have it in one place only
int verts_total = 0; int verts_total = 0;
glpoly_t* poly = fa->polys; glpoly_t* poly = fa->polys;
@ -867,10 +875,7 @@ int ClipFace (msurface_t * fa)
poly->numclippedverts = clipped_vertex_count; poly->numclippedverts = clipped_vertex_count;
} else { } else {
verts_total += unclipped_vertex_count; verts_total += unclipped_vertex_count;
poly->display_list_verts = poly->verts;
const std::size_t buffer_size = unclipped_vertex_count * sizeof(glvert_t);
poly->display_list_verts = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
memcpy(poly->display_list_verts, unclipped_vertices, buffer_size);
poly->numclippedverts = unclipped_vertex_count; poly->numclippedverts = unclipped_vertex_count;
} }
return verts_total; return verts_total;
@ -1162,22 +1167,25 @@ void R_DrawBrushModel (entity_t *e)
clmodel = e->model; clmodel = e->model;
int frustum_check;
if (e->angles[0] || e->angles[1] || e->angles[2]) if (e->angles[0] || e->angles[1] || e->angles[2])
{ {
rotated = qtrue; rotated = qtrue;
if (R_CullSphere(e->origin, clmodel->radius)) frustum_check = R_FrustumCheckSphere(e->origin, clmodel->radius);
return;
} }
else else
{ {
rotated = qfalse; rotated = qfalse;
VectorAdd (e->origin, clmodel->mins, mins); VectorAdd (e->origin, clmodel->mins, mins);
VectorAdd (e->origin, clmodel->maxs, maxs); VectorAdd (e->origin, clmodel->maxs, maxs);
frustum_check = R_FrustumCheckBox(mins, maxs);
if (R_CullBox (mins, maxs) == 2)
return;
} }
if (frustum_check < 0)
return;
memset (lightmap_chains, 0, sizeof(lightmap_chains)); memset (lightmap_chains, 0, sizeof(lightmap_chains));
num_lightmapped_faces = 0; num_lightmapped_faces = 0;
@ -1281,6 +1289,8 @@ void R_DrawBrushModel (entity_t *e)
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{ {
psurf->flags &= ~SURF_NEEDSCLIPPING;
psurf->flags |= SURF_NEEDSCLIPPING * (frustum_check > 1);
R_RenderBrushPoly (psurf); R_RenderBrushPoly (psurf);
} }
} }
@ -1356,7 +1366,11 @@ void R_RecursiveWorldNode (mnode_t *node)
if (node->visframe != r_visframecount) if (node->visframe != r_visframecount)
return; return;
if (R_CullBox (node->minmaxs, node->minmaxs+3) == 2)
// maybe we can avoid extra checks if we remember results for "completely inside",
// then we don't need to check at all for next one? experiment with it.
int frustum_check = R_FrustumCheckBox (node->minmaxs, node->minmaxs+3);
if (frustum_check < 0)
return; return;
// if a leaf node, draw stuff // if a leaf node, draw stuff
@ -1435,14 +1449,17 @@ void R_RecursiveWorldNode (mnode_t *node)
// if sorting by texture, just store it out // if sorting by texture, just store it out
/*if (gl_texsort.value)*/ /*if (gl_texsort.value)*/
if (!mirror
|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
{ {
if (!mirror surf->flags &= ~SURF_NEEDSCLIPPING;
|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) surf->flags |= SURF_NEEDSCLIPPING * (frustum_check > 1);
{
surf->texturechain = surf->texinfo->texture->texturechain; surf->texturechain = surf->texinfo->texture->texturechain;
surf->texinfo->texture->texturechain = surf; surf->texinfo->texture->texturechain = surf;
} }
}/* else if (surf->flags & SURF_DRAWSKY) { /* else if (surf->flags & SURF_DRAWSKY) {
surf->texturechain = skychain; surf->texturechain = skychain;
skychain = surf; skychain = surf;
} else if (surf->flags & SURF_DRAWTURB) { } else if (surf->flags & SURF_DRAWTURB) {
@ -1484,7 +1501,6 @@ void R_DrawWorld (void)
R_ClearSkyBox (); R_ClearSkyBox ();
R_RecursiveWorldNode (cl.worldmodel->nodes); R_RecursiveWorldNode (cl.worldmodel->nodes);
DrawTextureChains (); DrawTextureChains ();

View file

@ -398,6 +398,15 @@ void EmitWaterPolys (msurface_t *fa)
++dst; ++dst;
} }
if (!(fa->flags & SURF_NEEDSCLIPPING))
{
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
unclipped_vertex_count, 0, unclipped_vertices);
return;
}
// Do these vertices need clipped? // Do these vertices need clipped?
if (clipping::is_clipping_required(unclipped_vertices, unclipped_vertex_count)) if (clipping::is_clipping_required(unclipped_vertices, unclipped_vertex_count))
{ {