Browse Source

A bit of cleanup and moved the facesWithPoint function to world_t, for easier reuse

master
Nico de Poel 3 years ago
parent
commit
5137fe0a15
  1. 60
      bsp.h
  2. 132
      lighting.cpp
  3. 2
      lighting.h

60
bsp.h

@ -172,7 +172,7 @@ typedef struct
unsigned char sndlava; //
} dleaf_t;
typedef struct
typedef struct World
{
const char* name;
dheader_t header;
@ -214,4 +214,62 @@ typedef struct
int lightmapLength;
unsigned char* lightmap;
// Find the list of all faces that contain the given point, i.e. the point lies on the face's plane and is contained within its polygon bounds
std::vector<const face_t*> facesWithPoint(const Vec3& point) const
{
std::vector<const face_t*> outFaces;
for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
{
const face_t* face = &faces[faceIdx];
const plane_t* plane = &planes[face->plane_id];
// Check if the point lies on the face's plane (it's not strictly necessary to do this, but this check makes the whole function a lot faster)
double pointPlaneDist = ((double)point.x * plane->normal.x + (double)point.y * plane->normal.y + (double)point.z * plane->normal.z) - plane->dist;
if (fabs(pointPlaneDist) > 0.0001)
continue;
// Check if the point is contained within the face's polygon
double angleSum = 0;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
int edgeIdx = edgeList[face->ledge_id + edgeListIdx];
Vec3 v0, v1;
if (edgeIdx > 0)
{
const edge_t* edge = &edges[edgeIdx];
v0 = vertices[edge->vertex0].toVec();
v1 = vertices[edge->vertex1].toVec();
}
else
{
const edge_t* edge = &edges[-edgeIdx];
v0 = vertices[edge->vertex1].toVec();
v1 = vertices[edge->vertex0].toVec();
}
Vec3 p0 = v0 - point;
Vec3 p1 = v1 - point;
double m0 = p0.magnitude();
double m1 = p1.magnitude();
if ((m0 * m1) <= 0.0001)
{
// Point is on one of the vertices
outFaces.push_back(face);
break;
}
double dot = p0.dotProduct(p1) / (m0 * m1);
angleSum += acos(dot);
}
// If the point is inside the polygon, then the sum of all the above angles will be exactly 360 degrees
if (fabs(2 * M_PI - angleSum) <= 0.0001)
outFaces.push_back(face);
}
return outFaces;
}
} world_t;

132
lighting.cpp

