Browse Source

Add four bounding vertex references to each face, for more accurate behind-the-camera/frustum culling

master
Nico de Poel 3 years ago
parent
commit
7fd5f09a34
  1. 31
      main.cpp
  2. 7
      ps1bsp.h

31
main.cpp

@ -89,6 +89,7 @@ int process_faces(const world_t* world, const TextureList& textures)
// Traverse the list of face edges to collect all of the face's vertices
Vec3 vertexSum;
std::vector<Vec3> faceVertices;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
int edgeIdx = world->edgeList[face->ledge_id + edgeListIdx];
@ -97,8 +98,10 @@ int process_faces(const world_t* world, const TextureList& textures)
world->edges[edgeIdx].vertex0 :
world->edges[-edgeIdx].vertex1;
// TODO: some faces have redundant/degenerate vertices. We could optimize those by passing their polygons through GPC.
const vertex_t* vertex = &world->vertices[vertIndex];
Vec3 vertexPoint = vertex->toVec();
faceVertices.push_back(vertexPoint);
// Calculate bounding boxes of this face
Vec3 texturePoint = bounds.textureTransform.TransformPoint(vertexPoint);
@ -117,6 +120,30 @@ int process_faces(const world_t* world, const TextureList& textures)
//if (face->ledge_num >= 10)
// export_lightmap(world, face, bounds, faceIdx);
// Determine the face's bounding rectangle in world space (only four vertices, on the face's plane)
switch (faceVertices.size())
{
case 3: // Special case: a triangle
for (int i = 0; i < 3; ++i)
outFace.bounds[i] = (unsigned short)tesselator.addVertex(faceVertices[i]);
outFace.bounds[3] = outFace.bounds[2];
break;
case 4: // Special case: a quad
for (int i = 0; i < 4; ++i)
outFace.bounds[i] = (unsigned short)tesselator.addVertex(faceVertices[i]);
break;
default:
// TODO: this is far from optimal. We don't need a bounding rectangle, but a minimal bounding quad of any shape. Solve this problem: https://mathoverflow.net/questions/11580/minimum-area-bounding-quadrilateral-algorithm
bounds.textureTransform.Invert();
outFace.bounds[0] = (unsigned short)tesselator.addVertex(bounds.textureTransform.TransformPoint(Vec3(bounds.textureBounds.min.x, bounds.textureBounds.min.y, 0.0f)));
outFace.bounds[1] = (unsigned short)tesselator.addVertex(bounds.textureTransform.TransformPoint(Vec3(bounds.textureBounds.min.x, bounds.textureBounds.max.y, 0.0f)));
outFace.bounds[2] = (unsigned short)tesselator.addVertex(bounds.textureTransform.TransformPoint(Vec3(bounds.textureBounds.max.x, bounds.textureBounds.max.y, 0.0f)));
outFace.bounds[3] = (unsigned short)tesselator.addVertex(bounds.textureTransform.TransformPoint(Vec3(bounds.textureBounds.max.x, bounds.textureBounds.min.y, 0.0f)));
break;
}
outFace.numFaceVertices = (unsigned char)(outFaceVertices.size() - outFace.firstFaceVertex);
outFace.center = (vertexSum / face->ledge_num).convertWorldPosition();
double area = face_computeArea(world, face);
@ -124,7 +151,7 @@ int process_faces(const world_t* world, const TextureList& textures)
outFaces.push_back(outFace);
}
printf("Tesselating faces...\n");
printf("Tessellating faces...\n");
std::vector<ps1bsp_polyvertex_t> outPolyVertices;
std::vector<ps1bsp_polygon_t> outPolygons;
@ -248,7 +275,7 @@ int process_faces(const world_t* world, const TextureList& textures)
outPoly.numPolyVertices = (unsigned short)(outPolyVertices.size() - outPoly.firstPolyVertex);
outPolygons.push_back(outPoly);
outFace->totalQuads += (outPoly.numPolyVertices - 1) / 2;
outFace->totalPrimitives += (outPoly.numPolyVertices - 1) / 2;
}
outFace->numPolygons = (unsigned char)(outPolygons.size() - outFace->firstPolygon);

7
ps1bsp.h

@ -106,10 +106,14 @@ typedef struct ps1bsp_face_s
unsigned short planeId;
unsigned char side;
// TODO: not sure if we should make separate lists for triangles and non-triangle polygons here
// Could potentially improve drawing performance but at the cost of more memory use per face
// Used for high-quality tesselated textured drawing
unsigned short firstPolygon;
unsigned char numPolygons;
unsigned char totalQuads;
unsigned char totalPrimitives; // Used for early primitive buffer checks
// Used for low-quality untextured vertex colored drawing
unsigned short firstFaceVertex;
@ -120,6 +124,7 @@ typedef struct ps1bsp_face_s
// Used for backface culling
SVECTOR center;
unsigned short bounds[4];
// Run-time data
const struct ps1bsp_face_s* nextFace; // For chaining faces in drawing order

Loading…
Cancel
Save