|
|
@ -64,7 +64,7 @@ static INLINE short world_pointPlaneDist(const VECTOR *point, const ps1bsp_plane |
|
|
return (short)m_pointPlaneDist2(point, &plane->normal, plane->dist); |
|
|
return (short)m_pointPlaneDist2(point, &plane->normal, plane->dist); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_t *face) |
|
|
|
|
|
|
|
|
static INLINE short world_cull_backface(const world_t *world, ps1bsp_face_t *face) |
|
|
{ |
|
|
{ |
|
|
// Backface culling using the face's plane and center point |
|
|
// Backface culling using the face's plane and center point |
|
|
// This eliminates the need for normal clipping per polygon |
|
|
// This eliminates the need for normal clipping per polygon |
|
|
@ -77,7 +77,7 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_ |
|
|
const ps1bsp_plane_t *plane = &world->planes[face->planeId]; |
|
|
const ps1bsp_plane_t *plane = &world->planes[face->planeId]; |
|
|
int planeDot = m_dot12(&cam_vec, &plane->normal); |
|
|
int planeDot = m_dot12(&cam_vec, &plane->normal); |
|
|
if ((planeDot >= 0) ^ face->side) |
|
|
if ((planeDot >= 0) ^ face->side) |
|
|
return 0; |
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
// Check if the face is behind the camera |
|
|
// Check if the face is behind the camera |
|
|
// NOTE: disabling the behind-the-camera check does *not* actually solve the problem of polygons disappearing when too close to the camera! |
|
|
// NOTE: disabling the behind-the-camera check does *not* actually solve the problem of polygons disappearing when too close to the camera! |
|
|
@ -93,24 +93,35 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_ |
|
|
if (frustum_pointInside((SVECTOR*)vert)) |
|
|
if (frustum_pointInside((SVECTOR*)vert)) |
|
|
{ |
|
|
{ |
|
|
// TODO: use a simplified formula with only face area to determine tessellation LOD |
|
|
// TODO: use a simplified formula with only face area to determine tessellation LOD |
|
|
return 1; |
|
|
|
|
|
|
|
|
face->flags &= ~3; |
|
|
|
|
|
face->flags |= 1; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Face really isn't visible |
|
|
// Face really isn't visible |
|
|
return 0; |
|
|
|
|
|
|
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Flip angle for faces that are on the opposite side of their plane |
|
|
// Flip angle for faces that are on the opposite side of their plane |
|
|
char flip = 2 * face->side - 1; |
|
|
|
|
|
planeDot = planeDot * flip; |
|
|
|
|
|
|
|
|
planeDot = planeDot * (2 * face->side - 1); |
|
|
|
|
|
|
|
|
// Calculate an LOD value for this face, based on camera position & direction, face normal & area and distance. |
|
|
// Calculate an LOD value for this face, based on camera position & direction, face normal & area and distance. |
|
|
// This is used to determine how many tessellation subdivisions are necessary to prevent texture warping. |
|
|
// This is used to determine how many tessellation subdivisions are necessary to prevent texture warping. |
|
|
int vecLenSqr = m_dot12(&cam_vec, &cam_vec); |
|
|
int vecLenSqr = m_dot12(&cam_vec, &cam_vec); |
|
|
int lod = (planeDot * vecLenSqr) / (camDot + 1); |
|
|
int lod = (planeDot * vecLenSqr) / (camDot + 1); |
|
|
lod = (lod << 6) / (face->center.pad + 1); |
|
|
lod = (lod << 6) / (face->center.pad + 1); |
|
|
return (short)lod; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Use flags to store the selected LOD level |
|
|
|
|
|
face->flags &= ~3; |
|
|
|
|
|
if (lod < 64) |
|
|
|
|
|
face->flags |= 1; |
|
|
|
|
|
else if (lod < 128) |
|
|
|
|
|
face->flags |= 2; |
|
|
|
|
|
// else if (lod < 256) |
|
|
|
|
|
// face->flags |= 3; |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static u_short world_leafAtPoint(const world_t *world, const VECTOR *point) |
|
|
static u_short world_leafAtPoint(const world_t *world, const VECTOR *point) |
|
|
@ -272,7 +283,7 @@ static ps1bsp_face_t *world_sortModelFaces(const world_t* world, const ps1bsp_mo |
|
|
face->drawFrame = frameNum; |
|
|
face->drawFrame = frameNum; |
|
|
|
|
|
|
|
|
// Cull faces that are facing away from the camera |
|
|
// Cull faces that are facing away from the camera |
|
|
if (!world_cull_backface(world, face)) |
|
|
|
|
|
|
|
|
if (world_cull_backface(world, face)) |
|
|
continue; |
|
|
continue; |
|
|
|
|
|
|
|
|
if (!firstFace) |
|
|
if (!firstFace) |
|
|
@ -319,18 +330,9 @@ static ps1bsp_face_t *world_sortFaces(const world_t *world, const ps1bsp_leaf_t |
|
|
|
|
|
|
|
|
// Cull faces that are facing away from the camera |
|
|
// Cull faces that are facing away from the camera |
|
|
// This also returns an LOD value used to determine tessellation level |
|
|
// This also returns an LOD value used to determine tessellation level |
|
|
short lod = world_cull_backface(world, face); |
|
|
|
|
|
if (!lod) |
|
|
|
|
|
|
|
|
if (world_cull_backface(world, face)) |
|
|
continue; |
|
|
continue; |
|
|
|
|
|
|
|
|
face->flags &= ~3; |
|
|
|
|
|
if (lod < 64) |
|
|
|
|
|
face->flags |= 1; |
|
|
|
|
|
else if (lod < 128) |
|
|
|
|
|
face->flags |= 2; |
|
|
|
|
|
// else if (lod < 256) |
|
|
|
|
|
// face->flags |= 3; |
|
|
|
|
|
|
|
|
|
|
|
// Sort the faces to draw in front-to-back order |
|
|
// Sort the faces to draw in front-to-back order |
|
|
face->nextFace = firstFace; |
|
|
face->nextFace = firstFace; |
|
|
firstFace = face; |
|
|
firstFace = face; |
|
|
|