light: make CalcPointNormal more robust; don't use micro-triangles (<1 unit area) for interpolating normals

This commit is contained in:
Eric Wasylishen 2016-02-16 00:28:21 -07:00
parent 465cb2a555
commit ae04899ce5
1 changed files with 35 additions and 7 deletions

View File

@ -524,7 +524,19 @@ static int ClipPointToTriangle(const vec_t *orig, vec_t *point, const vec_t *nor
return 1;
}
static void CalcBarycentric(vec_t *p, vec_t *a, vec_t *b, vec_t *c, vec_t *res)
static vec_t
TriangleArea(const vec3_t v0, const vec3_t v1, const vec3_t v2)
{
vec3_t edge0, edge1, cross;
VectorSubtract(v2, v0, edge0);
VectorSubtract(v1, v0, edge1);
CrossProduct(edge0, edge1, cross);
return VectorLength(cross) * 0.5;
}
static void CalcBarycentric(const vec_t *p, const vec_t *a, const vec_t *b, const vec_t *c, vec_t *res)
{
vec3_t v0,v1,v2;
VectorSubtract(b, a, v0);
@ -542,8 +554,15 @@ static void CalcBarycentric(vec_t *p, vec_t *a, vec_t *b, vec_t *c, vec_t *res)
res[0] = 1.0f - res[1] - res[2];
}
static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, const vec_t *surfnorm, vec_t *norm, vec_t *point)
static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, plane_t surfplane, vec_t *norm, const vec_t *point)
{
// project `point` onto the surface plane (it's hovering 1 unit above)
vec3_t pointOnPlane;
{
vec_t dist = DotProduct(point, surfplane.normal) - surfplane.dist;
VectorMA(point, -dist, surfplane.normal, pointOnPlane);
}
#if 1
int j;
vec_t *v1, *v2, *v3;
@ -559,11 +578,14 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, const v
for (best = 0,j = 2; j < face->numedges; j++)
{
v3 = GetSurfaceVertexPoint(bsp, face, j);
if (ClipPointToTriangle(point, clipped, surfnorm, v1, v2, v3))
vec_t triarea = TriangleArea(v1, v2, v3);
if (ClipPointToTriangle(pointOnPlane, clipped, surfplane.normal, v1, v2, v3))
{
VectorSubtract(clipped, point, t);
VectorSubtract(clipped, pointOnPlane, t);
cost = VectorLength(t);
if (cost < bestcost)
if (cost < bestcost && triarea >= 1)
{
best = j;
bestcost = cost;
@ -583,7 +605,13 @@ static void CalcPointNormal(const bsp2_t *bsp, const bsp2_dface_t *face, const v
v1 = GetSurfaceVertexPoint(bsp, face, 0);
v2 = GetSurfaceVertexPoint(bsp, face, best-1);
v3 = GetSurfaceVertexPoint(bsp, face, best);
CalcBarycentric(point, v1, v2, v3, barry);
if (TriangleArea(v1, v2, v3) < 1) {
VectorCopy(surfplane.normal, norm);
return;
}
CalcBarycentric(pointOnPlane, v1, v2, v3, barry);
v1 = GetSurfaceVertexNormal(bsp, face, 0);
v2 = GetSurfaceVertexNormal(bsp, face, best-1);
@ -695,7 +723,7 @@ CalcPoints(const dmodel_t *model, const vec3_t offset, const texorg_t *texorg, l
if (surf->curved)
{
CalcPointNormal(bsp, face, surf->plane.normal, norm, point);
CalcPointNormal(bsp, face, surf->plane, norm, point);
}
else
{