light: fence texture tracing
This commit is contained in:
parent
a33c4b0136
commit
54e7c2ab8e
|
|
@ -144,4 +144,9 @@ extern qboolean write_litfile;
|
|||
|
||||
void SetupDirt();
|
||||
|
||||
/* Used by fence texture sampling */
|
||||
void WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2]);
|
||||
|
||||
extern qboolean testFenceTextures;
|
||||
|
||||
#endif /* __LIGHT_LIGHT_H__ */
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ qboolean dirtDepthSetOnCmdline = false;
|
|||
qboolean dirtScaleSetOnCmdline = false;
|
||||
qboolean dirtGainSetOnCmdline = false;
|
||||
|
||||
qboolean testFenceTextures = false;
|
||||
|
||||
byte *filebase; // start of lightmap data
|
||||
static byte *file_p; // start of free space after data
|
||||
static byte *file_end; // end of free space for lightmap data
|
||||
|
|
@ -224,6 +226,22 @@ LightWorld(bsp2_t *bsp)
|
|||
logprint("lightdatasize: %i\n", bsp->lightdatasize);
|
||||
}
|
||||
|
||||
static void
|
||||
CheckFenceTextures(bsp2_t *bsp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < bsp->numfaces; i++) {
|
||||
const bsp2_dface_t *face = &bsp->dfaces[i];
|
||||
const texinfo_t *tex = &bsp->texinfo[face->texinfo];
|
||||
const int offset = bsp->dtexdata.header->dataofs[tex->miptex];
|
||||
const miptex_t *miptex = (const miptex_t *)(bsp->dtexdata.base + offset);
|
||||
if (miptex->name[0] == '{') {
|
||||
logprint("Fence texture detected, enabling fence texture tracing on bmodels\n");
|
||||
testFenceTextures = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ==================
|
||||
|
|
@ -370,6 +388,8 @@ main(int argc, const char **argv)
|
|||
if (dirty)
|
||||
SetupDirt();
|
||||
|
||||
CheckFenceTextures(bsp);
|
||||
|
||||
MakeTnodes(bsp);
|
||||
modelinfo = malloc(bsp->nummodels * sizeof(*modelinfo));
|
||||
FindModelInfo(bsp);
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ TexCoordToWorld(vec_t s, vec_t t, const texorg_t *texorg, vec3_t world)
|
|||
Solve3(&texorg->transform, rhs, world);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2])
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
206
light/trace.c
206
light/trace.c
|
|
@ -25,10 +25,13 @@ typedef struct tnode_s {
|
|||
int type;
|
||||
int children[2];
|
||||
const dplane_t *plane;
|
||||
const bsp2_dleaf_t *childleafs[2];
|
||||
const bsp2_dnode_t *node;
|
||||
} tnode_t;
|
||||
|
||||
static tnode_t *tnodes;
|
||||
static tnode_t *tnode_p;
|
||||
static const bsp2_t *bsp_static;
|
||||
|
||||
/*
|
||||
* ==============
|
||||
|
|
@ -42,11 +45,13 @@ MakeTnodes_r(int nodenum, const bsp2_t *bsp)
|
|||
tnode_t *tnode;
|
||||
int i;
|
||||
bsp2_dnode_t *node;
|
||||
bsp2_dleaf_t *leaf;
|
||||
|
||||
tnode = tnode_p++;
|
||||
|
||||
node = bsp->dnodes + nodenum;
|
||||
tnode->plane = bsp->dplanes + node->planenum;
|
||||
tnode->node = node;
|
||||
|
||||
tnode->type = tnode->plane->type;
|
||||
VectorCopy(tnode->plane->normal, tnode->normal);
|
||||
|
|
@ -54,7 +59,9 @@ MakeTnodes_r(int nodenum, const bsp2_t *bsp)
|
|||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (node->children[i] < 0) {
|
||||
tnode->children[i] = bsp->dleafs[-node->children[i] - 1].contents;
|
||||
leaf = &bsp->dleafs[-node->children[i] - 1];
|
||||
tnode->children[i] = leaf->contents;
|
||||
tnode->childleafs[i] = leaf;
|
||||
} else {
|
||||
tnode->children[i] = tnode_p - tnodes;
|
||||
MakeTnodes_r(node->children[i], bsp);
|
||||
|
|
@ -66,12 +73,165 @@ void
|
|||
MakeTnodes(const bsp2_t *bsp)
|
||||
{
|
||||
int i;
|
||||
|
||||
bsp_static = bsp;
|
||||
tnode_p = tnodes = malloc(bsp->numnodes * sizeof(tnode_t));
|
||||
for (i = 0; i < bsp->nummodels; i++)
|
||||
MakeTnodes_r(bsp->dmodels[i].headnode[0], bsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* FENCE TEXTURE TESTING
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
static qboolean
|
||||
PointInTri(const vec3_t v0,
|
||||
const vec3_t v1,
|
||||
const vec3_t v2,
|
||||
const vec3_t point,
|
||||
const vec3_t facenormal)
|
||||
{
|
||||
vec3_t temp;
|
||||
vec3_t normal[3];
|
||||
vec_t dist[3];
|
||||
|
||||
VectorSubtract (v1, v0, temp);
|
||||
VectorNormalize (temp);
|
||||
CrossProduct (temp, facenormal, normal[0]);
|
||||
dist[0] = DotProduct (v0, normal[0]);
|
||||
|
||||
VectorSubtract (v2, v1, temp);
|
||||
VectorNormalize (temp);
|
||||
CrossProduct (temp, facenormal, normal[1]);
|
||||
dist[1] = DotProduct (v1, normal[1]);
|
||||
|
||||
VectorSubtract (v0, v2, temp);
|
||||
VectorNormalize (temp);
|
||||
CrossProduct (temp, facenormal, normal[2]);
|
||||
dist[2] = DotProduct (v2, normal[2]);
|
||||
|
||||
// check each plane
|
||||
|
||||
if (DotProduct (normal[0], point) - dist[0] < 0) return false;
|
||||
if (DotProduct (normal[1], point) - dist[1] < 0) return false;
|
||||
if (DotProduct (normal[2], point) - dist[2] < 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean
|
||||
PointInFace(const bsp2_dface_t *face, const bsp2_t *bsp, const vec3_t point)
|
||||
{
|
||||
int i, edgenum;
|
||||
dvertex_t *v0, *v1, *v2;
|
||||
|
||||
edgenum = bsp->dsurfedges[face->firstedge];
|
||||
if (edgenum >= 0)
|
||||
v0 = bsp->dvertexes + bsp->dedges[edgenum].v[0];
|
||||
else
|
||||
v0 = bsp->dvertexes + bsp->dedges[-edgenum].v[1];
|
||||
|
||||
for (i = 1; i < face->numedges - 1; i++) {
|
||||
edgenum = bsp->dsurfedges[face->firstedge + i];
|
||||
if (edgenum >= 0) {
|
||||
v1 = bsp->dvertexes + bsp->dedges[edgenum].v[0];
|
||||
v2 = bsp->dvertexes + bsp->dedges[edgenum].v[1];
|
||||
} else {
|
||||
v1 = bsp->dvertexes + bsp->dedges[-edgenum].v[1];
|
||||
v2 = bsp->dvertexes + bsp->dedges[-edgenum].v[0];
|
||||
}
|
||||
|
||||
vec3_t p0 = {v0->point[0], v0->point[1], v0->point[2]};
|
||||
vec3_t p1 = {v1->point[0], v1->point[1], v1->point[2]};
|
||||
vec3_t p2 = {v2->point[0], v2->point[1], v2->point[2]};
|
||||
|
||||
vec3_t facenormal;
|
||||
VectorCopy(bsp->dplanes[face->planenum].normal, facenormal);
|
||||
if (face->side) {
|
||||
VectorSubtract(vec3_origin, facenormal, facenormal);
|
||||
}
|
||||
|
||||
if (PointInTri(p0, p1, p2, point, facenormal)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static miptex_t *
|
||||
MiptexForFace(const bsp2_dface_t *face, const bsp2_t *bsp)
|
||||
{
|
||||
const texinfo_t *tex;
|
||||
dmiptexlump_t *miplump = bsp->dtexdata.header;
|
||||
miptex_t *miptex;
|
||||
tex = &bsp->texinfo[face->texinfo];
|
||||
|
||||
miptex = (miptex_t*)(bsp->dtexdata.base + miplump->dataofs[tex->miptex]);
|
||||
return miptex;
|
||||
}
|
||||
|
||||
static int
|
||||
SampleTexture(const bsp2_dface_t *face, const bsp2_t *bsp, const vec3_t point)
|
||||
{
|
||||
vec_t texcoord[2];
|
||||
const texinfo_t *tex;
|
||||
dmiptexlump_t *miplump = bsp->dtexdata.header;
|
||||
miptex_t *miptex;
|
||||
int x, y;
|
||||
byte *data;
|
||||
int sample;
|
||||
|
||||
tex = &bsp->texinfo[face->texinfo];
|
||||
|
||||
WorldToTexCoord(point, tex, texcoord);
|
||||
|
||||
if (miplump->dataofs[tex->miptex] == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
miptex = (miptex_t*)(bsp->dtexdata.base + miplump->dataofs[tex->miptex]);
|
||||
|
||||
x = (int)texcoord[0] % miptex->width;
|
||||
y = (int)texcoord[1] % miptex->height;
|
||||
|
||||
data = (byte*)miptex + miptex->offsets[0];
|
||||
sample = data[(miptex->width * y) + x];
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
static qboolean
|
||||
TestHitFace(bsp2_dface_t *face, const vec3_t point)
|
||||
{
|
||||
const dplane_t *plane;
|
||||
vec_t d;
|
||||
plane = &bsp_static->dplanes[face->planenum];
|
||||
d = DotProduct(point, plane->normal) - plane->dist;
|
||||
if (d >= -ON_EPSILON && d <= ON_EPSILON)
|
||||
{
|
||||
int val = PointInFace(face, bsp_static, point);
|
||||
if (val)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bsp2_dface_t *
|
||||
SearchNodeForHitFace(const bsp2_dnode_t *bspnode, const vec3_t point)
|
||||
{
|
||||
// search the faces on this node
|
||||
int i;
|
||||
for (i=0; i<bspnode->numfaces; i++)
|
||||
{
|
||||
bsp2_dface_t *face;
|
||||
face = &bsp_static->dfaces[bspnode->firstface + i];
|
||||
if (TestHitFace(face, point)) {
|
||||
return face;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* LINE TRACING
|
||||
|
|
@ -105,11 +265,14 @@ TraceLine(const dmodel_t *model, const int traceflags,
|
|||
tracestack_t *tstack, *crossnode;
|
||||
tnode_t *tnode;
|
||||
const tracestack_t *const tstack_max = tracestack + MAX_TSTACK;
|
||||
|
||||
qboolean isbmodel;
|
||||
|
||||
if (traceflags <= 0)
|
||||
Error("Internal error: %s - bad traceflags (%d)",
|
||||
__func__, traceflags);
|
||||
|
||||
isbmodel = (model != tracelist[0]);
|
||||
|
||||
VectorCopy(start, front);
|
||||
VectorCopy(stop, back);
|
||||
|
||||
|
|
@ -145,15 +308,40 @@ TraceLine(const dmodel_t *model, const int traceflags,
|
|||
break;
|
||||
}
|
||||
if (tracehit != TRACE_HIT_NONE) {
|
||||
qboolean done = true;
|
||||
|
||||
/* If we haven't crossed, start was inside flagged contents */
|
||||
if (!crossnode)
|
||||
return -tracehit;
|
||||
if (hitpoint) {
|
||||
hitpoint->dplane = crossnode->plane;
|
||||
hitpoint->side = crossnode->side;
|
||||
VectorCopy(crossnode->front, hitpoint->point);
|
||||
}
|
||||
return tracehit;
|
||||
|
||||
if (isbmodel && testFenceTextures) {
|
||||
const bsp2_dnode_t *bspnode = tnodes[crossnode->node].node;
|
||||
bsp2_dface_t *face = SearchNodeForHitFace(bspnode, crossnode->front);
|
||||
|
||||
if (face) {
|
||||
miptex_t *mt = MiptexForFace(face, bsp_static);
|
||||
if (mt && mt->name[0] == '{') {
|
||||
int sample = SampleTexture(face, bsp_static, crossnode->front);
|
||||
done = (sample != 255);
|
||||
} else {
|
||||
/* Non-fence texture was hit, we are done */
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
/* Continue tracing until we find the face we hit */
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (done) {
|
||||
if (hitpoint) {
|
||||
hitpoint->dplane = crossnode->plane;
|
||||
hitpoint->side = crossnode->side;
|
||||
VectorCopy(crossnode->front, hitpoint->point);
|
||||
}
|
||||
|
||||
return tracehit;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the stack is empty, no obstructions were hit */
|
||||
|
|
|
|||
Loading…
Reference in New Issue