@ -325,139 +325,9 @@ SurfaceList group_surfaces(const world_t* world, const VertexFaces& vertexFaces)
return surfaces;
}
// To sample lightmap at any arbitrary world position:
// - Find the surface that the face belongs to
// - Select all faces from the surface where the position lies in its plane and is inside polygon boundaries
// - Sample those faces at the specified position (sample_lightmap) and average
std::vector<const face_t*> find_facesWithPoint(const world_t* world, const face_t* refFace, const SurfaceList& surfaces, Vec3 point)
{
std::vector<const face_t*> faces;
// Find the surface that the face belongs to
for (auto surfIter = surfaces.begin(); surfIter != surfaces.end(); ++surfIter)
{
if (surfIter->faces.find(refFace) == surfIter->faces.end())
continue;
// Select all faces from the surface where the point lies in its plane and is inside polygon boundaries
for (auto faceIter = surfIter->faces.begin(); faceIter != surfIter->faces.end(); ++faceIter)
{
const face_t* face = *faceIter;
const plane_t* plane = &world->planes[face->plane_id];
// Check if the point lies on the face's plane
float pointPlaneDist = (point.x * plane->normal.x + point.y * plane->normal.y + point.z * plane->normal.z) - plane->dist;
if (fabs(pointPlaneDist) > FLT_EPSILON)
continue;
// Simple case first: check if this point lies on one of the face's edges
bool onEdge = false;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
int edgeIdx = world->edgeList[face->ledge_id + edgeListIdx];
const edge_t* edge = &world->edges[abs(edgeIdx)];
Vec3 vert0 = world->vertices[edge->vertex0].toVec();
Vec3 vert1 = world->vertices[edge->vertex1].toVec();
Vec3 dir0 = vert1 - vert0;
Vec3 dir1 = point - vert0;
float mag0 = dir0.magnitude();
float mag1 = dir1.magnitude();
if (mag1 / mag0 <= 1.0f + FLT_EPSILON && dir0.dotProduct(dir1) >= (mag0 - FLT_EPSILON) * (mag1 - FLT_EPSILON))
onEdge = true;
}
if (onEdge)
faces.push_back(face);
}
break;
}
return faces;
}
// 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
unsigned char compute_faceVertex_light3(const world_t* world, const face_t* refFace, const SurfaceList& surfaces, const FaceBounds& faceBounds, Vec3 point)
{
auto faces = find_facesWithPoint(world, refFace, surfaces, point);
if (faces.empty())
return 0;
unsigned int light = 0;
for (auto faceIter = faces.begin(); faceIter != faces.end(); ++faceIter)
{
const face_t* face = *faceIter;
light += sample_lightmap(world, face, faceBounds.find(face)->second, point) + (0xFF - face->baselight);
}
return (unsigned char)(light / faces.size());
}
// Find the list of all faces that contain the given point, i.e. the point lies on the face's plane and is contained within its polygon bounds
std::vector<const face_t*> world_facesWithPoint(const world_t* world, Vec3 point)
{
std::vector<const face_t*> faces;
for (int faceIdx = 0; faceIdx < world->numFaces; ++faceIdx)
{
const face_t* face = &world->faces[faceIdx];
const plane_t* plane = &world->planes[face->plane_id];
// Check if the point lies on the face's plane (it's not strictly necessary to do this, but this check makes the whole function a lot faster)
double pointPlaneDist = ((double)point.x * plane->normal.x + (double)point.y * plane->normal.y + (double)point.z * plane->normal.z) - plane->dist;
if (fabs(pointPlaneDist) > 0.0001)
continue;
// Check if the point is contained within the face's polygon
double angleSum = 0;
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
int edgeIdx = world->edgeList[face->ledge_id + edgeListIdx];
Vec3 v0, v1;
if (edgeIdx > 0)
{
const edge_t* edge = &world->edges[edgeIdx];
v0 = world->vertices[edge->vertex0].toVec();
v1 = world->vertices[edge->vertex1].toVec();
}
else
{
const edge_t* edge = &world->edges[-edgeIdx];
v0 = world->vertices[edge->vertex1].toVec();
v1 = world->vertices[edge->vertex0].toVec();
}
Vec3 p0 = v0 - point;
Vec3 p1 = v1 - point;
double m0 = p0.magnitude();
double m1 = p1.magnitude();
if ((m0 * m1) <= 0.0001)
{
faces.push_back(face);
break;
}
double dot = p0.dotProduct(p1) / (m0 * m1);
angleSum += acos(dot);
}
if (fabs(2 * M_PI - angleSum) <= 0.0001)
faces.push_back(face);
}
return faces;
}
unsigned char compute_faceVertex_light4(const world_t* world, const face_t* refFace, const FaceBounds& faceBounds, Vec3 point)
{
auto faces = world_facesWithPoint(world, point);
auto faces = world->facesWithPoint(point);
if (faces.empty())
return 0;

2
lighting.h

@ -27,6 +27,4 @@ unsigned char compute_faceVertex_light(const world_t* world, const face_t* face,
unsigned char compute_faceVertex_light2(const world_t* world, const face_t* face, unsigned short vertexIndex, const FaceBounds& faceBounds, const VertexFaces& vertexFaces);
SurfaceList group_surfaces(const world_t* world, const VertexFaces& vertexFaces);
unsigned char compute_faceVertex_light3(const world_t* world, const face_t* refFace, const SurfaceList& surfaces, const FaceBounds& faceBounds, Vec3 point);
unsigned char compute_faceVertex_light4(const world_t* world, const face_t* refFace, const FaceBounds& faceBounds, Vec3 point);
Loading…
Cancel
Save