mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 08:59:32 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
298
tools/quake2/q2map/trace.c
Normal file
298
tools/quake2/q2map/trace.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
// trace.c
|
||||
/*
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
*/
|
||||
|
||||
#include "qrad.h"
|
||||
|
||||
#define ON_EPSILON 0.1
|
||||
|
||||
typedef struct tnode_s
|
||||
{
|
||||
int type;
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
int children[2];
|
||||
int pad;
|
||||
} tnode_t;
|
||||
|
||||
tnode_t *tnodes, *tnode_p;
|
||||
|
||||
/*
|
||||
==============
|
||||
MakeTnode
|
||||
|
||||
Converts the disk node structure into the efficient tracing structure
|
||||
==============
|
||||
*/
|
||||
void MakeTnode (int nodenum)
|
||||
{
|
||||
tnode_t *t;
|
||||
dplane_t *plane;
|
||||
int i;
|
||||
dnode_t *node;
|
||||
|
||||
t = tnode_p++;
|
||||
|
||||
node = dnodes + nodenum;
|
||||
plane = dplanes + node->planenum;
|
||||
|
||||
t->type = plane->type;
|
||||
VectorCopy (plane->normal, t->normal);
|
||||
t->dist = plane->dist;
|
||||
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (node->children[i] < 0)
|
||||
t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
|
||||
else
|
||||
{
|
||||
t->children[i] = tnode_p - tnodes;
|
||||
MakeTnode (node->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
MakeTnodes
|
||||
|
||||
Loads the node structure out of a .bsp file to be used for light occlusion
|
||||
=============
|
||||
*/
|
||||
void MakeTnodes (dmodel_t *bm)
|
||||
{
|
||||
// 32 byte align the structs
|
||||
tnodes = malloc( (numnodes+1) * sizeof(tnode_t));
|
||||
tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
|
||||
tnode_p = tnodes;
|
||||
|
||||
MakeTnode (0);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
|
||||
int TestLine_r (int node, vec3_t start, vec3_t stop)
|
||||
{
|
||||
tnode_t *tnode;
|
||||
float front, back;
|
||||
vec3_t mid;
|
||||
float frac;
|
||||
int side;
|
||||
int r;
|
||||
|
||||
if (node & (1<<31))
|
||||
return node & ~(1<<31); // leaf node
|
||||
|
||||
tnode = &tnodes[node];
|
||||
switch (tnode->type)
|
||||
{
|
||||
case PLANE_X:
|
||||
front = start[0] - tnode->dist;
|
||||
back = stop[0] - tnode->dist;
|
||||
break;
|
||||
case PLANE_Y:
|
||||
front = start[1] - tnode->dist;
|
||||
back = stop[1] - tnode->dist;
|
||||
break;
|
||||
case PLANE_Z:
|
||||
front = start[2] - tnode->dist;
|
||||
back = stop[2] - tnode->dist;
|
||||
break;
|
||||
default:
|
||||
front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
|
||||
back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
|
||||
break;
|
||||
}
|
||||
|
||||
if (front >= -ON_EPSILON && back >= -ON_EPSILON)
|
||||
return TestLine_r (tnode->children[0], start, stop);
|
||||
|
||||
if (front < ON_EPSILON && back < ON_EPSILON)
|
||||
return TestLine_r (tnode->children[1], start, stop);
|
||||
|
||||
side = front < 0;
|
||||
|
||||
frac = front / (front-back);
|
||||
|
||||
mid[0] = start[0] + (stop[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (stop[1] - start[1])*frac;
|
||||
mid[2] = start[2] + (stop[2] - start[2])*frac;
|
||||
|
||||
r = TestLine_r (tnode->children[side], start, mid);
|
||||
if (r)
|
||||
return r;
|
||||
return TestLine_r (tnode->children[!side], mid, stop);
|
||||
}
|
||||
|
||||
int TestLine (vec3_t start, vec3_t stop)
|
||||
{
|
||||
return TestLine_r (0, start, stop);
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
LINE TRACING
|
||||
|
||||
The major lighting operation is a point to point visibility test, performed
|
||||
by recursive subdivision of the line by the BSP tree.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t backpt;
|
||||
int side;
|
||||
int node;
|
||||
} tracestack_t;
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
TestLine
|
||||
==============
|
||||
*/
|
||||
qboolean _TestLine (vec3_t start, vec3_t stop)
|
||||
{
|
||||
int node;
|
||||
float front, back;
|
||||
tracestack_t *tstack_p;
|
||||
int side;
|
||||
float frontx,fronty, frontz, backx, backy, backz;
|
||||
tracestack_t tracestack[64];
|
||||
tnode_t *tnode;
|
||||
|
||||
frontx = start[0];
|
||||
fronty = start[1];
|
||||
frontz = start[2];
|
||||
backx = stop[0];
|
||||
backy = stop[1];
|
||||
backz = stop[2];
|
||||
|
||||
tstack_p = tracestack;
|
||||
node = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (node == CONTENTS_SOLID)
|
||||
{
|
||||
#if 0
|
||||
float d1, d2, d3;
|
||||
|
||||
d1 = backx - frontx;
|
||||
d2 = backy - fronty;
|
||||
d3 = backz - frontz;
|
||||
|
||||
if (d1*d1 + d2*d2 + d3*d3 > 1)
|
||||
#endif
|
||||
return false; // DONE!
|
||||
}
|
||||
|
||||
while (node < 0)
|
||||
{
|
||||
// pop up the stack for a back side
|
||||
tstack_p--;
|
||||
if (tstack_p < tracestack)
|
||||
return true;
|
||||
node = tstack_p->node;
|
||||
|
||||
// set the hit point for this plane
|
||||
|
||||
frontx = backx;
|
||||
fronty = backy;
|
||||
frontz = backz;
|
||||
|
||||
// go down the back side
|
||||
|
||||
backx = tstack_p->backpt[0];
|
||||
backy = tstack_p->backpt[1];
|
||||
backz = tstack_p->backpt[2];
|
||||
|
||||
node = tnodes[tstack_p->node].children[!tstack_p->side];
|
||||
}
|
||||
|
||||
tnode = &tnodes[node];
|
||||
|
||||
switch (tnode->type)
|
||||
{
|
||||
case PLANE_X:
|
||||
front = frontx - tnode->dist;
|
||||
back = backx - tnode->dist;
|
||||
break;
|
||||
case PLANE_Y:
|
||||
front = fronty - tnode->dist;
|
||||
back = backy - tnode->dist;
|
||||
break;
|
||||
case PLANE_Z:
|
||||
front = frontz - tnode->dist;
|
||||
back = backz - tnode->dist;
|
||||
break;
|
||||
default:
|
||||
front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
|
||||
back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
|
||||
break;
|
||||
}
|
||||
|
||||
if (front > -ON_EPSILON && back > -ON_EPSILON)
|
||||
// if (front > 0 && back > 0)
|
||||
{
|
||||
node = tnode->children[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (front < ON_EPSILON && back < ON_EPSILON)
|
||||
// if (front <= 0 && back <= 0)
|
||||
{
|
||||
node = tnode->children[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
side = front < 0;
|
||||
|
||||
front = front / (front-back);
|
||||
|
||||
tstack_p->node = node;
|
||||
tstack_p->side = side;
|
||||
tstack_p->backpt[0] = backx;
|
||||
tstack_p->backpt[1] = backy;
|
||||
tstack_p->backpt[2] = backz;
|
||||
|
||||
tstack_p++;
|
||||
|
||||
backx = frontx + front*(backx-frontx);
|
||||
backy = fronty + front*(backy-fronty);
|
||||
backz = frontz + front*(backz-frontz);
|
||||
|
||||
node = tnode->children[side];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user