light: avoid recomputing things in CalcPointNormal

This commit is contained in:
Eric Wasylishen 2017-02-26 22:58:08 -07:00
parent 5630257164
commit 97a00f0f41
5 changed files with 89 additions and 25 deletions

View File

@ -334,21 +334,24 @@ GLM_MakeInwardFacingEdgePlane(const vec3 &v0, const vec3 &v1, const vec3 &faceNo
}
vector<vec4>
GLM_MakeInwardFacingEdgePlanes(std::vector<vec3> points)
GLM_MakeInwardFacingEdgePlanes(const std::vector<vec3> &points)
{
if (points.size() < 3)
const int N = points.size();
if (N < 3)
return {};
vector<vec4> result;
result.reserve(points.size());
const vec3 faceNormal = GLM_FaceNormal(points);
if (faceNormal == vec3(0,0,0))
return {};
for (int i=0; i<points.size(); i++)
for (int i=0; i<N; i++)
{
const vec3 v0 = points.at(i);
const vec3 v1 = points.at((i+1) % points.size());
const vec3 v0 = points[i];
const vec3 v1 = points[(i+1) % N];
const auto edgeplane = GLM_MakeInwardFacingEdgePlane(v0, v1, faceNormal);
if (!edgeplane.first)

View File

@ -323,7 +323,7 @@ static inline void glm_to_vec3_t(const glm::vec3 &glm, vec3_t out) {
// Returns (0 0 0) if we couldn't determine the normal
glm::vec3 GLM_FaceNormal(std::vector<glm::vec3> points);
std::pair<bool, glm::vec4> GLM_MakeInwardFacingEdgePlane(const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &faceNormal);
std::vector<glm::vec4> GLM_MakeInwardFacingEdgePlanes(std::vector<glm::vec3> points);
std::vector<glm::vec4> GLM_MakeInwardFacingEdgePlanes(const std::vector<glm::vec3> &points);
bool GLM_EdgePlanes_PointInside(const std::vector<glm::vec4> &edgeplanes, const glm::vec3 &point);
float GLM_EdgePlanes_PointInsideDist(const std::vector<glm::vec4> &edgeplanes, const glm::vec3 &point);
glm::vec3 GLM_TriangleCentroid(const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &v2);

View File

@ -23,6 +23,7 @@
#include <common/cmdlib.hh>
#include <common/mathlib.hh>
#include <common/bsputils.hh>
#include <common/bspfile.hh>
#include <common/log.hh>
@ -33,6 +34,7 @@
#include <vector>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
void CalcualateVertexNormals(const bsp2_t *bsp);
const glm::vec3 GetSurfaceVertexNormal(const bsp2_t *bsp, const bsp2_dface_t *f, const int vertindex);
@ -47,4 +49,43 @@ using edgeToFaceMap_t = std::map<std::pair<int,int>, std::vector<const bsp2_dfac
const edgeToFaceMap_t &GetEdgeToFaceMap();
class face_cache_t {
private:
std::vector<glm::vec3> m_points;
std::vector<glm::vec3> m_normals;
glm::vec4 m_plane;
std::vector<glm::vec4> m_edgePlanes;
std::vector<glm::vec3> m_pointsShrunkBy1Unit;
public:
face_cache_t(const bsp2_t *bsp, const bsp2_dface_t *face, const std::vector<glm::vec3> &normals) :
m_points(GLM_FacePoints(bsp, face)),
m_normals(normals),
m_plane(Face_Plane_E(bsp, face)),
m_edgePlanes(GLM_MakeInwardFacingEdgePlanes(m_points)),
m_pointsShrunkBy1Unit(GLM_ShrinkPoly(m_points, 1.0f))
{ }
const std::vector<glm::vec3> &points() const {
return m_points;
}
const std::vector<glm::vec3> &normals() const {
return m_normals;
}
const glm::vec4 &plane() const {
return m_plane;
}
const glm::vec3 normal() const {
return glm::vec3(m_plane);
}
const std::vector<glm::vec4> &edgePlanes() const {
return m_edgePlanes;
}
const std::vector<glm::vec3> &pointsShrunkBy1Unit() const {
return m_pointsShrunkBy1Unit;
}
};
const face_cache_t &FaceCacheForFNum(int fnum);
#endif /* __LIGHT_PHONG_H__ */

View File

@ -239,16 +239,6 @@ FractionOfLine(const glm::vec3 &v, const glm::vec3 &w, const glm::vec3& p) {
return t;
}
vector<vec3> Face_VertexNormals(const bsp2_t *bsp, const bsp2_dface_t *face)
{
vector<vec3> normals;
for (int i=0; i<face->numedges; i++) {
const glm::vec3 n = GetSurfaceVertexNormal(bsp, face, i);
normals.push_back(n);
}
return normals;
}
using position_t = std::tuple<bool, const bsp2_dface_t *, glm::vec3, glm::vec3>;
constexpr float sampleOffPlaneDist = 1.0f;
@ -270,10 +260,10 @@ PositionSamplePointOnFace(const bsp2_t *bsp,
position_t CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, const glm::vec3 &origPoint, bool phongShaded, float face_lmscale, int recursiondepth)
{
const glm::vec4 surfplane = Face_Plane_E(bsp, face);
const auto points = GLM_FacePoints(bsp, face);
const auto normals = Face_VertexNormals(bsp, face);
const auto edgeplanes = GLM_MakeInwardFacingEdgePlanes(points);
const auto &facecache = FaceCacheForFNum(Face_GetNum(bsp, face));
const glm::vec4 &surfplane = facecache.plane();
const auto &points = facecache.points();
const auto &edgeplanes = facecache.edgePlanes();
// project `point` onto the surface plane, then lift it off again
const glm::vec3 point = GLM_ProjectPointOntoPlane(surfplane, origPoint) + (vec3(surfplane) * sampleOffPlaneDist);
@ -473,16 +463,17 @@ PositionSamplePointOnFace(const bsp2_t *bsp,
const bool phongShaded,
const glm::vec3 &point)
{
const auto points = GLM_FacePoints(bsp, face);
const auto normals = Face_VertexNormals(bsp, face);
const auto &facecache = FaceCacheForFNum(Face_GetNum(bsp, face));
const auto &points = facecache.points();
const auto &normals = facecache.normals();
const auto &edgeplanes = facecache.edgePlanes();
const auto &plane = facecache.plane();
const auto edgeplanes = GLM_MakeInwardFacingEdgePlanes(points);
if (edgeplanes.empty()) {
// degenerate polygon
return {false, nullptr, point, vec3(0)};
}
const auto plane = Face_Plane_E(bsp, face);
const float planedist = GLM_DistAbovePlane(plane, point);
Q_assert(fabs(planedist - sampleOffPlaneDist) <= POINT_EQUAL_EPSILON);
@ -512,7 +503,7 @@ PositionSamplePointOnFace(const bsp2_t *bsp,
const float distanceInside = GLM_EdgePlanes_PointInsideDist(edgeplanes, point);
if (distanceInside < 1.0f) {
// Point is too close to the border. Try nudging it inside.
const auto shrunk = GLM_ShrinkPoly(points, 1.0f);
const auto &shrunk = facecache.pointsShrunkBy1Unit();
if (!shrunk.empty()) {
const pair<int, vec3> closest = GLM_ClosestPointOnPolyBoundary(shrunk, point);
const vec3 newPoint = closest.second + (sampleOffPlaneDist * vec3(plane));
@ -670,11 +661,13 @@ CalcPoints(const modelinfo_t *modelinfo, const vec3_t offset, lightsurf_t *surf,
TexCoordToWorld(surf->exactmid[0], surf->exactmid[1], &surf->texorg, surf->midpoint);
VectorAdd(surf->midpoint, offset, surf->midpoint);
#if 0
// Get faces which could contribute to this one.
const auto contribFaces = SetupContributingFaces(bsp, face, GetEdgeToFaceMap());
// Get edge planes of this face which will block light for the purposes of placing the sample points
// to avoid light leaks.
const auto blockers = BlockingPlanes(bsp, face, GetEdgeToFaceMap());
#endif
surf->width = (surf->texsize[0] + 1) * oversample;
surf->height = (surf->texsize[1] + 1) * oversample;

View File

@ -73,6 +73,7 @@ static map<const bsp2_dface_t *, set<const bsp2_dface_t *>> smoothFaces;
static map<int, vector<const bsp2_dface_t *>> vertsToFaces;
static map<int, vector<const bsp2_dface_t *>> planesToFaces;
static edgeToFaceMap_t EdgeToFaceMap;
static vector<face_cache_t> FaceCache;
const edgeToFaceMap_t &GetEdgeToFaceMap()
{
@ -233,6 +234,26 @@ static edgeToFaceMap_t MakeEdgeToFaceMap(const bsp2_t *bsp)
return result;
}
static vector<vec3> Face_VertexNormals(const bsp2_t *bsp, const bsp2_dface_t *face)
{
vector<vec3> normals;
for (int i=0; i<face->numedges; i++) {
const glm::vec3 n = GetSurfaceVertexNormal(bsp, face, i);
normals.push_back(n);
}
return normals;
}
static vector<face_cache_t> MakeFaceCache(const bsp2_t *bsp)
{
vector<face_cache_t> result;
for (int i=0; i<bsp->numfaces; i++) {
const bsp2_dface_t *face = &bsp->dfaces[i];
result.push_back(face_cache_t{bsp, face, Face_VertexNormals(bsp, face)});
}
return result;
}
void
CalcualateVertexNormals(const bsp2_t *bsp)
{
@ -396,4 +417,10 @@ CalcualateVertexNormals(const bsp2_t *bsp)
vertex_normals[f].push_back(smoothedNormals[v]);
}
}
FaceCache = MakeFaceCache(bsp);
}
const face_cache_t &FaceCacheForFNum(int fnum) {
return FaceCache.at(fnum);
}