light: when interpolating a normal that lies outside of a face, recursively look it up on adjacent faces

This commit is contained in:
Eric Wasylishen 2016-04-26 00:29:50 -06:00
parent 8c28413a31
commit c58528499d
3 changed files with 76 additions and 6 deletions

View File

@ -222,6 +222,9 @@ void MakeTnodes(const bsp2_t *bsp);
/* access the final phong-shaded vertex normal */
const vec_t *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);
extern float scaledist;
extern float rangescale;
@ -300,6 +303,9 @@ Face_TextureName(const bsp2_t *bsp, const bsp2_dface_t *face);
void
Face_MakeInwardFacingEdgePlanes(const bsp2_t *bsp, const bsp2_dface_t *face, plane_t *out);
plane_t Face_Plane(const bsp2_t *bsp, const bsp2_dface_t *f);
void Face_Normal(const bsp2_t *bsp, const bsp2_dface_t *f, vec3_t norm);
/* vis testing */
const bsp2_dleaf_t *Light_PointInLeaf( const bsp2_t *bsp, const vec3_t point );
int Light_PointContents( const bsp2_t *bsp, const vec3_t point );

View File

@ -350,7 +350,8 @@ public:
std::map<const bsp2_dface_t *, std::vector<vec3_struct_t>> vertex_normals;
std::set<int> interior_verts;
map<const bsp2_dface_t *, set<const bsp2_dface_t *>> smoothFaces;
map<int, vector<const bsp2_dface_t *>> vertsToFaces;
/* 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 */
@ -381,7 +382,7 @@ static int GetSurfaceVertex(const bsp2_t *bsp, const bsp2_dface_t *f, int v)
return bsp->dedges[edge].v[0];
}
static void
void
Face_Normal(const bsp2_t *bsp, const bsp2_dface_t *f, vec3_t norm)
{
if (f->side)
@ -411,12 +412,63 @@ FacesOnSamePlane(const std::vector<const bsp2_dface_t *> &faces)
return true;
}
static void
Vertex_GetPos(const bsp2_t *bsp, int num, vec3_t out)
{
assert(num >= 0 && num < bsp->numvertexes);
const dvertex_t *v = &bsp->dvertexes[num];
for (int i=0; i<3; i++)
out[i] = v->point[i];
}
plane_t
Face_Plane(const bsp2_t *bsp, const bsp2_dface_t *f)
{
const int vertnum = GetSurfaceVertex(bsp, f, 0);
vec3_t vertpos;
Vertex_GetPos(bsp, vertnum, vertpos);
plane_t res;
Face_Normal(bsp, f, res.normal);
res.dist = DotProduct(vertpos, res.normal);
return res;
}
const bsp2_dface_t *
Face_EdgeIndexSmoothed(const bsp2_t *bsp, const bsp2_dface_t *f, const int edgeindex)
{
if (smoothFaces.find(f) == smoothFaces.end()) {
return nullptr;
}
int v0 = GetSurfaceVertex(bsp, f, edgeindex);
int v1 = GetSurfaceVertex(bsp, f, (edgeindex + 1) % f->numedges);
const auto &v0_faces = vertsToFaces.at(v0);
const auto &v1_faces = vertsToFaces.at(v1);
// find a face f2 that has both verts v0 and v1
for (auto f2 : v0_faces) {
if (f2 == f)
continue;
if (find(v1_faces.begin(), v1_faces.end(), f2) != v1_faces.end()) {
const auto &f_smoothfaces = smoothFaces.at(f);
bool smoothed = (f_smoothfaces.find(f2) != f_smoothfaces.end());
return smoothed ? f2 : nullptr;
}
}
return nullptr;
}
static void
CalcualateVertexNormals(const bsp2_t *bsp)
{
// clear in case we are run twice
vertex_normals.clear();
interior_verts.clear();
smoothFaces.clear();
vertsToFaces.clear();
// read _phong and _phong_angle from entities for compatiblity with other qbsp's, at the expense of no
// support on func_detail/func_group
@ -436,7 +488,6 @@ CalcualateVertexNormals(const bsp2_t *bsp)
}
// build "vert index -> faces" map
std::map<int, std::vector<const bsp2_dface_t *>> vertsToFaces;
for (int i = 0; i < bsp->numfaces; i++) {
const bsp2_dface_t *f = &bsp->dfaces[i];
for (int j = 0; j < f->numedges; j++) {
@ -455,7 +506,6 @@ CalcualateVertexNormals(const bsp2_t *bsp)
printf("CalcualateVertexNormals: %d interior verts\n", (int)interior_verts.size());
// build the "face -> faces to smooth with" map
std::map<const bsp2_dface_t *, std::set<const bsp2_dface_t *>> smoothFaces;
for (int i = 0; i < bsp->numfaces; i++) {
bsp2_dface_t *f = &bsp->dfaces[i];

View File

@ -19,6 +19,7 @@
#include <light/light.h>
#include <light/entities.h>
#include <assert.h>
/* ======================================================================== */
@ -460,8 +461,10 @@ FractionOfLine(const vec3_t v, const vec3_t w, const vec3_t p) {
return t;
}
static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, plane_t surfplane, vec_t *norm, const vec_t *point)
static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t *norm, const vec_t *point, int inside)
{
plane_t surfplane = Face_Plane(bsp, face);
// project `point` onto the surface plane (it's hovering 1 unit above)
vec3_t pointOnPlane;
{
@ -507,6 +510,17 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, plane_t
if (dist < ON_EPSILON) {
// behind this plane
const bsp2_dface_t *smoothed = Face_EdgeIndexSmoothed(bsp, face, i);
if (smoothed) {
if (inside < 3) {
free(edgeplanes);
// call recursively to look up normal in the adjacent face
CalcPointNormal(bsp, smoothed, norm, point, inside + 1);
return;
}
}
v1 = GetSurfaceVertexPoint(bsp, face, i);
v2 = GetSurfaceVertexPoint(bsp, face, (i+1)%face->numedges);
@ -620,7 +634,7 @@ CalcPoints(const modelinfo_t *modelinfo, const vec3_t offset, lightsurf_t *surf,
if (surf->curved)
{
CalcPointNormal(bsp, face, surf->plane, norm, point);
CalcPointNormal(bsp, face, norm, point, 0);
}
else
{