light: make CalcPointNormal more robust; don't use micro-triangles (<1 unit area) for interpolating normals
This commit is contained in:
parent
465cb2a555
commit
ae04899ce5
|
|
@ -524,7 +524,19 @@ static int ClipPointToTriangle(const vec_t *orig, vec_t *point, const vec_t *nor
|
||||||
return 1;
|
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;
|
vec3_t v0,v1,v2;
|
||||||
VectorSubtract(b, a, v0);
|
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];
|
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
|
#if 1
|
||||||
int j;
|
int j;
|
||||||
vec_t *v1, *v2, *v3;
|
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++)
|
for (best = 0,j = 2; j < face->numedges; j++)
|
||||||
{
|
{
|
||||||
v3 = GetSurfaceVertexPoint(bsp, face, 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);
|
cost = VectorLength(t);
|
||||||
if (cost < bestcost)
|
if (cost < bestcost && triarea >= 1)
|
||||||
{
|
{
|
||||||
best = j;
|
best = j;
|
||||||
bestcost = cost;
|
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);
|
v1 = GetSurfaceVertexPoint(bsp, face, 0);
|
||||||
v2 = GetSurfaceVertexPoint(bsp, face, best-1);
|
v2 = GetSurfaceVertexPoint(bsp, face, best-1);
|
||||||
v3 = GetSurfaceVertexPoint(bsp, face, best);
|
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);
|
v1 = GetSurfaceVertexNormal(bsp, face, 0);
|
||||||
v2 = GetSurfaceVertexNormal(bsp, face, best-1);
|
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)
|
if (surf->curved)
|
||||||
{
|
{
|
||||||
CalcPointNormal(bsp, face, surf->plane.normal, norm, point);
|
CalcPointNormal(bsp, face, surf->plane, norm, point);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue