Browse Source

Added computation of face area by projecting its vertices onto its plane and then generating a bounding box. Will be used for determining tessellation subdivisions.

master
Nico de Poel 3 years ago
parent
commit
bf3bf810f6
  1. 13
      bsp.h
  2. 37
      common.h
  3. 9
      lighting.cpp
  4. 47
      main.cpp
  5. 3
      ps1bsp.h

13
bsp.h

@ -49,7 +49,7 @@ typedef struct BoundBox // Bounding Box, Float values
vec3_t min; // minimum values of X,Y,Z
vec3_t max; // maximum values of X,Y,Z
BoundBox() { }
BoundBox(): min(FLT_MAX, FLT_MAX, FLT_MAX), max(FLT_MIN, FLT_MIN, FLT_MIN) { }
void init(vec3_t point)
{
@ -75,10 +75,19 @@ typedef struct BoundBox // Bounding Box, Float values
}
} boundbox_t;
typedef struct // Bounding Box, Short values
typedef struct BBoxShort // Bounding Box, Short values
{
short min[3]; // minimum values of X,Y,Z
short max[3]; // maximum values of X,Y,Z
vec3_t getCenter() const
{
return vec3_t(
((float)max[0] + (float)min[0]) / 2,
((float)max[1] + (float)min[1]) / 2,
((float)max[2] + (float)min[2]) / 2
);
}
} bboxshort_t;
typedef struct // Mip texture list header

37
common.h

@ -3,6 +3,7 @@
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cfloat>
#include <vector>
#include <unordered_map>
#include <unordered_set>
@ -23,6 +24,16 @@ typedef struct Vec3 // Vector or Position
return Vec3(x + other.x, y + other.y, z + other.z);
}
Vec3 operator-(const Vec3& other) const
{
return Vec3(x - other.x, y - other.y, z - other.z);
}
Vec3 operator*(float mul) const
{
return Vec3(x * mul, y * mul, z * mul);
}
Vec3 operator/(float div) const
{
return Vec3(x / div, y / div, z / div);
@ -32,9 +43,25 @@ typedef struct Vec3 // Vector or Position
{
return Vec3(-x, -y, -z);
}
} vec3_t;
inline float dotProduct(vec3_t a, vec3_t b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
float magnitude() const
{
return sqrtf(x * x + y * y + z * z);
}
Vec3 normalized() const
{
float invMag = 1.0f / magnitude();
return Vec3(x * invMag, y * invMag, z * invMag);
}
float dotProduct(const Vec3 &other) const
{
return x * other.x + y * other.y + z * other.z;
}
Vec3 crossProduct(const Vec3 &other) const
{
return Vec3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x);
}
} vec3_t;

9
lighting.cpp

@ -147,7 +147,7 @@ std::unordered_map<const edge_t*, EdgeData> analyze_edges(const world_t* world)
const plane_t* planeB = &world->planes[faceB->plane_id];
vec3_t normalA = faceA->side ? -planeA->normal : planeA->normal;
vec3_t normalB = faceB->side ? -planeB->normal : planeB->normal;
float dot = dotProduct(normalA, normalB);
float dot = normalA.dotProduct(normalB);
bool isSmooth = dot >= 0.5f;//&& dot <= 1;
iter->second.isSharpEdge = !isSmooth;
break;
@ -239,7 +239,7 @@ unsigned char compute_faceVertex_light2(const world_t* world, const face_t* face
const plane_t* otherPlane = &world->planes[otherFace->plane_id];
vec3_t otherNormal = otherFace->side ? -otherPlane->normal : otherPlane->normal;
float dot = dotProduct(thisNormal, otherNormal);
float dot = thisNormal.dotProduct(otherNormal);
if (dot < 0.5f)
continue; // Sharp edge, we don't want light contribution from this face
@ -249,3 +249,8 @@ unsigned char compute_faceVertex_light2(const world_t* world, const face_t* face
return (unsigned char)(light / numSamples);
}
// Further improvements:
// - Reconstruct connected surfaces through vertices and edges, so we can fully sample all adjacent lightmaps.
// Right now we don't properly detect when one face has vertices halfway along the edge of an adjacent face.
// - Sample more lightmap points around each vertex to obtain a more representative average value

47
main.cpp

@ -179,7 +179,7 @@ static SVECTOR convertNormal(vec3_t normal)
return outNormal;
}
static SVECTOR convertPoint(vec3_t point)
static SVECTOR convertWorldPosition(vec3_t point)
{
SVECTOR outPoint;
outPoint.vx = (short)(point.x * 4);
@ -189,6 +189,42 @@ static SVECTOR convertPoint(vec3_t point)
return outPoint;
}
static float computeFaceArea(const world_t* world, const face_t* face)
{
const plane_t* plane = &world->planes[face->plane_id];
// Construct a tangent and bitangent for the plane using the face's first vertex
int edgeIdx = world->edgeList[face->ledge_id];
unsigned short vertIndex = edgeIdx > 0 ?
world->edges[edgeIdx].vertex0 :
world->edges[-edgeIdx].vertex1;
const vertex_t* vertex = &world->vertices[vertIndex];
Vec3 refPoint = plane->normal * plane->dist;
Vec3 tangent = (vertex->toVec() - refPoint).normalized();
Vec3 bitangent = plane->normal.crossProduct(tangent);
// Project all face vertices onto the face's plane
BoundBox bounds;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
edgeIdx = world->edgeList[face->ledge_id + edgeListIdx];
vertIndex = edgeIdx > 0 ?
world->edges[edgeIdx].vertex0 :
world->edges[-edgeIdx].vertex1;
vertex_t* vertex = &world->vertices[vertIndex];
Vec3 vec = vertex->toVec();
float x = tangent.dotProduct(vec);
float y = bitangent.dotProduct(vec);
bounds.includePoint(Vec3(x, y, 0));
}
Vec3 extents = bounds.max - bounds.min;
return extents.x * extents.y;
}
int process_faces(const world_t* world)
{
// Write some data to a file
@ -241,9 +277,8 @@ int process_faces(const world_t* world)
outFace.side = face->side;
outFace.firstFaceVertex = (unsigned short)outFaceVertices.size();
Vec3 vertexSum;
// Traverse the list of face edges to collect all of the face's vertices
Vec3 vertexSum;
BoundBox bounds;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
@ -283,7 +318,9 @@ int process_faces(const world_t* world)
// export_lightmap(world, face, bounds, faceIdx);
outFace.numFaceVertices = (unsigned short)(outFaceVertices.size() - outFace.firstFaceVertex);
outFace.centerPoint = convertPoint(vertexSum / outFace.numFaceVertices);
outFace.centerPoint = convertWorldPosition(vertexSum / outFace.numFaceVertices);
float area = computeFaceArea(world, face);
outFace.centerPoint.pad = (short)(sqrt(area));
outFaces.push_back(outFace);
}
@ -363,6 +400,8 @@ int process_faces(const world_t* world)
outLeaf.firstLeafFace = leaf->lface_id;
outLeaf.numLeafFaces = leaf->lface_num;
//outLeaf.center = convertWorldPosition(leaf->bound.getCenter());
outLeaves.push_back(outLeaf);
}

3
ps1bsp.h

@ -105,7 +105,8 @@ typedef struct
int type;
int vislist;
// TODO: add bounding box for frustum culing
// TODO: add bounding box for frustum culling (or do we? could save half the number of bounds checks if we only check nodes)
//SVECTOR center;
u_short firstLeafFace;
u_short numLeafFaces;

Loading…
Cancel
Save