Browse Source

Added bounding spheres to node data, used for frustum culling

master
Nico de Poel 3 years ago
parent
commit
c91e8e6167
  1. 10
      bsp.h
  2. 24
      common.h
  3. 40
      main.cpp
  4. 13
      ps1bsp.h
  5. 2
      ps1types.h
  6. 4
      tesselate.cpp

10
bsp.h

@ -130,6 +130,16 @@ typedef struct BBoxShort // Bounding Box, Short values
((float)max[2] + (float)min[2]) / 2
);
}
SVECTOR toBoundingSphere() const
{
Vec3 center = getCenter();
Vec3 extents = Vec3(max[0], max[1], max[2]) - center;
SVECTOR sphere = center.convertWorldPosition();
sphere.pad = (short)(extents.magnitude() * 4);
return sphere;
}
} bboxshort_t;
typedef struct // Mip texture list header

24
common.h

@ -10,6 +10,8 @@
#include <unordered_map>
#include <unordered_set>
#include "ps1types.h"
typedef float scalar_t; // Scalar value,
typedef struct Vec3 // Vector or Position
@ -21,6 +23,8 @@ typedef struct Vec3 // Vector or Position
Vec3() : x(0), y(0), z(0) { }
Vec3(float x, float y, float z) : x(x), y(y), z(z) { }
Vec3(double x, double y, double z) : x((float)x), y((float)y), z((float)z) { }
Vec3(int x, int y, int z) : x((float)x), y((float)y), z((float)z) { }
Vec3(short x, short y, short z) : x((float)x), y((float)y), z((float)z) { }
Vec3 operator+(const Vec3& other) const
{
@ -91,6 +95,26 @@ typedef struct Vec3 // Vector or Position
{
return Vec3(ceilf(x), ceilf(y), ceilf(z));
}
SVECTOR convertNormal()
{
SVECTOR outNormal;
outNormal.vx = (short)(x * ONE);
outNormal.vy = (short)(y * ONE);
outNormal.vz = (short)(z * ONE);
outNormal.pad = 0;
return outNormal;
}
SVECTOR convertWorldPosition()
{
SVECTOR outPoint;
outPoint.vx = (short)(x * 4);
outPoint.vy = (short)(y * 4);
outPoint.vz = (short)(z * 4);
outPoint.pad = ONE;
return outPoint;
}
} vec3_t;
template<> struct std::hash<Vec3>

40
main.cpp

