2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
5 This file is part of Quake 2 Tools source code.
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
27 #define ON_EPSILON 0.1
29 typedef struct tnode_s
38 tnode_t *tnodes, *tnode_p;
44 Converts the disk node structure into the efficient tracing structure
47 void MakeTnode (int nodenum)
56 node = dnodes + nodenum;
57 plane = dplanes + node->planenum;
59 t->type = plane->type;
60 VectorCopy (plane->normal, t->normal);
61 t->dist = plane->dist;
65 if (node->children[i] < 0)
66 t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
69 t->children[i] = tnode_p - tnodes;
70 MakeTnode (node->children[i]);
81 Loads the node structure out of a .bsp file to be used for light occlusion
84 void MakeTnodes (dmodel_t *bm)
86 // 32 byte align the structs
87 tnodes = malloc( (numnodes+1) * sizeof(tnode_t));
88 tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
95 //==========================================================
98 int TestLine_r (int node, vec3_t start, vec3_t stop)
108 return node & ~(1<<31); // leaf node
110 tnode = &tnodes[node];
114 front = start[0] - tnode->dist;
115 back = stop[0] - tnode->dist;
118 front = start[1] - tnode->dist;
119 back = stop[1] - tnode->dist;
122 front = start[2] - tnode->dist;
123 back = stop[2] - tnode->dist;
126 front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
127 back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
131 if (front >= -ON_EPSILON && back >= -ON_EPSILON)
132 return TestLine_r (tnode->children[0], start, stop);
134 if (front < ON_EPSILON && back < ON_EPSILON)
135 return TestLine_r (tnode->children[1], start, stop);
139 frac = front / (front-back);
141 mid[0] = start[0] + (stop[0] - start[0])*frac;
142 mid[1] = start[1] + (stop[1] - start[1])*frac;
143 mid[2] = start[2] + (stop[2] - start[2])*frac;
145 r = TestLine_r (tnode->children[side], start, mid);
148 return TestLine_r (tnode->children[!side], mid, stop);
151 int TestLine (vec3_t start, vec3_t stop)
153 return TestLine_r (0, start, stop);
157 ==============================================================================
161 The major lighting operation is a point to point visibility test, performed
162 by recursive subdivision of the line by the BSP tree.
164 ==============================================================================
180 qboolean _TestLine (vec3_t start, vec3_t stop)
184 tracestack_t *tstack_p;
186 float frontx,fronty, frontz, backx, backy, backz;
187 tracestack_t tracestack[64];
197 tstack_p = tracestack;
202 if (node == CONTENTS_SOLID)
211 if (d1*d1 + d2*d2 + d3*d3 > 1)
213 return false; // DONE!
218 // pop up the stack for a back side
220 if (tstack_p < tracestack)
222 node = tstack_p->node;
224 // set the hit point for this plane
230 // go down the back side
232 backx = tstack_p->backpt[0];
233 backy = tstack_p->backpt[1];
234 backz = tstack_p->backpt[2];
236 node = tnodes[tstack_p->node].children[!tstack_p->side];
239 tnode = &tnodes[node];
244 front = frontx - tnode->dist;
245 back = backx - tnode->dist;
248 front = fronty - tnode->dist;
249 back = backy - tnode->dist;
252 front = frontz - tnode->dist;
253 back = backz - tnode->dist;
256 front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
257 back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
261 if (front > -ON_EPSILON && back > -ON_EPSILON)
262 // if (front > 0 && back > 0)
264 node = tnode->children[0];
268 if (front < ON_EPSILON && back < ON_EPSILON)
269 // if (front <= 0 && back <= 0)
271 node = tnode->children[1];
277 front = front / (front-back);
279 tstack_p->node = node;
280 tstack_p->side = side;
281 tstack_p->backpt[0] = backx;
282 tstack_p->backpt[1] = backy;
283 tstack_p->backpt[2] = backz;
287 backx = frontx + front*(backx-frontx);
288 backy = fronty + front*(backy-fronty);
289 backz = frontz + front*(backz-frontz);
291 node = tnode->children[side];