diff --git a/bsp.h b/bsp.h index 0d85329..1198e59 100644 --- a/bsp.h +++ b/bsp.h @@ -239,7 +239,7 @@ typedef struct World // 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) + if (fabs(pointPlaneDist) > 0.001) continue; // Check if the point is contained within the face's polygon @@ -267,7 +267,7 @@ typedef struct World double m0 = p0.magnitude(); double m1 = p1.magnitude(); - if ((m0 * m1) <= 0.0001) + if ((m0 * m1) <= 0.001) { // Point is on one of the vertices outFaces.push_back(face); @@ -279,7 +279,7 @@ typedef struct World } // 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) + if (fabs(2 * M_PI - angleSum) <= 0.001) outFaces.push_back(face); } diff --git a/common.h b/common.h index 188222f..ab9d029 100644 --- a/common.h +++ b/common.h @@ -65,4 +65,14 @@ typedef struct Vec3 // Vector or Position { return Vec3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x); } + + Vec3 floor() const + { + return Vec3(floorf(x), floorf(y), floorf(z)); + } + + Vec3 ceil() const + { + return Vec3(ceilf(x), ceilf(y), ceilf(z)); + } } vec3_t; diff --git a/lighting.cpp b/lighting.cpp index 0d3544e..0a4e7e4 100644 --- a/lighting.cpp +++ b/lighting.cpp @@ -1,51 +1,64 @@ #include "common.h" #include "lighting.h" -unsigned char sample_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, const Vec3& point) +bool sample_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, const Vec3& point, unsigned char* outSample) { if (face->lightmap < 0) - return 0; + return false; const unsigned char* lightmap = &world->lightmap[face->lightmap]; const plane_t* plane = &world->planes[face->plane_id]; + Vec3 minBounds = (bounds.min / 16).floor() * 16; + Vec3 maxBounds = (bounds.max / 16).ceil() * 16; + int width, height; - float u, v; + int u, v; switch (plane->type) { case 0: case 3: // Towards X - width = (int)(ceil(bounds.max.y / 16) - floor(bounds.min.y / 16)) * 16; - height = (int)(ceil(bounds.max.z / 16) - floor(bounds.min.z / 16)) * 16; - u = (point.y - bounds.min.y) / (bounds.max.y - bounds.min.y); - v = (point.z - bounds.min.z) / (bounds.max.z - bounds.min.z); + width = (int)(maxBounds.y - minBounds.y); + height = (int)(maxBounds.z - minBounds.z); + u = (int)(point.y - minBounds.y); + v = (int)(point.z - minBounds.z); break; case 1: case 4: // Towards Y - width = (int)(ceil(bounds.max.x / 16) - floor(bounds.min.x / 16)) * 16; - height = (int)(ceil(bounds.max.z / 16) - floor(bounds.min.z / 16)) * 16; - u = (point.x - bounds.min.x) / (bounds.max.x - bounds.min.x); - v = (point.z - bounds.min.z) / (bounds.max.z - bounds.min.z); + width = (int)(maxBounds.x - minBounds.x); + height = (int)(maxBounds.z - minBounds.z); + u = (int)(point.x - minBounds.x); + v = (int)(point.z - minBounds.z); break; case 2: case 5: // Towards Z - width = (int)(ceil(bounds.max.x / 16) - floor(bounds.min.x / 16)) * 16; - height = (int)(ceil(bounds.max.y / 16) - floor(bounds.min.y / 16)) * 16; - u = (point.x - bounds.min.x) / (bounds.max.x - bounds.min.x); - v = (point.y - bounds.min.y) / (bounds.max.y - bounds.min.y); + width = (int)(maxBounds.x - minBounds.x); + height = (int)(maxBounds.y - minBounds.y); + u = (int)(point.x - minBounds.x); + v = (int)(point.y - minBounds.y); break; default: printf("Error: unknown plane type %d\n", plane->type); return 0; } - height >>= 4; - width >>= 4; + if (u < 0 || v < 0 || u > width || v > height) + return false; - return lightmap[(int)(v * (width + 1) + u)]; + *outSample = lightmap[(v >> 4) * (width >> 4) + (u >> 4)]; + return true; +} + +unsigned char sample_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, const Vec3& point) +{ + unsigned char sample; + if (!sample_lightmap(world, face, bounds, point, &sample)) + return 0; + + return sample; } void export_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, int faceIdx) @@ -327,6 +340,9 @@ SurfaceList group_surfaces(const world_t* world, const VertexFaces& vertexFaces) unsigned char compute_faceVertex_light4(const world_t* world, const face_t* refFace, const FaceBounds& faceBounds, Vec3 point) { + if (refFace->lightmap < 0) + return 0; + auto faces = world->facesWithPoint(point); if (faces.empty()) return 0; @@ -346,7 +362,11 @@ unsigned char compute_faceVertex_light4(const world_t* world, const face_t* refF if (dot < 0.5f) continue; - light += sample_lightmap(world, face, faceBounds.find(face)->second, point) + (0xFF - face->baselight); + unsigned char sample; + if (!sample_lightmap(world, face, faceBounds.find(face)->second, point, &sample)) + continue; + + light += sample + (0xFF - face->baselight); numSamples++; } diff --git a/lighting.h b/lighting.h index 066813a..75ea3f7 100644 --- a/lighting.h +++ b/lighting.h @@ -19,6 +19,7 @@ typedef std::unordered_map FaceBounds; typedef std::unordered_map> VertexFaces; typedef std::vector SurfaceList; +bool sample_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, const Vec3& point, unsigned char* outSample); unsigned char sample_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, const Vec3& point); void export_lightmap(const world_t* world, const face_t* face, const BoundBox& bounds, int faceIdx);