@ -15,26 +15,6 @@ template<class TData> size_t writeMapData(const std::vector<TData>& data, ps1bsp
return fwrite(data.data(), sizeof(TData), data.size(), f);
}
static SVECTOR convertNormal(vec3_t normal)
{
SVECTOR outNormal;
outNormal.vx = (short)(normal.x * 4096);
outNormal.vy = (short)(normal.y * 4096);
outNormal.vz = (short)(normal.z * 4096);
outNormal.pad = 0;
return outNormal;
}
static SVECTOR convertWorldPosition(vec3_t point)
{
SVECTOR outPoint;
outPoint.vx = (short)(point.x * 4);
outPoint.vy = (short)(point.y * 4);
outPoint.vz = (short)(point.z * 4);
outPoint.pad = 1;
return outPoint;
}
static float computeFaceArea(const world_t* world, const face_t* face)
{
const plane_t* plane = &world->planes[face->plane_id];
@ -57,7 +37,7 @@ static float computeFaceArea(const world_t* world, const face_t* face)
double x = tangent.dotProduct(vec);
double y = bitangent.dotProduct(vec);
bounds.includePoint(Vec3(x, y, 0));
bounds.includePoint(Vec3(x, y, 0.0));
}
Vec3 extents = bounds.max - bounds.min;
@ -131,7 +111,7 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
// export_lightmap(world, face, bounds, faceIdx);
outFace.numFaceVertices = (unsigned char)(outFaceVertices.size() - outFace.firstFaceVertex);
outFace.center = convertWorldPosition(vertexSum / face->ledge_num);
outFace.center = (vertexSum / face->ledge_num).convertWorldPosition();
float area = computeFaceArea(world, face); // TODO: divide by number of polygons
outFace.center.pad = (short)(sqrt(area));
outFaces.push_back(outFace);
@ -159,6 +139,13 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
continue;
}
// Invisible collision volumes don't have to be tessellated
if (!strcmp(miptex->name, "clip") || !strcmp(miptex->name, "trigger"))
{
outFace->numPolygons = 0;
continue;
}
// Draw water as fullbright transparent surfaces
if (miptex->name[0] == '*')
{
@ -233,7 +220,7 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
plane_t* plane = &world->planes[planeIdx];
ps1bsp_plane_t outPlane = { 0 };
outPlane.normal = convertNormal(plane->normal);
outPlane.normal = plane->normal.convertNormal();
outPlane.dist = (short)(plane->dist * 4);
outPlane.type = (short)plane->type;
@ -246,13 +233,12 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
{
node_t* node = &world->nodes[nodeIdx];
ps1bsp_node_t outNode;
ps1bsp_node_t outNode = { 0 };
outNode.planeId = node->plane_id;
outNode.children[0] = node->front;
outNode.children[1] = node->back;
outNode.firstFace = node->face_id;
outNode.numFaces = node->face_num;
outNode.boundingSphere = node->box.toBoundingSphere();
outNodes.push_back(outNode);
}
@ -263,7 +249,7 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
{
dleaf_t* leaf = &world->leaves[leafIdx];
ps1bsp_leaf_t outLeaf;
ps1bsp_leaf_t outLeaf = { 0 };
outLeaf.type = leaf->type;
outLeaf.vislist = leaf->vislist;
outLeaf.firstLeafFace = leaf->lface_id;

13
ps1bsp.h

@ -119,8 +119,8 @@ typedef struct
// Used for backface culling
SVECTOR center;
// Which frame was this face last drawn on? Used to check if this face should be drawn.
u_long drawFrame;
// Run-time data
u_long drawFrame; // Which frame was this face last drawn on? Used to check if this face should be drawn.
} ps1bsp_face_t;
typedef struct
@ -135,10 +135,7 @@ typedef struct
int planeId;
short children[2];
// TODO: add bounding box for frustum culling (or bounding sphere, might be cheaper)
u_short firstFace;
u_short numFaces;
SVECTOR boundingSphere;
} ps1bsp_node_t;
typedef struct
@ -151,6 +148,10 @@ typedef struct
u_short firstLeafFace;
u_short numLeafFaces;
// Run-time data
u_short nextLeaf; // For chaining leafs in drawing order
u_short leafDepth; // At what depth the leaf's faces should be placed in the ordering table
} ps1bsp_leaf_t;
// Pre-parsed and encoded entity data (this runs the risk of becoming too bloated)

2
ps1types.h

@ -1,6 +1,8 @@
#pragma once
#include <stdint.h>
#define ONE 4096
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;

4
tesselate.cpp

@ -94,10 +94,10 @@ std::vector<Tesselator::Polygon> Tesselator::tesselateFace(const face_t* face)
const auto vert = &result.contour[0].vertex[v];
// Transform the vertex back to world space
Vec3 newVert = textureTrsf.TransformPoint(Vec3(vert->x, vert->y, 0));
Vec3 newVert = textureTrsf.TransformPoint(Vec3(vert->x, vert->y, 0.0));
size_t vertIndex = addVertex(newVert);
Vec3 normalizedUV(vert->x - x, vert->y - y, 0); // Normalize the UV to fall within [0..1] range
Vec3 normalizedUV(vert->x - x, vert->y - y, 0.0); // Normalize the UV to fall within [0..1] range
newPoly.polyVertices.push_back(PolyVertex{ vertIndex, normalizedUV });
}

Loading…
Cancel
Save