cm_patch.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "cm_local.h"
  19. #include "cm_patch.h"
  20. /*
  21. This file does not reference any globals, and has these entry points:
  22. void CM_ClearLevelPatches( void );
  23. struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points );
  24. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
  25. qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
  26. void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) );
  27. WARNING: this may misbehave with meshes that have rows or columns that only
  28. degenerate a few triangles. Completely degenerate rows and columns are handled
  29. properly.
  30. */
  31. /*
  32. #define MAX_FACETS 1024
  33. #define MAX_PATCH_PLANES 2048
  34. typedef struct {
  35. float plane[4];
  36. int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision
  37. } patchPlane_t;
  38. typedef struct {
  39. int surfacePlane;
  40. int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels
  41. int borderPlanes[4+6+16];
  42. int borderInward[4+6+16];
  43. qboolean borderNoAdjust[4+6+16];
  44. } facet_t;
  45. typedef struct patchCollide_s {
  46. vec3_t bounds[2];
  47. int numPlanes; // surface planes plus edge planes
  48. patchPlane_t *planes;
  49. int numFacets;
  50. facet_t *facets;
  51. } patchCollide_t;
  52. #define MAX_GRID_SIZE 129
  53. typedef struct {
  54. int width;
  55. int height;
  56. qboolean wrapWidth;
  57. qboolean wrapHeight;
  58. vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height]
  59. } cGrid_t;
  60. #define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve
  61. #define PLANE_TRI_EPSILON 0.1
  62. #define WRAP_POINT_EPSILON 0.1
  63. */
  64. int c_totalPatchBlocks;
  65. int c_totalPatchSurfaces;
  66. int c_totalPatchEdges;
  67. static const patchCollide_t *debugPatchCollide;
  68. static const facet_t *debugFacet;
  69. static qboolean debugBlock;
  70. static vec3_t debugBlockPoints[4];
  71. /*
  72. =================
  73. CM_ClearLevelPatches
  74. =================
  75. */
  76. void CM_ClearLevelPatches( void ) {
  77. debugPatchCollide = NULL;
  78. debugFacet = NULL;
  79. }
  80. /*
  81. =================
  82. CM_SignbitsForNormal
  83. =================
  84. */
  85. static int CM_SignbitsForNormal( vec3_t normal ) {
  86. int bits, j;
  87. bits = 0;
  88. for (j=0 ; j<3 ; j++) {
  89. if ( normal[j] < 0 ) {
  90. bits |= 1<<j;
  91. }
  92. }
  93. return bits;
  94. }
  95. /*
  96. =====================
  97. CM_PlaneFromPoints
  98. Returns false if the triangle is degenrate.
  99. The normal will point out of the clock for clockwise ordered points
  100. =====================
  101. */
  102. static qboolean CM_PlaneFromPoints( vec4_t plane, vec3_t a, vec3_t b, vec3_t c ) {
  103. vec3_t d1, d2;
  104. VectorSubtract( b, a, d1 );
  105. VectorSubtract( c, a, d2 );
  106. CrossProduct( d2, d1, plane );
  107. if ( VectorNormalize( plane ) == 0 ) {
  108. return qfalse;
  109. }
  110. plane[3] = DotProduct( a, plane );
  111. return qtrue;
  112. }
  113. /*
  114. ================================================================================
  115. GRID SUBDIVISION
  116. ================================================================================
  117. */
  118. /*
  119. =================
  120. CM_NeedsSubdivision
  121. Returns true if the given quadratic curve is not flat enough for our
  122. collision detection purposes
  123. =================
  124. */
  125. static qboolean CM_NeedsSubdivision( vec3_t a, vec3_t b, vec3_t c ) {
  126. vec3_t cmid;
  127. vec3_t lmid;
  128. vec3_t delta;
  129. float dist;
  130. int i;
  131. // calculate the linear midpoint
  132. for ( i = 0 ; i < 3 ; i++ ) {
  133. lmid[i] = 0.5*(a[i] + c[i]);
  134. }
  135. // calculate the exact curve midpoint
  136. for ( i = 0 ; i < 3 ; i++ ) {
  137. cmid[i] = 0.5 * ( 0.5*(a[i] + b[i]) + 0.5*(b[i] + c[i]) );
  138. }
  139. // see if the curve is far enough away from the linear mid
  140. VectorSubtract( cmid, lmid, delta );
  141. dist = VectorLength( delta );
  142. return dist >= SUBDIVIDE_DISTANCE;
  143. }
  144. /*
  145. ===============
  146. CM_Subdivide
  147. a, b, and c are control points.
  148. the subdivided sequence will be: a, out1, out2, out3, c
  149. ===============
  150. */
  151. static void CM_Subdivide( vec3_t a, vec3_t b, vec3_t c, vec3_t out1, vec3_t out2, vec3_t out3 ) {
  152. int i;
  153. for ( i = 0 ; i < 3 ; i++ ) {
  154. out1[i] = 0.5 * (a[i] + b[i]);
  155. out3[i] = 0.5 * (b[i] + c[i]);
  156. out2[i] = 0.5 * (out1[i] + out3[i]);
  157. }
  158. }
  159. /*
  160. =================
  161. CM_TransposeGrid
  162. Swaps the rows and columns in place
  163. =================
  164. */
  165. static void CM_TransposeGrid( cGrid_t *grid ) {
  166. int i, j, l;
  167. vec3_t temp;
  168. qboolean tempWrap;
  169. if ( grid->width > grid->height ) {
  170. for ( i = 0 ; i < grid->height ; i++ ) {
  171. for ( j = i + 1 ; j < grid->width ; j++ ) {
  172. if ( j < grid->height ) {
  173. // swap the value
  174. VectorCopy( grid->points[i][j], temp );
  175. VectorCopy( grid->points[j][i], grid->points[i][j] );
  176. VectorCopy( temp, grid->points[j][i] );
  177. } else {
  178. // just copy
  179. VectorCopy( grid->points[j][i], grid->points[i][j] );
  180. }
  181. }
  182. }
  183. } else {
  184. for ( i = 0 ; i < grid->width ; i++ ) {
  185. for ( j = i + 1 ; j < grid->height ; j++ ) {
  186. if ( j < grid->width ) {
  187. // swap the value
  188. VectorCopy( grid->points[j][i], temp );
  189. VectorCopy( grid->points[i][j], grid->points[j][i] );
  190. VectorCopy( temp, grid->points[i][j] );
  191. } else {
  192. // just copy
  193. VectorCopy( grid->points[i][j], grid->points[j][i] );
  194. }
  195. }
  196. }
  197. }
  198. l = grid->width;
  199. grid->width = grid->height;
  200. grid->height = l;
  201. tempWrap = grid->wrapWidth;
  202. grid->wrapWidth = grid->wrapHeight;
  203. grid->wrapHeight = tempWrap;
  204. }
  205. /*
  206. ===================
  207. CM_SetGridWrapWidth
  208. If the left and right columns are exactly equal, set grid->wrapWidth qtrue
  209. ===================
  210. */
  211. static void CM_SetGridWrapWidth( cGrid_t *grid ) {
  212. int i, j;
  213. float d;
  214. for ( i = 0 ; i < grid->height ; i++ ) {
  215. for ( j = 0 ; j < 3 ; j++ ) {
  216. d = grid->points[0][i][j] - grid->points[grid->width-1][i][j];
  217. if ( d < -WRAP_POINT_EPSILON || d > WRAP_POINT_EPSILON ) {
  218. break;
  219. }
  220. }
  221. if ( j != 3 ) {
  222. break;
  223. }
  224. }
  225. if ( i == grid->height ) {
  226. grid->wrapWidth = qtrue;
  227. } else {
  228. grid->wrapWidth = qfalse;
  229. }
  230. }
  231. /*
  232. =================
  233. CM_SubdivideGridColumns
  234. Adds columns as necessary to the grid until
  235. all the aproximating points are within SUBDIVIDE_DISTANCE
  236. from the true curve
  237. =================
  238. */
  239. static void CM_SubdivideGridColumns( cGrid_t *grid ) {
  240. int i, j, k;
  241. for ( i = 0 ; i < grid->width - 2 ; ) {
  242. // grid->points[i][x] is an interpolating control point
  243. // grid->points[i+1][x] is an aproximating control point
  244. // grid->points[i+2][x] is an interpolating control point
  245. //
  246. // first see if we can collapse the aproximating collumn away
  247. //
  248. for ( j = 0 ; j < grid->height ; j++ ) {
  249. if ( CM_NeedsSubdivision( grid->points[i][j], grid->points[i+1][j], grid->points[i+2][j] ) ) {
  250. break;
  251. }
  252. }
  253. if ( j == grid->height ) {
  254. // all of the points were close enough to the linear midpoints
  255. // that we can collapse the entire column away
  256. for ( j = 0 ; j < grid->height ; j++ ) {
  257. // remove the column
  258. for ( k = i + 2 ; k < grid->width ; k++ ) {
  259. VectorCopy( grid->points[k][j], grid->points[k-1][j] );
  260. }
  261. }
  262. grid->width--;
  263. // go to the next curve segment
  264. i++;
  265. continue;
  266. }
  267. //
  268. // we need to subdivide the curve
  269. //
  270. for ( j = 0 ; j < grid->height ; j++ ) {
  271. vec3_t prev, mid, next;
  272. // save the control points now
  273. VectorCopy( grid->points[i][j], prev );
  274. VectorCopy( grid->points[i+1][j], mid );
  275. VectorCopy( grid->points[i+2][j], next );
  276. // make room for two additional columns in the grid
  277. // columns i+1 will be replaced, column i+2 will become i+4
  278. // i+1, i+2, and i+3 will be generated
  279. for ( k = grid->width - 1 ; k > i + 1 ; k-- ) {
  280. VectorCopy( grid->points[k][j], grid->points[k+2][j] );
  281. }
  282. // generate the subdivided points
  283. CM_Subdivide( prev, mid, next, grid->points[i+1][j], grid->points[i+2][j], grid->points[i+3][j] );
  284. }
  285. grid->width += 2;
  286. // the new aproximating point at i+1 may need to be removed
  287. // or subdivided farther, so don't advance i
  288. }
  289. }
  290. /*
  291. ======================
  292. CM_ComparePoints
  293. ======================
  294. */
  295. #define POINT_EPSILON 0.1
  296. static qboolean CM_ComparePoints( float *a, float *b ) {
  297. float d;
  298. d = a[0] - b[0];
  299. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  300. return qfalse;
  301. }
  302. d = a[1] - b[1];
  303. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  304. return qfalse;
  305. }
  306. d = a[2] - b[2];
  307. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  308. return qfalse;
  309. }
  310. return qtrue;
  311. }
  312. /*
  313. =================
  314. CM_RemoveDegenerateColumns
  315. If there are any identical columns, remove them
  316. =================
  317. */
  318. static void CM_RemoveDegenerateColumns( cGrid_t *grid ) {
  319. int i, j, k;
  320. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  321. for ( j = 0 ; j < grid->height ; j++ ) {
  322. if ( !CM_ComparePoints( grid->points[i][j], grid->points[i+1][j] ) ) {
  323. break;
  324. }
  325. }
  326. if ( j != grid->height ) {
  327. continue; // not degenerate
  328. }
  329. for ( j = 0 ; j < grid->height ; j++ ) {
  330. // remove the column
  331. for ( k = i + 2 ; k < grid->width ; k++ ) {
  332. VectorCopy( grid->points[k][j], grid->points[k-1][j] );
  333. }
  334. }
  335. grid->width--;
  336. // check against the next column
  337. i--;
  338. }
  339. }
  340. /*
  341. ================================================================================
  342. PATCH COLLIDE GENERATION
  343. ================================================================================
  344. */
  345. static int numPlanes;
  346. static patchPlane_t planes[MAX_PATCH_PLANES];
  347. static int numFacets;
  348. static facet_t facets[MAX_PATCH_PLANES]; //maybe MAX_FACETS ??
  349. #define NORMAL_EPSILON 0.0001
  350. #define DIST_EPSILON 0.02
  351. /*
  352. ==================
  353. CM_PlaneEqual
  354. ==================
  355. */
  356. int CM_PlaneEqual(patchPlane_t *p, float plane[4], int *flipped) {
  357. float invplane[4];
  358. if (
  359. fabs(p->plane[0] - plane[0]) < NORMAL_EPSILON
  360. && fabs(p->plane[1] - plane[1]) < NORMAL_EPSILON
  361. && fabs(p->plane[2] - plane[2]) < NORMAL_EPSILON
  362. && fabs(p->plane[3] - plane[3]) < DIST_EPSILON )
  363. {
  364. *flipped = qfalse;
  365. return qtrue;
  366. }
  367. VectorNegate(plane, invplane);
  368. invplane[3] = -plane[3];
  369. if (
  370. fabs(p->plane[0] - invplane[0]) < NORMAL_EPSILON
  371. && fabs(p->plane[1] - invplane[1]) < NORMAL_EPSILON
  372. && fabs(p->plane[2] - invplane[2]) < NORMAL_EPSILON
  373. && fabs(p->plane[3] - invplane[3]) < DIST_EPSILON )
  374. {
  375. *flipped = qtrue;
  376. return qtrue;
  377. }
  378. return qfalse;
  379. }
  380. /*
  381. ==================
  382. CM_SnapVector
  383. ==================
  384. */
  385. void CM_SnapVector(vec3_t normal) {
  386. int i;
  387. for (i=0 ; i<3 ; i++)
  388. {
  389. if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
  390. {
  391. VectorClear (normal);
  392. normal[i] = 1;
  393. break;
  394. }
  395. if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
  396. {
  397. VectorClear (normal);
  398. normal[i] = -1;
  399. break;
  400. }
  401. }
  402. }
  403. /*
  404. ==================
  405. CM_FindPlane2
  406. ==================
  407. */
  408. int CM_FindPlane2(float plane[4], int *flipped) {
  409. int i;
  410. // see if the points are close enough to an existing plane
  411. for ( i = 0 ; i < numPlanes ; i++ ) {
  412. if (CM_PlaneEqual(&planes[i], plane, flipped)) return i;
  413. }
  414. // add a new plane
  415. if ( numPlanes == MAX_PATCH_PLANES ) {
  416. Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
  417. }
  418. Vector4Copy( plane, planes[numPlanes].plane );
  419. planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
  420. numPlanes++;
  421. *flipped = qfalse;
  422. return numPlanes-1;
  423. }
  424. /*
  425. ==================
  426. CM_FindPlane
  427. ==================
  428. */
  429. static int CM_FindPlane( float *p1, float *p2, float *p3 ) {
  430. float plane[4];
  431. int i;
  432. float d;
  433. if ( !CM_PlaneFromPoints( plane, p1, p2, p3 ) ) {
  434. return -1;
  435. }
  436. // see if the points are close enough to an existing plane
  437. for ( i = 0 ; i < numPlanes ; i++ ) {
  438. if ( DotProduct( plane, planes[i].plane ) < 0 ) {
  439. continue; // allow backwards planes?
  440. }
  441. d = DotProduct( p1, planes[i].plane ) - planes[i].plane[3];
  442. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  443. continue;
  444. }
  445. d = DotProduct( p2, planes[i].plane ) - planes[i].plane[3];
  446. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  447. continue;
  448. }
  449. d = DotProduct( p3, planes[i].plane ) - planes[i].plane[3];
  450. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  451. continue;
  452. }
  453. // found it
  454. return i;
  455. }
  456. // add a new plane
  457. if ( numPlanes == MAX_PATCH_PLANES ) {
  458. Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
  459. }
  460. Vector4Copy( plane, planes[numPlanes].plane );
  461. planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
  462. numPlanes++;
  463. return numPlanes-1;
  464. }
  465. /*
  466. ==================
  467. CM_PointOnPlaneSide
  468. ==================
  469. */
  470. static int CM_PointOnPlaneSide( float *p, int planeNum ) {
  471. float *plane;
  472. float d;
  473. if ( planeNum == -1 ) {
  474. return SIDE_ON;
  475. }
  476. plane = planes[ planeNum ].plane;
  477. d = DotProduct( p, plane ) - plane[3];
  478. if ( d > PLANE_TRI_EPSILON ) {
  479. return SIDE_FRONT;
  480. }
  481. if ( d < -PLANE_TRI_EPSILON ) {
  482. return SIDE_BACK;
  483. }
  484. return SIDE_ON;
  485. }
  486. /*
  487. ==================
  488. CM_GridPlane
  489. ==================
  490. */
  491. static int CM_GridPlane( int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2], int i, int j, int tri ) {
  492. int p;
  493. p = gridPlanes[i][j][tri];
  494. if ( p != -1 ) {
  495. return p;
  496. }
  497. p = gridPlanes[i][j][!tri];
  498. if ( p != -1 ) {
  499. return p;
  500. }
  501. // should never happen
  502. Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
  503. return -1;
  504. }
  505. /*
  506. ==================
  507. CM_EdgePlaneNum
  508. ==================
  509. */
  510. static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2], int i, int j, int k ) {
  511. float *p1, *p2;
  512. vec3_t up;
  513. int p;
  514. switch ( k ) {
  515. case 0: // top border
  516. p1 = grid->points[i][j];
  517. p2 = grid->points[i+1][j];
  518. p = CM_GridPlane( gridPlanes, i, j, 0 );
  519. VectorMA( p1, 4, planes[ p ].plane, up );
  520. return CM_FindPlane( p1, p2, up );
  521. case 2: // bottom border
  522. p1 = grid->points[i][j+1];
  523. p2 = grid->points[i+1][j+1];
  524. p = CM_GridPlane( gridPlanes, i, j, 1 );
  525. VectorMA( p1, 4, planes[ p ].plane, up );
  526. return CM_FindPlane( p2, p1, up );
  527. case 3: // left border
  528. p1 = grid->points[i][j];
  529. p2 = grid->points[i][j+1];
  530. p = CM_GridPlane( gridPlanes, i, j, 1 );
  531. VectorMA( p1, 4, planes[ p ].plane, up );
  532. return CM_FindPlane( p2, p1, up );
  533. case 1: // right border
  534. p1 = grid->points[i+1][j];
  535. p2 = grid->points[i+1][j+1];
  536. p = CM_GridPlane( gridPlanes, i, j, 0 );
  537. VectorMA( p1, 4, planes[ p ].plane, up );
  538. return CM_FindPlane( p1, p2, up );
  539. case 4: // diagonal out of triangle 0
  540. p1 = grid->points[i+1][j+1];
  541. p2 = grid->points[i][j];
  542. p = CM_GridPlane( gridPlanes, i, j, 0 );
  543. VectorMA( p1, 4, planes[ p ].plane, up );
  544. return CM_FindPlane( p1, p2, up );
  545. case 5: // diagonal out of triangle 1
  546. p1 = grid->points[i][j];
  547. p2 = grid->points[i+1][j+1];
  548. p = CM_GridPlane( gridPlanes, i, j, 1 );
  549. VectorMA( p1, 4, planes[ p ].plane, up );
  550. return CM_FindPlane( p1, p2, up );
  551. }
  552. Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
  553. return -1;
  554. }
  555. /*
  556. ===================
  557. CM_SetBorderInward
  558. ===================
  559. */
  560. static void CM_SetBorderInward( facet_t *facet, cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2],
  561. int i, int j, int which ) {
  562. int k, l;
  563. float *points[4];
  564. int numPoints;
  565. switch ( which ) {
  566. case -1:
  567. points[0] = grid->points[i][j];
  568. points[1] = grid->points[i+1][j];
  569. points[2] = grid->points[i+1][j+1];
  570. points[3] = grid->points[i][j+1];
  571. numPoints = 4;
  572. break;
  573. case 0:
  574. points[0] = grid->points[i][j];
  575. points[1] = grid->points[i+1][j];
  576. points[2] = grid->points[i+1][j+1];
  577. numPoints = 3;
  578. break;
  579. case 1:
  580. points[0] = grid->points[i+1][j+1];
  581. points[1] = grid->points[i][j+1];
  582. points[2] = grid->points[i][j];
  583. numPoints = 3;
  584. break;
  585. default:
  586. Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
  587. numPoints = 0;
  588. break;
  589. }
  590. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  591. int front, back;
  592. front = 0;
  593. back = 0;
  594. for ( l = 0 ; l < numPoints ; l++ ) {
  595. int side;
  596. side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
  597. if ( side == SIDE_FRONT ) {
  598. front++;
  599. } if ( side == SIDE_BACK ) {
  600. back++;
  601. }
  602. }
  603. if ( front && !back ) {
  604. facet->borderInward[k] = qtrue;
  605. } else if ( back && !front ) {
  606. facet->borderInward[k] = qfalse;
  607. } else if ( !front && !back ) {
  608. // flat side border
  609. facet->borderPlanes[k] = -1;
  610. } else {
  611. // bisecting side border
  612. Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
  613. facet->borderInward[k] = qfalse;
  614. if ( !debugBlock ) {
  615. debugBlock = qtrue;
  616. VectorCopy( grid->points[i][j], debugBlockPoints[0] );
  617. VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
  618. VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
  619. VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
  620. }
  621. }
  622. }
  623. }
  624. /*
  625. ==================
  626. CM_ValidateFacet
  627. If the facet isn't bounded by its borders, we screwed up.
  628. ==================
  629. */
  630. static qboolean CM_ValidateFacet( facet_t *facet ) {
  631. float plane[4];
  632. int j;
  633. winding_t *w;
  634. vec3_t bounds[2];
  635. if ( facet->surfacePlane == -1 ) {
  636. return qfalse;
  637. }
  638. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  639. w = BaseWindingForPlane( plane, plane[3] );
  640. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  641. if ( facet->borderPlanes[j] == -1 ) {
  642. return qfalse;
  643. }
  644. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  645. if ( !facet->borderInward[j] ) {
  646. VectorSubtract( vec3_origin, plane, plane );
  647. plane[3] = -plane[3];
  648. }
  649. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  650. }
  651. if ( !w ) {
  652. return qfalse; // winding was completely chopped away
  653. }
  654. // see if the facet is unreasonably large
  655. WindingBounds( w, bounds[0], bounds[1] );
  656. FreeWinding( w );
  657. for ( j = 0 ; j < 3 ; j++ ) {
  658. if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
  659. return qfalse; // we must be missing a plane
  660. }
  661. if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
  662. return qfalse;
  663. }
  664. if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
  665. return qfalse;
  666. }
  667. }
  668. return qtrue; // winding is fine
  669. }
  670. /*
  671. ==================
  672. CM_AddFacetBevels
  673. ==================
  674. */
  675. void CM_AddFacetBevels( facet_t *facet ) {
  676. int i, j, k, l;
  677. int axis, dir, order, flipped;
  678. float plane[4], d, newplane[4];
  679. winding_t *w, *w2;
  680. vec3_t mins, maxs, vec, vec2;
  681. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  682. w = BaseWindingForPlane( plane, plane[3] );
  683. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  684. if (facet->borderPlanes[j] == facet->surfacePlane) continue;
  685. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  686. if ( !facet->borderInward[j] ) {
  687. VectorSubtract( vec3_origin, plane, plane );
  688. plane[3] = -plane[3];
  689. }
  690. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  691. }
  692. if ( !w ) {
  693. return;
  694. }
  695. WindingBounds(w, mins, maxs);
  696. // add the axial planes
  697. order = 0;
  698. for ( axis = 0 ; axis < 3 ; axis++ )
  699. {
  700. for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
  701. {
  702. VectorClear(plane);
  703. plane[axis] = dir;
  704. if (dir == 1) {
  705. plane[3] = maxs[axis];
  706. }
  707. else {
  708. plane[3] = -mins[axis];
  709. }
  710. //if it's the surface plane
  711. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  712. continue;
  713. }
  714. // see if the plane is allready present
  715. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  716. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
  717. break;
  718. }
  719. if ( i == facet->numBorders ) {
  720. if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
  721. facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
  722. facet->borderNoAdjust[facet->numBorders] = 0;
  723. facet->borderInward[facet->numBorders] = flipped;
  724. facet->numBorders++;
  725. }
  726. }
  727. }
  728. //
  729. // add the edge bevels
  730. //
  731. // test the non-axial plane edges
  732. for ( j = 0 ; j < w->numpoints ; j++ )
  733. {
  734. k = (j+1)%w->numpoints;
  735. VectorSubtract (w->p[j], w->p[k], vec);
  736. //if it's a degenerate edge
  737. if (VectorNormalize (vec) < 0.5)
  738. continue;
  739. CM_SnapVector(vec);
  740. for ( k = 0; k < 3 ; k++ )
  741. if ( vec[k] == -1 || vec[k] == 1 )
  742. break; // axial
  743. if ( k < 3 )
  744. continue; // only test non-axial edges
  745. // try the six possible slanted axials from this edge
  746. for ( axis = 0 ; axis < 3 ; axis++ )
  747. {
  748. for ( dir = -1 ; dir <= 1 ; dir += 2 )
  749. {
  750. // construct a plane
  751. VectorClear (vec2);
  752. vec2[axis] = dir;
  753. CrossProduct (vec, vec2, plane);
  754. if (VectorNormalize (plane) < 0.5)
  755. continue;
  756. plane[3] = DotProduct (w->p[j], plane);
  757. // if all the points of the facet winding are
  758. // behind this plane, it is a proper edge bevel
  759. for ( l = 0 ; l < w->numpoints ; l++ )
  760. {
  761. d = DotProduct (w->p[l], plane) - plane[3];
  762. if (d > 0.1)
  763. break; // point in front
  764. }
  765. if ( l < w->numpoints )
  766. continue;
  767. //if it's the surface plane
  768. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  769. continue;
  770. }
  771. // see if the plane is allready present
  772. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  773. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
  774. break;
  775. }
  776. }
  777. if ( i == facet->numBorders ) {
  778. if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
  779. facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
  780. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  781. if (facet->borderPlanes[facet->numBorders] ==
  782. facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
  783. }
  784. facet->borderNoAdjust[facet->numBorders] = 0;
  785. facet->borderInward[facet->numBorders] = flipped;
  786. //
  787. w2 = CopyWinding(w);
  788. Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
  789. if (!facet->borderInward[facet->numBorders])
  790. {
  791. VectorNegate(newplane, newplane);
  792. newplane[3] = -newplane[3];
  793. } //end if
  794. ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
  795. if (!w2) {
  796. Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
  797. continue;
  798. }
  799. else {
  800. FreeWinding(w2);
  801. }
  802. //
  803. facet->numBorders++;
  804. //already got a bevel
  805. // break;
  806. }
  807. }
  808. }
  809. }
  810. FreeWinding( w );
  811. #ifndef BSPC
  812. //add opposite plane
  813. facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
  814. facet->borderNoAdjust[facet->numBorders] = 0;
  815. facet->borderInward[facet->numBorders] = qtrue;
  816. facet->numBorders++;
  817. #endif //BSPC
  818. }
  819. typedef enum {
  820. EN_TOP,
  821. EN_RIGHT,
  822. EN_BOTTOM,
  823. EN_LEFT
  824. } edgeName_t;
  825. /*
  826. ==================
  827. CM_PatchCollideFromGrid
  828. ==================
  829. */
  830. static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf ) {
  831. int i, j;
  832. float *p1, *p2, *p3;
  833. MAC_STATIC int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2];
  834. facet_t *facet;
  835. int borders[4];
  836. int noAdjust[4];
  837. numPlanes = 0;
  838. numFacets = 0;
  839. // find the planes for each triangle of the grid
  840. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  841. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  842. p1 = grid->points[i][j];
  843. p2 = grid->points[i+1][j];
  844. p3 = grid->points[i+1][j+1];
  845. gridPlanes[i][j][0] = CM_FindPlane( p1, p2, p3 );
  846. p1 = grid->points[i+1][j+1];
  847. p2 = grid->points[i][j+1];
  848. p3 = grid->points[i][j];
  849. gridPlanes[i][j][1] = CM_FindPlane( p1, p2, p3 );
  850. }
  851. }
  852. // create the borders for each facet
  853. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  854. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  855. borders[EN_TOP] = -1;
  856. if ( j > 0 ) {
  857. borders[EN_TOP] = gridPlanes[i][j-1][1];
  858. } else if ( grid->wrapHeight ) {
  859. borders[EN_TOP] = gridPlanes[i][grid->height-2][1];
  860. }
  861. noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i][j][0] );
  862. if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
  863. borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
  864. }
  865. borders[EN_BOTTOM] = -1;
  866. if ( j < grid->height - 2 ) {
  867. borders[EN_BOTTOM] = gridPlanes[i][j+1][0];
  868. } else if ( grid->wrapHeight ) {
  869. borders[EN_BOTTOM] = gridPlanes[i][0][0];
  870. }
  871. noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i][j][1] );
  872. if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
  873. borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
  874. }
  875. borders[EN_LEFT] = -1;
  876. if ( i > 0 ) {
  877. borders[EN_LEFT] = gridPlanes[i-1][j][0];
  878. } else if ( grid->wrapWidth ) {
  879. borders[EN_LEFT] = gridPlanes[grid->width-2][j][0];
  880. }
  881. noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i][j][1] );
  882. if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
  883. borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
  884. }
  885. borders[EN_RIGHT] = -1;
  886. if ( i < grid->width - 2 ) {
  887. borders[EN_RIGHT] = gridPlanes[i+1][j][1];
  888. } else if ( grid->wrapWidth ) {
  889. borders[EN_RIGHT] = gridPlanes[0][j][1];
  890. }
  891. noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i][j][0] );
  892. if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
  893. borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
  894. }
  895. if ( numFacets == MAX_FACETS ) {
  896. Com_Error( ERR_DROP, "MAX_FACETS" );
  897. }
  898. facet = &facets[numFacets];
  899. Com_Memset( facet, 0, sizeof( *facet ) );
  900. if ( gridPlanes[i][j][0] == gridPlanes[i][j][1] ) {
  901. if ( gridPlanes[i][j][0] == -1 ) {
  902. continue; // degenrate
  903. }
  904. facet->surfacePlane = gridPlanes[i][j][0];
  905. facet->numBorders = 4;
  906. facet->borderPlanes[0] = borders[EN_TOP];
  907. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  908. facet->borderPlanes[1] = borders[EN_RIGHT];
  909. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  910. facet->borderPlanes[2] = borders[EN_BOTTOM];
  911. facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
  912. facet->borderPlanes[3] = borders[EN_LEFT];
  913. facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
  914. CM_SetBorderInward( facet, grid, gridPlanes, i, j, -1 );
  915. if ( CM_ValidateFacet( facet ) ) {
  916. CM_AddFacetBevels( facet );
  917. numFacets++;
  918. }
  919. } else {
  920. // two seperate triangles
  921. facet->surfacePlane = gridPlanes[i][j][0];
  922. facet->numBorders = 3;
  923. facet->borderPlanes[0] = borders[EN_TOP];
  924. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  925. facet->borderPlanes[1] = borders[EN_RIGHT];
  926. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  927. facet->borderPlanes[2] = gridPlanes[i][j][1];
  928. if ( facet->borderPlanes[2] == -1 ) {
  929. facet->borderPlanes[2] = borders[EN_BOTTOM];
  930. if ( facet->borderPlanes[2] == -1 ) {
  931. facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
  932. }
  933. }
  934. CM_SetBorderInward( facet, grid, gridPlanes, i, j, 0 );
  935. if ( CM_ValidateFacet( facet ) ) {
  936. CM_AddFacetBevels( facet );
  937. numFacets++;
  938. }
  939. if ( numFacets == MAX_FACETS ) {
  940. Com_Error( ERR_DROP, "MAX_FACETS" );
  941. }
  942. facet = &facets[numFacets];
  943. Com_Memset( facet, 0, sizeof( *facet ) );
  944. facet->surfacePlane = gridPlanes[i][j][1];
  945. facet->numBorders = 3;
  946. facet->borderPlanes[0] = borders[EN_BOTTOM];
  947. facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
  948. facet->borderPlanes[1] = borders[EN_LEFT];
  949. facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
  950. facet->borderPlanes[2] = gridPlanes[i][j][0];
  951. if ( facet->borderPlanes[2] == -1 ) {
  952. facet->borderPlanes[2] = borders[EN_TOP];
  953. if ( facet->borderPlanes[2] == -1 ) {
  954. facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
  955. }
  956. }
  957. CM_SetBorderInward( facet, grid, gridPlanes, i, j, 1 );
  958. if ( CM_ValidateFacet( facet ) ) {
  959. CM_AddFacetBevels( facet );
  960. numFacets++;
  961. }
  962. }
  963. }
  964. }
  965. // copy the results out
  966. pf->numPlanes = numPlanes;
  967. pf->numFacets = numFacets;
  968. pf->facets = Hunk_Alloc( numFacets * sizeof( *pf->facets ), h_high );
  969. Com_Memcpy( pf->facets, facets, numFacets * sizeof( *pf->facets ) );
  970. pf->planes = Hunk_Alloc( numPlanes * sizeof( *pf->planes ), h_high );
  971. Com_Memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
  972. }
  973. /*
  974. ===================
  975. CM_GeneratePatchCollide
  976. Creates an internal structure that will be used to perform
  977. collision detection with a patch mesh.
  978. Points is packed as concatenated rows.
  979. ===================
  980. */
  981. struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ) {
  982. patchCollide_t *pf;
  983. MAC_STATIC cGrid_t grid;
  984. int i, j;
  985. if ( width <= 2 || height <= 2 || !points ) {
  986. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
  987. width, height, points );
  988. }
  989. if ( !(width & 1) || !(height & 1) ) {
  990. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
  991. }
  992. if ( width > MAX_GRID_SIZE || height > MAX_GRID_SIZE ) {
  993. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > MAX_GRID_SIZE" );
  994. }
  995. // build a grid
  996. grid.width = width;
  997. grid.height = height;
  998. grid.wrapWidth = qfalse;
  999. grid.wrapHeight = qfalse;
  1000. for ( i = 0 ; i < width ; i++ ) {
  1001. for ( j = 0 ; j < height ; j++ ) {
  1002. VectorCopy( points[j*width + i], grid.points[i][j] );
  1003. }
  1004. }
  1005. // subdivide the grid
  1006. CM_SetGridWrapWidth( &grid );
  1007. CM_SubdivideGridColumns( &grid );
  1008. CM_RemoveDegenerateColumns( &grid );
  1009. CM_TransposeGrid( &grid );
  1010. CM_SetGridWrapWidth( &grid );
  1011. CM_SubdivideGridColumns( &grid );
  1012. CM_RemoveDegenerateColumns( &grid );
  1013. // we now have a grid of points exactly on the curve
  1014. // the aproximate surface defined by these points will be
  1015. // collided against
  1016. pf = Hunk_Alloc( sizeof( *pf ), h_high );
  1017. ClearBounds( pf->bounds[0], pf->bounds[1] );
  1018. for ( i = 0 ; i < grid.width ; i++ ) {
  1019. for ( j = 0 ; j < grid.height ; j++ ) {
  1020. AddPointToBounds( grid.points[i][j], pf->bounds[0], pf->bounds[1] );
  1021. }
  1022. }
  1023. c_totalPatchBlocks += ( grid.width - 1 ) * ( grid.height - 1 );
  1024. // generate a bsp tree for the surface
  1025. CM_PatchCollideFromGrid( &grid, pf );
  1026. // expand by one unit for epsilon purposes
  1027. pf->bounds[0][0] -= 1;
  1028. pf->bounds[0][1] -= 1;
  1029. pf->bounds[0][2] -= 1;
  1030. pf->bounds[1][0] += 1;
  1031. pf->bounds[1][1] += 1;
  1032. pf->bounds[1][2] += 1;
  1033. return pf;
  1034. }
  1035. /*
  1036. ================================================================================
  1037. TRACE TESTING
  1038. ================================================================================
  1039. */
  1040. /*
  1041. ====================
  1042. CM_TracePointThroughPatchCollide
  1043. special case for point traces because the patch collide "brushes" have no volume
  1044. ====================
  1045. */
  1046. void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  1047. qboolean frontFacing[MAX_PATCH_PLANES];
  1048. float intersection[MAX_PATCH_PLANES];
  1049. float intersect;
  1050. const patchPlane_t *planes;
  1051. const facet_t *facet;
  1052. int i, j, k;
  1053. float offset;
  1054. float d1, d2;
  1055. #ifndef BSPC
  1056. static cvar_t *cv;
  1057. #endif //BSPC
  1058. #ifndef BSPC
  1059. if ( !cm_playerCurveClip->integer || !tw->isPoint ) {
  1060. return;
  1061. }
  1062. #endif
  1063. // determine the trace's relationship to all planes
  1064. planes = pc->planes;
  1065. for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
  1066. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1067. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1068. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1069. if ( d1 <= 0 ) {
  1070. frontFacing[i] = qfalse;
  1071. } else {
  1072. frontFacing[i] = qtrue;
  1073. }
  1074. if ( d1 == d2 ) {
  1075. intersection[i] = 99999;
  1076. } else {
  1077. intersection[i] = d1 / ( d1 - d2 );
  1078. if ( intersection[i] <= 0 ) {
  1079. intersection[i] = 99999;
  1080. }
  1081. }
  1082. }
  1083. // see if any of the surface planes are intersected
  1084. facet = pc->facets;
  1085. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  1086. if ( !frontFacing[facet->surfacePlane] ) {
  1087. continue;
  1088. }
  1089. intersect = intersection[facet->surfacePlane];
  1090. if ( intersect < 0 ) {
  1091. continue; // surface is behind the starting point
  1092. }
  1093. if ( intersect > tw->trace.fraction ) {
  1094. continue; // already hit something closer
  1095. }
  1096. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  1097. k = facet->borderPlanes[j];
  1098. if ( frontFacing[k] ^ facet->borderInward[j] ) {
  1099. if ( intersection[k] > intersect ) {
  1100. break;
  1101. }
  1102. } else {
  1103. if ( intersection[k] < intersect ) {
  1104. break;
  1105. }
  1106. }
  1107. }
  1108. if ( j == facet->numBorders ) {
  1109. // we hit this facet
  1110. #ifndef BSPC
  1111. if (!cv) {
  1112. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  1113. }
  1114. if (cv->integer) {
  1115. debugPatchCollide = pc;
  1116. debugFacet = facet;
  1117. }
  1118. #endif //BSPC
  1119. planes = &pc->planes[facet->surfacePlane];
  1120. // calculate intersection with a slight pushoff
  1121. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1122. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1123. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1124. tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
  1125. if ( tw->trace.fraction < 0 ) {
  1126. tw->trace.fraction = 0;
  1127. }
  1128. VectorCopy( planes->plane, tw->trace.plane.normal );
  1129. tw->trace.plane.dist = planes->plane[3];
  1130. }
  1131. }
  1132. }
  1133. /*
  1134. ====================
  1135. CM_CheckFacetPlane
  1136. ====================
  1137. */
  1138. int CM_CheckFacetPlane(float *plane, vec3_t start, vec3_t end, float *enterFrac, float *leaveFrac, int *hit) {
  1139. float d1, d2, f;
  1140. *hit = qfalse;
  1141. d1 = DotProduct( start, plane ) - plane[3];
  1142. d2 = DotProduct( end, plane ) - plane[3];
  1143. // if completely in front of face, no intersection with the entire facet
  1144. if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
  1145. return qfalse;
  1146. }
  1147. // if it doesn't cross the plane, the plane isn't relevent
  1148. if (d1 <= 0 && d2 <= 0 ) {
  1149. return qtrue;
  1150. }
  1151. // crosses face
  1152. if (d1 > d2) { // enter
  1153. f = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
  1154. if ( f < 0 ) {
  1155. f = 0;
  1156. }
  1157. //always favor previous plane hits and thus also the surface plane hit
  1158. if (f > *enterFrac) {
  1159. *enterFrac = f;
  1160. *hit = qtrue;
  1161. }
  1162. } else { // leave
  1163. f = (d1+SURFACE_CLIP_EPSILON) / (d1-d2);
  1164. if ( f > 1 ) {
  1165. f = 1;
  1166. }
  1167. if (f < *leaveFrac) {
  1168. *leaveFrac = f;
  1169. }
  1170. }
  1171. return qtrue;
  1172. }
  1173. /*
  1174. ====================
  1175. CM_TraceThroughPatchCollide
  1176. ====================
  1177. */
  1178. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  1179. int i, j, hit, hitnum;
  1180. float offset, enterFrac, leaveFrac, t;
  1181. patchPlane_t *planes;
  1182. facet_t *facet;
  1183. float plane[4], bestplane[4];
  1184. vec3_t startp, endp;
  1185. #ifndef BSPC
  1186. static cvar_t *cv;
  1187. #endif //BSPC
  1188. if (tw->isPoint) {
  1189. CM_TracePointThroughPatchCollide( tw, pc );
  1190. return;
  1191. }
  1192. facet = pc->facets;
  1193. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  1194. enterFrac = -1.0;
  1195. leaveFrac = 1.0;
  1196. hitnum = -1;
  1197. //
  1198. planes = &pc->planes[ facet->surfacePlane ];
  1199. VectorCopy(planes->plane, plane);
  1200. plane[3] = planes->plane[3];
  1201. if ( tw->sphere.use ) {
  1202. // adjust the plane distance apropriately for radius
  1203. plane[3] += tw->sphere.radius;
  1204. // find the closest point on the capsule to the plane
  1205. t = DotProduct( plane, tw->sphere.offset );
  1206. if ( t > 0.0f ) {
  1207. VectorSubtract( tw->start, tw->sphere.offset, startp );
  1208. VectorSubtract( tw->end, tw->sphere.offset, endp );
  1209. }
  1210. else {
  1211. VectorAdd( tw->start, tw->sphere.offset, startp );
  1212. VectorAdd( tw->end, tw->sphere.offset, endp );
  1213. }
  1214. }
  1215. else {
  1216. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  1217. plane[3] -= offset;
  1218. VectorCopy( tw->start, startp );
  1219. VectorCopy( tw->end, endp );
  1220. }
  1221. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  1222. continue;
  1223. }
  1224. if (hit) {
  1225. Vector4Copy(plane, bestplane);
  1226. }
  1227. for ( j = 0; j < facet->numBorders; j++ ) {
  1228. planes = &pc->planes[ facet->borderPlanes[j] ];
  1229. if (facet->borderInward[j]) {
  1230. VectorNegate(planes->plane, plane);
  1231. plane[3] = -planes->plane[3];
  1232. }
  1233. else {
  1234. VectorCopy(planes->plane, plane);
  1235. plane[3] = planes->plane[3];
  1236. }
  1237. if ( tw->sphere.use ) {
  1238. // adjust the plane distance apropriately for radius
  1239. plane[3] += tw->sphere.radius;
  1240. // find the closest point on the capsule to the plane
  1241. t = DotProduct( plane, tw->sphere.offset );
  1242. if ( t > 0.0f ) {
  1243. VectorSubtract( tw->start, tw->sphere.offset, startp );
  1244. VectorSubtract( tw->end, tw->sphere.offset, endp );
  1245. }
  1246. else {
  1247. VectorAdd( tw->start, tw->sphere.offset, startp );
  1248. VectorAdd( tw->end, tw->sphere.offset, endp );
  1249. }
  1250. }
  1251. else {
  1252. // NOTE: this works even though the plane might be flipped because the bbox is centered
  1253. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  1254. plane[3] += fabs(offset);
  1255. VectorCopy( tw->start, startp );
  1256. VectorCopy( tw->end, endp );
  1257. }
  1258. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  1259. break;
  1260. }
  1261. if (hit) {
  1262. hitnum = j;
  1263. Vector4Copy(plane, bestplane);
  1264. }
  1265. }
  1266. if (j < facet->numBorders) continue;
  1267. //never clip against the back side
  1268. if (hitnum == facet->numBorders - 1) continue;
  1269. if (enterFrac < leaveFrac && enterFrac >= 0) {
  1270. if (enterFrac < tw->trace.fraction) {
  1271. if (enterFrac < 0) {
  1272. enterFrac = 0;
  1273. }
  1274. #ifndef BSPC
  1275. if (!cv) {
  1276. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  1277. }
  1278. if (cv && cv->integer) {
  1279. debugPatchCollide = pc;
  1280. debugFacet = facet;
  1281. }
  1282. #endif //BSPC
  1283. tw->trace.fraction = enterFrac;
  1284. VectorCopy( bestplane, tw->trace.plane.normal );
  1285. tw->trace.plane.dist = bestplane[3];
  1286. }
  1287. }
  1288. }
  1289. }
  1290. /*
  1291. =======================================================================
  1292. POSITION TEST
  1293. =======================================================================
  1294. */
  1295. /*
  1296. ====================
  1297. CM_PositionTestInPatchCollide
  1298. ====================
  1299. */
  1300. qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  1301. int i, j;
  1302. float offset, t;
  1303. patchPlane_t *planes;
  1304. facet_t *facet;
  1305. float plane[4];
  1306. vec3_t startp;
  1307. if (tw->isPoint) {
  1308. return qfalse;
  1309. }
  1310. //
  1311. facet = pc->facets;
  1312. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  1313. planes = &pc->planes[ facet->surfacePlane ];
  1314. VectorCopy(planes->plane, plane);
  1315. plane[3] = planes->plane[3];
  1316. if ( tw->sphere.use ) {
  1317. // adjust the plane distance apropriately for radius
  1318. plane[3] += tw->sphere.radius;
  1319. // find the closest point on the capsule to the plane
  1320. t = DotProduct( plane, tw->sphere.offset );
  1321. if ( t > 0 ) {
  1322. VectorSubtract( tw->start, tw->sphere.offset, startp );
  1323. }
  1324. else {
  1325. VectorAdd( tw->start, tw->sphere.offset, startp );
  1326. }
  1327. }
  1328. else {
  1329. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  1330. plane[3] -= offset;
  1331. VectorCopy( tw->start, startp );
  1332. }
  1333. if ( DotProduct( plane, startp ) - plane[3] > 0.0f ) {
  1334. continue;
  1335. }
  1336. for ( j = 0; j < facet->numBorders; j++ ) {
  1337. planes = &pc->planes[ facet->borderPlanes[j] ];
  1338. if (facet->borderInward[j]) {
  1339. VectorNegate(planes->plane, plane);
  1340. plane[3] = -planes->plane[3];
  1341. }
  1342. else {
  1343. VectorCopy(planes->plane, plane);
  1344. plane[3] = planes->plane[3];
  1345. }
  1346. if ( tw->sphere.use ) {
  1347. // adjust the plane distance apropriately for radius
  1348. plane[3] += tw->sphere.radius;
  1349. // find the closest point on the capsule to the plane
  1350. t = DotProduct( plane, tw->sphere.offset );
  1351. if ( t > 0.0f ) {
  1352. VectorSubtract( tw->start, tw->sphere.offset, startp );
  1353. }
  1354. else {
  1355. VectorAdd( tw->start, tw->sphere.offset, startp );
  1356. }
  1357. }
  1358. else {
  1359. // NOTE: this works even though the plane might be flipped because the bbox is centered
  1360. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  1361. plane[3] += fabs(offset);
  1362. VectorCopy( tw->start, startp );
  1363. }
  1364. if ( DotProduct( plane, startp ) - plane[3] > 0.0f ) {
  1365. break;
  1366. }
  1367. }
  1368. if (j < facet->numBorders) {
  1369. continue;
  1370. }
  1371. // inside this patch facet
  1372. return qtrue;
  1373. }
  1374. return qfalse;
  1375. }
  1376. /*
  1377. =======================================================================
  1378. DEBUGGING
  1379. =======================================================================
  1380. */
  1381. /*
  1382. ==================
  1383. CM_DrawDebugSurface
  1384. Called from the renderer
  1385. ==================
  1386. */
  1387. #ifndef BSPC
  1388. void BotDrawDebugPolygons(void (*drawPoly)(int color, int numPoints, float *points), int value);
  1389. #endif
  1390. void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ) {
  1391. static cvar_t *cv;
  1392. #ifndef BSPC
  1393. static cvar_t *cv2;
  1394. #endif
  1395. const patchCollide_t *pc;
  1396. facet_t *facet;
  1397. winding_t *w;
  1398. int i, j, k, n;
  1399. int curplanenum, planenum, curinward, inward;
  1400. float plane[4];
  1401. vec3_t mins = {-15, -15, -28}, maxs = {15, 15, 28};
  1402. //vec3_t mins = {0, 0, 0}, maxs = {0, 0, 0};
  1403. vec3_t v1, v2;
  1404. #ifndef BSPC
  1405. if ( !cv2 )
  1406. {
  1407. cv2 = Cvar_Get( "r_debugSurface", "0", 0 );
  1408. }
  1409. if (cv2->integer != 1)
  1410. {
  1411. BotDrawDebugPolygons(drawPoly, cv2->integer);
  1412. return;
  1413. }
  1414. #endif
  1415. if ( !debugPatchCollide ) {
  1416. return;
  1417. }
  1418. #ifndef BSPC
  1419. if ( !cv ) {
  1420. cv = Cvar_Get( "cm_debugSize", "2", 0 );
  1421. }
  1422. #endif
  1423. pc = debugPatchCollide;
  1424. for ( i = 0, facet = pc->facets ; i < pc->numFacets ; i++, facet++ ) {
  1425. for ( k = 0 ; k < facet->numBorders + 1; k++ ) {
  1426. //
  1427. if (k < facet->numBorders) {
  1428. planenum = facet->borderPlanes[k];
  1429. inward = facet->borderInward[k];
  1430. }
  1431. else {
  1432. planenum = facet->surfacePlane;
  1433. inward = qfalse;
  1434. //continue;
  1435. }
  1436. Vector4Copy( pc->planes[ planenum ].plane, plane );
  1437. //planenum = facet->surfacePlane;
  1438. if ( inward ) {
  1439. VectorSubtract( vec3_origin, plane, plane );
  1440. plane[3] = -plane[3];
  1441. }
  1442. plane[3] += cv->value;
  1443. //*
  1444. for (n = 0; n < 3; n++)
  1445. {
  1446. if (plane[n] > 0) v1[n] = maxs[n];
  1447. else v1[n] = mins[n];
  1448. } //end for
  1449. VectorNegate(plane, v2);
  1450. plane[3] += fabs(DotProduct(v1, v2));
  1451. //*/
  1452. w = BaseWindingForPlane( plane, plane[3] );
  1453. for ( j = 0 ; j < facet->numBorders + 1 && w; j++ ) {
  1454. //
  1455. if (j < facet->numBorders) {
  1456. curplanenum = facet->borderPlanes[j];
  1457. curinward = facet->borderInward[j];
  1458. }
  1459. else {
  1460. curplanenum = facet->surfacePlane;
  1461. curinward = qfalse;
  1462. //continue;
  1463. }
  1464. //
  1465. if (curplanenum == planenum) continue;
  1466. Vector4Copy( pc->planes[ curplanenum ].plane, plane );
  1467. if ( !curinward ) {
  1468. VectorSubtract( vec3_origin, plane, plane );
  1469. plane[3] = -plane[3];
  1470. }
  1471. // if ( !facet->borderNoAdjust[j] ) {
  1472. plane[3] -= cv->value;
  1473. // }
  1474. for (n = 0; n < 3; n++)
  1475. {
  1476. if (plane[n] > 0) v1[n] = maxs[n];
  1477. else v1[n] = mins[n];
  1478. } //end for
  1479. VectorNegate(plane, v2);
  1480. plane[3] -= fabs(DotProduct(v1, v2));
  1481. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  1482. }
  1483. if ( w ) {
  1484. if ( facet == debugFacet ) {
  1485. drawPoly( 4, w->numpoints, w->p[0] );
  1486. //Com_Printf("blue facet has %d border planes\n", facet->numBorders);
  1487. } else {
  1488. drawPoly( 1, w->numpoints, w->p[0] );
  1489. }
  1490. FreeWinding( w );
  1491. }
  1492. else
  1493. Com_Printf("winding chopped away by border planes\n");
  1494. }
  1495. }
  1496. // draw the debug block
  1497. {
  1498. vec3_t v[3];
  1499. VectorCopy( debugBlockPoints[0], v[0] );
  1500. VectorCopy( debugBlockPoints[1], v[1] );
  1501. VectorCopy( debugBlockPoints[2], v[2] );
  1502. drawPoly( 2, 3, v[0] );
  1503. VectorCopy( debugBlockPoints[2], v[0] );
  1504. VectorCopy( debugBlockPoints[3], v[1] );
  1505. VectorCopy( debugBlockPoints[0], v[2] );
  1506. drawPoly( 2, 3, v[0] );
  1507. }
  1508. #if 0
  1509. vec3_t v[4];
  1510. v[0][0] = pc->bounds[1][0];
  1511. v[0][1] = pc->bounds[1][1];
  1512. v[0][2] = pc->bounds[1][2];
  1513. v[1][0] = pc->bounds[1][0];
  1514. v[1][1] = pc->bounds[0][1];
  1515. v[1][2] = pc->bounds[1][2];
  1516. v[2][0] = pc->bounds[0][0];
  1517. v[2][1] = pc->bounds[0][1];
  1518. v[2][2] = pc->bounds[1][2];
  1519. v[3][0] = pc->bounds[0][0];
  1520. v[3][1] = pc->bounds[1][1];
  1521. v[3][2] = pc->bounds[1][2];
  1522. drawPoly( 4, v[0] );
  1523. #endif
  1524. }