00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "light.h"
00023
00024
00025
00026 #define CURVE_FACET_ERROR 8
00027
00028 int c_totalTrace;
00029 int c_cullTrace, c_testTrace;
00030 int c_testFacets;
00031
00032 surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS];
00033
00034
00035
00036
00037
00038
00039 void CM_GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) {
00040 vec3_t d1;
00041
00042
00043 VectorSubtract( b, a, d1 );
00044 CrossProduct( plane, d1, boundary );
00045 VectorNormalize( boundary, boundary );
00046 boundary[3] = DotProduct( a, boundary );
00047 }
00048
00049
00050
00051
00052
00053
00054 void TextureMatrixFromPoints( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) {
00055 int i, j;
00056 float t;
00057 float m[3][4];
00058 float s;
00059
00060
00061 for ( i = 0 ; i < 2 ; i++ ) {
00062
00063 m[0][0] = a->xyz[0];
00064 m[0][1] = a->xyz[1];
00065 m[0][2] = a->xyz[2];
00066 m[0][3] = a->st[i];
00067
00068 m[1][0] = b->xyz[0];
00069 m[1][1] = b->xyz[1];
00070 m[1][2] = b->xyz[2];
00071 m[1][3] = b->st[i];
00072
00073 m[2][0] = c->xyz[0];
00074 m[2][1] = c->xyz[1];
00075 m[2][2] = c->xyz[2];
00076 m[2][3] = c->st[i];
00077
00078 if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) {
00079 for ( j = 0 ; j < 4 ; j ++ ) {
00080 t = m[0][j];
00081 m[0][j] = m[1][j];
00082 m[1][j] = t;
00083 }
00084 } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) {
00085 for ( j = 0 ; j < 4 ; j ++ ) {
00086 t = m[0][j];
00087 m[0][j] = m[2][j];
00088 m[2][j] = t;
00089 }
00090 }
00091
00092 s = 1.0 / m[0][0];
00093 m[0][0] *= s;
00094 m[0][1] *= s;
00095 m[0][2] *= s;
00096 m[0][3] *= s;
00097
00098 s = m[1][0];
00099 m[1][0] -= m[0][0] * s;
00100 m[1][1] -= m[0][1] * s;
00101 m[1][2] -= m[0][2] * s;
00102 m[1][3] -= m[0][3] * s;
00103
00104 s = m[2][0];
00105 m[2][0] -= m[0][0] * s;
00106 m[2][1] -= m[0][1] * s;
00107 m[2][2] -= m[0][2] * s;
00108 m[2][3] -= m[0][3] * s;
00109
00110 if ( fabs(m[2][1]) > fabs(m[1][1]) ) {
00111 for ( j = 0 ; j < 4 ; j ++ ) {
00112 t = m[1][j];
00113 m[1][j] = m[2][j];
00114 m[2][j] = t;
00115 }
00116 }
00117
00118 s = 1.0 / m[1][1];
00119 m[1][0] *= s;
00120 m[1][1] *= s;
00121 m[1][2] *= s;
00122 m[1][3] *= s;
00123
00124 s = m[2][1];
00125 m[2][0] -= m[1][0] * s;
00126 m[2][1] -= m[1][1] * s;
00127 m[2][2] -= m[1][2] * s;
00128 m[2][3] -= m[1][3] * s;
00129
00130 s = 1.0 / m[2][2];
00131 m[2][0] *= s;
00132 m[2][1] *= s;
00133 m[2][2] *= s;
00134 m[2][3] *= s;
00135
00136 f->textureMatrix[i][2] = m[2][3];
00137 f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2];
00138 f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1];
00139
00140 f->textureMatrix[i][3] = 0;
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163 qboolean CM_GenerateFacetFor3Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) {
00164
00165 if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) {
00166 f->numBoundaries = 0;
00167 return qfalse;
00168 }
00169
00170
00171 f->numBoundaries = 3;
00172
00173 CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz );
00174 CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz );
00175 CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, a->xyz );
00176
00177 VectorCopy( a->xyz, f->points[0] );
00178 VectorCopy( b->xyz, f->points[1] );
00179 VectorCopy( c->xyz, f->points[2] );
00180
00181 TextureMatrixFromPoints( f, a, b, c );
00182
00183 return qtrue;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 #define PLANAR_EPSILON 0.1
00194 qboolean CM_GenerateFacetFor4Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) {
00195 float dist;
00196 int i;
00197 vec4_t plane;
00198
00199
00200 if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) {
00201 f->numBoundaries = 0;
00202 return qfalse;
00203 }
00204
00205
00206 dist = DotProduct( d->xyz, f->surface ) - f->surface[3];
00207 if ( fabs( dist ) > PLANAR_EPSILON ) {
00208 f->numBoundaries = 0;
00209 return qfalse;
00210 }
00211
00212
00213 f->numBoundaries = 4;
00214
00215 CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz );
00216 CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz );
00217 CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, d->xyz );
00218 CM_GenerateBoundaryForPoints( f->boundaries[3], f->surface, d->xyz, a->xyz );
00219
00220 VectorCopy( a->xyz, f->points[0] );
00221 VectorCopy( b->xyz, f->points[1] );
00222 VectorCopy( c->xyz, f->points[2] );
00223 VectorCopy( d->xyz, f->points[3] );
00224
00225 for (i = 1; i < 4; i++)
00226 {
00227 if ( !PlaneFromPoints( plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) {
00228 f->numBoundaries = 0;
00229 return qfalse;
00230 }
00231
00232 if (DotProduct(f->surface, plane) < 0.9) {
00233 f->numBoundaries = 0;
00234 return qfalse;
00235 }
00236 }
00237
00238 TextureMatrixFromPoints( f, a, b, c );
00239
00240 return qtrue;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 void SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) {
00252 vec3_t temp;
00253
00254 VectorAdd( mins, maxs, origin );
00255 VectorScale( origin, 0.5, origin );
00256 VectorSubtract( maxs, origin, temp );
00257 *radius = VectorLength( temp );
00258 }
00259
00260
00261
00262
00263
00264
00265
00266 void FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) {
00267 int i;
00268 drawVert_t *v1, *v2, *v3, *v4;
00269 int count;
00270 int i1, i2, i3, i4, i5, i6;
00271
00272 test->patch = qfalse;
00273 test->numFacets = dsurf->numIndexes / 3;
00274 test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets );
00275 test->shader = si;
00276
00277 count = 0;
00278 for ( i = 0 ; i < test->numFacets ; i++ ) {
00279 i1 = drawIndexes[ dsurf->firstIndex + i*3 ];
00280 i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ];
00281 i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ];
00282
00283 v1 = &drawVerts[ dsurf->firstVert + i1 ];
00284 v2 = &drawVerts[ dsurf->firstVert + i2 ];
00285 v3 = &drawVerts[ dsurf->firstVert + i3 ];
00286
00287
00288 if ( i != test->numFacets - 1 ) {
00289 i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ];
00290 i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ];
00291 i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ];
00292 if ( i4 == i3 && i5 == i2 ) {
00293 v4 = &drawVerts[ dsurf->firstVert + i6 ];
00294 if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v2, v4, v3 ) ) {
00295 count++;
00296 i++;
00297 continue;
00298 }
00299 }
00300 }
00301
00302 if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v2, v3 ))
00303 count++;
00304 }
00305
00306
00307 test->numFacets = count;
00308 }
00309
00310
00311
00312
00313
00314
00315 void FacetsForPatch( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) {
00316 int i, j;
00317 drawVert_t *v1, *v2, *v3, *v4;
00318 int count;
00319 mesh_t srcMesh, *subdivided, *mesh;
00320
00321 srcMesh.width = dsurf->patchWidth;
00322 srcMesh.height = dsurf->patchHeight;
00323 srcMesh.verts = &drawVerts[ dsurf->firstVert ];
00324
00325
00326 mesh = SubdivideMesh( srcMesh, 8, 999 );
00327 PutMeshOnCurve( *mesh );
00328 MakeMeshNormals( *mesh );
00329
00330 subdivided = RemoveLinearMeshColumnsRows( mesh );
00331 FreeMesh(mesh);
00332
00333 test->patch = qtrue;
00334 test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2;
00335 test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets );
00336 test->shader = si;
00337
00338 count = 0;
00339 for ( i = 0 ; i < subdivided->width - 1 ; i++ ) {
00340 for ( j = 0 ; j < subdivided->height - 1 ; j++ ) {
00341
00342 v1 = subdivided->verts + j * subdivided->width + i;
00343 v2 = v1 + 1;
00344 v3 = v1 + subdivided->width + 1;
00345 v4 = v1 + subdivided->width;
00346
00347 if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v4, v3, v2 ) ) {
00348 count++;
00349 } else {
00350 if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v4, v3 ))
00351 count++;
00352 if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v3, v2 ))
00353 count++;
00354 }
00355 }
00356 }
00357 test->numFacets = count;
00358 FreeMesh(subdivided);
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 void InitSurfacesForTesting( void ) {
00370
00371 int i, j;
00372 dsurface_t *dsurf;
00373 surfaceTest_t *test;
00374 drawVert_t *dvert;
00375 shaderInfo_t *si;
00376
00377 for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
00378 dsurf = &drawSurfaces[ i ];
00379 if ( !dsurf->numIndexes && !dsurf->patchWidth ) {
00380 continue;
00381 }
00382
00383
00384
00385 si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader );
00386 if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) {
00387 continue;
00388 }
00389
00390 test = malloc( sizeof( *test ) );
00391 surfaceTest[i] = test;
00392 ClearBounds( test->mins, test->maxs );
00393
00394 dvert = &drawVerts[ dsurf->firstVert ];
00395 for ( j = 0 ; j < dsurf->numVerts ; j++, dvert++ ) {
00396 AddPointToBounds( dvert->xyz, test->mins, test->maxs );
00397 }
00398
00399 SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius );
00400
00401 if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) {
00402 FacetsForTriangleSurface( dsurf, si, test );
00403 } else if ( dsurf->surfaceType == MST_PATCH ) {
00404 FacetsForPatch( dsurf, si, test );
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 void GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) {
00416 vec3_t d1;
00417
00418
00419 VectorSubtract( b, a, d1 );
00420 CrossProduct( plane, d1, boundary );
00421 VectorNormalize( boundary, boundary );
00422 boundary[3] = DotProduct( a, boundary );
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 void SetFacetFilter( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet, vec3_t point ) {
00435 float s, t;
00436 int is, it;
00437 byte *image;
00438 int b;
00439
00440
00441 if ( !(shader->surfaceFlags & SURF_ALPHASHADOW) ) {
00442 VectorClear( tr->trace->filter );
00443 return;
00444 }
00445
00446 s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3];
00447 t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3];
00448
00449 if ( !shader->pixels ) {
00450
00451 VectorClear( point );
00452 return;
00453 }
00454
00455 s = s - floor( s );
00456 t = t - floor( t );
00457
00458 is = s * shader->width;
00459 it = t * shader->height;
00460
00461 image = shader->pixels + 4 * ( it * shader->width + is );
00462
00463
00464 b = image[3];
00465
00466
00467 b = b < 128 ? 0 : 255;
00468
00469 tr->trace->filter[0] = tr->trace->filter[0] * (255-b) / 255;
00470 tr->trace->filter[1] = tr->trace->filter[1] * (255-b) / 255;
00471 tr->trace->filter[2] = tr->trace->filter[2] * (255-b) / 255;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 void TraceAgainstFacet( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet ) {
00483 int j;
00484 float d1, d2, d, f;
00485 vec3_t point;
00486 float dist;
00487
00488
00489 if ( facet->numBoundaries < 3 ) {
00490 return;
00491 }
00492
00493 dist = facet->surface[3];
00494
00495
00496 d1 = DotProduct( tr->start, facet->surface ) - dist;
00497 if ( d1 > -1 && d1 < 1 ) {
00498 return;
00499 }
00500 d2 = DotProduct( tr->end, facet->surface ) - dist;
00501 if ( d2 > -1 && d2 < 1 ) {
00502 return;
00503 }
00504
00505
00506 f = ( d1 - ON_EPSILON ) / ( d1 - d2 );
00507 if ( f <= 0 ) {
00508 return;
00509 }
00510 if ( f >= tr->trace->hitFraction ) {
00511 return;
00512 }
00513
00514
00515 for ( j = 0 ; j < 3 ; j++ ) {
00516 point[j] = tr->start[j] + f * ( tr->end[j] - tr->start[j] );
00517 }
00518
00519
00520 for ( j = 0 ; j < facet->numBoundaries ; j++ ) {
00521
00522 dist = facet->boundaries[j][3];
00523
00524 d = DotProduct( point, facet->boundaries[j] );
00525 if ( d > dist + ON_EPSILON ) {
00526 break;
00527 }
00528 }
00529
00530 if ( j != facet->numBoundaries ) {
00531 return;
00532 }
00533
00534
00535
00536
00537 if ( shader->surfaceFlags & SURF_ALPHASHADOW ) {
00538 SetFacetFilter( tr, shader, facet, point );
00539 } else {
00540
00541 VectorClear( tr->trace->filter );
00542 tr->trace->hitFraction = f;
00543 }
00544
00545
00546
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 #define TRACE_ON_EPSILON 0.1
00560
00561 typedef struct tnode_s
00562 {
00563 int type;
00564 vec3_t normal;
00565 float dist;
00566 int children[2];
00567 int planeNum;
00568 } tnode_t;
00569
00570 #define MAX_TNODES (MAX_MAP_NODES*4)
00571 tnode_t *tnodes, *tnode_p;
00572
00573
00574
00575
00576
00577
00578
00579
00580 void MakeTnode (int nodenum)
00581 {
00582 tnode_t *t;
00583 dplane_t *plane;
00584 int i;
00585 dnode_t *node;
00586 int leafNum;
00587
00588 t = tnode_p++;
00589
00590 node = dnodes + nodenum;
00591 plane = dplanes + node->planeNum;
00592
00593 t->planeNum = node->planeNum;
00594 t->type = PlaneTypeForNormal( plane->normal );
00595 VectorCopy (plane->normal, t->normal);
00596 t->dist = plane->dist;
00597
00598 for (i=0 ; i<2 ; i++)
00599 {
00600 if (node->children[i] < 0) {
00601 leafNum = -node->children[i] - 1;
00602 if ( dleafs[leafNum].cluster == -1 ) {
00603
00604 t->children[i] = leafNum | ( 1 << 31 ) | ( 1 << 30 );
00605 } else {
00606 t->children[i] = leafNum | ( 1 << 31 );
00607 }
00608 } else {
00609 t->children[i] = tnode_p - tnodes;
00610 MakeTnode (node->children[i]);
00611 }
00612 }
00613
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623 void InitTrace( void ) {
00624
00625 tnodes = malloc( (MAX_TNODES+1) * sizeof(tnode_t));
00626 tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
00627 tnode_p = tnodes;
00628
00629 MakeTnode (0);
00630
00631 InitSurfacesForTesting();
00632 }
00633
00634
00635
00636
00637
00638
00639
00640 qboolean PointInSolid_r( vec3_t start, int node ) {
00641 tnode_t *tnode;
00642 float front;
00643
00644 while ( !(node & (1<<31) ) ) {
00645 tnode = &tnodes[node];
00646 switch (tnode->type) {
00647 case PLANE_X:
00648 front = start[0] - tnode->dist;
00649 break;
00650 case PLANE_Y:
00651 front = start[1] - tnode->dist;
00652 break;
00653 case PLANE_Z:
00654 front = start[2] - tnode->dist;
00655 break;
00656 default:
00657 front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
00658 break;
00659 }
00660
00661 if ( front == 0 ) {
00662
00663 return (qboolean) ( PointInSolid_r( start, tnode->children[0] )
00664 | PointInSolid_r( start, tnode->children[1] ) );
00665 }
00666
00667 if ( front > 0 ) {
00668 node = tnode->children[0];
00669 } else {
00670 node = tnode->children[1];
00671 }
00672 }
00673
00674 if ( node & ( 1 << 30 ) ) {
00675 return qtrue;
00676 }
00677 return qfalse;
00678 }
00679
00680
00681
00682
00683
00684
00685
00686 qboolean PointInSolid( vec3_t start ) {
00687 return PointInSolid_r( start, 0 );
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 int TraceLine_r( int node, const vec3_t start, const vec3_t stop, traceWork_t *tw ) {
00699 tnode_t *tnode;
00700 float front, back;
00701 vec3_t mid;
00702 float frac;
00703 int side;
00704 int r;
00705
00706 if (node & (1<<31)) {
00707 if (node & ( 1 << 30 ) ) {
00708 VectorCopy (start, tw->trace->hit);
00709 tw->trace->passSolid = qtrue;
00710 return qtrue;
00711 } else {
00712
00713 if ( tw->numOpenLeafs == MAX_MAP_LEAFS ) {
00714 return qfalse;
00715 }
00716 tw->openLeafNumbers[ tw->numOpenLeafs ] = node & ~(3 << 30);
00717 tw->numOpenLeafs++;
00718 return qfalse;
00719 }
00720 }
00721
00722 tnode = &tnodes[node];
00723 switch (tnode->type) {
00724 case PLANE_X:
00725 front = start[0] - tnode->dist;
00726 back = stop[0] - tnode->dist;
00727 break;
00728 case PLANE_Y:
00729 front = start[1] - tnode->dist;
00730 back = stop[1] - tnode->dist;
00731 break;
00732 case PLANE_Z:
00733 front = start[2] - tnode->dist;
00734 back = stop[2] - tnode->dist;
00735 break;
00736 default:
00737 front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
00738 back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
00739 break;
00740 }
00741
00742 if (front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON) {
00743 return TraceLine_r (tnode->children[0], start, stop, tw);
00744 }
00745
00746 if (front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON) {
00747 return TraceLine_r (tnode->children[1], start, stop, tw);
00748 }
00749
00750 side = front < 0;
00751
00752 frac = front / (front-back);
00753
00754 mid[0] = start[0] + (stop[0] - start[0])*frac;
00755 mid[1] = start[1] + (stop[1] - start[1])*frac;
00756 mid[2] = start[2] + (stop[2] - start[2])*frac;
00757
00758 r = TraceLine_r (tnode->children[side], start, mid, tw);
00759
00760 if (r) {
00761 return r;
00762 }
00763
00764
00765 return TraceLine_r (tnode->children[!side], mid, stop, tw);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 qboolean SphereCull( vec3_t start, vec3_t stop, vec3_t origin, float radius ) {
00777 vec3_t v;
00778 float d;
00779 vec3_t dir;
00780 float len;
00781 vec3_t on;
00782
00783 VectorSubtract( stop, start, dir );
00784 len = VectorNormalize( dir, dir );
00785
00786 VectorSubtract( origin, start, v );
00787 d = DotProduct( v, dir );
00788 if ( d > len + radius ) {
00789 return qtrue;
00790 }
00791 if ( d < -radius ) {
00792 return qtrue;
00793 }
00794 VectorMA( start, d, dir, on );
00795
00796 VectorSubtract( on, origin, v );
00797
00798 len = VectorLength( v );
00799
00800 if ( len > radius ) {
00801 return qtrue;
00802 }
00803
00804 return qfalse;
00805 }
00806
00807
00808
00809
00810
00811
00812 void TraceAgainstSurface( traceWork_t *tw, surfaceTest_t *surf ) {
00813 int i;
00814
00815
00816 if ( SphereCull( tw->start, tw->end, surf->origin, surf->radius ) ) {
00817 if ( numthreads == 1 ) {
00818 c_cullTrace++;
00819 }
00820 return;
00821 }
00822
00823 if ( numthreads == 1 ) {
00824 c_testTrace++;
00825 c_testFacets += surf->numFacets;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 for ( i = 0 ; i < surf->numFacets ; i++ ) {
00843 TraceAgainstFacet( tw, surf->shader, surf->facets + i );
00844 }
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 extern qboolean patchshadows;
00865
00866 void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, qboolean testAll, traceWork_t *tw ) {
00867 int r;
00868 int i, j;
00869 dleaf_t *leaf;
00870 float oldHitFrac;
00871 surfaceTest_t *test;
00872 int surfaceNum;
00873 byte surfaceTested[MAX_MAP_DRAW_SURFS/8];
00874 ;
00875
00876 if ( numthreads == 1 ) {
00877 c_totalTrace++;
00878 }
00879
00880
00881
00882 trace->filter[0] = 1.0;
00883 trace->filter[1] = 1.0;
00884 trace->filter[2] = 1.0;
00885
00886 VectorCopy( start, tw->start );
00887 VectorCopy( stop, tw->end );
00888 tw->trace = trace;
00889
00890 tw->numOpenLeafs = 0;
00891
00892 trace->passSolid = qfalse;
00893 trace->hitFraction = 1.0;
00894
00895 r = TraceLine_r( 0, start, stop, tw );
00896
00897
00898
00899
00900 if ( r && !testAll ) {
00901 return;
00902 }
00903
00904 if ( noSurfaces ) {
00905 return;
00906 }
00907
00908 memset( surfaceTested, 0, (numDrawSurfaces+7)/8 );
00909 oldHitFrac = trace->hitFraction;
00910
00911 for ( i = 0 ; i < tw->numOpenLeafs ; i++ ) {
00912 leaf = &dleafs[ tw->openLeafNumbers[ i ] ];
00913 for ( j = 0 ; j < leaf->numLeafSurfaces ; j++ ) {
00914 surfaceNum = dleafsurfaces[ leaf->firstLeafSurface + j ];
00915
00916
00917 if ( surfaceTested[ surfaceNum>>3 ] & ( 1 << ( surfaceNum & 7) ) ) {
00918 continue;
00919 }
00920 surfaceTested[ surfaceNum>>3 ] |= ( 1 << ( surfaceNum & 7 ) );
00921
00922 test = surfaceTest[ surfaceNum ];
00923 if ( !test ) {
00924 continue;
00925 }
00926
00927 if ( !tw->patchshadows && test->patch ) {
00928 continue;
00929 }
00930 TraceAgainstSurface( tw, test );
00931 }
00932
00933
00934 if ( trace->hitFraction < oldHitFrac ) {
00935 trace->passSolid = qtrue;
00936 break;
00937 }
00938 }
00939
00940 for ( i = 0 ; i < 3 ; i++ ) {
00941 trace->hit[i] = start[i] + ( stop[i] - start[i] ) * trace->hitFraction;
00942 }
00943 }
00944