diff --git a/bsp.h b/bsp.h index 138191b..3de9b93 100644 --- a/bsp.h +++ b/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 diff --git a/common.h b/common.h index c7fc01a..4852c15 100644 --- a/common.h +++ b/common.h @@ -10,6 +10,8 @@ #include #include +#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 diff --git a/main.cpp b/main.cpp index 6836a91..f9d47b7 100644 --- a/main.cpp +++ b/main.cpp @@ -15,26 +15,6 @@ template size_t writeMapData(const std::vector& 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& 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& 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& 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& 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& 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; diff --git a/ps1bsp.h b/ps1bsp.h index 43959eb..38e21aa 100644 --- a/ps1bsp.h +++ b/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) diff --git a/ps1types.h b/ps1types.h index 570ebdf..2697411 100644 --- a/ps1types.h +++ b/ps1types.h @@ -1,6 +1,8 @@ #pragma once #include +#define ONE 4096 + typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; diff --git a/tesselate.cpp b/tesselate.cpp index 691211c..a7fbd61 100644 --- a/tesselate.cpp +++ b/tesselate.cpp @@ -94,10 +94,10 @@ std::vector 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 }); }