00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "cm_local.h"
00024 #include "cm_patch.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 int c_totalPatchBlocks;
00084 int c_totalPatchSurfaces;
00085 int c_totalPatchEdges;
00086
00087 static const patchCollide_t *debugPatchCollide;
00088 static const facet_t *debugFacet;
00089 static qboolean debugBlock;
00090 static vec3_t debugBlockPoints[4];
00091
00092
00093
00094
00095
00096
00097 void CM_ClearLevelPatches( void ) {
00098 debugPatchCollide = NULL;
00099 debugFacet = NULL;
00100 }
00101
00102
00103
00104
00105
00106
00107 static int CM_SignbitsForNormal( vec3_t normal ) {
00108 int bits, j;
00109
00110 bits = 0;
00111 for (j=0 ; j<3 ; j++) {
00112 if ( normal[j] < 0 ) {
00113 bits |= 1<<j;
00114 }
00115 }
00116 return bits;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 static qboolean CM_PlaneFromPoints( vec4_t plane, vec3_t a, vec3_t b, vec3_t c ) {
00128 vec3_t d1, d2;
00129
00130 VectorSubtract( b, a, d1 );
00131 VectorSubtract( c, a, d2 );
00132 CrossProduct( d2, d1, plane );
00133 if ( VectorNormalize( plane ) == 0 ) {
00134 return qfalse;
00135 }
00136
00137 plane[3] = DotProduct( a, plane );
00138 return qtrue;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static qboolean CM_NeedsSubdivision( vec3_t a, vec3_t b, vec3_t c ) {
00159 vec3_t cmid;
00160 vec3_t lmid;
00161 vec3_t delta;
00162 float dist;
00163 int i;
00164
00165
00166 for ( i = 0 ; i < 3 ; i++ ) {
00167 lmid[i] = 0.5*(a[i] + c[i]);
00168 }
00169
00170
00171 for ( i = 0 ; i < 3 ; i++ ) {
00172 cmid[i] = 0.5 * ( 0.5*(a[i] + b[i]) + 0.5*(b[i] + c[i]) );
00173 }
00174
00175
00176 VectorSubtract( cmid, lmid, delta );
00177 dist = VectorLength( delta );
00178
00179 return dist >= SUBDIVIDE_DISTANCE;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 static void CM_Subdivide( vec3_t a, vec3_t b, vec3_t c, vec3_t out1, vec3_t out2, vec3_t out3 ) {
00191 int i;
00192
00193 for ( i = 0 ; i < 3 ; i++ ) {
00194 out1[i] = 0.5 * (a[i] + b[i]);
00195 out3[i] = 0.5 * (b[i] + c[i]);
00196 out2[i] = 0.5 * (out1[i] + out3[i]);
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207 static void CM_TransposeGrid( cGrid_t *grid ) {
00208 int i, j, l;
00209 vec3_t temp;
00210 qboolean tempWrap;
00211
00212 if ( grid->width > grid->height ) {
00213 for ( i = 0 ; i < grid->height ; i++ ) {
00214 for ( j = i + 1 ; j < grid->width ; j++ ) {
00215 if ( j < grid->height ) {
00216
00217 VectorCopy( grid->points[i][j], temp );
00218 VectorCopy( grid->points[j][i], grid->points[i][j] );
00219 VectorCopy( temp, grid->points[j][i] );
00220 } else {
00221
00222 VectorCopy( grid->points[j][i], grid->points[i][j] );
00223 }
00224 }
00225 }
00226 } else {
00227 for ( i = 0 ; i < grid->width ; i++ ) {
00228 for ( j = i + 1 ; j < grid->height ; j++ ) {
00229 if ( j < grid->width ) {
00230
00231 VectorCopy( grid->points[j][i], temp );
00232 VectorCopy( grid->points[i][j], grid->points[j][i] );
00233 VectorCopy( temp, grid->points[i][j] );
00234 } else {
00235
00236 VectorCopy( grid->points[i][j], grid->points[j][i] );
00237 }
00238 }
00239 }
00240 }
00241
00242 l = grid->width;
00243 grid->width = grid->height;
00244 grid->height = l;
00245
00246 tempWrap = grid->wrapWidth;
00247 grid->wrapWidth = grid->wrapHeight;
00248 grid->wrapHeight = tempWrap;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 static void CM_SetGridWrapWidth( cGrid_t *grid ) {
00259 int i, j;
00260 float d;
00261
00262 for ( i = 0 ; i < grid->height ; i++ ) {
00263 for ( j = 0 ; j < 3 ; j++ ) {
00264 d = grid->points[0][i][j] - grid->points[grid->width-1][i][j];
00265 if ( d < -WRAP_POINT_EPSILON || d > WRAP_POINT_EPSILON ) {
00266 break;
00267 }
00268 }
00269 if ( j != 3 ) {
00270 break;
00271 }
00272 }
00273 if ( i == grid->height ) {
00274 grid->wrapWidth = qtrue;
00275 } else {
00276 grid->wrapWidth = qfalse;
00277 }
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 static void CM_SubdivideGridColumns( cGrid_t *grid ) {
00290 int i, j, k;
00291
00292 for ( i = 0 ; i < grid->width - 2 ; ) {
00293
00294
00295
00296
00297
00298
00299
00300 for ( j = 0 ; j < grid->height ; j++ ) {
00301 if ( CM_NeedsSubdivision( grid->points[i][j], grid->points[i+1][j], grid->points[i+2][j] ) ) {
00302 break;
00303 }
00304 }
00305 if ( j == grid->height ) {
00306
00307
00308 for ( j = 0 ; j < grid->height ; j++ ) {
00309
00310 for ( k = i + 2 ; k < grid->width ; k++ ) {
00311 VectorCopy( grid->points[k][j], grid->points[k-1][j] );
00312 }
00313 }
00314
00315 grid->width--;
00316
00317
00318 i++;
00319 continue;
00320 }
00321
00322
00323
00324
00325 for ( j = 0 ; j < grid->height ; j++ ) {
00326 vec3_t prev, mid, next;
00327
00328
00329 VectorCopy( grid->points[i][j], prev );
00330 VectorCopy( grid->points[i+1][j], mid );
00331 VectorCopy( grid->points[i+2][j], next );
00332
00333
00334
00335
00336 for ( k = grid->width - 1 ; k > i + 1 ; k-- ) {
00337 VectorCopy( grid->points[k][j], grid->points[k+2][j] );
00338 }
00339
00340
00341 CM_Subdivide( prev, mid, next, grid->points[i+1][j], grid->points[i+2][j], grid->points[i+3][j] );
00342 }
00343
00344 grid->width += 2;
00345
00346
00347
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356 #define POINT_EPSILON 0.1
00357 static qboolean CM_ComparePoints( float *a, float *b ) {
00358 float d;
00359
00360 d = a[0] - b[0];
00361 if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
00362 return qfalse;
00363 }
00364 d = a[1] - b[1];
00365 if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
00366 return qfalse;
00367 }
00368 d = a[2] - b[2];
00369 if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
00370 return qfalse;
00371 }
00372 return qtrue;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382 static void CM_RemoveDegenerateColumns( cGrid_t *grid ) {
00383 int i, j, k;
00384
00385 for ( i = 0 ; i < grid->width - 1 ; i++ ) {
00386 for ( j = 0 ; j < grid->height ; j++ ) {
00387 if ( !CM_ComparePoints( grid->points[i][j], grid->points[i+1][j] ) ) {
00388 break;
00389 }
00390 }
00391
00392 if ( j != grid->height ) {
00393 continue;
00394 }
00395
00396 for ( j = 0 ; j < grid->height ; j++ ) {
00397
00398 for ( k = i + 2 ; k < grid->width ; k++ ) {
00399 VectorCopy( grid->points[k][j], grid->points[k-1][j] );
00400 }
00401 }
00402 grid->width--;
00403
00404
00405 i--;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 static int numPlanes;
00418 static patchPlane_t planes[MAX_PATCH_PLANES];
00419
00420 static int numFacets;
00421 static facet_t facets[MAX_PATCH_PLANES];
00422
00423 #define NORMAL_EPSILON 0.0001
00424 #define DIST_EPSILON 0.02
00425
00426
00427
00428
00429
00430
00431 int CM_PlaneEqual(patchPlane_t *p, float plane[4], int *flipped) {
00432 float invplane[4];
00433
00434 if (
00435 fabs(p->plane[0] - plane[0]) < NORMAL_EPSILON
00436 && fabs(p->plane[1] - plane[1]) < NORMAL_EPSILON
00437 && fabs(p->plane[2] - plane[2]) < NORMAL_EPSILON
00438 && fabs(p->plane[3] - plane[3]) < DIST_EPSILON )
00439 {
00440 *flipped = qfalse;
00441 return qtrue;
00442 }
00443
00444 VectorNegate(plane, invplane);
00445 invplane[3] = -plane[3];
00446
00447 if (
00448 fabs(p->plane[0] - invplane[0]) < NORMAL_EPSILON
00449 && fabs(p->plane[1] - invplane[1]) < NORMAL_EPSILON
00450 && fabs(p->plane[2] - invplane[2]) < NORMAL_EPSILON
00451 && fabs(p->plane[3] - invplane[3]) < DIST_EPSILON )
00452 {
00453 *flipped = qtrue;
00454 return qtrue;
00455 }
00456
00457 return qfalse;
00458 }
00459
00460
00461
00462
00463
00464
00465 void CM_SnapVector(vec3_t normal) {
00466 int i;
00467
00468 for (i=0 ; i<3 ; i++)
00469 {
00470 if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
00471 {
00472 VectorClear (normal);
00473 normal[i] = 1;
00474 break;
00475 }
00476 if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
00477 {
00478 VectorClear (normal);
00479 normal[i] = -1;
00480 break;
00481 }
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 int CM_FindPlane2(float plane[4], int *flipped) {
00491 int i;
00492
00493
00494 for ( i = 0 ; i < numPlanes ; i++ ) {
00495 if (CM_PlaneEqual(&planes[i], plane, flipped)) return i;
00496 }
00497
00498
00499 if ( numPlanes == MAX_PATCH_PLANES ) {
00500 Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
00501 }
00502
00503 Vector4Copy( plane, planes[numPlanes].plane );
00504 planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
00505
00506 numPlanes++;
00507
00508 *flipped = qfalse;
00509
00510 return numPlanes-1;
00511 }
00512
00513
00514
00515
00516
00517
00518 static int CM_FindPlane( float *p1, float *p2, float *p3 ) {
00519 float plane[4];
00520 int i;
00521 float d;
00522
00523 if ( !CM_PlaneFromPoints( plane, p1, p2, p3 ) ) {
00524 return -1;
00525 }
00526
00527
00528 for ( i = 0 ; i < numPlanes ; i++ ) {
00529 if ( DotProduct( plane, planes[i].plane ) < 0 ) {
00530 continue;
00531 }
00532
00533 d = DotProduct( p1, planes[i].plane ) - planes[i].plane[3];
00534 if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
00535 continue;
00536 }
00537
00538 d = DotProduct( p2, planes[i].plane ) - planes[i].plane[3];
00539 if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
00540 continue;
00541 }
00542
00543 d = DotProduct( p3, planes[i].plane ) - planes[i].plane[3];
00544 if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
00545 continue;
00546 }
00547
00548
00549 return i;
00550 }
00551
00552
00553 if ( numPlanes == MAX_PATCH_PLANES ) {
00554 Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
00555 }
00556
00557 Vector4Copy( plane, planes[numPlanes].plane );
00558 planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
00559
00560 numPlanes++;
00561
00562 return numPlanes-1;
00563 }
00564
00565
00566
00567
00568
00569
00570 static int CM_PointOnPlaneSide( float *p, int planeNum ) {
00571 float *plane;
00572 float d;
00573
00574 if ( planeNum == -1 ) {
00575 return SIDE_ON;
00576 }
00577 plane = planes[ planeNum ].plane;
00578
00579 d = DotProduct( p, plane ) - plane[3];
00580
00581 if ( d > PLANE_TRI_EPSILON ) {
00582 return SIDE_FRONT;
00583 }
00584
00585 if ( d < -PLANE_TRI_EPSILON ) {
00586 return SIDE_BACK;
00587 }
00588
00589 return SIDE_ON;
00590 }
00591
00592
00593
00594
00595
00596
00597 static int CM_GridPlane( int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2], int i, int j, int tri ) {
00598 int p;
00599
00600 p = gridPlanes[i][j][tri];
00601 if ( p != -1 ) {
00602 return p;
00603 }
00604 p = gridPlanes[i][j][!tri];
00605 if ( p != -1 ) {
00606 return p;
00607 }
00608
00609
00610 Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
00611 return -1;
00612 }
00613
00614
00615
00616
00617
00618
00619 static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2], int i, int j, int k ) {
00620 float *p1, *p2;
00621 vec3_t up;
00622 int p;
00623
00624 switch ( k ) {
00625 case 0:
00626 p1 = grid->points[i][j];
00627 p2 = grid->points[i+1][j];
00628 p = CM_GridPlane( gridPlanes, i, j, 0 );
00629 VectorMA( p1, 4, planes[ p ].plane, up );
00630 return CM_FindPlane( p1, p2, up );
00631
00632 case 2:
00633 p1 = grid->points[i][j+1];
00634 p2 = grid->points[i+1][j+1];
00635 p = CM_GridPlane( gridPlanes, i, j, 1 );
00636 VectorMA( p1, 4, planes[ p ].plane, up );
00637 return CM_FindPlane( p2, p1, up );
00638
00639 case 3:
00640 p1 = grid->points[i][j];
00641 p2 = grid->points[i][j+1];
00642 p = CM_GridPlane( gridPlanes, i, j, 1 );
00643 VectorMA( p1, 4, planes[ p ].plane, up );
00644 return CM_FindPlane( p2, p1, up );
00645
00646 case 1:
00647 p1 = grid->points[i+1][j];
00648 p2 = grid->points[i+1][j+1];
00649 p = CM_GridPlane( gridPlanes, i, j, 0 );
00650 VectorMA( p1, 4, planes[ p ].plane, up );
00651 return CM_FindPlane( p1, p2, up );
00652
00653 case 4:
00654 p1 = grid->points[i+1][j+1];
00655 p2 = grid->points[i][j];
00656 p = CM_GridPlane( gridPlanes, i, j, 0 );
00657 VectorMA( p1, 4, planes[ p ].plane, up );
00658 return CM_FindPlane( p1, p2, up );
00659
00660 case 5:
00661 p1 = grid->points[i][j];
00662 p2 = grid->points[i+1][j+1];
00663 p = CM_GridPlane( gridPlanes, i, j, 1 );
00664 VectorMA( p1, 4, planes[ p ].plane, up );
00665 return CM_FindPlane( p1, p2, up );
00666
00667 }
00668
00669 Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
00670 return -1;
00671 }
00672
00673
00674
00675
00676
00677
00678 static void CM_SetBorderInward( facet_t *facet, cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2],
00679 int i, int j, int which ) {
00680 int k, l;
00681 float *points[4];
00682 int numPoints;
00683
00684 switch ( which ) {
00685 case -1:
00686 points[0] = grid->points[i][j];
00687 points[1] = grid->points[i+1][j];
00688 points[2] = grid->points[i+1][j+1];
00689 points[3] = grid->points[i][j+1];
00690 numPoints = 4;
00691 break;
00692 case 0:
00693 points[0] = grid->points[i][j];
00694 points[1] = grid->points[i+1][j];
00695 points[2] = grid->points[i+1][j+1];
00696 numPoints = 3;
00697 break;
00698 case 1:
00699 points[0] = grid->points[i+1][j+1];
00700 points[1] = grid->points[i][j+1];
00701 points[2] = grid->points[i][j];
00702 numPoints = 3;
00703 break;
00704 default:
00705 Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
00706 numPoints = 0;
00707 break;
00708 }
00709
00710 for ( k = 0 ; k < facet->numBorders ; k++ ) {
00711 int front, back;
00712
00713 front = 0;
00714 back = 0;
00715
00716 for ( l = 0 ; l < numPoints ; l++ ) {
00717 int side;
00718
00719 side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
00720 if ( side == SIDE_FRONT ) {
00721 front++;
00722 } if ( side == SIDE_BACK ) {
00723 back++;
00724 }
00725 }
00726
00727 if ( front && !back ) {
00728 facet->borderInward[k] = qtrue;
00729 } else if ( back && !front ) {
00730 facet->borderInward[k] = qfalse;
00731 } else if ( !front && !back ) {
00732
00733 facet->borderPlanes[k] = -1;
00734 } else {
00735
00736 Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
00737 facet->borderInward[k] = qfalse;
00738 if ( !debugBlock ) {
00739 debugBlock = qtrue;
00740 VectorCopy( grid->points[i][j], debugBlockPoints[0] );
00741 VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
00742 VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
00743 VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
00744 }
00745 }
00746 }
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756 static qboolean CM_ValidateFacet( facet_t *facet ) {
00757 float plane[4];
00758 int j;
00759 winding_t *w;
00760 vec3_t bounds[2];
00761
00762 if ( facet->surfacePlane == -1 ) {
00763 return qfalse;
00764 }
00765
00766 Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
00767 w = BaseWindingForPlane( plane, plane[3] );
00768 for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
00769 if ( facet->borderPlanes[j] == -1 ) {
00770 return qfalse;
00771 }
00772 Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
00773 if ( !facet->borderInward[j] ) {
00774 VectorSubtract( vec3_origin, plane, plane );
00775 plane[3] = -plane[3];
00776 }
00777 ChopWindingInPlace( &w, plane, plane[3], 0.1f );
00778 }
00779
00780 if ( !w ) {
00781 return qfalse;
00782 }
00783
00784
00785 WindingBounds( w, bounds[0], bounds[1] );
00786 FreeWinding( w );
00787
00788 for ( j = 0 ; j < 3 ; j++ ) {
00789 if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
00790 return qfalse;
00791 }
00792 if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
00793 return qfalse;
00794 }
00795 if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
00796 return qfalse;
00797 }
00798 }
00799 return qtrue;
00800 }
00801
00802
00803
00804
00805
00806
00807 void CM_AddFacetBevels( facet_t *facet ) {
00808
00809 int i, j, k, l;
00810 int axis, dir, order, flipped;
00811 float plane[4], d, newplane[4];
00812 winding_t *w, *w2;
00813 vec3_t mins, maxs, vec, vec2;
00814
00815 Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
00816
00817 w = BaseWindingForPlane( plane, plane[3] );
00818 for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
00819 if (facet->borderPlanes[j] == facet->surfacePlane) continue;
00820 Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
00821
00822 if ( !facet->borderInward[j] ) {
00823 VectorSubtract( vec3_origin, plane, plane );
00824 plane[3] = -plane[3];
00825 }
00826
00827 ChopWindingInPlace( &w, plane, plane[3], 0.1f );
00828 }
00829 if ( !w ) {
00830 return;
00831 }
00832
00833 WindingBounds(w, mins, maxs);
00834
00835
00836 order = 0;
00837 for ( axis = 0 ; axis < 3 ; axis++ )
00838 {
00839 for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
00840 {
00841 VectorClear(plane);
00842 plane[axis] = dir;
00843 if (dir == 1) {
00844 plane[3] = maxs[axis];
00845 }
00846 else {
00847 plane[3] = -mins[axis];
00848 }
00849
00850 if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
00851 continue;
00852 }
00853
00854 for ( i = 0 ; i < facet->numBorders ; i++ ) {
00855 if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
00856 break;
00857 }
00858
00859 if ( i == facet->numBorders ) {
00860 if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
00861 facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
00862 facet->borderNoAdjust[facet->numBorders] = 0;
00863 facet->borderInward[facet->numBorders] = flipped;
00864 facet->numBorders++;
00865 }
00866 }
00867 }
00868
00869
00870
00871
00872 for ( j = 0 ; j < w->numpoints ; j++ )
00873 {
00874 k = (j+1)%w->numpoints;
00875 VectorSubtract (w->p[j], w->p[k], vec);
00876
00877 if (VectorNormalize (vec) < 0.5)
00878 continue;
00879 CM_SnapVector(vec);
00880 for ( k = 0; k < 3 ; k++ )
00881 if ( vec[k] == -1 || vec[k] == 1 )
00882 break;
00883 if ( k < 3 )
00884 continue;
00885
00886
00887 for ( axis = 0 ; axis < 3 ; axis++ )
00888 {
00889 for ( dir = -1 ; dir <= 1 ; dir += 2 )
00890 {
00891
00892 VectorClear (vec2);
00893 vec2[axis] = dir;
00894 CrossProduct (vec, vec2, plane);
00895 if (VectorNormalize (plane) < 0.5)
00896 continue;
00897 plane[3] = DotProduct (w->p[j], plane);
00898
00899
00900
00901 for ( l = 0 ; l < w->numpoints ; l++ )
00902 {
00903 d = DotProduct (w->p[l], plane) - plane[3];
00904 if (d > 0.1)
00905 break;
00906 }
00907 if ( l < w->numpoints )
00908 continue;
00909
00910
00911 if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
00912 continue;
00913 }
00914
00915 for ( i = 0 ; i < facet->numBorders ; i++ ) {
00916 if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
00917 break;
00918 }
00919 }
00920
00921 if ( i == facet->numBorders ) {
00922 if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
00923 facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
00924
00925 for ( k = 0 ; k < facet->numBorders ; k++ ) {
00926 if (facet->borderPlanes[facet->numBorders] ==
00927 facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
00928 }
00929
00930 facet->borderNoAdjust[facet->numBorders] = 0;
00931 facet->borderInward[facet->numBorders] = flipped;
00932
00933 w2 = CopyWinding(w);
00934 Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
00935 if (!facet->borderInward[facet->numBorders])
00936 {
00937 VectorNegate(newplane, newplane);
00938 newplane[3] = -newplane[3];
00939 }
00940 ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
00941 if (!w2) {
00942 Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
00943 continue;
00944 }
00945 else {
00946 FreeWinding(w2);
00947 }
00948
00949 facet->numBorders++;
00950
00951
00952 }
00953 }
00954 }
00955 }
00956 FreeWinding( w );
00957
00958 #ifndef BSPC
00959
00960 facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
00961 facet->borderNoAdjust[facet->numBorders] = 0;
00962 facet->borderInward[facet->numBorders] = qtrue;
00963 facet->numBorders++;
00964 #endif //BSPC
00965
00966 }
00967
00968 typedef enum {
00969 EN_TOP,
00970 EN_RIGHT,
00971 EN_BOTTOM,
00972 EN_LEFT
00973 } edgeName_t;
00974
00975
00976
00977
00978
00979
00980 static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf ) {
00981 int i, j;
00982 float *p1, *p2, *p3;
00983 MAC_STATIC int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2];
00984 facet_t *facet;
00985 int borders[4];
00986 int noAdjust[4];
00987
00988 numPlanes = 0;
00989 numFacets = 0;
00990
00991
00992 for ( i = 0 ; i < grid->width - 1 ; i++ ) {
00993 for ( j = 0 ; j < grid->height - 1 ; j++ ) {
00994 p1 = grid->points[i][j];
00995 p2 = grid->points[i+1][j];
00996 p3 = grid->points[i+1][j+1];
00997 gridPlanes[i][j][0] = CM_FindPlane( p1, p2, p3 );
00998
00999 p1 = grid->points[i+1][j+1];
01000 p2 = grid->points[i][j+1];
01001 p3 = grid->points[i][j];
01002 gridPlanes[i][j][1] = CM_FindPlane( p1, p2, p3 );
01003 }
01004 }
01005
01006
01007 for ( i = 0 ; i < grid->width - 1 ; i++ ) {
01008 for ( j = 0 ; j < grid->height - 1 ; j++ ) {
01009
01010 borders[EN_TOP] = -1;
01011 if ( j > 0 ) {
01012 borders[EN_TOP] = gridPlanes[i][j-1][1];
01013 } else if ( grid->wrapHeight ) {
01014 borders[EN_TOP] = gridPlanes[i][grid->height-2][1];
01015 }
01016 noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i][j][0] );
01017 if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
01018 borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
01019 }
01020
01021 borders[EN_BOTTOM] = -1;
01022 if ( j < grid->height - 2 ) {
01023 borders[EN_BOTTOM] = gridPlanes[i][j+1][0];
01024 } else if ( grid->wrapHeight ) {
01025 borders[EN_BOTTOM] = gridPlanes[i][0][0];
01026 }
01027 noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i][j][1] );
01028 if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
01029 borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
01030 }
01031
01032 borders[EN_LEFT] = -1;
01033 if ( i > 0 ) {
01034 borders[EN_LEFT] = gridPlanes[i-1][j][0];
01035 } else if ( grid->wrapWidth ) {
01036 borders[EN_LEFT] = gridPlanes[grid->width-2][j][0];
01037 }
01038 noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i][j][1] );
01039 if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
01040 borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
01041 }
01042
01043 borders[EN_RIGHT] = -1;
01044 if ( i < grid->width - 2 ) {
01045 borders[EN_RIGHT] = gridPlanes[i+1][j][1];
01046 } else if ( grid->wrapWidth ) {
01047 borders[EN_RIGHT] = gridPlanes[0][j][1];
01048 }
01049 noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i][j][0] );
01050 if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
01051 borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
01052 }
01053
01054 if ( numFacets == MAX_FACETS ) {
01055 Com_Error( ERR_DROP, "MAX_FACETS" );
01056 }
01057 facet = &facets[numFacets];
01058 Com_Memset( facet, 0, sizeof( *facet ) );
01059
01060 if ( gridPlanes[i][j][0] == gridPlanes[i][j][1] ) {
01061 if ( gridPlanes[i][j][0] == -1 ) {
01062 continue;
01063 }
01064 facet->surfacePlane = gridPlanes[i][j][0];
01065 facet->numBorders = 4;
01066 facet->borderPlanes[0] = borders[EN_TOP];
01067 facet->borderNoAdjust[0] = noAdjust[EN_TOP];
01068 facet->borderPlanes[1] = borders[EN_RIGHT];
01069 facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
01070 facet->borderPlanes[2] = borders[EN_BOTTOM];
01071 facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
01072 facet->borderPlanes[3] = borders[EN_LEFT];
01073 facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
01074 CM_SetBorderInward( facet, grid, gridPlanes, i, j, -1 );
01075 if ( CM_ValidateFacet( facet ) ) {
01076 CM_AddFacetBevels( facet );
01077 numFacets++;
01078 }
01079 } else {
01080
01081 facet->surfacePlane = gridPlanes[i][j][0];
01082 facet->numBorders = 3;
01083 facet->borderPlanes[0] = borders[EN_TOP];
01084 facet->borderNoAdjust[0] = noAdjust[EN_TOP];
01085 facet->borderPlanes[1] = borders[EN_RIGHT];
01086 facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
01087 facet->borderPlanes[2] = gridPlanes[i][j][1];
01088 if ( facet->borderPlanes[2] == -1 ) {
01089 facet->borderPlanes[2] = borders[EN_BOTTOM];
01090 if ( facet->borderPlanes[2] == -1 ) {
01091 facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
01092 }
01093 }
01094 CM_SetBorderInward( facet, grid, gridPlanes, i, j, 0 );
01095 if ( CM_ValidateFacet( facet ) ) {
01096 CM_AddFacetBevels( facet );
01097 numFacets++;
01098 }
01099
01100 if ( numFacets == MAX_FACETS ) {
01101 Com_Error( ERR_DROP, "MAX_FACETS" );
01102 }
01103 facet = &facets[numFacets];
01104 Com_Memset( facet, 0, sizeof( *facet ) );
01105
01106 facet->surfacePlane = gridPlanes[i][j][1];
01107 facet->numBorders = 3;
01108 facet->borderPlanes[0] = borders[EN_BOTTOM];
01109 facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
01110 facet->borderPlanes[1] = borders[EN_LEFT];
01111 facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
01112 facet->borderPlanes[2] = gridPlanes[i][j][0];
01113 if ( facet->borderPlanes[2] == -1 ) {
01114 facet->borderPlanes[2] = borders[EN_TOP];
01115 if ( facet->borderPlanes[2] == -1 ) {
01116 facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
01117 }
01118 }
01119 CM_SetBorderInward( facet, grid, gridPlanes, i, j, 1 );
01120 if ( CM_ValidateFacet( facet ) ) {
01121 CM_AddFacetBevels( facet );
01122 numFacets++;
01123 }
01124 }
01125 }
01126 }
01127
01128
01129 pf->numPlanes = numPlanes;
01130 pf->numFacets = numFacets;
01131 pf->facets = Hunk_Alloc( numFacets * sizeof( *pf->facets ), h_high );
01132 Com_Memcpy( pf->facets, facets, numFacets * sizeof( *pf->facets ) );
01133 pf->planes = Hunk_Alloc( numPlanes * sizeof( *pf->planes ), h_high );
01134 Com_Memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ) {
01149 patchCollide_t *pf;
01150 MAC_STATIC cGrid_t grid;
01151 int i, j;
01152
01153 if ( width <= 2 || height <= 2 || !points ) {
01154 Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
01155 width, height, points );
01156 }
01157
01158 if ( !(width & 1) || !(height & 1) ) {
01159 Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
01160 }
01161
01162 if ( width > MAX_GRID_SIZE || height > MAX_GRID_SIZE ) {
01163 Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > MAX_GRID_SIZE" );
01164 }
01165
01166
01167 grid.width = width;
01168 grid.height = height;
01169 grid.wrapWidth = qfalse;
01170 grid.wrapHeight = qfalse;
01171 for ( i = 0 ; i < width ; i++ ) {
01172 for ( j = 0 ; j < height ; j++ ) {
01173 VectorCopy( points[j*width + i], grid.points[i][j] );
01174 }
01175 }
01176
01177
01178 CM_SetGridWrapWidth( &grid );
01179 CM_SubdivideGridColumns( &grid );
01180 CM_RemoveDegenerateColumns( &grid );
01181
01182 CM_TransposeGrid( &grid );
01183
01184 CM_SetGridWrapWidth( &grid );
01185 CM_SubdivideGridColumns( &grid );
01186 CM_RemoveDegenerateColumns( &grid );
01187
01188
01189
01190
01191 pf = Hunk_Alloc( sizeof( *pf ), h_high );
01192 ClearBounds( pf->bounds[0], pf->bounds[1] );
01193 for ( i = 0 ; i < grid.width ; i++ ) {
01194 for ( j = 0 ; j < grid.height ; j++ ) {
01195 AddPointToBounds( grid.points[i][j], pf->bounds[0], pf->bounds[1] );
01196 }
01197 }
01198
01199 c_totalPatchBlocks += ( grid.width - 1 ) * ( grid.height - 1 );
01200
01201
01202 CM_PatchCollideFromGrid( &grid, pf );
01203
01204
01205 pf->bounds[0][0] -= 1;
01206 pf->bounds[0][1] -= 1;
01207 pf->bounds[0][2] -= 1;
01208
01209 pf->bounds[1][0] += 1;
01210 pf->bounds[1][1] += 1;
01211 pf->bounds[1][2] += 1;
01212
01213 return pf;
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
01232 qboolean frontFacing[MAX_PATCH_PLANES];
01233 float intersection[MAX_PATCH_PLANES];
01234 float intersect;
01235 const patchPlane_t *planes;
01236 const facet_t *facet;
01237 int i, j, k;
01238 float offset;
01239 float d1, d2;
01240 #ifndef BSPC
01241 static cvar_t *cv;
01242 #endif //BSPC
01243
01244 #ifndef BSPC
01245 if ( !cm_playerCurveClip->integer || !tw->isPoint ) {
01246 return;
01247 }
01248 #endif
01249
01250
01251 planes = pc->planes;
01252 for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
01253 offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
01254 d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
01255 d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
01256 if ( d1 <= 0 ) {
01257 frontFacing[i] = qfalse;
01258 } else {
01259 frontFacing[i] = qtrue;
01260 }
01261 if ( d1 == d2 ) {
01262 intersection[i] = 99999;
01263 } else {
01264 intersection[i] = d1 / ( d1 - d2 );
01265 if ( intersection[i] <= 0 ) {
01266 intersection[i] = 99999;
01267 }
01268 }
01269 }
01270
01271
01272
01273 facet = pc->facets;
01274 for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
01275 if ( !frontFacing[facet->surfacePlane] ) {
01276 continue;
01277 }
01278 intersect = intersection[facet->surfacePlane];
01279 if ( intersect < 0 ) {
01280 continue;
01281 }
01282 if ( intersect > tw->trace.fraction ) {
01283 continue;
01284 }
01285 for ( j = 0 ; j < facet->numBorders ; j++ ) {
01286 k = facet->borderPlanes[j];
01287 if ( frontFacing[k] ^ facet->borderInward[j] ) {
01288 if ( intersection[k] > intersect ) {
01289 break;
01290 }
01291 } else {
01292 if ( intersection[k] < intersect ) {
01293 break;
01294 }
01295 }
01296 }
01297 if ( j == facet->numBorders ) {
01298
01299 #ifndef BSPC
01300 if (!cv) {
01301 cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
01302 }
01303 if (cv->integer) {
01304 debugPatchCollide = pc;
01305 debugFacet = facet;
01306 }
01307 #endif //BSPC
01308 planes = &pc->planes[facet->surfacePlane];
01309
01310
01311 offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
01312 d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
01313 d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
01314 tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
01315
01316 if ( tw->trace.fraction < 0 ) {
01317 tw->trace.fraction = 0;
01318 }
01319
01320 VectorCopy( planes->plane, tw->trace.plane.normal );
01321 tw->trace.plane.dist = planes->plane[3];
01322 }
01323 }
01324 }
01325
01326
01327
01328
01329
01330
01331 int CM_CheckFacetPlane(float *plane, vec3_t start, vec3_t end, float *enterFrac, float *leaveFrac, int *hit) {
01332 float d1, d2, f;
01333
01334 *hit = qfalse;
01335
01336 d1 = DotProduct( start, plane ) - plane[3];
01337 d2 = DotProduct( end, plane ) - plane[3];
01338
01339
01340 if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
01341 return qfalse;
01342 }
01343
01344
01345 if (d1 <= 0 && d2 <= 0 ) {
01346 return qtrue;
01347 }
01348
01349
01350 if (d1 > d2) {
01351 f = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
01352 if ( f < 0 ) {
01353 f = 0;
01354 }
01355
01356 if (f > *enterFrac) {
01357 *enterFrac = f;
01358 *hit = qtrue;
01359 }
01360 } else {
01361 f = (d1+SURFACE_CLIP_EPSILON) / (d1-d2);
01362 if ( f > 1 ) {
01363 f = 1;
01364 }
01365 if (f < *leaveFrac) {
01366 *leaveFrac = f;
01367 }
01368 }
01369 return qtrue;
01370 }
01371
01372
01373
01374
01375
01376
01377 void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
01378 int i, j, hit, hitnum;
01379 float offset, enterFrac, leaveFrac, t;
01380 patchPlane_t *planes;
01381 facet_t *facet;
01382 float plane[4], bestplane[4];
01383 vec3_t startp, endp;
01384 #ifndef BSPC
01385 static cvar_t *cv;
01386 #endif //BSPC
01387
01388 if (tw->isPoint) {
01389 CM_TracePointThroughPatchCollide( tw, pc );
01390 return;
01391 }
01392
01393 facet = pc->facets;
01394 for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
01395 enterFrac = -1.0;
01396 leaveFrac = 1.0;
01397 hitnum = -1;
01398
01399 planes = &pc->planes[ facet->surfacePlane ];
01400 VectorCopy(planes->plane, plane);
01401 plane[3] = planes->plane[3];
01402 if ( tw->sphere.use ) {
01403
01404 plane[3] += tw->sphere.radius;
01405
01406
01407 t = DotProduct( plane, tw->sphere.offset );
01408 if ( t > 0.0f ) {
01409 VectorSubtract( tw->start, tw->sphere.offset, startp );
01410 VectorSubtract( tw->end, tw->sphere.offset, endp );
01411 }
01412 else {
01413 VectorAdd( tw->start, tw->sphere.offset, startp );
01414 VectorAdd( tw->end, tw->sphere.offset, endp );
01415 }
01416 }
01417 else {
01418 offset = DotProduct( tw->offsets[ planes->signbits ], plane);
01419 plane[3] -= offset;
01420 VectorCopy( tw->start, startp );
01421 VectorCopy( tw->end, endp );
01422 }
01423
01424 if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
01425 continue;
01426 }
01427 if (hit) {
01428 Vector4Copy(plane, bestplane);
01429 }
01430
01431 for ( j = 0; j < facet->numBorders; j++ ) {
01432 planes = &pc->planes[ facet->borderPlanes[j] ];
01433 if (facet->borderInward[j]) {
01434 VectorNegate(planes->plane, plane);
01435 plane[3] = -planes->plane[3];
01436 }
01437 else {
01438 VectorCopy(planes->plane, plane);
01439 plane[3] = planes->plane[3];
01440 }
01441 if ( tw->sphere.use ) {
01442
01443 plane[3] += tw->sphere.radius;
01444
01445
01446 t = DotProduct( plane, tw->sphere.offset );
01447 if ( t > 0.0f ) {
01448 VectorSubtract( tw->start, tw->sphere.offset, startp );
01449 VectorSubtract( tw->end, tw->sphere.offset, endp );
01450 }
01451 else {
01452 VectorAdd( tw->start, tw->sphere.offset, startp );
01453 VectorAdd( tw->end, tw->sphere.offset, endp );
01454 }
01455 }
01456 else {
01457
01458 offset = DotProduct( tw->offsets[ planes->signbits ], plane);
01459 plane[3] += fabs(offset);
01460 VectorCopy( tw->start, startp );
01461 VectorCopy( tw->end, endp );
01462 }
01463
01464 if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
01465 break;
01466 }
01467 if (hit) {
01468 hitnum = j;
01469 Vector4Copy(plane, bestplane);
01470 }
01471 }
01472 if (j < facet->numBorders) continue;
01473
01474 if (hitnum == facet->numBorders - 1) continue;
01475
01476 if (enterFrac < leaveFrac && enterFrac >= 0) {
01477 if (enterFrac < tw->trace.fraction) {
01478 if (enterFrac < 0) {
01479 enterFrac = 0;
01480 }
01481 #ifndef BSPC
01482 if (!cv) {
01483 cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
01484 }
01485 if (cv && cv->integer) {
01486 debugPatchCollide = pc;
01487 debugFacet = facet;
01488 }
01489 #endif //BSPC
01490
01491 tw->trace.fraction = enterFrac;
01492 VectorCopy( bestplane, tw->trace.plane.normal );
01493 tw->trace.plane.dist = bestplane[3];
01494 }
01495 }
01496 }
01497 }
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
01514 int i, j;
01515 float offset, t;
01516 patchPlane_t *planes;
01517 facet_t *facet;
01518 float plane[4];
01519 vec3_t startp;
01520
01521 if (tw->isPoint) {
01522 return qfalse;
01523 }
01524
01525 facet = pc->facets;
01526 for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
01527 planes = &pc->planes[ facet->surfacePlane ];
01528 VectorCopy(planes->plane, plane);
01529 plane[3] = planes->plane[3];
01530 if ( tw->sphere.use ) {
01531
01532 plane[3] += tw->sphere.radius;
01533
01534
01535 t = DotProduct( plane, tw->sphere.offset );
01536 if ( t > 0 ) {
01537 VectorSubtract( tw->start, tw->sphere.offset, startp );
01538 }
01539 else {
01540 VectorAdd( tw->start, tw->sphere.offset, startp );
01541 }
01542 }
01543 else {
01544 offset = DotProduct( tw->offsets[ planes->signbits ], plane);
01545 plane[3] -= offset;
01546 VectorCopy( tw->start, startp );
01547 }
01548
01549 if ( DotProduct( plane, startp ) - plane[3] > 0.0f ) {
01550 continue;
01551 }
01552
01553 for ( j = 0; j < facet->numBorders; j++ ) {
01554 planes = &pc->planes[ facet->borderPlanes[j] ];
01555 if (facet->borderInward[j]) {
01556 VectorNegate(planes->plane, plane);
01557 plane[3] = -planes->plane[3];
01558 }
01559 else {
01560 VectorCopy(planes->plane, plane);
01561 plane[3] = planes->plane[3];
01562 }
01563 if ( tw->sphere.use ) {
01564
01565 plane[3] += tw->sphere.radius;
01566
01567
01568 t = DotProduct( plane, tw->sphere.offset );
01569 if ( t > 0.0f ) {
01570 VectorSubtract( tw->start, tw->sphere.offset, startp );
01571 }
01572 else {
01573 VectorAdd( tw->start, tw->sphere.offset, startp );
01574 }
01575 }
01576 else {
01577
01578 offset = DotProduct( tw->offsets[ planes->signbits ], plane);
01579 plane[3] += fabs(offset);
01580 VectorCopy( tw->start, startp );
01581 }
01582
01583 if ( DotProduct( plane, startp ) - plane[3] > 0.0f ) {
01584 break;
01585 }
01586 }
01587 if (j < facet->numBorders) {
01588 continue;
01589 }
01590
01591 return qtrue;
01592 }
01593 return qfalse;
01594 }
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612 #ifndef BSPC
01613 void BotDrawDebugPolygons(void (*drawPoly)(int color, int numPoints, float *points), int value);
01614 #endif
01615
01616 void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ) {
01617 static cvar_t *cv;
01618 #ifndef BSPC
01619 static cvar_t *cv2;
01620 #endif
01621 const patchCollide_t *pc;
01622 facet_t *facet;
01623 winding_t *w;
01624 int i, j, k, n;
01625 int curplanenum, planenum, curinward, inward;
01626 float plane[4];
01627 vec3_t mins = {-15, -15, -28}, maxs = {15, 15, 28};
01628
01629 vec3_t v1, v2;
01630
01631 #ifndef BSPC
01632 if ( !cv2 )
01633 {
01634 cv2 = Cvar_Get( "r_debugSurface", "0", 0 );
01635 }
01636
01637 if (cv2->integer != 1)
01638 {
01639 BotDrawDebugPolygons(drawPoly, cv2->integer);
01640 return;
01641 }
01642 #endif
01643
01644 if ( !debugPatchCollide ) {
01645 return;
01646 }
01647
01648 #ifndef BSPC
01649 if ( !cv ) {
01650 cv = Cvar_Get( "cm_debugSize", "2", 0 );
01651 }
01652 #endif
01653 pc = debugPatchCollide;
01654
01655 for ( i = 0, facet = pc->facets ; i < pc->numFacets ; i++, facet++ ) {
01656
01657 for ( k = 0 ; k < facet->numBorders + 1; k++ ) {
01658
01659 if (k < facet->numBorders) {
01660 planenum = facet->borderPlanes[k];
01661 inward = facet->borderInward[k];
01662 }
01663 else {
01664 planenum = facet->surfacePlane;
01665 inward = qfalse;
01666
01667 }
01668
01669 Vector4Copy( pc->planes[ planenum ].plane, plane );
01670
01671
01672 if ( inward ) {
01673 VectorSubtract( vec3_origin, plane, plane );
01674 plane[3] = -plane[3];
01675 }
01676
01677 plane[3] += cv->value;
01678
01679 for (n = 0; n < 3; n++)
01680 {
01681 if (plane[n] > 0) v1[n] = maxs[n];
01682 else v1[n] = mins[n];
01683 }
01684 VectorNegate(plane, v2);
01685 plane[3] += fabs(DotProduct(v1, v2));
01686
01687
01688 w = BaseWindingForPlane( plane, plane[3] );
01689 for ( j = 0 ; j < facet->numBorders + 1 && w; j++ ) {
01690
01691 if (j < facet->numBorders) {
01692 curplanenum = facet->borderPlanes[j];
01693 curinward = facet->borderInward[j];
01694 }
01695 else {
01696 curplanenum = facet->surfacePlane;
01697 curinward = qfalse;
01698
01699 }
01700
01701 if (curplanenum == planenum) continue;
01702
01703 Vector4Copy( pc->planes[ curplanenum ].plane, plane );
01704 if ( !curinward ) {
01705 VectorSubtract( vec3_origin, plane, plane );
01706 plane[3] = -plane[3];
01707 }
01708
01709 plane[3] -= cv->value;
01710
01711 for (n = 0; n < 3; n++)
01712 {
01713 if (plane[n] > 0) v1[n] = maxs[n];
01714 else v1[n] = mins[n];
01715 }
01716 VectorNegate(plane, v2);
01717 plane[3] -= fabs(DotProduct(v1, v2));
01718
01719 ChopWindingInPlace( &w, plane, plane[3], 0.1f );
01720 }
01721 if ( w ) {
01722 if ( facet == debugFacet ) {
01723 drawPoly( 4, w->numpoints, w->p[0] );
01724
01725 } else {
01726 drawPoly( 1, w->numpoints, w->p[0] );
01727 }
01728 FreeWinding( w );
01729 }
01730 else
01731 Com_Printf("winding chopped away by border planes\n");
01732 }
01733 }
01734
01735
01736 {
01737 vec3_t v[3];
01738
01739 VectorCopy( debugBlockPoints[0], v[0] );
01740 VectorCopy( debugBlockPoints[1], v[1] );
01741 VectorCopy( debugBlockPoints[2], v[2] );
01742 drawPoly( 2, 3, v[0] );
01743
01744 VectorCopy( debugBlockPoints[2], v[0] );
01745 VectorCopy( debugBlockPoints[3], v[1] );
01746 VectorCopy( debugBlockPoints[0], v[2] );
01747 drawPoly( 2, 3, v[0] );
01748 }
01749
01750 #if 0
01751 vec3_t v[4];
01752
01753 v[0][0] = pc->bounds[1][0];
01754 v[0][1] = pc->bounds[1][1];
01755 v[0][2] = pc->bounds[1][2];
01756
01757 v[1][0] = pc->bounds[1][0];
01758 v[1][1] = pc->bounds[0][1];
01759 v[1][2] = pc->bounds[1][2];
01760
01761 v[2][0] = pc->bounds[0][0];
01762 v[2][1] = pc->bounds[0][1];
01763 v[2][2] = pc->bounds[1][2];
01764
01765 v[3][0] = pc->bounds[0][0];
01766 v[3][1] = pc->bounds[1][1];
01767 v[3][2] = pc->bounds[1][2];
01768
01769 drawPoly( 4, v[0] );
01770 #endif
01771 }