2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
40 If we resort the vertexes so all silverts come first, we can save some work here.
43 localTrace_t R_LocalTrace( const idVec3 &start, const idVec3 &end, const float radius, const srfTriangles_t *tri ) {
48 int c_testEdges, c_testPlanes, c_intersect;
60 // create two planes orthogonal to each other that intersect along the trace
61 startDir = end - start;
63 startDir.NormalVectors( planes[0].Normal(), planes[1].Normal() );
64 planes[0][3] = - start * planes[0].Normal();
65 planes[1][3] = - start * planes[1].Normal();
67 // create front and end planes so the trace is on the positive sides of both
69 planes[2][3] = - start * planes[2].Normal();
70 planes[3] = -startDir;
71 planes[3][3] = - end * planes[3].Normal();
73 // catagorize each point against the four planes
74 cullBits = (byte *) _alloca16( tri->numVerts );
75 SIMDProcessor->TracePointCull( cullBits, totalOr, radius, planes, tri->verts, tri->numVerts );
77 // if we don't have points on both sides of both the ray planes, no intersection
78 if ( ( totalOr ^ ( totalOr >> 4 ) ) & 3 ) {
79 //common->Printf( "nothing crossed the trace planes\n" );
83 // if we don't have any points between front and end, no intersection
84 if ( ( totalOr ^ ( totalOr >> 1 ) ) & 4 ) {
85 //common->Printf( "trace didn't reach any triangles\n" );
89 // scan for triangles that cross both planes
94 radiusSqr = Square( radius );
95 startDir = end - start;
97 if ( !tri->facePlanes || !tri->facePlanesCalculated ) {
98 R_DeriveFacePlanes( const_cast<srfTriangles_t *>( tri ) );
101 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
111 // get sidedness info for the triangle
112 triOr = cullBits[ tri->indexes[i+0] ];
113 triOr |= cullBits[ tri->indexes[i+1] ];
114 triOr |= cullBits[ tri->indexes[i+2] ];
116 // if we don't have points on both sides of both the ray planes, no intersection
117 if ( ( triOr ^ ( triOr >> 4 ) ) & 3 ) {
121 // if we don't have any points between front and end, no intersection
122 if ( ( triOr ^ ( triOr >> 1 ) ) & 4 ) {
128 plane = &tri->facePlanes[j];
129 d1 = plane->Distance( start );
130 d2 = plane->Distance( end );
133 continue; // comning at it from behind or parallel
137 continue; // starts past it
141 continue; // finishes in front of it
144 f = d1 / ( d1 - d2 );
147 continue; // shouldn't happen
150 if ( f >= hit.fraction ) {
151 continue; // have already hit something closer
156 // find the exact point of impact with the plane
157 point = start + f * startDir;
159 // see if the point is within the three edges
160 // if radius > 0 the triangle is expanded with a circle in the triangle plane
162 dir[0] = tri->verts[ tri->indexes[i+0] ].xyz - point;
163 dir[1] = tri->verts[ tri->indexes[i+1] ].xyz - point;
165 cross = dir[0].Cross( dir[1] );
166 d = plane->Normal() * cross;
168 if ( radiusSqr <= 0.0f ) {
171 edge = tri->verts[ tri->indexes[i+0] ].xyz - tri->verts[ tri->indexes[i+1] ].xyz;
172 edgeLengthSqr = edge.LengthSqr();
173 if ( cross.LengthSqr() > edgeLengthSqr * radiusSqr ) {
178 edge = tri->verts[ tri->indexes[i+0] ].xyz - tri->verts[ tri->indexes[i+2] ].xyz;
181 if ( dir[0].LengthSqr() > radiusSqr ) {
185 } else if ( d > edgeLengthSqr ) {
186 edge = tri->verts[ tri->indexes[i+1] ].xyz - tri->verts[ tri->indexes[i+2] ].xyz;
189 if ( dir[1].LengthSqr() > radiusSqr ) {
196 dir[2] = tri->verts[ tri->indexes[i+2] ].xyz - point;
198 cross = dir[1].Cross( dir[2] );
199 d = plane->Normal() * cross;
201 if ( radiusSqr <= 0.0f ) {
204 edge = tri->verts[ tri->indexes[i+1] ].xyz - tri->verts[ tri->indexes[i+2] ].xyz;
205 edgeLengthSqr = edge.LengthSqr();
206 if ( cross.LengthSqr() > edgeLengthSqr * radiusSqr ) {
211 edge = tri->verts[ tri->indexes[i+1] ].xyz - tri->verts[ tri->indexes[i+0] ].xyz;
214 if ( dir[1].LengthSqr() > radiusSqr ) {
218 } else if ( d > edgeLengthSqr ) {
219 edge = tri->verts[ tri->indexes[i+2] ].xyz - tri->verts[ tri->indexes[i+0] ].xyz;
222 if ( dir[2].LengthSqr() > radiusSqr ) {
229 cross = dir[2].Cross( dir[0] );
230 d = plane->Normal() * cross;
232 if ( radiusSqr <= 0.0f ) {
235 edge = tri->verts[ tri->indexes[i+2] ].xyz - tri->verts[ tri->indexes[i+0] ].xyz;
236 edgeLengthSqr = edge.LengthSqr();
237 if ( cross.LengthSqr() > edgeLengthSqr * radiusSqr ) {
242 edge = tri->verts[ tri->indexes[i+2] ].xyz - tri->verts[ tri->indexes[i+1] ].xyz;
245 if ( dir[2].LengthSqr() > radiusSqr ) {
249 } else if ( d > edgeLengthSqr ) {
250 edge = tri->verts[ tri->indexes[i+0] ].xyz - tri->verts[ tri->indexes[i+1] ].xyz;
253 if ( dir[0].LengthSqr() > radiusSqr ) {
264 hit.normal = plane->Normal();
266 hit.indexes[0] = tri->indexes[i];
267 hit.indexes[1] = tri->indexes[i+1];
268 hit.indexes[2] = tri->indexes[i+2];
274 common->Printf( "testVerts:%i c_testPlanes:%i c_testEdges:%i c_intersect:%i msec:%1.4f\n",
275 tri->numVerts, c_testPlanes, c_testEdges, c_intersect, trace_timer.Milliseconds() );
283 RB_DrawExpandedTriangles
286 void RB_DrawExpandedTriangles( const srfTriangles_t *tri, const float radius, const idVec3 &vieworg ) {
288 idVec3 dir[6], normal, point;
290 for ( i = 0; i < tri->numIndexes; i += 3 ) {
292 idVec3 p[3] = { tri->verts[ tri->indexes[ i + 0 ] ].xyz, tri->verts[ tri->indexes[ i + 1 ] ].xyz, tri->verts[ tri->indexes[ i + 2 ] ].xyz };
294 dir[0] = p[0] - p[1];
295 dir[1] = p[1] - p[2];
296 dir[2] = p[2] - p[0];
298 normal = dir[0].Cross( dir[1] );
300 if ( normal * p[0] < normal * vieworg ) {
304 dir[0] = normal.Cross( dir[0] );
305 dir[1] = normal.Cross( dir[1] );
306 dir[2] = normal.Cross( dir[2] );
312 qglBegin( GL_LINE_LOOP );
314 for ( j = 0; j < 3; j++ ) {
317 dir[4] = ( dir[j] + dir[k] ) * 0.5f;
320 dir[3] = ( dir[j] + dir[4] ) * 0.5f;
323 dir[5] = ( dir[4] + dir[k] ) * 0.5f;
326 point = p[k] + dir[j] * radius;
327 qglVertex3f( point[0], point[1], point[2] );
329 point = p[k] + dir[3] * radius;
330 qglVertex3f( point[0], point[1], point[2] );
332 point = p[k] + dir[4] * radius;
333 qglVertex3f( point[0], point[1], point[2] );
335 point = p[k] + dir[5] * radius;
336 qglVertex3f( point[0], point[1], point[2] );
338 point = p[k] + dir[k] * radius;
339 qglVertex3f( point[0], point[1], point[2] );
353 void RB_ShowTrace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
355 const srfTriangles_t *tri;
356 const drawSurf_t *surf;
358 idVec3 localStart, localEnd;
362 if ( r_showTrace.GetInteger() == 0 ) {
366 if ( r_showTrace.GetInteger() == 2 ) {
372 // determine the points of the trace
373 start = backEnd.viewDef->renderView.vieworg;
374 end = start + 4000 * backEnd.viewDef->renderView.viewaxis[0];
376 // check and draw the surfaces
377 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
378 GL_TexEnv( GL_MODULATE );
380 globalImages->whiteImage->Bind();
382 // find how many are ambient
383 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
387 if ( tri == NULL || tri->verts == NULL ) {
391 // transform the points into local space
392 R_GlobalPointToLocal( surf->space->modelMatrix, start, localStart );
393 R_GlobalPointToLocal( surf->space->modelMatrix, end, localEnd );
395 // check the bounding box
396 if ( !tri->bounds.Expand( radius ).LineIntersection( localStart, localEnd ) ) {
400 qglLoadMatrixf( surf->space->modelViewMatrix );
402 // highlight the surface
403 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
405 qglColor4f( 1, 0, 0, 0.25 );
406 RB_DrawElementsImmediate( tri );
408 // draw the bounding box
409 GL_State( GLS_DEPTHFUNC_ALWAYS );
411 qglColor4f( 1, 1, 1, 1 );
412 RB_DrawBounds( tri->bounds );
414 if ( radius != 0.0f ) {
415 // draw the expanded triangles
416 qglColor4f( 0.5f, 0.5f, 1.0f, 1.0f );
417 RB_DrawExpandedTriangles( tri, radius, localStart );
420 // check the exact surfaces
421 hit = R_LocalTrace( localStart, localEnd, radius, tri );
422 if ( hit.fraction < 1.0 ) {
423 qglColor4f( 1, 1, 1, 1 );
424 RB_DrawBounds( idBounds( hit.point ).Expand( 1 ) );