light: fix dirtmapping traces
This commit is contained in:
parent
98a020fde7
commit
0b4c044473
|
|
@ -45,8 +45,15 @@ extern "C" {
|
|||
typedef struct traceinfo_s {
|
||||
vec3_t point;
|
||||
const bsp2_dface_t *face;
|
||||
/* returns true if sky was hit. */
|
||||
bool hitsky;
|
||||
bool hitback;
|
||||
|
||||
// internal
|
||||
vec3_t dir;
|
||||
} traceinfo_t;
|
||||
|
||||
/* Stopped by solid and sky */
|
||||
bool TraceFaces (traceinfo_t *ti, int node, const vec3_t start, const vec3_t end);
|
||||
|
||||
|
||||
|
|
@ -92,6 +99,7 @@ int TraceLine(const dmodel_t *model, const int traceflags,
|
|||
*/
|
||||
qboolean TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self);
|
||||
qboolean TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self);
|
||||
qboolean DirtTrace(const vec3_t start, const vec3_t stop, const dmodel_t *self, vec3_t hitpoint_out);
|
||||
|
||||
typedef struct {
|
||||
vec_t light;
|
||||
|
|
|
|||
|
|
@ -679,25 +679,18 @@ CalcPoints(const dmodel_t *model, const vec3_t offset, const texorg_t *texorg, l
|
|||
VectorCopy(surf->plane.normal, norm);
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
const int flags = TRACE_HIT_SOLID;
|
||||
tracepoint_t hit;
|
||||
int result;
|
||||
vec_t dist;
|
||||
|
||||
result = TraceLine(model, flags, midpoint, point, &hit);
|
||||
if (result == TRACE_HIT_NONE)
|
||||
break;
|
||||
if (result != TRACE_HIT_SOLID) {
|
||||
WarnBadMidpoint(midpoint);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move the point 1 unit above the obstructing surface */
|
||||
dist = DotProduct(point, hit.dplane->normal) - hit.dplane->dist;
|
||||
dist = hit.side ? -dist - 1 : -dist + 1;
|
||||
VectorScale(hit.dplane->normal, dist, move);
|
||||
VectorAdd(point, move, point);
|
||||
vec3_t tracedir;
|
||||
VectorSubtract(point, midpoint, tracedir);
|
||||
VectorNormalize(tracedir);
|
||||
|
||||
// trace 1 unit further than we need to go to ensure 1 unit clearance
|
||||
vec3_t dest;
|
||||
VectorMA(point, 1, tracedir, dest);
|
||||
|
||||
vec3_t hitpoint = {0};
|
||||
if (DirtTrace(midpoint, dest, model, hitpoint)) {
|
||||
// we hit a solid. pull back 1 unit from the hitpoint and hope that's in empty space.
|
||||
VectorMA(hitpoint, -1, tracedir, point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1484,22 +1477,20 @@ qboolean
|
|||
DirtTrace(const vec3_t start, const vec3_t stop, const dmodel_t *self, vec3_t hitpoint_out)
|
||||
{
|
||||
const dmodel_t *const *model;
|
||||
const int traceflags = TRACE_HIT_SOLID | TRACE_HIT_SKY;
|
||||
int result = TRACE_HIT_NONE;
|
||||
tracepoint_t hitpoint;
|
||||
|
||||
traceinfo_t ti = {0};
|
||||
|
||||
VectorSubtract(stop, start, ti.dir);
|
||||
VectorNormalize(ti.dir);
|
||||
|
||||
if (self) {
|
||||
result = TraceLine(self, traceflags, start, stop, &hitpoint);
|
||||
if (result == -TRACE_HIT_SOLID) {
|
||||
/* We started in the void, which ideally wouldn't happen,
|
||||
but does (say on e1m1). Return the start point as the hitpoint,
|
||||
which will make fully black dirt.
|
||||
*/
|
||||
VectorCopy(start, hitpoint_out);
|
||||
return true;
|
||||
} else if (result == TRACE_HIT_SOLID) {
|
||||
VectorCopy(hitpoint.point, hitpoint_out);
|
||||
return true;
|
||||
if (TraceFaces (&ti, self->headnode[0], start, stop)) {
|
||||
VectorCopy(ti.point, hitpoint_out);
|
||||
|
||||
if (ti.hitback) {
|
||||
VectorCopy(start, hitpoint_out);
|
||||
}
|
||||
|
||||
return !ti.hitsky;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1507,13 +1498,14 @@ DirtTrace(const vec3_t start, const vec3_t stop, const dmodel_t *self, vec3_t hi
|
|||
for (model = tracelist; *model; model++) {
|
||||
if (*model == self)
|
||||
continue;
|
||||
result = TraceLine(*model, traceflags, start, stop, &hitpoint);
|
||||
if (result == -TRACE_HIT_SOLID) {
|
||||
VectorCopy(start, hitpoint_out);
|
||||
return true;
|
||||
} else if (result == TRACE_HIT_SOLID) {
|
||||
VectorCopy(hitpoint.point, hitpoint_out);
|
||||
return true;
|
||||
if (TraceFaces (&ti, (*model)->headnode[0], start, stop)) {
|
||||
VectorCopy(ti.point, hitpoint_out);
|
||||
|
||||
if (ti.hitback) {
|
||||
VectorCopy(start, hitpoint_out);
|
||||
}
|
||||
|
||||
return !ti.hitsky;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ typedef struct faceinfo_s {
|
|||
vec3_t origin;
|
||||
vec_t radiusSquared;
|
||||
|
||||
int content;
|
||||
plane_t plane;
|
||||
} faceinfo_t;
|
||||
|
||||
static tnode_t *tnodes;
|
||||
|
|
@ -137,14 +139,43 @@ static inline bool SphereCullPoint(const faceinfo_t *info, const vec3_t point)
|
|||
return deltaLengthSquared > info->radiusSquared;
|
||||
}
|
||||
|
||||
static int
|
||||
Face_Contents(const bsp2_t *bsp, const bsp2_dface_t *face)
|
||||
{
|
||||
if (face->texinfo < 0)
|
||||
return CONTENTS_SOLID;
|
||||
|
||||
if (!(bsp->texinfo[face->texinfo].flags & TEX_SPECIAL))
|
||||
return CONTENTS_SOLID;
|
||||
|
||||
int texnum = bsp->texinfo[face->texinfo].miptex;
|
||||
const dmiptexlump_t *miplump = bsp->dtexdata.header;
|
||||
const miptex_t *miptex;
|
||||
|
||||
if (!miplump->dataofs[texnum])
|
||||
return CONTENTS_SOLID; //sometimes the texture just wasn't written. including its name.
|
||||
|
||||
miptex = (miptex_t*)(bsp->dtexdata.base + miplump->dataofs[texnum]);
|
||||
|
||||
if (!Q_strncasecmp(miptex->name, "sky", 3))
|
||||
return CONTENTS_SKY;
|
||||
else if (!Q_strncasecmp(miptex->name, "*lava", 5))
|
||||
return CONTENTS_LAVA;
|
||||
else if (!Q_strncasecmp(miptex->name, "*slime", 6))
|
||||
return CONTENTS_SLIME;
|
||||
else if (miptex->name[0] == '*')
|
||||
return CONTENTS_WATER;
|
||||
else
|
||||
return CONTENTS_SOLID;
|
||||
}
|
||||
|
||||
void
|
||||
MakeFaceInfo(const bsp2_t *bsp, const bsp2_dface_t *face, faceinfo_t *info)
|
||||
{
|
||||
info->numedges = face->numedges;
|
||||
info->edgeplanes = calloc(face->numedges, sizeof(plane_t));
|
||||
|
||||
plane_t surfplane;
|
||||
GetFaceNormal(bsp, face, &surfplane);
|
||||
GetFaceNormal(bsp, face, &info->plane);
|
||||
|
||||
// make edge planes
|
||||
for (int i=0; i<face->numedges; i++)
|
||||
|
|
@ -158,7 +189,7 @@ MakeFaceInfo(const bsp2_t *bsp, const bsp2_dface_t *face, faceinfo_t *info)
|
|||
VectorSubtract(v1, v0, edgevec);
|
||||
VectorNormalize(edgevec);
|
||||
|
||||
CrossProduct(edgevec, surfplane.normal, dest->normal);
|
||||
CrossProduct(edgevec, info->plane.normal, dest->normal);
|
||||
|
||||
dest->dist = DotProduct(dest->normal, v0);
|
||||
}
|
||||
|
|
@ -187,6 +218,8 @@ MakeFaceInfo(const bsp2_t *bsp, const bsp2_dface_t *face, faceinfo_t *info)
|
|||
}
|
||||
info->radiusSquared = maxRadiusSq;
|
||||
|
||||
info->content = Face_Contents(bsp, face);
|
||||
|
||||
#if 0
|
||||
//test
|
||||
for (int i=0; i<face->numedges; i++)
|
||||
|
|
@ -572,8 +605,19 @@ bool TraceFaces (traceinfo_t *ti, int node, const vec3_t start, const vec3_t end
|
|||
|
||||
bsp2_dface_t *face = SearchNodeForHitFace(tnode->node, mid);
|
||||
if (face) {
|
||||
ti->face = face;
|
||||
return true;
|
||||
int facenum = face - bsp_static->dfaces;
|
||||
const faceinfo_t *fi = &faceinfos[facenum];
|
||||
|
||||
// only solid and sky faces stop the trace.
|
||||
if (fi->content == CONTENTS_SOLID || fi->content == CONTENTS_SKY) {
|
||||
ti->face = face;
|
||||
ti->hitsky = (fi->content == CONTENTS_SKY);
|
||||
|
||||
// check if we hit the back side
|
||||
ti->hitback = (DotProduct(ti->dir, fi->plane.normal) >= 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//ericw -- no impact found on this node.
|
||||
|
|
|
|||
Loading…
Reference in New Issue