From d9e7fe2f4c5938ed6537eacd2efed357e59bb385 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 5 Sep 2023 08:45:55 +0300 Subject: [PATCH] port broad phase clipping checks from interstice --- source/psp/video_hardware.h | 2 ++ source/psp/video_hardware_main.cpp | 44 +++++++++++++++++++++++ source/psp/video_hardware_model.h | 2 ++ source/psp/video_hardware_surface.cpp | 52 +++++++++++++++++---------- source/psp/video_hardware_warp.cpp | 9 +++++ 5 files changed, 91 insertions(+), 18 deletions(-) diff --git a/source/psp/video_hardware.h b/source/psp/video_hardware.h index f5fee61..8d190af 100644 --- a/source/psp/video_hardware.h +++ b/source/psp/video_hardware.h @@ -332,6 +332,8 @@ void EmitBothSkyLayers (msurface_t *fa); void EmitUnderWaterPolys (void); void EmitDetailPolys (void); 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); qboolean R_CullSphere (vec3_t centre, float radius); void R_MarkLights (dlight_t *light, int bit, mnode_t *node); diff --git a/source/psp/video_hardware_main.cpp b/source/psp/video_hardware_main.cpp index 2327e2b..4b6eb70 100644 --- a/source/psp/video_hardware_main.cpp +++ b/source/psp/video_hardware_main.cpp @@ -309,6 +309,50 @@ void R_RotateForViewEntity (entity_t *ent) 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 diff --git a/source/psp/video_hardware_model.h b/source/psp/video_hardware_model.h index 9dfdcfe..29b442a 100644 --- a/source/psp/video_hardware_model.h +++ b/source/psp/video_hardware_model.h @@ -120,6 +120,8 @@ typedef struct texture_s #define TEXFLAG_REFLECT 512 #define TEXFLAG_NORMAL 1024 +#define SURF_NEEDSCLIPPING 2048 // see texflags below + // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { diff --git a/source/psp/video_hardware_surface.cpp b/source/psp/video_hardware_surface.cpp index 7ae01b1..dd64160 100644 --- a/source/psp/video_hardware_surface.cpp +++ b/source/psp/video_hardware_surface.cpp @@ -832,6 +832,14 @@ static void R_BlendLightmaps (void) 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 int verts_total = 0; glpoly_t* poly = fa->polys; @@ -867,10 +875,7 @@ int ClipFace (msurface_t * fa) poly->numclippedverts = clipped_vertex_count; } else { verts_total += unclipped_vertex_count; - - const std::size_t buffer_size = unclipped_vertex_count * sizeof(glvert_t); - poly->display_list_verts = static_cast(sceGuGetMemory(buffer_size)); - memcpy(poly->display_list_verts, unclipped_vertices, buffer_size); + poly->display_list_verts = poly->verts; poly->numclippedverts = unclipped_vertex_count; } return verts_total; @@ -1162,22 +1167,25 @@ void R_DrawBrushModel (entity_t *e) clmodel = e->model; + int frustum_check; + if (e->angles[0] || e->angles[1] || e->angles[2]) { rotated = qtrue; - if (R_CullSphere(e->origin, clmodel->radius)) - return; + frustum_check = R_FrustumCheckSphere(e->origin, clmodel->radius); + } else { rotated = qfalse; VectorAdd (e->origin, clmodel->mins, mins); VectorAdd (e->origin, clmodel->maxs, maxs); - - if (R_CullBox (mins, maxs) == 2) - return; + frustum_check = R_FrustumCheckBox(mins, maxs); } + if (frustum_check < 0) + return; + memset (lightmap_chains, 0, sizeof(lightmap_chains)); num_lightmapped_faces = 0; @@ -1281,6 +1289,8 @@ void R_DrawBrushModel (entity_t *e) if (((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); } } @@ -1356,7 +1366,11 @@ void R_RecursiveWorldNode (mnode_t *node) if (node->visframe != r_visframecount) 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; // 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 (gl_texsort.value)*/ + + if (!mirror + || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) { - if (!mirror - || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) - { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - }/* else if (surf->flags & SURF_DRAWSKY) { + surf->flags &= ~SURF_NEEDSCLIPPING; + surf->flags |= SURF_NEEDSCLIPPING * (frustum_check > 1); + + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } + /* else if (surf->flags & SURF_DRAWSKY) { surf->texturechain = skychain; skychain = surf; } else if (surf->flags & SURF_DRAWTURB) { @@ -1484,7 +1501,6 @@ void R_DrawWorld (void) R_ClearSkyBox (); - R_RecursiveWorldNode (cl.worldmodel->nodes); DrawTextureChains (); diff --git a/source/psp/video_hardware_warp.cpp b/source/psp/video_hardware_warp.cpp index d0ba6ce..7756c09 100644 --- a/source/psp/video_hardware_warp.cpp +++ b/source/psp/video_hardware_warp.cpp @@ -398,6 +398,15 @@ void EmitWaterPolys (msurface_t *fa) ++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? if (clipping::is_clipping_required(unclipped_vertices, unclipped_vertex_count)) {