diff --git a/include/common/mathlib.hh b/include/common/mathlib.hh index 5cf533b9..3b04300c 100644 --- a/include/common/mathlib.hh +++ b/include/common/mathlib.hh @@ -311,6 +311,12 @@ static inline glm::vec3 vec3_t_to_glm(const vec3_t vec) { return glm::vec3(vec[0], vec[1], vec[2]); } +static inline void glm_to_vec3_t(const glm::vec3 &glm, vec3_t out) { + out[0] = glm.x; + out[1] = glm.y; + out[2] = glm.z; +} + glm::vec3 GLM_FaceNormal(std::vector points); std::vector GLM_MakeInwardFacingEdgePlanes(std::vector points); bool GLM_EdgePlanes_PointInside(const std::vector &edgeplanes, const glm::vec3 &point); diff --git a/include/light/light.hh b/include/light/light.hh index f5f73ef6..cf105df0 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -80,7 +80,7 @@ typedef struct { } pmatrix3_t; typedef struct { - pmatrix3_t transform; + glm::mat4x4 texSpaceToWorld; const texinfo_t *texinfo; vec_t planedist; } texorg_t; diff --git a/include/light/ltface.hh b/include/light/ltface.hh index 33a52da3..6924a0b7 100644 --- a/include/light/ltface.hh +++ b/include/light/ltface.hh @@ -44,6 +44,7 @@ extern std::atomic total_bounce_rays, total_bounce_ray_hits; void FaceCentroid(const bsp2_dface_t *face, const bsp2_t *bsp, vec3_t out); void WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2]); +void PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp); // FIXME: remove light param. add normal param and dir params. vec_t GetLightValue(const globalconfig_t &cfg, const light_t *entity, vec_t dist); void GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origin, const vec3_t normal, vec3_t colorout); diff --git a/light/light2.cc b/light/light2.cc index 97d11261..35140706 100644 --- a/light/light2.cc +++ b/light/light2.cc @@ -96,6 +96,13 @@ pair RotationAboutLineSegment(glm::vec3 p0, glm::vec3 p1, glm::mat4x4 TexSpaceToWorld(const bsp2_t *bsp, const bsp2_dface_t *f) { const glm::mat4x4 T = WorldToTexSpace(bsp, f); + + if (glm::determinant(T) == 0) { + logprint("Bad texture axes on face:\n"); + PrintFaceInfo(f, bsp); + Error("CreateFaceTransform"); + } + return glm::inverse(T); } diff --git a/light/ltface.cc b/light/ltface.cc index fa1a4cf0..5efb92d6 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -33,97 +34,8 @@ std::atomic total_light_rays, total_light_ray_hits, total_samplepoints; std::atomic total_bounce_rays, total_bounce_ray_hits; -static void -PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp); - /* ======================================================================== */ - -/* - * To do arbitrary transformation of texture coordinates to world - * coordinates requires solving for three simultaneous equations. We - * set up the LU decomposed form of the transform matrix here. - */ -#define ZERO_EPSILON (0.001) -static qboolean -PMatrix3_LU_Decompose(pmatrix3_t *matrix) -{ - int i, j, k, tmp; - vec_t max; - int max_r, max_c; - - /* Do gauss elimination */ - for (i = 0; i < 3; ++i) { - max = 0; - max_r = max_c = i; - for (j = i; j < 3; ++j) { - for (k = i; k < 3; ++k) { - if (fabs(matrix->data[j][k]) > max) { - max = fabs(matrix->data[j][k]); - max_r = j; - max_c = k; - } - } - } - - /* Check for parallel planes */ - if (max < ZERO_EPSILON) - return false; - - /* Swap rows/columns if necessary */ - if (max_r != i) { - for (j = 0; j < 3; ++j) { - max = matrix->data[i][j]; - matrix->data[i][j] = matrix->data[max_r][j]; - matrix->data[max_r][j] = max; - } - tmp = matrix->row[i]; - matrix->row[i] = matrix->row[max_r]; - matrix->row[max_r] = tmp; - } - if (max_c != i) { - for (j = 0; j < 3; ++j) { - max = matrix->data[j][i]; - matrix->data[j][i] = matrix->data[j][max_c]; - matrix->data[j][max_c] = max; - } - tmp = matrix->col[i]; - matrix->col[i] = matrix->col[max_c]; - matrix->col[max_c] = tmp; - } - - /* Do pivot */ - for (j = i + 1; j < 3; ++j) { - matrix->data[j][i] /= matrix->data[i][i]; - for (k = i + 1; k < 3; ++k) - matrix->data[j][k] -= matrix->data[j][i] * matrix->data[i][k]; - } - } - - return true; -} - -static void -Solve3(const pmatrix3_t *matrix, const vec3_t rhs, vec3_t out) -{ - /* Use local short names just for readability (should optimize away) */ - const vec3_t *data = matrix->data; - const int *r = matrix->row; - const int *c = matrix->col; - vec3_t tmp; - - /* forward-substitution */ - tmp[0] = rhs[r[0]]; - tmp[1] = rhs[r[1]] - data[1][0] * tmp[0]; - tmp[2] = rhs[r[2]] - data[2][0] * tmp[0] - data[2][1] * tmp[1]; - - /* back-substitution */ - out[c[2]] = tmp[2] / data[2][2]; - out[c[1]] = (tmp[1] - data[1][2] * out[c[2]]) / data[1][1]; - out[c[0]] = (tmp[0] - data[0][1] * out[c[1]] - data[0][2] * out[c[2]]) - / data[0][0]; -} - /* * ============================================================================ * SAMPLE POINT DETERMINATION @@ -205,47 +117,12 @@ FaceCentroid(const bsp2_dface_t *face, const bsp2_t *bsp, vec3_t out) VectorScale(poly_centroid, 1.0 / poly_area, out); } -/* - * ================ - * CreateFaceTransform - * Fills in the transform matrix for converting tex coord <-> world coord - * ================ - */ -static void -CreateFaceTransform(const bsp2_dface_t *face, const bsp2_t *bsp, - pmatrix3_t *transform) -{ - /* Prepare the transform matrix and init row/column permutations */ - const dplane_t *plane = &bsp->dplanes[face->planenum]; - const texinfo_t *tex = &bsp->texinfo[face->texinfo]; - for (int i = 0; i < 3; i++) { - transform->data[0][i] = tex->vecs[0][i]; - transform->data[1][i] = tex->vecs[1][i]; - transform->data[2][i] = plane->normal[i]; - transform->row[i] = transform->col[i] = i; - } - if (face->side) - VectorSubtract(vec3_origin, transform->data[2], transform->data[2]); - - /* Decompose the matrix. If we can't, texture axes are invalid. */ - if (!PMatrix3_LU_Decompose(transform)) { - logprint("Bad texture axes on face:\n"); - PrintFaceInfo(face, bsp); - Error("CreateFaceTransform"); - } -} - static void TexCoordToWorld(vec_t s, vec_t t, const texorg_t *texorg, vec3_t world) { - vec3_t rhs; - - rhs[0] = s - texorg->texinfo->vecs[0][3]; - rhs[1] = t - texorg->texinfo->vecs[1][3]; - // FIXME: This could be more or less than one unit in world space? - rhs[2] = texorg->planedist + 1; /* one "unit" in front of surface */ - - Solve3(&texorg->transform, rhs, world); + glm::vec4 worldPos = texorg->texSpaceToWorld * glm::vec4(s, t, /* one "unit" in front of surface */ 1.0, 1.0); + + glm_to_vec3_t(glm::vec3(worldPos), world); } void @@ -275,8 +152,7 @@ WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2]) } /* Debug helper - move elsewhere? */ -static void -PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp) +void PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp) { const texinfo_t *tex = &bsp->texinfo[face->texinfo]; const char *texname = Face_TextureName(bsp, face); @@ -779,7 +655,7 @@ Lightsurf_Init(const modelinfo_t *modelinfo, const bsp2_dface_t *face, } /* Set up the texorg for coordinate transformation */ - CreateFaceTransform(face, bsp, &lightsurf->texorg.transform); + lightsurf->texorg.texSpaceToWorld = TexSpaceToWorld(bsp, face); lightsurf->texorg.texinfo = &bsp->texinfo[face->texinfo]; lightsurf->texorg.planedist = plane->dist;