From f018b7324df5e21f91dc307fd87d652cc74d59e7 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 6 Feb 2017 22:50:56 -0700 Subject: [PATCH] light: refactor phong shading to use GLM --- include/common/mathlib.hh | 23 ++++++++++ include/light/light.hh | 2 +- light/light.cc | 92 ++++++++++++++++++--------------------- light/ltface.cc | 27 ++++++------ 4 files changed, 79 insertions(+), 65 deletions(-) diff --git a/include/common/mathlib.hh b/include/common/mathlib.hh index b1332144..43bafa05 100644 --- a/include/common/mathlib.hh +++ b/include/common/mathlib.hh @@ -60,6 +60,15 @@ extern const vec3_t vec3_origin; qboolean VectorCompare(const vec3_t v1, const vec3_t v2); +static inline bool +GLMVectorCompare(const glm::vec3 &v1, const glm::vec3 &v2) +{ + for (int i = 0; i < 3; i++) + if (fabs(v1[i] - v2[i]) > EQUAL_EPSILON) + return false; + return true; +} + static inline vec_t DotProduct(const vec3_t x, const vec3_t y) { @@ -114,6 +123,20 @@ VectorSet(vec3_t out, vec_t x, vec_t y, vec_t z) out[2] = z; } +static inline void +VectorCopyFromGLM(const glm::vec3 &in, vec3_t out) +{ + out[0] = in.x; + out[1] = in.y; + out[2] = in.z; +} + +static inline glm::vec3 +VectorToGLM(const vec3_t in) +{ + return glm::vec3(in[0], in[1], in[2]); +} + static inline vec_t Q_rint(vec_t in) { diff --git a/include/light/light.hh b/include/light/light.hh index 5b2d75f8..ef0fa97e 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -412,7 +412,7 @@ const modelinfo_t *ModelInfoForFace(const bsp2_t *bsp, int facenum); bool FacesSmoothed(const bsp2_dface_t *f1, const bsp2_dface_t *f2); const std::set &GetSmoothFaces(const bsp2_dface_t *face); const std::vector &GetPlaneFaces(const bsp2_dface_t *face); -const vec_t *GetSurfaceVertexNormal(const bsp2_t *bsp, const bsp2_dface_t *f, const int v); +const glm::vec3 GetSurfaceVertexNormal(const bsp2_t *bsp, const bsp2_dface_t *f, const int v); const bsp2_dface_t *Face_EdgeIndexSmoothed(const bsp2_t *bsp, const bsp2_dface_t *f, const int edgeindex); const std::vector &BounceLights(); std::vector BounceLightsForFaceNum(int facenum); diff --git a/light/light.cc b/light/light.cc index be0d3820..90145212 100644 --- a/light/light.cc +++ b/light/light.cc @@ -45,7 +45,10 @@ #include #include +#include + using namespace std; +using namespace glm; globalconfig_t cfg_static {}; @@ -342,12 +345,12 @@ FindModelInfo(const bsp2_t *bsp, const char *lmscaleoverride) /* return 0 if either vector is zero-length */ static float -AngleBetweenVectors(const vec3_t d1, const vec3_t d2) +AngleBetweenVectors(const vec3 &d1, const vec3 &d2) { - float length_product = (VectorLength(d1)*VectorLength(d2)); + float length_product = (length(d1)*length(d2)); if (length_product == 0) return 0; - float cosangle = DotProduct(d1, d2)/length_product; + float cosangle = dot(d1, d2)/length_product; if (cosangle < -1) cosangle = -1; if (cosangle > 1) cosangle = 1; @@ -357,24 +360,15 @@ AngleBetweenVectors(const vec3_t d1, const vec3_t d2) /* returns the angle between vectors p2->p1 and p2->p3 */ static float -AngleBetweenPoints(const vec3_t p1, const vec3_t p2, const vec3_t p3) +AngleBetweenPoints(const vec3 &p1, const vec3 &p2, const vec3 &p3) { - vec3_t d1, d2; - VectorSubtract(p1, p2, d1); - VectorSubtract(p3, p2, d2); + const vec3 d1 = p1 - p2; + const vec3 d2 = p3 - p2; float result = AngleBetweenVectors(d1, d2); return result; } -class vec3_struct_t { -public: - vec3_t v; - vec3_struct_t() { - VectorSet(v, 0, 0, 0); - } -}; - -std::map> vertex_normals; +std::map> vertex_normals; std::set interior_verts; map> smoothFaces; map> vertsToFaces; @@ -418,28 +412,28 @@ const std::vector &GetPlaneFaces(const bsp2_dface_t *face) /* given a triangle, just adds the contribution from the triangle to the given vertexes normals, based upon angles at the verts. * v1, v2, v3 are global vertex indices */ static void -AddTriangleNormals(std::map &smoothed_normals, const vec_t *norm, const dvertex_t *verts, int v1, int v2, int v3) +AddTriangleNormals(std::map &smoothed_normals, const vec3 &norm, const bsp2_t *bsp, int v1, int v2, int v3) { - const vec_t *p1 = verts[v1].point; - const vec_t *p2 = verts[v2].point; - const vec_t *p3 = verts[v3].point; + const vec3 p1 = Vertex_GetPos_E(bsp, v1); + const vec3 p2 = Vertex_GetPos_E(bsp, v2); + const vec3 p3 = Vertex_GetPos_E(bsp, v3); float weight; weight = AngleBetweenPoints(p2, p1, p3); - VectorMA(smoothed_normals[v1].v, weight, norm, smoothed_normals[v1].v); + smoothed_normals[v1] = smoothed_normals[v1] + (weight * norm); weight = AngleBetweenPoints(p1, p2, p3); - VectorMA(smoothed_normals[v2].v, weight, norm, smoothed_normals[v2].v); + smoothed_normals[v2] = smoothed_normals[v2] + (weight * norm); weight = AngleBetweenPoints(p1, p3, p2); - VectorMA(smoothed_normals[v3].v, weight, norm, smoothed_normals[v3].v); + smoothed_normals[v3] = smoothed_normals[v3] + (weight * norm); } /* access the final phong-shaded vertex normal */ -const vec_t *GetSurfaceVertexNormal(const bsp2_t *bsp, const bsp2_dface_t *f, const int vertindex) +const glm::vec3 GetSurfaceVertexNormal(const bsp2_t *bsp, const bsp2_dface_t *f, const int vertindex) { const auto &face_normals_vector = vertex_normals.at(f); - return face_normals_vector.at(vertindex).v; + return face_normals_vector.at(vertindex); } static bool @@ -537,8 +531,7 @@ CalcualateVertexNormals(const bsp2_t *bsp) for (int i = 0; i < bsp->numfaces; i++) { bsp2_dface_t *f = &bsp->dfaces[i]; - vec3_t f_norm; - Face_Normal(bsp, f, f_norm); + const vec3 f_norm = Face_Normal_E(bsp, f); // any face normal within this many degrees can be smoothed with this face const int f_smoothangle = (extended_texinfo_flags[f->texinfo] & TEX_PHONG_ANGLE_MASK) >> TEX_PHONG_ANGLE_SHIFT; @@ -556,10 +549,9 @@ CalcualateVertexNormals(const bsp2_t *bsp) if (!f2_smoothangle) continue; - vec3_t f2_norm; - Face_Normal(bsp, f2, f2_norm); + const vec3 f2_norm = Face_Normal_E(bsp, f2); - const vec_t cosangle = DotProduct(f_norm, f2_norm); + const vec_t cosangle = dot(f_norm, f2_norm); const vec_t cosmaxangle = cos(DEG2RAD(qmin(f_smoothangle, f2_smoothangle))); // check the angle between the face normals @@ -580,10 +572,7 @@ CalcualateVertexNormals(const bsp2_t *bsp) } const auto &neighboursToSmooth = smoothFaces[f]; - vec3_t f_norm; - - // get the face normal - Face_Normal(bsp, f, f_norm); + const vec3 f_norm = Face_Normal_E(bsp, f); // get the face normal // gather up f and neighboursToSmooth std::vector fPlusNeighbours; @@ -593,12 +582,11 @@ CalcualateVertexNormals(const bsp2_t *bsp) } // global vertex index -> smoothed normal - std::map smoothedNormals; + std::map smoothedNormals; // walk fPlusNeighbours for (auto f2 : fPlusNeighbours) { - vec3_t f2_norm; - Face_Normal(bsp, f2, f2_norm); + const vec3 f2_norm = Face_Normal_E(bsp, f2); /* now just walk around the surface as a triangle fan */ int v1, v2, v3; @@ -607,16 +595,16 @@ CalcualateVertexNormals(const bsp2_t *bsp) for (int j = 2; j < f2->numedges; j++) { v3 = Face_VertexAtIndex(bsp, f2, j); - AddTriangleNormals(smoothedNormals, f2_norm, bsp->dvertexes, v1, v2, v3); + AddTriangleNormals(smoothedNormals, f2_norm, bsp, v1, v2, v3); v2 = v3; } } - // normalize vertex normals + // normalize vertex normals (NOTE: updates smoothedNormals map) for (auto &pair : smoothedNormals) { const int vertIndex = pair.first; - vec_t *vertNormal = pair.second.v; - if (0 == VectorNormalize(vertNormal)) { + const vec3 vertNormal = pair.second; + if (0 == length(vertNormal)) { // this happens when there are colinear vertices, which give zero-area triangles, // so there is no contribution to the normal of the triangle in the middle of the // line. Not really an error, just set it to use the face normal. @@ -627,14 +615,18 @@ CalcualateVertexNormals(const bsp2_t *bsp) bsp->dvertexes[vertIndex].point[1], bsp->dvertexes[vertIndex].point[2]); #endif - VectorCopy(f_norm, vertNormal); + pair.second = f_norm; + } + else + { + pair.second = normalize(vertNormal); } } // sanity check if (!neighboursToSmooth.size()) { for (auto vertIndexNormalPair : smoothedNormals) { - Q_assert(VectorCompare(vertIndexNormalPair.second.v, f_norm)); + Q_assert(GLMVectorCompare(vertIndexNormalPair.second, f_norm)); } } @@ -797,7 +789,7 @@ LoadExtendedTexinfoFlags(const char *sourcefilename, const bsp2_t *bsp) // radiosity mutex radlights_lock; -map texturecolors; +map texturecolors; std::vector radlights; std::map> radlightsByFacenum; // duplicate of `radlights` but indexed by face @@ -875,8 +867,8 @@ Face_LookupTextureColor(const bsp2_t *bsp, const bsp2_dface_t *face, vec3_t colo const char *facename = Face_TextureName(bsp, face); if (texturecolors.find(facename) != texturecolors.end()) { - vec3_struct_t texcolor = texturecolors.at(facename); - VectorCopy(texcolor.v, color); + const vec3 texcolor = texturecolors.at(facename); + VectorCopyFromGLM(texcolor, color); } else { VectorSet(color, 127, 127, 127); } @@ -1042,11 +1034,11 @@ MakeTextureColors (const bsp2_t *bsp) const miptex_t *miptex = (miptex_t *)(bsp->dtexdata.base + ofs); string name { miptex->name }; - vec3_struct_t color; - Texture_AvgColor(bsp, miptex, color.v); + vec3_t color; + Texture_AvgColor(bsp, miptex, color); // printf("%s has color %f %f %f\n", name.c_str(), color.v[0], color.v[1], color.v[2]); - texturecolors[name] = color; + texturecolors[name] = VectorToGLM(color); } } @@ -1091,7 +1083,7 @@ ExportObjFace(FILE *f, const bsp2_t *bsp, const bsp2_dface_t *face, int *vertcou for (int i=0; inumedges; i++) { int vertnum = Face_VertexAtIndex(bsp, face, i); - const vec_t *normal = GetSurfaceVertexNormal(bsp, face, i); + const vec3 normal = GetSurfaceVertexNormal(bsp, face, i); const float *pos = bsp->dvertexes[vertnum].point; fprintf(f, "v %.9g %.9g %.9g\n", pos[0], pos[1], pos[2]); fprintf(f, "vn %.9g %.9g %.9g\n", normal[0], normal[1], normal[2]); diff --git a/light/ltface.cc b/light/ltface.cc index 77fae182..7891ea89 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -290,7 +290,7 @@ PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp) int edge = bsp->dsurfedges[face->firstedge + i]; int vert = Face_VertexAtIndex(bsp, face, i); const vec_t *point = GetSurfaceVertexPoint(bsp, face, i); - const vec_t *norm = GetSurfaceVertexNormal(bsp, face, i); + const glm::vec3 norm = GetSurfaceVertexNormal(bsp, face, i); logprint("%s %3d (%3.3f, %3.3f, %3.3f) :: normal (%3.3f, %3.3f, %3.3f) :: edge %d\n", i ? " " : " verts ", vert, point[0], point[1], point[2], @@ -466,13 +466,13 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t * // area test rejects the case when v1, v2, v3 are colinear if (TriangleArea(v1, v2, v3) >= 1) { - v1 = GetSurfaceVertexNormal(bsp, face, 0); - v2 = GetSurfaceVertexNormal(bsp, face, j-1); - v3 = GetSurfaceVertexNormal(bsp, face, j); - VectorScale(v1, bary[0], norm); - VectorMA(norm, bary[1], v2, norm); - VectorMA(norm, bary[2], v3, norm); - VectorNormalize(norm); + const glm::vec3 v1 = GetSurfaceVertexNormal(bsp, face, 0); + const glm::vec3 v2 = GetSurfaceVertexNormal(bsp, face, j-1); + const glm::vec3 v3 = GetSurfaceVertexNormal(bsp, face, j); + + const glm::vec3 glmnorm = normalize((bary[0] * v1) + (bary[1] * v2) + (bary[2] * v3)); + + VectorCopyFromGLM(glmnorm, norm); return; } } @@ -533,12 +533,11 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t * vec_t t = FractionOfLine(v1, v2, point); t = qmax(qmin(t, 1.0f), 0.0f); - v1 = GetSurfaceVertexNormal(bsp, face, bestplane); - v2 = GetSurfaceVertexNormal(bsp, face, (bestplane+1)%face->numedges); + const glm::vec3 v1 = GetSurfaceVertexNormal(bsp, face, bestplane); + const glm::vec3 v2 = GetSurfaceVertexNormal(bsp, face, (bestplane+1)%face->numedges); - VectorScale(v2, t, norm); - VectorMA(norm, 1-t, v1, norm); - VectorNormalize(norm); + const glm::vec3 glmnorm = normalize((v2 * t) + (1-t)*v1); + VectorCopyFromGLM(glmnorm, norm); free(edgeplanes); return; @@ -561,7 +560,7 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t * { bestd = dist; bestv = v; - VectorCopy(GetSurfaceVertexNormal(bsp, face, i), norm); + VectorCopyFromGLM(GetSurfaceVertexNormal(bsp, face, i), norm); } } VectorNormalize(norm);