cm_patch.cpp 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931
  1. #include "cm_local.h"
  2. #include "cm_patch.h"
  3. //#define CULL_BBOX
  4. /*
  5. This file does not reference any globals, and has these entry points:
  6. void CM_ClearLevelPatches( void );
  7. struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points );
  8. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
  9. qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
  10. void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) );
  11. Issues for collision against curved surfaces:
  12. Surface edges need to be handled differently than surface planes
  13. Plane expansion causes raw surfaces to expand past expanded bounding box
  14. Position test of a volume against a surface is tricky.
  15. Position test of a point against a surface is not well defined, because the surface has no volume.
  16. Tracing leading edge points instead of volumes?
  17. Position test by tracing corner to corner? (8*7 traces -- ouch)
  18. coplanar edges
  19. triangulated patches
  20. degenerate patches
  21. endcaps
  22. degenerate
  23. WARNING: this may misbehave with meshes that have rows or columns that only
  24. degenerate a few triangles. Completely degenerate rows and columns are handled
  25. properly.
  26. */
  27. /*
  28. #define MAX_FACETS 1024
  29. #define MAX_PATCH_PLANES 2048
  30. typedef struct {
  31. float plane[4];
  32. int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision
  33. } patchPlane_t;
  34. typedef struct {
  35. int surfacePlane;
  36. int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels
  37. int borderPlanes[4+6+16];
  38. int borderInward[4+6+16];
  39. qboolean borderNoAdjust[4+6+16];
  40. } facet_t;
  41. typedef struct patchCollide_s {
  42. vec3_t bounds[2];
  43. int numPlanes; // surface planes plus edge planes
  44. patchPlane_t *planes;
  45. int numFacets;
  46. facet_t *facets;
  47. } patchCollide_t;
  48. #define MAX_GRID_SIZE 129
  49. typedef struct {
  50. int width;
  51. int height;
  52. qboolean wrapWidth;
  53. qboolean wrapHeight;
  54. vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height]
  55. } cGrid_t;
  56. #define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve
  57. #define PLANE_TRI_EPSILON 0.1
  58. #define WRAP_POINT_EPSILON 0.1
  59. */
  60. #define ADDBEVELS
  61. int c_totalPatchBlocks;
  62. int c_totalPatchSurfaces;
  63. int c_totalPatchEdges;
  64. static const patchCollide_t *debugPatchCollide;
  65. static const facet_t *debugFacet;
  66. static qboolean debugBlock;
  67. static vec3_t debugBlockPoints[4];
  68. /*
  69. =================
  70. CM_ClearLevelPatches
  71. =================
  72. */
  73. void CM_ClearLevelPatches( void ) {
  74. debugPatchCollide = NULL;
  75. debugFacet = NULL;
  76. }
  77. /*
  78. =================
  79. CM_SignbitsForNormal
  80. =================
  81. */
  82. static int CM_SignbitsForNormal( vec3_t normal ) {
  83. int bits, j;
  84. bits = 0;
  85. for (j=0 ; j<3 ; j++) {
  86. if ( normal[j] < 0 ) {
  87. bits |= 1<<j;
  88. }
  89. }
  90. return bits;
  91. }
  92. /*
  93. =====================
  94. CM_PlaneFromPoints
  95. Returns false if the triangle is degenrate.
  96. The normal will point out of the clock for clockwise ordered points
  97. =====================
  98. */
  99. static qboolean CM_PlaneFromPoints( vec4_t plane, vec3_t a, vec3_t b, vec3_t c ) {
  100. vec3_t d1, d2;
  101. VectorSubtract( b, a, d1 );
  102. VectorSubtract( c, a, d2 );
  103. CrossProduct( d2, d1, plane );
  104. if ( VectorNormalize( plane ) == 0 ) {
  105. return qfalse;
  106. }
  107. plane[3] = DotProduct( a, plane );
  108. return qtrue;
  109. }
  110. /*
  111. ================================================================================
  112. GRID SUBDIVISION
  113. ================================================================================
  114. */
  115. /*
  116. =================
  117. CM_NeedsSubdivision
  118. Returns true if the given quadratic curve is not flat enough for our
  119. collision detection purposes
  120. =================
  121. */
  122. static qboolean CM_NeedsSubdivision( vec3_t a, vec3_t b, vec3_t c ) {
  123. vec3_t cmid;
  124. vec3_t lmid;
  125. vec3_t delta;
  126. float dist;
  127. int i;
  128. // calculate the linear midpoint
  129. for ( i = 0 ; i < 3 ; i++ ) {
  130. lmid[i] = 0.5*(a[i] + c[i]);
  131. }
  132. // calculate the exact curve midpoint
  133. for ( i = 0 ; i < 3 ; i++ ) {
  134. cmid[i] = 0.5 * ( 0.5*(a[i] + b[i]) + 0.5*(b[i] + c[i]) );
  135. }
  136. // see if the curve is far enough away from the linear mid
  137. VectorSubtract( cmid, lmid, delta );
  138. dist = VectorLengthSquared( delta );
  139. return dist >= SUBDIVIDE_DISTANCE * SUBDIVIDE_DISTANCE;
  140. }
  141. /*
  142. ===============
  143. CM_Subdivide
  144. a, b, and c are control points.
  145. the subdivided sequence will be: a, out1, out2, out3, c
  146. ===============
  147. */
  148. static void CM_Subdivide( vec3_t a, vec3_t b, vec3_t c, vec3_t out1, vec3_t out2, vec3_t out3 ) {
  149. int i;
  150. for ( i = 0 ; i < 3 ; i++ ) {
  151. out1[i] = 0.5 * (a[i] + b[i]);
  152. out3[i] = 0.5 * (b[i] + c[i]);
  153. out2[i] = 0.5 * (out1[i] + out3[i]);
  154. }
  155. }
  156. /*
  157. =================
  158. CM_TransposeGrid
  159. Swaps the rows and columns in place
  160. =================
  161. */
  162. static void CM_TransposeGrid( cGrid_t *grid ) {
  163. int i, j, l;
  164. vec3_t temp;
  165. qboolean tempWrap;
  166. if ( grid->width > grid->height ) {
  167. for ( i = 0 ; i < grid->height ; i++ ) {
  168. for ( j = i + 1 ; j < grid->width ; j++ ) {
  169. if ( j < grid->height ) {
  170. // swap the value
  171. VectorCopy( grid->points[i][j], temp );
  172. VectorCopy( grid->points[j][i], grid->points[i][j] );
  173. VectorCopy( temp, grid->points[j][i] );
  174. } else {
  175. // just copy
  176. VectorCopy( grid->points[j][i], grid->points[i][j] );
  177. }
  178. }
  179. }
  180. } else {
  181. for ( i = 0 ; i < grid->width ; i++ ) {
  182. for ( j = i + 1 ; j < grid->height ; j++ ) {
  183. if ( j < grid->width ) {
  184. // swap the value
  185. VectorCopy( grid->points[j][i], temp );
  186. VectorCopy( grid->points[i][j], grid->points[j][i] );
  187. VectorCopy( temp, grid->points[i][j] );
  188. } else {
  189. // just copy
  190. VectorCopy( grid->points[i][j], grid->points[j][i] );
  191. }
  192. }
  193. }
  194. }
  195. l = grid->width;
  196. grid->width = grid->height;
  197. grid->height = l;
  198. tempWrap = grid->wrapWidth;
  199. grid->wrapWidth = grid->wrapHeight;
  200. grid->wrapHeight = tempWrap;
  201. }
  202. /*
  203. ===================
  204. CM_SetGridWrapWidth
  205. If the left and right columns are exactly equal, set grid->wrapWidth qtrue
  206. ===================
  207. */
  208. static void CM_SetGridWrapWidth( cGrid_t *grid ) {
  209. int i, j;
  210. float d;
  211. for ( i = 0 ; i < grid->height ; i++ ) {
  212. for ( j = 0 ; j < 3 ; j++ ) {
  213. d = grid->points[0][i][j] - grid->points[grid->width-1][i][j];
  214. if ( d < -WRAP_POINT_EPSILON || d > WRAP_POINT_EPSILON ) {
  215. break;
  216. }
  217. }
  218. if ( j != 3 ) {
  219. break;
  220. }
  221. }
  222. if ( i == grid->height ) {
  223. grid->wrapWidth = qtrue;
  224. } else {
  225. grid->wrapWidth = qfalse;
  226. }
  227. }
  228. /*
  229. =================
  230. CM_SubdivideGridColumns
  231. Adds columns as necessary to the grid until
  232. all the aproximating points are within SUBDIVIDE_DISTANCE
  233. from the true curve
  234. =================
  235. */
  236. static void CM_SubdivideGridColumns( cGrid_t *grid ) {
  237. int i, j, k;
  238. for ( i = 0 ; i < grid->width - 2 ; ) {
  239. // grid->points[i][x] is an interpolating control point
  240. // grid->points[i+1][x] is an aproximating control point
  241. // grid->points[i+2][x] is an interpolating control point
  242. //
  243. // first see if we can collapse the aproximating collumn away
  244. //
  245. for ( j = 0 ; j < grid->height ; j++ ) {
  246. if ( CM_NeedsSubdivision( grid->points[i][j], grid->points[i+1][j], grid->points[i+2][j] ) ) {
  247. break;
  248. }
  249. }
  250. if ( j == grid->height ) {
  251. // all of the points were close enough to the linear midpoints
  252. // that we can collapse the entire column away
  253. for ( j = 0 ; j < grid->height ; j++ ) {
  254. // remove the column
  255. for ( k = i + 2 ; k < grid->width ; k++ ) {
  256. VectorCopy( grid->points[k][j], grid->points[k-1][j] );
  257. }
  258. }
  259. grid->width--;
  260. // go to the next curve segment
  261. i++;
  262. continue;
  263. }
  264. //
  265. // we need to subdivide the curve
  266. //
  267. for ( j = 0 ; j < grid->height ; j++ ) {
  268. vec3_t prev, mid, next;
  269. // save the control points now
  270. VectorCopy( grid->points[i][j], prev );
  271. VectorCopy( grid->points[i+1][j], mid );
  272. VectorCopy( grid->points[i+2][j], next );
  273. // make room for two additional columns in the grid
  274. // columns i+1 will be replaced, column i+2 will become i+4
  275. // i+1, i+2, and i+3 will be generated
  276. for ( k = grid->width - 1 ; k > i + 1 ; k-- ) {
  277. VectorCopy( grid->points[k][j], grid->points[k+2][j] );
  278. }
  279. // generate the subdivided points
  280. CM_Subdivide( prev, mid, next, grid->points[i+1][j], grid->points[i+2][j], grid->points[i+3][j] );
  281. }
  282. grid->width += 2;
  283. // the new aproximating point at i+1 may need to be removed
  284. // or subdivided farther, so don't advance i
  285. }
  286. }
  287. #define POINT_EPSILON 0.1
  288. /*
  289. ======================
  290. CM_ComparePoints
  291. ======================
  292. */
  293. static qboolean CM_ComparePoints( float *a, float *b ) {
  294. float d;
  295. d = a[0] - b[0];
  296. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  297. return qfalse;
  298. }
  299. d = a[1] - b[1];
  300. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  301. return qfalse;
  302. }
  303. d = a[2] - b[2];
  304. if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
  305. return qfalse;
  306. }
  307. return qtrue;
  308. }
  309. /*
  310. =================
  311. CM_RemoveDegenerateColumns
  312. If there are any identical columns, remove them
  313. =================
  314. */
  315. static void CM_RemoveDegenerateColumns( cGrid_t *grid ) {
  316. int i, j, k;
  317. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  318. for ( j = 0 ; j < grid->height ; j++ ) {
  319. if ( !CM_ComparePoints( grid->points[i][j], grid->points[i+1][j] ) ) {
  320. break;
  321. }
  322. }
  323. if ( j != grid->height ) {
  324. continue; // not degenerate
  325. }
  326. for ( j = 0 ; j < grid->height ; j++ ) {
  327. // remove the column
  328. for ( k = i + 2 ; k < grid->width ; k++ ) {
  329. VectorCopy( grid->points[k][j], grid->points[k-1][j] );
  330. }
  331. }
  332. grid->width--;
  333. // check against the next column
  334. i--;
  335. }
  336. }
  337. /*
  338. ================================================================================
  339. PATCH COLLIDE GENERATION
  340. ================================================================================
  341. */
  342. static int numPlanes;
  343. #ifdef _XBOX
  344. static patchPlane_t *planes = NULL;
  345. void CM_TempPatchPlanesAlloc(void)
  346. {
  347. if(!planes) {
  348. planes = (patchPlane_t*)Z_Malloc(MAX_PATCH_PLANES*sizeof(patchPlane_t),
  349. TAG_TEMP_WORKSPACE, qfalse);
  350. }
  351. }
  352. void CM_TempPatchPlanesDealloc(void)
  353. {
  354. if(planes) {
  355. Z_Free(planes);
  356. planes = NULL;
  357. }
  358. }
  359. #else
  360. static patchPlane_t planes[MAX_PATCH_PLANES];
  361. #endif
  362. //static int numFacets;
  363. // static facet_t facets[MAX_PATCH_PLANES]; //maybe MAX_FACETS ??
  364. //static facet_t facets[MAX_FACETS]; // Switched to MAX_FACETS = VV_FIXME, allocate these only during use
  365. static facet_t *facets = NULL;
  366. #define NORMAL_EPSILON 0.0001
  367. #define DIST_EPSILON 0.02
  368. int CM_PlaneEqual(patchPlane_t *p, float plane[4], int *flipped) {
  369. float invplane[4];
  370. if (
  371. Q_fabs(p->plane[0] - plane[0]) < NORMAL_EPSILON
  372. && Q_fabs(p->plane[1] - plane[1]) < NORMAL_EPSILON
  373. && Q_fabs(p->plane[2] - plane[2]) < NORMAL_EPSILON
  374. && Q_fabs(p->plane[3] - plane[3]) < DIST_EPSILON )
  375. {
  376. *flipped = qfalse;
  377. return qtrue;
  378. }
  379. VectorNegate(plane, invplane);
  380. invplane[3] = -plane[3];
  381. if (
  382. Q_fabs(p->plane[0] - invplane[0]) < NORMAL_EPSILON
  383. && Q_fabs(p->plane[1] - invplane[1]) < NORMAL_EPSILON
  384. && Q_fabs(p->plane[2] - invplane[2]) < NORMAL_EPSILON
  385. && Q_fabs(p->plane[3] - invplane[3]) < DIST_EPSILON )
  386. {
  387. *flipped = qtrue;
  388. return qtrue;
  389. }
  390. return qfalse;
  391. }
  392. void CM_SnapVector(vec3_t normal) {
  393. int i;
  394. for (i=0 ; i<3 ; i++)
  395. {
  396. if ( Q_fabs(normal[i] - 1) < NORMAL_EPSILON )
  397. {
  398. VectorClear (normal);
  399. normal[i] = 1;
  400. break;
  401. }
  402. if ( Q_fabs(normal[i] - -1) < NORMAL_EPSILON )
  403. {
  404. VectorClear (normal);
  405. normal[i] = -1;
  406. break;
  407. }
  408. }
  409. }
  410. int CM_FindPlane2(float plane[4], int *flipped) {
  411. int i;
  412. // see if the points are close enough to an existing plane
  413. for ( i = 0 ; i < numPlanes ; i++ ) {
  414. if (CM_PlaneEqual(&planes[i], plane, flipped)) return i;
  415. }
  416. // add a new plane
  417. if ( numPlanes == MAX_PATCH_PLANES ) {
  418. Com_Error( ERR_DROP, "MAX_PATCH_PLANES reached (%d)", MAX_PATCH_PLANES );
  419. }
  420. Vector4Copy( plane, planes[numPlanes].plane );
  421. planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
  422. numPlanes++;
  423. *flipped = qfalse;
  424. return numPlanes-1;
  425. }
  426. /*
  427. ==================
  428. CM_FindPlane
  429. ==================
  430. */
  431. static int CM_FindPlane( float *p1, float *p2, float *p3 ) {
  432. float plane[4];
  433. int i;
  434. float d;
  435. if ( !CM_PlaneFromPoints( plane, p1, p2, p3 ) ) {
  436. return -1;
  437. }
  438. // see if the points are close enough to an existing plane
  439. for ( i = 0 ; i < numPlanes ; i++ ) {
  440. if ( DotProduct( plane, planes[i].plane ) < 0 ) {
  441. continue; // allow backwards planes?
  442. }
  443. d = DotProduct( p1, planes[i].plane ) - planes[i].plane[3];
  444. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  445. continue;
  446. }
  447. d = DotProduct( p2, planes[i].plane ) - planes[i].plane[3];
  448. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  449. continue;
  450. }
  451. d = DotProduct( p3, planes[i].plane ) - planes[i].plane[3];
  452. if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
  453. continue;
  454. }
  455. // found it
  456. return i;
  457. }
  458. // add a new plane
  459. if ( numPlanes == MAX_PATCH_PLANES ) {
  460. Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
  461. }
  462. Vector4Copy( plane, planes[numPlanes].plane );
  463. planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
  464. numPlanes++;
  465. return numPlanes-1;
  466. }
  467. /*
  468. ==================
  469. CM_PointOnPlaneSide
  470. ==================
  471. */
  472. static int CM_PointOnPlaneSide( float *p, int planeNum ) {
  473. float *plane;
  474. float d;
  475. if ( planeNum == -1 ) {
  476. return SIDE_ON;
  477. }
  478. plane = planes[ planeNum ].plane;
  479. d = DotProduct( p, plane ) - plane[3];
  480. if ( d > PLANE_TRI_EPSILON ) {
  481. return SIDE_FRONT;
  482. }
  483. if ( d < -PLANE_TRI_EPSILON ) {
  484. return SIDE_BACK;
  485. }
  486. return SIDE_ON;
  487. }
  488. #ifdef _XBOX
  489. static int CM_GridPlane( int* gridPlanes, int i, int j, int tri ) {
  490. int p;
  491. p = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+tri];
  492. if ( p != -1 ) {
  493. return p;
  494. }
  495. p = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+(!tri)];
  496. if ( p != -1 ) {
  497. return p;
  498. }
  499. // should never happen
  500. Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
  501. return -1;
  502. }
  503. #else // _XBOX
  504. static int CM_GridPlane( int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2], int i, int j, int tri ) {
  505. int p;
  506. p = gridPlanes[i][j][tri];
  507. if ( p != -1 ) {
  508. return p;
  509. }
  510. p = gridPlanes[i][j][!tri];
  511. if ( p != -1 ) {
  512. return p;
  513. }
  514. // should never happen
  515. Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
  516. return -1;
  517. }
  518. #endif // _XBOX
  519. /*
  520. ==================
  521. CM_EdgePlaneNum
  522. ==================
  523. */
  524. #ifdef _XBOX
  525. static int CM_EdgePlaneNum( cGrid_t *grid, int* gridPlanes/*[PATCH_MAX_GRID_SIZE][PATCH_MAX_GRID_SIZE][2]*/, int i, int j, int k ) {
  526. float *p1, *p2;
  527. vec3_t up;
  528. int p;
  529. switch ( k ) {
  530. case 0: // top border
  531. p1 = grid->points[i][j];
  532. p2 = grid->points[i+1][j];
  533. p = CM_GridPlane( gridPlanes, i, j, 0 );
  534. VectorMA( p1, 4, planes[ p ].plane, up );
  535. return CM_FindPlane( p1, p2, up );
  536. case 2: // bottom border
  537. p1 = grid->points[i][j+1];
  538. p2 = grid->points[i+1][j+1];
  539. p = CM_GridPlane( gridPlanes, i, j, 1 );
  540. VectorMA( p1, 4, planes[ p ].plane, up );
  541. return CM_FindPlane( p2, p1, up );
  542. case 3: // left border
  543. p1 = grid->points[i][j];
  544. p2 = grid->points[i][j+1];
  545. p = CM_GridPlane( gridPlanes, i, j, 1 );
  546. VectorMA( p1, 4, planes[ p ].plane, up );
  547. return CM_FindPlane( p2, p1, up );
  548. case 1: // right border
  549. p1 = grid->points[i+1][j];
  550. p2 = grid->points[i+1][j+1];
  551. p = CM_GridPlane( gridPlanes, i, j, 0 );
  552. VectorMA( p1, 4, planes[ p ].plane, up );
  553. return CM_FindPlane( p1, p2, up );
  554. case 4: // diagonal out of triangle 0
  555. p1 = grid->points[i+1][j+1];
  556. p2 = grid->points[i][j];
  557. p = CM_GridPlane( gridPlanes, i, j, 0 );
  558. VectorMA( p1, 4, planes[ p ].plane, up );
  559. return CM_FindPlane( p1, p2, up );
  560. case 5: // diagonal out of triangle 1
  561. p1 = grid->points[i][j];
  562. p2 = grid->points[i+1][j+1];
  563. p = CM_GridPlane( gridPlanes, i, j, 1 );
  564. VectorMA( p1, 4, planes[ p ].plane, up );
  565. return CM_FindPlane( p1, p2, up );
  566. }
  567. Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
  568. return -1;
  569. }
  570. #else
  571. static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2], int i, int j, int k ) {
  572. float *p1, *p2;
  573. vec3_t up;
  574. int p;
  575. switch ( k ) {
  576. case 0: // top border
  577. p1 = grid->points[i][j];
  578. p2 = grid->points[i+1][j];
  579. p = CM_GridPlane( gridPlanes, i, j, 0 );
  580. VectorMA( p1, 4, planes[ p ].plane, up );
  581. return CM_FindPlane( p1, p2, up );
  582. case 2: // bottom border
  583. p1 = grid->points[i][j+1];
  584. p2 = grid->points[i+1][j+1];
  585. p = CM_GridPlane( gridPlanes, i, j, 1 );
  586. VectorMA( p1, 4, planes[ p ].plane, up );
  587. return CM_FindPlane( p2, p1, up );
  588. case 3: // left border
  589. p1 = grid->points[i][j];
  590. p2 = grid->points[i][j+1];
  591. p = CM_GridPlane( gridPlanes, i, j, 1 );
  592. VectorMA( p1, 4, planes[ p ].plane, up );
  593. return CM_FindPlane( p2, p1, up );
  594. case 1: // right border
  595. p1 = grid->points[i+1][j];
  596. p2 = grid->points[i+1][j+1];
  597. p = CM_GridPlane( gridPlanes, i, j, 0 );
  598. VectorMA( p1, 4, planes[ p ].plane, up );
  599. return CM_FindPlane( p1, p2, up );
  600. case 4: // diagonal out of triangle 0
  601. p1 = grid->points[i+1][j+1];
  602. p2 = grid->points[i][j];
  603. p = CM_GridPlane( gridPlanes, i, j, 0 );
  604. VectorMA( p1, 4, planes[ p ].plane, up );
  605. return CM_FindPlane( p1, p2, up );
  606. case 5: // diagonal out of triangle 1
  607. p1 = grid->points[i][j];
  608. p2 = grid->points[i+1][j+1];
  609. p = CM_GridPlane( gridPlanes, i, j, 1 );
  610. VectorMA( p1, 4, planes[ p ].plane, up );
  611. return CM_FindPlane( p1, p2, up );
  612. }
  613. Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
  614. return -1;
  615. }
  616. #endif
  617. /*
  618. ===================
  619. CM_SetBorderInward
  620. ===================
  621. */
  622. #ifdef _XBOX
  623. static void CM_SetBorderInward( facetLoad_t *facet, cGrid_t *grid,
  624. int i, int j, int which ) {
  625. int k, l;
  626. float *points[4];
  627. int numPoints;
  628. switch ( which ) {
  629. case -1:
  630. points[0] = grid->points[i][j];
  631. points[1] = grid->points[i+1][j];
  632. points[2] = grid->points[i+1][j+1];
  633. points[3] = grid->points[i][j+1];
  634. numPoints = 4;
  635. break;
  636. case 0:
  637. points[0] = grid->points[i][j];
  638. points[1] = grid->points[i+1][j];
  639. points[2] = grid->points[i+1][j+1];
  640. numPoints = 3;
  641. break;
  642. case 1:
  643. points[0] = grid->points[i+1][j+1];
  644. points[1] = grid->points[i][j+1];
  645. points[2] = grid->points[i][j];
  646. numPoints = 3;
  647. break;
  648. default:
  649. Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
  650. numPoints = 0;
  651. break;
  652. }
  653. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  654. int front, back;
  655. front = 0;
  656. back = 0;
  657. for ( l = 0 ; l < numPoints ; l++ ) {
  658. int side;
  659. side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
  660. if ( side == SIDE_FRONT ) {
  661. front++;
  662. } if ( side == SIDE_BACK ) {
  663. back++;
  664. }
  665. }
  666. if ( front && !back ) {
  667. facet->borderInward[k] = qtrue;
  668. } else if ( back && !front ) {
  669. facet->borderInward[k] = qfalse;
  670. } else if ( !front && !back ) {
  671. // flat side border
  672. facet->borderPlanes[k] = -1;
  673. } else {
  674. // bisecting side border
  675. Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
  676. facet->borderInward[k] = qfalse;
  677. if ( !debugBlock ) {
  678. debugBlock = qtrue;
  679. VectorCopy( grid->points[i][j], debugBlockPoints[0] );
  680. VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
  681. VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
  682. VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
  683. }
  684. }
  685. }
  686. }
  687. #else // _XBOX
  688. static void CM_SetBorderInward( facet_t *facet, cGrid_t *grid, int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2],
  689. int i, int j, int which ) {
  690. int k, l;
  691. float *points[4];
  692. int numPoints;
  693. switch ( which ) {
  694. case -1:
  695. points[0] = grid->points[i][j];
  696. points[1] = grid->points[i+1][j];
  697. points[2] = grid->points[i+1][j+1];
  698. points[3] = grid->points[i][j+1];
  699. numPoints = 4;
  700. break;
  701. case 0:
  702. points[0] = grid->points[i][j];
  703. points[1] = grid->points[i+1][j];
  704. points[2] = grid->points[i+1][j+1];
  705. numPoints = 3;
  706. break;
  707. case 1:
  708. points[0] = grid->points[i+1][j+1];
  709. points[1] = grid->points[i][j+1];
  710. points[2] = grid->points[i][j];
  711. numPoints = 3;
  712. break;
  713. default:
  714. Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
  715. numPoints = 0;
  716. break;
  717. }
  718. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  719. int front, back;
  720. front = 0;
  721. back = 0;
  722. for ( l = 0 ; l < numPoints ; l++ ) {
  723. int side;
  724. side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
  725. if ( side == SIDE_FRONT ) {
  726. front++;
  727. } if ( side == SIDE_BACK ) {
  728. back++;
  729. }
  730. }
  731. if ( front && !back ) {
  732. facet->borderInward[k] = qtrue;
  733. } else if ( back && !front ) {
  734. facet->borderInward[k] = qfalse;
  735. } else if ( !front && !back ) {
  736. // flat side border
  737. facet->borderPlanes[k] = -1;
  738. } else {
  739. // bisecting side border
  740. Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
  741. facet->borderInward[k] = qfalse;
  742. if ( !debugBlock ) {
  743. debugBlock = qtrue;
  744. VectorCopy( grid->points[i][j], debugBlockPoints[0] );
  745. VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
  746. VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
  747. VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
  748. }
  749. }
  750. }
  751. }
  752. #endif
  753. /*
  754. ==================
  755. CM_ValidateFacet
  756. If the facet isn't bounded by its borders, we screwed up.
  757. ==================
  758. */
  759. #ifdef _XBOX
  760. static qboolean CM_ValidateFacet( facetLoad_t *facet ) {
  761. float plane[4];
  762. int j;
  763. winding_t *w;
  764. vec3_t bounds[2];
  765. if ( facet->surfacePlane == -1 ) {
  766. return qfalse;
  767. }
  768. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  769. w = BaseWindingForPlane( plane, plane[3] );
  770. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  771. if ( facet->borderPlanes[j] == -1 ) {
  772. FreeWinding(w);
  773. return qfalse;
  774. }
  775. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  776. if ( !facet->borderInward[j] ) {
  777. VectorSubtract( vec3_origin, plane, plane );
  778. plane[3] = -plane[3];
  779. }
  780. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  781. }
  782. if ( !w ) {
  783. return qfalse; // winding was completely chopped away
  784. }
  785. // see if the facet is unreasonably large
  786. WindingBounds( w, bounds[0], bounds[1] );
  787. FreeWinding( w );
  788. for ( j = 0 ; j < 3 ; j++ ) {
  789. if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
  790. return qfalse; // we must be missing a plane
  791. }
  792. if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
  793. return qfalse;
  794. }
  795. if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
  796. return qfalse;
  797. }
  798. }
  799. return qtrue; // winding is fine
  800. }
  801. #else // _XBOX
  802. static qboolean CM_ValidateFacet( facet_t *facet ) {
  803. float plane[4];
  804. int j;
  805. winding_t *w;
  806. vec3_t bounds[2];
  807. if ( facet->surfacePlane == -1 ) {
  808. return qfalse;
  809. }
  810. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  811. w = BaseWindingForPlane( plane, plane[3] );
  812. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  813. if ( facet->borderPlanes[j] == -1 ) {
  814. FreeWinding(w);
  815. return qfalse;
  816. }
  817. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  818. if ( !facet->borderInward[j] ) {
  819. VectorSubtract( vec3_origin, plane, plane );
  820. plane[3] = -plane[3];
  821. }
  822. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  823. }
  824. if ( !w ) {
  825. return qfalse; // winding was completely chopped away
  826. }
  827. // see if the facet is unreasonably large
  828. WindingBounds( w, bounds[0], bounds[1] );
  829. FreeWinding( w );
  830. for ( j = 0 ; j < 3 ; j++ ) {
  831. if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
  832. return qfalse; // we must be missing a plane
  833. }
  834. if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
  835. return qfalse;
  836. }
  837. if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
  838. return qfalse;
  839. }
  840. }
  841. return qtrue; // winding is fine
  842. }
  843. #endif // _XBOX
  844. /*
  845. ==================
  846. CM_AddFacetBevels
  847. ==================
  848. */
  849. #ifdef _XBOX
  850. void CM_AddFacetBevels( facetLoad_t *facet ) {
  851. int i, j, k, l;
  852. int axis, dir, order, flipped;
  853. float plane[4], d, newplane[4];
  854. winding_t *w, *w2;
  855. vec3_t mins, maxs, vec, vec2;
  856. #ifndef ADDBEVELS
  857. return;
  858. #endif
  859. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  860. w = BaseWindingForPlane( plane, plane[3] );
  861. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  862. if (facet->borderPlanes[j] == facet->surfacePlane) continue;
  863. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  864. if ( !facet->borderInward[j] ) {
  865. VectorSubtract( vec3_origin, plane, plane );
  866. plane[3] = -plane[3];
  867. }
  868. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  869. }
  870. if ( !w ) {
  871. return;
  872. }
  873. WindingBounds(w, mins, maxs);
  874. // add the axial planes
  875. order = 0;
  876. for ( axis = 0 ; axis < 3 ; axis++ )
  877. {
  878. for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
  879. {
  880. VectorClear(plane);
  881. plane[axis] = dir;
  882. if (dir == 1) {
  883. plane[3] = maxs[axis];
  884. }
  885. else {
  886. plane[3] = -mins[axis];
  887. }
  888. //if it's the surface plane
  889. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  890. continue;
  891. }
  892. // see if the plane is allready present
  893. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  894. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
  895. break;
  896. }
  897. if ( i == facet->numBorders ) {
  898. if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
  899. int num = CM_FindPlane2(plane, &flipped);
  900. assert(num > -32768 && num < 32768);
  901. facet->borderPlanes[facet->numBorders] = num;
  902. facet->borderNoAdjust[facet->numBorders] = 0;
  903. facet->borderInward[facet->numBorders] = flipped;
  904. facet->numBorders++;
  905. }
  906. }
  907. }
  908. //
  909. // add the edge bevels
  910. //
  911. // test the non-axial plane edges
  912. for ( j = 0 ; j < w->numpoints ; j++ )
  913. {
  914. k = (j+1)%w->numpoints;
  915. VectorSubtract (w->p[j], w->p[k], vec);
  916. //if it's a degenerate edge
  917. if (VectorNormalize (vec) < 0.5)
  918. continue;
  919. CM_SnapVector(vec);
  920. for ( k = 0; k < 3 ; k++ )
  921. if ( vec[k] == -1 || vec[k] == 1 )
  922. break; // axial
  923. if ( k < 3 )
  924. continue; // only test non-axial edges
  925. // try the six possible slanted axials from this edge
  926. for ( axis = 0 ; axis < 3 ; axis++ )
  927. {
  928. for ( dir = -1 ; dir <= 1 ; dir += 2 )
  929. {
  930. // construct a plane
  931. VectorClear (vec2);
  932. vec2[axis] = dir;
  933. CrossProduct (vec, vec2, plane);
  934. if (VectorNormalize (plane) < 0.5)
  935. continue;
  936. plane[3] = DotProduct (w->p[j], plane);
  937. // if all the points of the facet winding are
  938. // behind this plane, it is a proper edge bevel
  939. for ( l = 0 ; l < w->numpoints ; l++ )
  940. {
  941. d = DotProduct (w->p[l], plane) - plane[3];
  942. if (d > 0.1)
  943. break; // point in front
  944. }
  945. if ( l < w->numpoints )
  946. continue;
  947. //if it's the surface plane
  948. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  949. continue;
  950. }
  951. // see if the plane is allready present
  952. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  953. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
  954. break;
  955. }
  956. }
  957. if ( i == facet->numBorders ) {
  958. if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
  959. int num = CM_FindPlane2(plane, &flipped);
  960. assert(num > -32768 && num < 32768);
  961. facet->borderPlanes[facet->numBorders] = num;
  962. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  963. if (facet->borderPlanes[facet->numBorders] ==
  964. facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
  965. }
  966. facet->borderNoAdjust[facet->numBorders] = 0;
  967. facet->borderInward[facet->numBorders] = flipped;
  968. //
  969. w2 = CopyWinding(w);
  970. Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
  971. if (!facet->borderInward[facet->numBorders])
  972. {
  973. VectorNegate(newplane, newplane);
  974. newplane[3] = -newplane[3];
  975. } //end if
  976. ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
  977. if (!w2) {
  978. Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
  979. continue;
  980. }
  981. else {
  982. FreeWinding(w2);
  983. }
  984. //
  985. facet->numBorders++;
  986. //already got a bevel
  987. // break;
  988. }
  989. }
  990. }
  991. }
  992. FreeWinding( w );
  993. #ifndef BSPC
  994. //add opposite plane
  995. assert(facet->surfacePlane > -32768 && facet->surfacePlane < 32768);
  996. facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
  997. facet->borderNoAdjust[facet->numBorders] = 0;
  998. facet->borderInward[facet->numBorders] = qtrue;
  999. facet->numBorders++;
  1000. #endif //BSPC
  1001. }
  1002. #else // _XBOX
  1003. void CM_AddFacetBevels( facet_t *facet ) {
  1004. int i, j, k, l;
  1005. int axis, dir, order, flipped;
  1006. float plane[4], d, newplane[4];
  1007. winding_t *w, *w2;
  1008. vec3_t mins, maxs, vec, vec2;
  1009. #ifndef ADDBEVELS
  1010. return;
  1011. #endif
  1012. Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
  1013. w = BaseWindingForPlane( plane, plane[3] );
  1014. for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
  1015. if (facet->borderPlanes[j] == facet->surfacePlane) continue;
  1016. Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
  1017. if ( !facet->borderInward[j] ) {
  1018. VectorSubtract( vec3_origin, plane, plane );
  1019. plane[3] = -plane[3];
  1020. }
  1021. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  1022. }
  1023. if ( !w ) {
  1024. return;
  1025. }
  1026. WindingBounds(w, mins, maxs);
  1027. // add the axial planes
  1028. order = 0;
  1029. for ( axis = 0 ; axis < 3 ; axis++ )
  1030. {
  1031. for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
  1032. {
  1033. VectorClear(plane);
  1034. plane[axis] = dir;
  1035. if (dir == 1) {
  1036. plane[3] = maxs[axis];
  1037. }
  1038. else {
  1039. plane[3] = -mins[axis];
  1040. }
  1041. //if it's the surface plane
  1042. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  1043. continue;
  1044. }
  1045. // see if the plane is allready present
  1046. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  1047. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
  1048. break;
  1049. }
  1050. if ( i == facet->numBorders ) {
  1051. if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
  1052. facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
  1053. facet->borderNoAdjust[facet->numBorders] = 0;
  1054. facet->borderInward[facet->numBorders] = flipped;
  1055. facet->numBorders++;
  1056. }
  1057. }
  1058. }
  1059. //
  1060. // add the edge bevels
  1061. //
  1062. // test the non-axial plane edges
  1063. for ( j = 0 ; j < w->numpoints ; j++ )
  1064. {
  1065. k = (j+1)%w->numpoints;
  1066. VectorSubtract (w->p[j], w->p[k], vec);
  1067. //if it's a degenerate edge
  1068. if (VectorNormalize (vec) < 0.5)
  1069. continue;
  1070. CM_SnapVector(vec);
  1071. for ( k = 0; k < 3 ; k++ )
  1072. if ( vec[k] == -1 || vec[k] == 1 )
  1073. break; // axial
  1074. if ( k < 3 )
  1075. continue; // only test non-axial edges
  1076. // try the six possible slanted axials from this edge
  1077. for ( axis = 0 ; axis < 3 ; axis++ )
  1078. {
  1079. for ( dir = -1 ; dir <= 1 ; dir += 2 )
  1080. {
  1081. // construct a plane
  1082. VectorClear (vec2);
  1083. vec2[axis] = dir;
  1084. CrossProduct (vec, vec2, plane);
  1085. if (VectorNormalize (plane) < 0.5)
  1086. continue;
  1087. plane[3] = DotProduct (w->p[j], plane);
  1088. // if all the points of the facet winding are
  1089. // behind this plane, it is a proper edge bevel
  1090. for ( l = 0 ; l < w->numpoints ; l++ )
  1091. {
  1092. d = DotProduct (w->p[l], plane) - plane[3];
  1093. if (d > 0.1)
  1094. break; // point in front
  1095. }
  1096. if ( l < w->numpoints )
  1097. continue;
  1098. //if it's the surface plane
  1099. if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
  1100. continue;
  1101. }
  1102. // see if the plane is allready present
  1103. for ( i = 0 ; i < facet->numBorders ; i++ ) {
  1104. if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
  1105. break;
  1106. }
  1107. }
  1108. if ( i == facet->numBorders ) {
  1109. if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
  1110. facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
  1111. for ( k = 0 ; k < facet->numBorders ; k++ ) {
  1112. if (facet->borderPlanes[facet->numBorders] ==
  1113. facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
  1114. }
  1115. facet->borderNoAdjust[facet->numBorders] = 0;
  1116. facet->borderInward[facet->numBorders] = flipped;
  1117. //
  1118. w2 = CopyWinding(w);
  1119. Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
  1120. if (!facet->borderInward[facet->numBorders])
  1121. {
  1122. VectorNegate(newplane, newplane);
  1123. newplane[3] = -newplane[3];
  1124. } //end if
  1125. ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
  1126. if (!w2) {
  1127. Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
  1128. continue;
  1129. }
  1130. else {
  1131. FreeWinding(w2);
  1132. }
  1133. //
  1134. facet->numBorders++;
  1135. //already got a bevel
  1136. // break;
  1137. }
  1138. }
  1139. }
  1140. }
  1141. FreeWinding( w );
  1142. #ifndef BSPC
  1143. //add opposite plane
  1144. facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
  1145. facet->borderNoAdjust[facet->numBorders] = 0;
  1146. facet->borderInward[facet->numBorders] = qtrue;
  1147. facet->numBorders++;
  1148. #endif //BSPC
  1149. }
  1150. #endif // _XBOX
  1151. typedef enum {
  1152. EN_TOP,
  1153. EN_RIGHT,
  1154. EN_BOTTOM,
  1155. EN_LEFT
  1156. } edgeName_t;
  1157. #ifdef _XBOX
  1158. facetLoad_t* cm_facets = 0;
  1159. int* cm_gridPlanes = 0;
  1160. void CM_PatchCollideFromGridTempAlloc()
  1161. {
  1162. if (!cm_facets)
  1163. {
  1164. cm_facets = (facetLoad_t*)Z_Malloc(MAX_PATCH_PLANES*sizeof(facetLoad_t), TAG_TEMP_WORKSPACE, qfalse);
  1165. }
  1166. if (!cm_gridPlanes)
  1167. {
  1168. cm_gridPlanes = (int*)Z_Malloc(CM_MAX_GRID_SIZE*CM_MAX_GRID_SIZE*2*sizeof(int), TAG_TEMP_WORKSPACE, qfalse);
  1169. }
  1170. }
  1171. void CM_PatchCollideFromGridTempDealloc()
  1172. {
  1173. Z_Free(cm_gridPlanes);
  1174. Z_Free(cm_facets);
  1175. cm_gridPlanes = 0;
  1176. cm_facets = 0;
  1177. }
  1178. #endif
  1179. /*
  1180. ==================
  1181. CM_PatchCollideFromGrid
  1182. ==================
  1183. */
  1184. #ifdef _XBOX
  1185. int min1 = 0, max1 = 0, min2 = 0, max2 = 0;
  1186. static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf,
  1187. facetLoad_t *facetbuf, int *gridbuf ) {
  1188. int i, j;
  1189. float *p1, *p2, *p3;
  1190. int *gridPlanes;
  1191. facetLoad_t *facet;
  1192. int borders[4];
  1193. int noAdjust[4];
  1194. facetLoad_t *facets;
  1195. int numFacets;
  1196. facets = cm_facets;
  1197. if (facets == 0)
  1198. {
  1199. facets = facetbuf;
  1200. }
  1201. gridPlanes = cm_gridPlanes;
  1202. if (gridPlanes == 0)
  1203. {
  1204. gridPlanes = gridbuf;
  1205. }
  1206. numPlanes = 0;
  1207. numFacets = 0;
  1208. // find the planes for each triangle of the grid
  1209. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  1210. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  1211. p1 = grid->points[i][j];
  1212. p2 = grid->points[i+1][j];
  1213. p3 = grid->points[i+1][j+1];
  1214. gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] = CM_FindPlane( p1, p2, p3 );
  1215. p1 = grid->points[i+1][j+1];
  1216. p2 = grid->points[i][j+1];
  1217. p3 = grid->points[i][j];
  1218. gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] = CM_FindPlane( p1, p2, p3 );
  1219. }
  1220. }
  1221. // create the borders for each facet
  1222. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  1223. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  1224. borders[EN_TOP] = -1;
  1225. if ( j > 0 ) {
  1226. borders[EN_TOP] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(j-1)*2+1];
  1227. } else if ( grid->wrapHeight ) {
  1228. borders[EN_TOP] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(grid->height-2)*2+1];
  1229. }
  1230. noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] );
  1231. if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
  1232. borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
  1233. }
  1234. borders[EN_BOTTOM] = -1;
  1235. if ( j < grid->height - 2 ) {
  1236. borders[EN_BOTTOM] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(j+1)*2+0];
  1237. } else if ( grid->wrapHeight ) {
  1238. borders[EN_BOTTOM] = gridPlanes[i*CM_MAX_GRID_SIZE*2+0*2+0];
  1239. }
  1240. noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] );
  1241. if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
  1242. borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
  1243. }
  1244. borders[EN_LEFT] = -1;
  1245. if ( i > 0 ) {
  1246. borders[EN_LEFT] = gridPlanes[(i-1)*CM_MAX_GRID_SIZE*2+j*2+0];
  1247. } else if ( grid->wrapWidth ) {
  1248. borders[EN_LEFT] = gridPlanes[(grid->width-2)*CM_MAX_GRID_SIZE*2+j*2+0];
  1249. }
  1250. noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] );
  1251. if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
  1252. borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
  1253. }
  1254. borders[EN_RIGHT] = -1;
  1255. if ( i < grid->width - 2 ) {
  1256. borders[EN_RIGHT] = gridPlanes[(i+1)*CM_MAX_GRID_SIZE*2+j*2+1];
  1257. } else if ( grid->wrapWidth ) {
  1258. borders[EN_RIGHT] = gridPlanes[0*CM_MAX_GRID_SIZE*2+j*2+1];
  1259. }
  1260. noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] );
  1261. if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
  1262. borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
  1263. }
  1264. if ( numFacets == MAX_FACETS ) {
  1265. Com_Error( ERR_DROP, "MAX_FACETS" );
  1266. }
  1267. facet = &facets[numFacets];
  1268. memset( facet, 0, sizeof( *facet ) );
  1269. if ( gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] ) {
  1270. if ( gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] == -1 ) {
  1271. continue; // degenrate
  1272. }
  1273. facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
  1274. facet->numBorders = 4;
  1275. facet->borderPlanes[0] = borders[EN_TOP];
  1276. assert(borders[EN_TOP] > -32768 && borders[EN_TOP] < 32768);
  1277. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  1278. assert(noAdjust[EN_TOP] >= 0 && noAdjust[EN_TOP] < 256);
  1279. facet->borderPlanes[1] = borders[EN_RIGHT];
  1280. assert(borders[EN_RIGHT] > -32768 && borders[EN_RIGHT] < 32768);
  1281. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  1282. assert(noAdjust[EN_RIGHT] >= 0 && noAdjust[EN_RIGHT] < 256);
  1283. facet->borderPlanes[2] = borders[EN_BOTTOM];
  1284. assert(borders[EN_BOTTOM] > -32768 &&
  1285. borders[EN_BOTTOM] < 32768);
  1286. facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
  1287. assert(noAdjust[EN_BOTTOM] >= 0 && noAdjust[EN_BOTTOM] < 256);
  1288. facet->borderPlanes[3] = borders[EN_LEFT];
  1289. assert(borders[EN_LEFT] > -32768 && borders[EN_LEFT] < 32768);
  1290. facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
  1291. assert(noAdjust[EN_LEFT] >= 0 && noAdjust[EN_LEFT] < 256);
  1292. CM_SetBorderInward( facet, grid, i, j, -1 );
  1293. if ( CM_ValidateFacet( facet ) ) {
  1294. CM_AddFacetBevels( facet );
  1295. numFacets++;
  1296. }
  1297. } else {
  1298. // two seperate triangles
  1299. facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
  1300. facet->numBorders = 3;
  1301. facet->borderPlanes[0] = borders[EN_TOP];
  1302. assert(borders[EN_TOP] > -32768 && borders[EN_TOP] < 32768);
  1303. assert(noAdjust[EN_TOP] >= 0 && noAdjust[EN_TOP] < 256);
  1304. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  1305. facet->borderPlanes[1] = borders[EN_RIGHT];
  1306. assert(borders[EN_RIGHT] > -32768 && borders[EN_RIGHT] < 32768);
  1307. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  1308. assert(noAdjust[EN_RIGHT] >= 0 && noAdjust[EN_RIGHT] < 256);
  1309. facet->borderPlanes[2] = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1];
  1310. assert(gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] > -32768 &&
  1311. gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] < 32768);
  1312. if ( facet->borderPlanes[2] == -1 ) {
  1313. facet->borderPlanes[2] = borders[EN_BOTTOM];
  1314. assert(borders[EN_BOTTOM] > -32768 &&
  1315. borders[EN_BOTTOM] < 32768);
  1316. if ( facet->borderPlanes[2] == -1 ) {
  1317. int num = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
  1318. assert(num > -32768 && num < 32768);
  1319. facet->borderPlanes[2] = num;
  1320. }
  1321. }
  1322. CM_SetBorderInward( facet, grid, i, j, 0 );
  1323. if ( CM_ValidateFacet( facet ) ) {
  1324. CM_AddFacetBevels( facet );
  1325. numFacets++;
  1326. }
  1327. if ( numFacets == MAX_FACETS ) {
  1328. Com_Error( ERR_DROP, "MAX_FACETS" );
  1329. }
  1330. facet = &facets[numFacets];
  1331. memset( facet, 0, sizeof( *facet ) );
  1332. facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1];
  1333. facet->numBorders = 3;
  1334. facet->borderPlanes[0] = borders[EN_BOTTOM];
  1335. assert(borders[EN_BOTTOM] > -32768 &&
  1336. borders[EN_BOTTOM] < 32768);
  1337. facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
  1338. assert(noAdjust[EN_BOTTOM] >= 0 && noAdjust[EN_BOTTOM] < 256);
  1339. facet->borderPlanes[1] = borders[EN_LEFT];
  1340. assert(borders[EN_LEFT] > -32768 && borders[EN_LEFT] < 32768);
  1341. facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
  1342. assert(noAdjust[EN_LEFT] >= 0 && noAdjust[EN_LEFT] < 256);
  1343. facet->borderPlanes[2] = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
  1344. assert(gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] > -32768 &&
  1345. gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] < 32768);
  1346. if ( facet->borderPlanes[2] == -1 ) {
  1347. facet->borderPlanes[2] = borders[EN_TOP];
  1348. assert(borders[EN_TOP] > -32768 &&
  1349. borders[EN_TOP] < 32768);
  1350. if ( facet->borderPlanes[2] == -1 ) {
  1351. int num = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
  1352. assert(num > -32768 && num < 32768);
  1353. facet->borderPlanes[2] = num;
  1354. }
  1355. }
  1356. CM_SetBorderInward( facet, grid, i, j, 1 );
  1357. if ( CM_ValidateFacet( facet ) ) {
  1358. CM_AddFacetBevels( facet );
  1359. numFacets++;
  1360. }
  1361. }
  1362. }
  1363. }
  1364. // copy the results out
  1365. pf->numPlanes = numPlanes;
  1366. pf->numFacets = numFacets;
  1367. if (numFacets)
  1368. {
  1369. pf->facets = (facet_t *) Z_Malloc( numFacets * sizeof( *pf->facets ), TAG_BSP, qfalse);
  1370. for(i=0; i<numFacets; i++) {
  1371. pf->facets[i].data = (char*)Z_Malloc(facets[i].numBorders * 4,
  1372. TAG_BSP, qfalse);
  1373. pf->facets[i].surfacePlane = facets[i].surfacePlane;
  1374. pf->facets[i].numBorders = facets[i].numBorders;
  1375. short *bp = pf->facets[i].GetBorderPlanes();
  1376. char *bi = pf->facets[i].GetBorderInward();
  1377. char *bna = pf->facets[i].GetBorderNoAdjust();
  1378. for(j=0; j<facets[i].numBorders; j++) {
  1379. bp[j] = facets[i].borderPlanes[j];
  1380. bi[j] = facets[i].borderInward[j];
  1381. bna[j] = facets[i].borderNoAdjust[j];
  1382. }
  1383. }
  1384. }
  1385. else
  1386. {
  1387. pf->facets = 0;
  1388. }
  1389. pf->planes = (patchPlane_t *) Z_Malloc( numPlanes * sizeof( *pf->planes ), TAG_BSP, qfalse);
  1390. memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
  1391. }
  1392. #else
  1393. static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf ) {
  1394. int i, j;
  1395. float *p1, *p2, *p3;
  1396. MAC_STATIC int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2];
  1397. facet_t *facet;
  1398. int borders[4];
  1399. int noAdjust[4];
  1400. int numFacets;
  1401. facets = (facet_t*) Z_Malloc(MAX_FACETS*sizeof(facet_t), TAG_TEMP_WORKSPACE, qfalse, 4);
  1402. numPlanes = 0;
  1403. numFacets = 0;
  1404. // find the planes for each triangle of the grid
  1405. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  1406. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  1407. p1 = grid->points[i][j];
  1408. p2 = grid->points[i+1][j];
  1409. p3 = grid->points[i+1][j+1];
  1410. gridPlanes[i][j][0] = CM_FindPlane( p1, p2, p3 );
  1411. p1 = grid->points[i+1][j+1];
  1412. p2 = grid->points[i][j+1];
  1413. p3 = grid->points[i][j];
  1414. gridPlanes[i][j][1] = CM_FindPlane( p1, p2, p3 );
  1415. }
  1416. }
  1417. // create the borders for each facet
  1418. for ( i = 0 ; i < grid->width - 1 ; i++ ) {
  1419. for ( j = 0 ; j < grid->height - 1 ; j++ ) {
  1420. borders[EN_TOP] = -1;
  1421. if ( j > 0 ) {
  1422. borders[EN_TOP] = gridPlanes[i][j-1][1];
  1423. } else if ( grid->wrapHeight ) {
  1424. borders[EN_TOP] = gridPlanes[i][grid->height-2][1];
  1425. }
  1426. noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i][j][0] );
  1427. if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
  1428. borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
  1429. }
  1430. borders[EN_BOTTOM] = -1;
  1431. if ( j < grid->height - 2 ) {
  1432. borders[EN_BOTTOM] = gridPlanes[i][j+1][0];
  1433. } else if ( grid->wrapHeight ) {
  1434. borders[EN_BOTTOM] = gridPlanes[i][0][0];
  1435. }
  1436. noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i][j][1] );
  1437. if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
  1438. borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
  1439. }
  1440. borders[EN_LEFT] = -1;
  1441. if ( i > 0 ) {
  1442. borders[EN_LEFT] = gridPlanes[i-1][j][0];
  1443. } else if ( grid->wrapWidth ) {
  1444. borders[EN_LEFT] = gridPlanes[grid->width-2][j][0];
  1445. }
  1446. noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i][j][1] );
  1447. if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
  1448. borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
  1449. }
  1450. borders[EN_RIGHT] = -1;
  1451. if ( i < grid->width - 2 ) {
  1452. borders[EN_RIGHT] = gridPlanes[i+1][j][1];
  1453. } else if ( grid->wrapWidth ) {
  1454. borders[EN_RIGHT] = gridPlanes[0][j][1];
  1455. }
  1456. noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i][j][0] );
  1457. if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
  1458. borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
  1459. }
  1460. if ( numFacets == MAX_FACETS ) {
  1461. Com_Error( ERR_DROP, "MAX_FACETS" );
  1462. }
  1463. facet = &facets[numFacets];
  1464. memset( facet, 0, sizeof( *facet ) );
  1465. if ( gridPlanes[i][j][0] == gridPlanes[i][j][1] ) {
  1466. if ( gridPlanes[i][j][0] == -1 ) {
  1467. continue; // degenrate
  1468. }
  1469. facet->surfacePlane = gridPlanes[i][j][0];
  1470. facet->numBorders = 4;
  1471. facet->borderPlanes[0] = borders[EN_TOP];
  1472. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  1473. facet->borderPlanes[1] = borders[EN_RIGHT];
  1474. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  1475. facet->borderPlanes[2] = borders[EN_BOTTOM];
  1476. facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
  1477. facet->borderPlanes[3] = borders[EN_LEFT];
  1478. facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
  1479. CM_SetBorderInward( facet, grid, gridPlanes, i, j, -1 );
  1480. if ( CM_ValidateFacet( facet ) ) {
  1481. CM_AddFacetBevels( facet );
  1482. numFacets++;
  1483. }
  1484. } else {
  1485. // two seperate triangles
  1486. facet->surfacePlane = gridPlanes[i][j][0];
  1487. facet->numBorders = 3;
  1488. facet->borderPlanes[0] = borders[EN_TOP];
  1489. facet->borderNoAdjust[0] = noAdjust[EN_TOP];
  1490. facet->borderPlanes[1] = borders[EN_RIGHT];
  1491. facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
  1492. facet->borderPlanes[2] = gridPlanes[i][j][1];
  1493. if ( facet->borderPlanes[2] == -1 ) {
  1494. facet->borderPlanes[2] = borders[EN_BOTTOM];
  1495. if ( facet->borderPlanes[2] == -1 ) {
  1496. facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
  1497. }
  1498. }
  1499. CM_SetBorderInward( facet, grid, gridPlanes, i, j, 0 );
  1500. if ( CM_ValidateFacet( facet ) ) {
  1501. CM_AddFacetBevels( facet );
  1502. numFacets++;
  1503. }
  1504. if ( numFacets == MAX_FACETS ) {
  1505. Com_Error( ERR_DROP, "MAX_FACETS" );
  1506. }
  1507. facet = &facets[numFacets];
  1508. memset( facet, 0, sizeof( *facet ) );
  1509. facet->surfacePlane = gridPlanes[i][j][1];
  1510. facet->numBorders = 3;
  1511. facet->borderPlanes[0] = borders[EN_BOTTOM];
  1512. facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
  1513. facet->borderPlanes[1] = borders[EN_LEFT];
  1514. facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
  1515. facet->borderPlanes[2] = gridPlanes[i][j][0];
  1516. if ( facet->borderPlanes[2] == -1 ) {
  1517. facet->borderPlanes[2] = borders[EN_TOP];
  1518. if ( facet->borderPlanes[2] == -1 ) {
  1519. facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
  1520. }
  1521. }
  1522. CM_SetBorderInward( facet, grid, gridPlanes, i, j, 1 );
  1523. if ( CM_ValidateFacet( facet ) ) {
  1524. CM_AddFacetBevels( facet );
  1525. numFacets++;
  1526. }
  1527. }
  1528. }
  1529. }
  1530. // copy the results out
  1531. pf->numPlanes = numPlanes;
  1532. pf->numFacets = numFacets;
  1533. if (numFacets)
  1534. {
  1535. pf->facets = (facet_t *) Z_Malloc( numFacets * sizeof( *pf->facets ), TAG_BSP, qfalse);
  1536. memcpy( pf->facets, facets, numFacets * sizeof( *pf->facets ) );
  1537. }
  1538. else
  1539. {
  1540. pf->facets = 0;
  1541. }
  1542. pf->planes = (patchPlane_t *) Z_Malloc( numPlanes * sizeof( *pf->planes ), TAG_BSP, qfalse);
  1543. memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
  1544. Z_Free(facets);
  1545. }
  1546. #endif // _XBOX
  1547. static patchCollide_t *pfScratch = 0;
  1548. void CM_PreparePatchCollide(int num)
  1549. {
  1550. pfScratch = (patchCollide_t *) Z_Malloc( sizeof( *pfScratch ) * num, TAG_BSP, qfalse );
  1551. }
  1552. cGrid_t *cm_grid = 0;
  1553. void CM_GridAlloc()
  1554. {
  1555. if (cm_grid) return;
  1556. cm_grid = (cGrid_t*)Z_Malloc(sizeof(cGrid_t), TAG_TEMP_WORKSPACE, qfalse);
  1557. }
  1558. void CM_GridDealloc()
  1559. {
  1560. Z_Free(cm_grid);
  1561. cm_grid = 0;
  1562. }
  1563. /*
  1564. ===================
  1565. CM_GeneratePatchCollide
  1566. Creates an internal structure that will be used to perform
  1567. collision detection with a patch mesh.
  1568. Points is packed as concatenated rows.
  1569. ===================
  1570. */
  1571. #ifdef _XBOX
  1572. struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points,
  1573. facetLoad_t *facetbuf, int *gridbuf ) {
  1574. patchCollide_t *pf;
  1575. // --AAA--AAA--
  1576. // cGrid_t *grid = new cGrid_t;
  1577. cGrid_t *grid = cm_grid;
  1578. // --AAA--AAA--
  1579. int i, j;
  1580. memset(grid, 0, sizeof(cGrid_t));
  1581. if ( width <= 2 || height <= 2 || !points ) {
  1582. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
  1583. width, height, points );
  1584. }
  1585. if ( !(width & 1) || !(height & 1) ) {
  1586. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
  1587. }
  1588. if ( width > CM_MAX_GRID_SIZE || height > CM_MAX_GRID_SIZE ) {
  1589. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > CM_MAX_GRID_SIZE" );
  1590. }
  1591. // build a grid
  1592. grid->width = width;
  1593. grid->height = height;
  1594. grid->wrapWidth = qfalse;
  1595. grid->wrapHeight = qfalse;
  1596. for ( i = 0 ; i < width ; i++ ) {
  1597. for ( j = 0 ; j < height ; j++ ) {
  1598. VectorCopy( points[j*width + i], grid->points[i][j] );
  1599. }
  1600. }
  1601. // subdivide the grid
  1602. CM_SetGridWrapWidth( grid );
  1603. CM_SubdivideGridColumns( grid );
  1604. CM_RemoveDegenerateColumns( grid );
  1605. CM_TransposeGrid( grid );
  1606. CM_SetGridWrapWidth( grid );
  1607. CM_SubdivideGridColumns( grid );
  1608. CM_RemoveDegenerateColumns( grid );
  1609. // we now have a grid of points exactly on the curve
  1610. // the aproximate surface defined by these points will be
  1611. // collided against
  1612. // --AAA--AAA--
  1613. // pf = (patchCollide_t *) Z_Malloc( sizeof( *pf ), TAG_BSP, qfalse );
  1614. pf = pfScratch++;
  1615. // --AAA--AAA--
  1616. ClearBounds( pf->bounds[0], pf->bounds[1] );
  1617. for ( i = 0 ; i < grid->width ; i++ ) {
  1618. for ( j = 0 ; j < grid->height ; j++ ) {
  1619. AddPointToBounds( grid->points[i][j], pf->bounds[0], pf->bounds[1] );
  1620. }
  1621. }
  1622. c_totalPatchBlocks += ( grid->width - 1 ) * ( grid->height - 1 );
  1623. // generate a bsp tree for the surface
  1624. CM_PatchCollideFromGrid( grid, pf, facetbuf, gridbuf );
  1625. // expand by one unit for epsilon purposes
  1626. pf->bounds[0][0] -= 1;
  1627. pf->bounds[0][1] -= 1;
  1628. pf->bounds[0][2] -= 1;
  1629. pf->bounds[1][0] += 1;
  1630. pf->bounds[1][1] += 1;
  1631. pf->bounds[1][2] += 1;
  1632. // --AAA--AAA--
  1633. // delete grid;
  1634. // --AAA--AAA--
  1635. return pf;
  1636. }
  1637. #else
  1638. struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ) {
  1639. patchCollide_t *pf;
  1640. MAC_STATIC cGrid_t grid;
  1641. int i, j;
  1642. if ( width <= 2 || height <= 2 || !points ) {
  1643. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
  1644. width, height, points );
  1645. }
  1646. if ( !(width & 1) || !(height & 1) ) {
  1647. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
  1648. }
  1649. if ( width > CM_MAX_GRID_SIZE || height > CM_MAX_GRID_SIZE ) {
  1650. Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > CM_MAX_GRID_SIZE" );
  1651. }
  1652. // build a grid
  1653. grid.width = width;
  1654. grid.height = height;
  1655. grid.wrapWidth = qfalse;
  1656. grid.wrapHeight = qfalse;
  1657. for ( i = 0 ; i < width ; i++ ) {
  1658. for ( j = 0 ; j < height ; j++ ) {
  1659. VectorCopy( points[j*width + i], grid.points[i][j] );
  1660. }
  1661. }
  1662. // subdivide the grid
  1663. CM_SetGridWrapWidth( &grid );
  1664. CM_SubdivideGridColumns( &grid );
  1665. CM_RemoveDegenerateColumns( &grid );
  1666. CM_TransposeGrid( &grid );
  1667. CM_SetGridWrapWidth( &grid );
  1668. CM_SubdivideGridColumns( &grid );
  1669. CM_RemoveDegenerateColumns( &grid );
  1670. // we now have a grid of points exactly on the curve
  1671. // the aproximate surface defined by these points will be
  1672. // collided against
  1673. pf = (patchCollide_t *) Z_Malloc( sizeof( *pf ), TAG_BSP, qfalse );
  1674. ClearBounds( pf->bounds[0], pf->bounds[1] );
  1675. for ( i = 0 ; i < grid.width ; i++ ) {
  1676. for ( j = 0 ; j < grid.height ; j++ ) {
  1677. AddPointToBounds( grid.points[i][j], pf->bounds[0], pf->bounds[1] );
  1678. }
  1679. }
  1680. c_totalPatchBlocks += ( grid.width - 1 ) * ( grid.height - 1 );
  1681. // generate a bsp tree for the surface
  1682. CM_PatchCollideFromGrid( &grid, pf );
  1683. // expand by one unit for epsilon purposes
  1684. pf->bounds[0][0] -= 1;
  1685. pf->bounds[0][1] -= 1;
  1686. pf->bounds[0][2] -= 1;
  1687. pf->bounds[1][0] += 1;
  1688. pf->bounds[1][1] += 1;
  1689. pf->bounds[1][2] += 1;
  1690. return pf;
  1691. }
  1692. #endif // _XBOX
  1693. /*
  1694. ================================================================================
  1695. TRACE TESTING
  1696. ================================================================================
  1697. */
  1698. /*
  1699. ====================
  1700. CM_TraceThroughPatchCollide
  1701. Modifies tr->tr if any of the facets effect the trace
  1702. ====================
  1703. */
  1704. /*
  1705. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
  1706. {
  1707. int i, j, n;
  1708. float d1, d2, offset, planedist, fraction;
  1709. vec3_t v1, v2, normal, point;
  1710. patchPlane_t *planes;
  1711. facet_t *facet;
  1712. //
  1713. facet = pc->facets;
  1714. for ( i = 0 ; i < pc->numFacets ; i++, facet++ )
  1715. {
  1716. planes = &pc->planes[ facet->surfacePlane ];
  1717. VectorCopy(planes->plane, normal);
  1718. for (n = 0; n < 3; n++)
  1719. {
  1720. if (normal[n] > 0) v1[n] = tw->size[0][n];
  1721. else v1[n] = tw->size[1][n];
  1722. } //end for
  1723. VectorNegate(normal, v2);
  1724. offset = DotProduct(v1, v2);
  1725. //offset = 0;
  1726. //
  1727. planedist = planes->plane[3] + offset;
  1728. //
  1729. d1 = DotProduct( tw->start, normal ) - planedist;
  1730. d2 = DotProduct( tw->end, normal ) - planedist;
  1731. // if completely in front of face, no intersection with the entire patch
  1732. if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
  1733. continue;
  1734. }
  1735. // if it doesn't cross the plane, the plane isn't relevent
  1736. if (d1 <= 0 && d2 <= 0 ) {
  1737. continue;
  1738. }
  1739. // crosses face
  1740. if (d1 > d2) { // enter
  1741. fraction = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
  1742. if ( fraction < 0 ) {
  1743. fraction = 0;
  1744. }
  1745. for (j = 0; j < 3; j++)
  1746. point[j] = tw->start[j] + (tw->end[j] - tw->start[j]) * fraction;
  1747. }
  1748. else {
  1749. continue;
  1750. }
  1751. //
  1752. for (j = 0; j < facet->numBorders; j++)
  1753. {
  1754. planes = &pc->planes[ facet->borderPlanes[j] ];
  1755. if (!facet->borderInward[j])
  1756. {
  1757. VectorNegate(planes->plane, normal);
  1758. planedist = -planes->plane[3];
  1759. } //end if
  1760. else
  1761. {
  1762. VectorCopy(planes->plane, normal);
  1763. planedist = planes->plane[3];
  1764. } //end else
  1765. for (n = 0; n < 3; n++)
  1766. {
  1767. if (normal[n] > 0) v1[n] = tw->size[0][n];
  1768. else v1[n] = tw->size[1][n];
  1769. } //end for
  1770. VectorNegate(normal, v2);
  1771. offset = DotProduct(v1, v2);
  1772. //offset = 0;
  1773. planedist -= offset;
  1774. //the hit point should be in front of the (inward facing) border plane
  1775. if (DotProduct(point, normal) - planedist < -ON_EPSILON) break;
  1776. } //end for
  1777. if (j < facet->numBorders) continue;
  1778. //
  1779. if (fraction < tw->trace.fraction)
  1780. {
  1781. debugPatchCollide = pc;
  1782. debugFacet = facet;
  1783. tw->trace.fraction = fraction;
  1784. planes = &pc->planes[ facet->surfacePlane ];
  1785. VectorCopy( planes->plane, tw->trace.plane.normal );
  1786. tw->trace.plane.dist = planes->plane[3];
  1787. } //end if
  1788. } //end for
  1789. } //end of the function CM_TraceThroughPatchCollide*/
  1790. /*
  1791. ====================
  1792. CM_TracePointThroughPatchCollide
  1793. special case for point traces because the patch collide "brushes" have no volume
  1794. ====================
  1795. */
  1796. #ifdef _XBOX
  1797. void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  1798. qboolean frontFacing[MAX_PATCH_PLANES];
  1799. float intersection[MAX_PATCH_PLANES];
  1800. float intersect;
  1801. const patchPlane_t *planes;
  1802. const facet_t *facet;
  1803. int i, j, k;
  1804. float offset;
  1805. float d1, d2;
  1806. #ifndef BSPC
  1807. static cvar_t *cv;
  1808. #endif //BSPC
  1809. #ifndef BSPC
  1810. if ( !cm_playerCurveClip->integer && !tw->isPoint ) {
  1811. return; // FIXME: until I get player sized clipping working right
  1812. }
  1813. #endif
  1814. if (!pc->numFacets)
  1815. { //not gonna do anything anyhow?
  1816. return;
  1817. }
  1818. // determine the trace's relationship to all planes
  1819. planes = pc->planes;
  1820. for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
  1821. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1822. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1823. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1824. if ( d1 <= 0 ) {
  1825. frontFacing[i] = qfalse;
  1826. } else {
  1827. frontFacing[i] = qtrue;
  1828. }
  1829. if ( d1 == d2 ) {
  1830. intersection[i] = WORLD_SIZE;
  1831. } else {
  1832. intersection[i] = d1 / ( d1 - d2 );
  1833. if ( intersection[i] <= 0 ) {
  1834. intersection[i] = WORLD_SIZE;
  1835. }
  1836. }
  1837. }
  1838. // see if any of the surface planes are intersected
  1839. facet = pc->facets;
  1840. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  1841. if ( !frontFacing[facet->surfacePlane] ) {
  1842. continue;
  1843. }
  1844. intersect = intersection[facet->surfacePlane];
  1845. if ( intersect < 0 ) {
  1846. continue; // surface is behind the starting point
  1847. }
  1848. if ( intersect > tw->trace.fraction ) {
  1849. continue; // already hit something closer
  1850. }
  1851. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  1852. k = facet->GetBorderPlanes()[j];
  1853. if ( frontFacing[k] ^ facet->GetBorderInward()[j] ) {
  1854. if ( intersection[k] > intersect ) {
  1855. break;
  1856. }
  1857. } else {
  1858. if ( intersection[k] < intersect ) {
  1859. break;
  1860. }
  1861. }
  1862. }
  1863. if ( j == facet->numBorders ) {
  1864. // we hit this facet
  1865. #ifndef BSPC
  1866. if (!cv) {
  1867. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  1868. }
  1869. if (cv->integer) {
  1870. debugPatchCollide = pc;
  1871. debugFacet = facet;
  1872. }
  1873. #endif //BSPC
  1874. planes = &pc->planes[facet->surfacePlane];
  1875. // calculate intersection with a slight pushoff
  1876. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1877. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1878. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1879. tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
  1880. if ( tw->trace.fraction < 0 ) {
  1881. tw->trace.fraction = 0;
  1882. }
  1883. VectorCopy( planes->plane, tw->trace.plane.normal );
  1884. tw->trace.plane.dist = planes->plane[3];
  1885. }
  1886. }
  1887. }
  1888. #else // _XBOX
  1889. void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  1890. qboolean frontFacing[MAX_PATCH_PLANES];
  1891. float intersection[MAX_PATCH_PLANES];
  1892. float intersect;
  1893. const patchPlane_t *planes;
  1894. const facet_t *facet;
  1895. int i, j, k;
  1896. float offset;
  1897. float d1, d2;
  1898. #ifndef BSPC
  1899. static cvar_t *cv;
  1900. #endif //BSPC
  1901. #ifndef BSPC
  1902. if ( !cm_playerCurveClip->integer && !tw->isPoint ) {
  1903. return; // FIXME: until I get player sized clipping working right
  1904. }
  1905. #endif
  1906. if (!pc->numFacets)
  1907. { //not gonna do anything anyhow?
  1908. return;
  1909. }
  1910. // determine the trace's relationship to all planes
  1911. planes = pc->planes;
  1912. for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
  1913. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1914. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1915. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1916. if ( d1 <= 0 ) {
  1917. frontFacing[i] = qfalse;
  1918. } else {
  1919. frontFacing[i] = qtrue;
  1920. }
  1921. if ( d1 == d2 ) {
  1922. intersection[i] = WORLD_SIZE;
  1923. } else {
  1924. intersection[i] = d1 / ( d1 - d2 );
  1925. if ( intersection[i] <= 0 ) {
  1926. intersection[i] = WORLD_SIZE;
  1927. }
  1928. }
  1929. }
  1930. // see if any of the surface planes are intersected
  1931. facet = pc->facets;
  1932. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  1933. if ( !frontFacing[facet->surfacePlane] ) {
  1934. continue;
  1935. }
  1936. intersect = intersection[facet->surfacePlane];
  1937. if ( intersect < 0 ) {
  1938. continue; // surface is behind the starting point
  1939. }
  1940. if ( intersect > tw->trace.fraction ) {
  1941. continue; // already hit something closer
  1942. }
  1943. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  1944. k = facet->borderPlanes[j];
  1945. if ( frontFacing[k] ^ facet->borderInward[j] ) {
  1946. if ( intersection[k] > intersect ) {
  1947. break;
  1948. }
  1949. } else {
  1950. if ( intersection[k] < intersect ) {
  1951. break;
  1952. }
  1953. }
  1954. }
  1955. if ( j == facet->numBorders ) {
  1956. // we hit this facet
  1957. #ifndef BSPC
  1958. if (!cv) {
  1959. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  1960. }
  1961. if (cv->integer) {
  1962. debugPatchCollide = pc;
  1963. debugFacet = facet;
  1964. }
  1965. #endif //BSPC
  1966. planes = &pc->planes[facet->surfacePlane];
  1967. // calculate intersection with a slight pushoff
  1968. offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
  1969. d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
  1970. d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
  1971. tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
  1972. if ( tw->trace.fraction < 0 ) {
  1973. tw->trace.fraction = 0;
  1974. }
  1975. VectorCopy( planes->plane, tw->trace.plane.normal );
  1976. tw->trace.plane.dist = planes->plane[3];
  1977. }
  1978. }
  1979. }
  1980. #endif
  1981. /*
  1982. ====================
  1983. CM_CheckFacetPlane
  1984. ====================
  1985. */
  1986. int CM_CheckFacetPlane(float *plane, vec3_t start, vec3_t end, float *enterFrac, float *leaveFrac, int *hit) {
  1987. float d1, d2, f;
  1988. *hit = qfalse;
  1989. d1 = DotProduct( start, plane ) - plane[3];
  1990. d2 = DotProduct( end, plane ) - plane[3];
  1991. // if completely in front of face, no intersection with the entire facet
  1992. if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
  1993. return qfalse;
  1994. }
  1995. // if it doesn't cross the plane, the plane isn't relevent
  1996. if (d1 <= 0 && d2 <= 0 ) {
  1997. return qtrue;
  1998. }
  1999. // crosses face
  2000. if (d1 > d2) { // enter
  2001. f = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
  2002. if ( f < 0 ) {
  2003. f = 0;
  2004. }
  2005. //always favor previous plane hits and thus also the surface plane hit
  2006. if (f > *enterFrac) {
  2007. *enterFrac = f;
  2008. *hit = qtrue;
  2009. }
  2010. } else { // leave
  2011. f = (d1+SURFACE_CLIP_EPSILON) / (d1-d2);
  2012. if ( f > 1 ) {
  2013. f = 1;
  2014. }
  2015. if (f < *leaveFrac) {
  2016. *leaveFrac = f;
  2017. }
  2018. }
  2019. return qtrue;
  2020. }
  2021. /*
  2022. ====================
  2023. CM_TraceThroughPatchCollide
  2024. ====================
  2025. */
  2026. #ifdef _XBOX
  2027. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
  2028. {
  2029. int i, j, hit, hitnum;
  2030. float offset, enterFrac, leaveFrac, t;
  2031. patchPlane_t *planes;
  2032. facet_t *facet;
  2033. float plane[4], bestplane[4];
  2034. vec3_t startp, endp;
  2035. #ifndef BSPC
  2036. static cvar_t *cv;
  2037. #endif //BSPC
  2038. #ifndef CULL_BBOX
  2039. // I'm not sure if test is strictly correct. Are all
  2040. // bboxes axis aligned? Do I care? It seems to work
  2041. // good enough...
  2042. for ( i = 0 ; i < 3 ; i++ ) {
  2043. if ( tw->bounds[0][i] > pc->bounds[1][i]
  2044. || tw->bounds[1][i] < pc->bounds[0][i] ) {
  2045. return;
  2046. }
  2047. }
  2048. #endif
  2049. if (tw->isPoint) {
  2050. CM_TracePointThroughPatchCollide( tw, pc );
  2051. return;
  2052. }
  2053. #ifndef ADDBEVELS
  2054. CM_TracePointThroughPatchCollide( tw, pc );
  2055. return;
  2056. #endif
  2057. //
  2058. facet = pc->facets;
  2059. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  2060. enterFrac = -1.0;
  2061. leaveFrac = 1.0;
  2062. hitnum = -1;
  2063. //
  2064. planes = &pc->planes[ facet->surfacePlane ];
  2065. VectorCopy(planes->plane, plane);
  2066. plane[3] = planes->plane[3];
  2067. if ( tw->sphere.use ) {
  2068. // adjust the plane distance apropriately for radius
  2069. plane[3] += tw->sphere.radius;
  2070. // find the closest point on the capsule to the plane
  2071. t = DotProduct( plane, tw->sphere.offset );
  2072. if ( t > 0.0f )
  2073. {
  2074. VectorSubtract( tw->start, tw->sphere.offset, startp );
  2075. VectorSubtract( tw->end, tw->sphere.offset, endp );
  2076. }
  2077. else
  2078. {
  2079. VectorAdd( tw->start, tw->sphere.offset, startp );
  2080. VectorAdd( tw->end, tw->sphere.offset, endp );
  2081. }
  2082. }
  2083. else {
  2084. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  2085. plane[3] -= offset;
  2086. VectorCopy( tw->start, startp );
  2087. VectorCopy( tw->end, endp );
  2088. }
  2089. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  2090. continue;
  2091. }
  2092. if (hit) {
  2093. Vector4Copy(plane, bestplane);
  2094. }
  2095. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  2096. planes = &pc->planes[ facet->GetBorderPlanes()[j] ];
  2097. if (facet->GetBorderInward()[j]) {
  2098. VectorNegate(planes->plane, plane);
  2099. plane[3] = -planes->plane[3];
  2100. }
  2101. else {
  2102. VectorCopy(planes->plane, plane);
  2103. plane[3] = planes->plane[3];
  2104. }
  2105. if ( tw->sphere.use ) {
  2106. // adjust the plane distance apropriately for radius
  2107. plane[3] += tw->sphere.radius;
  2108. // find the closest point on the capsule to the plane
  2109. t = DotProduct( plane, tw->sphere.offset );
  2110. if ( t > 0.0f )
  2111. {
  2112. VectorSubtract( tw->start, tw->sphere.offset, startp );
  2113. VectorSubtract( tw->end, tw->sphere.offset, endp );
  2114. }
  2115. else
  2116. {
  2117. VectorAdd( tw->start, tw->sphere.offset, startp );
  2118. VectorAdd( tw->end, tw->sphere.offset, endp );
  2119. }
  2120. }
  2121. else {
  2122. // NOTE: this works even though the plane might be flipped because the bbox is centered
  2123. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  2124. plane[3] += Q_fabs(offset);
  2125. VectorCopy( tw->start, startp );
  2126. VectorCopy( tw->end, endp );
  2127. }
  2128. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  2129. break;
  2130. }
  2131. if (hit) {
  2132. hitnum = j;
  2133. Vector4Copy(plane, bestplane);
  2134. }
  2135. }
  2136. if (j < facet->numBorders) continue;
  2137. //never clip against the back side
  2138. if (hitnum == facet->numBorders - 1) continue;
  2139. if (enterFrac < leaveFrac && enterFrac >= 0) {
  2140. if (enterFrac < tw->trace.fraction) {
  2141. if (enterFrac < 0) {
  2142. enterFrac = 0;
  2143. }
  2144. #ifndef BSPC
  2145. if (!cv) {
  2146. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  2147. }
  2148. if (cv && cv->integer) {
  2149. debugPatchCollide = pc;
  2150. debugFacet = facet;
  2151. }
  2152. #endif // BSPC
  2153. tw->trace.fraction = enterFrac;
  2154. VectorCopy( bestplane, tw->trace.plane.normal );
  2155. tw->trace.plane.dist = bestplane[3];
  2156. }
  2157. }
  2158. }
  2159. }
  2160. #else // _XBOX
  2161. void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
  2162. {
  2163. int i, j, hit, hitnum;
  2164. float offset, enterFrac, leaveFrac, t;
  2165. patchPlane_t *planes;
  2166. facet_t *facet;
  2167. float plane[4], bestplane[4];
  2168. vec3_t startp, endp;
  2169. #ifndef BSPC
  2170. static cvar_t *cv;
  2171. #endif //BSPC
  2172. if (tw->isPoint) {
  2173. CM_TracePointThroughPatchCollide( tw, pc );
  2174. return;
  2175. }
  2176. #ifndef ADDBEVELS
  2177. CM_TracePointThroughPatchCollide( tw, pc );
  2178. return;
  2179. #endif
  2180. //
  2181. facet = pc->facets;
  2182. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  2183. enterFrac = -1.0;
  2184. leaveFrac = 1.0;
  2185. hitnum = -1;
  2186. //
  2187. planes = &pc->planes[ facet->surfacePlane ];
  2188. VectorCopy(planes->plane, plane);
  2189. plane[3] = planes->plane[3];
  2190. if ( tw->sphere.use ) {
  2191. // adjust the plane distance apropriately for radius
  2192. plane[3] += tw->sphere.radius;
  2193. // find the closest point on the capsule to the plane
  2194. t = DotProduct( plane, tw->sphere.offset );
  2195. if ( t > 0.0f )
  2196. {
  2197. VectorSubtract( tw->start, tw->sphere.offset, startp );
  2198. VectorSubtract( tw->end, tw->sphere.offset, endp );
  2199. }
  2200. else
  2201. {
  2202. VectorAdd( tw->start, tw->sphere.offset, startp );
  2203. VectorAdd( tw->end, tw->sphere.offset, endp );
  2204. }
  2205. }
  2206. else {
  2207. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  2208. plane[3] -= offset;
  2209. VectorCopy( tw->start, startp );
  2210. VectorCopy( tw->end, endp );
  2211. }
  2212. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  2213. continue;
  2214. }
  2215. if (hit) {
  2216. Vector4Copy(plane, bestplane);
  2217. }
  2218. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  2219. planes = &pc->planes[ facet->borderPlanes[j] ];
  2220. if (facet->borderInward[j]) {
  2221. VectorNegate(planes->plane, plane);
  2222. plane[3] = -planes->plane[3];
  2223. }
  2224. else {
  2225. VectorCopy(planes->plane, plane);
  2226. plane[3] = planes->plane[3];
  2227. }
  2228. if ( tw->sphere.use ) {
  2229. // adjust the plane distance apropriately for radius
  2230. plane[3] += tw->sphere.radius;
  2231. // find the closest point on the capsule to the plane
  2232. t = DotProduct( plane, tw->sphere.offset );
  2233. if ( t > 0.0f )
  2234. {
  2235. VectorSubtract( tw->start, tw->sphere.offset, startp );
  2236. VectorSubtract( tw->end, tw->sphere.offset, endp );
  2237. }
  2238. else
  2239. {
  2240. VectorAdd( tw->start, tw->sphere.offset, startp );
  2241. VectorAdd( tw->end, tw->sphere.offset, endp );
  2242. }
  2243. }
  2244. else {
  2245. // NOTE: this works even though the plane might be flipped because the bbox is centered
  2246. offset = DotProduct( tw->offsets[ planes->signbits ], plane);
  2247. plane[3] += fabs(offset);
  2248. VectorCopy( tw->start, startp );
  2249. VectorCopy( tw->end, endp );
  2250. }
  2251. if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
  2252. break;
  2253. }
  2254. if (hit) {
  2255. hitnum = j;
  2256. Vector4Copy(plane, bestplane);
  2257. }
  2258. }
  2259. if (j < facet->numBorders) continue;
  2260. //never clip against the back side
  2261. if (hitnum == facet->numBorders - 1) continue;
  2262. if (enterFrac < leaveFrac && enterFrac >= 0) {
  2263. if (enterFrac < tw->trace.fraction) {
  2264. if (enterFrac < 0) {
  2265. enterFrac = 0;
  2266. }
  2267. #ifndef BSPC
  2268. if (!cv) {
  2269. cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
  2270. }
  2271. if (cv && cv->integer) {
  2272. debugPatchCollide = pc;
  2273. debugFacet = facet;
  2274. }
  2275. #endif // BSPC
  2276. tw->trace.fraction = enterFrac;
  2277. VectorCopy( bestplane, tw->trace.plane.normal );
  2278. tw->trace.plane.dist = bestplane[3];
  2279. }
  2280. }
  2281. }
  2282. }
  2283. #endif // _XBOX
  2284. /*
  2285. =======================================================================
  2286. POSITION TEST
  2287. =======================================================================
  2288. */
  2289. #define BOX_FRONT 0
  2290. #define BOX_BACK 1
  2291. #define BOX_CROSS 2
  2292. /*
  2293. ====================
  2294. CM_PositionTestInPatchCollide
  2295. Modifies tr->tr if any of the facets effect the trace
  2296. ====================
  2297. */
  2298. #ifdef _XBOX
  2299. qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  2300. int cross[MAX_PATCH_PLANES];
  2301. const patchPlane_t *planes;
  2302. const facet_t *facet;
  2303. int i, j, k;
  2304. float offset;
  2305. float d;
  2306. //return qfalse;
  2307. #ifndef CULL_BBOX
  2308. for ( i = 0 ; i < 3 ; i++ ) {
  2309. if ( tw->bounds[0][i] > pc->bounds[1][i]
  2310. || tw->bounds[1][i] < pc->bounds[0][i] ) {
  2311. return qfalse;
  2312. }
  2313. }
  2314. #endif
  2315. // determine if the box is in front, behind, or crossing each plane
  2316. planes = pc->planes;
  2317. for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
  2318. d = DotProduct( tw->start, planes->plane ) - planes->plane[3];
  2319. offset = Q_fabs( DotProduct( tw->offsets[ planes->signbits ], planes->plane ) );
  2320. if ( d < -offset ) {
  2321. cross[i] = BOX_FRONT;
  2322. } else if ( d > offset ) {
  2323. cross[i] = BOX_BACK;
  2324. } else {
  2325. cross[i] = BOX_CROSS;
  2326. }
  2327. }
  2328. // see if any of the surface planes are intersected
  2329. facet = pc->facets;
  2330. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  2331. // the facet plane must be in a cross state
  2332. if ( cross[facet->surfacePlane] != BOX_CROSS ) {
  2333. continue;
  2334. }
  2335. // all of the boundaries must be either cross or back
  2336. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  2337. k = facet->GetBorderPlanes()[j];
  2338. if ( cross[ k ] == BOX_CROSS ) {
  2339. continue;
  2340. }
  2341. if ( cross[k] ^ facet->GetBorderInward()[j] ) {
  2342. break;
  2343. }
  2344. }
  2345. // if we passed all borders, we are definately in this facet
  2346. if ( j == facet->numBorders ) {
  2347. return qtrue;
  2348. }
  2349. }
  2350. return qfalse;
  2351. }
  2352. #else // _XBOX
  2353. qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
  2354. int cross[MAX_PATCH_PLANES];
  2355. const patchPlane_t *planes;
  2356. const facet_t *facet;
  2357. int i, j, k;
  2358. float offset;
  2359. float d;
  2360. //return qfalse;
  2361. #ifndef CULL_BBOX
  2362. for ( i = 0 ; i < 3 ; i++ ) {
  2363. if ( tw->bounds[0][i] > pc->bounds[1][i]
  2364. || tw->bounds[1][i] < pc->bounds[0][i] ) {
  2365. return qfalse;
  2366. }
  2367. }
  2368. #endif
  2369. // determine if the box is in front, behind, or crossing each plane
  2370. planes = pc->planes;
  2371. for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
  2372. d = DotProduct( tw->start, planes->plane ) - planes->plane[3];
  2373. offset = fabs( DotProduct( tw->offsets[ planes->signbits ], planes->plane ) );
  2374. if ( d < -offset ) {
  2375. cross[i] = BOX_FRONT;
  2376. } else if ( d > offset ) {
  2377. cross[i] = BOX_BACK;
  2378. } else {
  2379. cross[i] = BOX_CROSS;
  2380. }
  2381. }
  2382. // see if any of the surface planes are intersected
  2383. facet = pc->facets;
  2384. for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
  2385. // the facet plane must be in a cross state
  2386. if ( cross[facet->surfacePlane] != BOX_CROSS ) {
  2387. continue;
  2388. }
  2389. // all of the boundaries must be either cross or back
  2390. for ( j = 0 ; j < facet->numBorders ; j++ ) {
  2391. k = facet->borderPlanes[j];
  2392. if ( cross[ k ] == BOX_CROSS ) {
  2393. continue;
  2394. }
  2395. if ( cross[k] ^ facet->borderInward[j] ) {
  2396. break;
  2397. }
  2398. }
  2399. // if we passed all borders, we are definately in this facet
  2400. if ( j == facet->numBorders ) {
  2401. return qtrue;
  2402. }
  2403. }
  2404. return qfalse;
  2405. }
  2406. #endif // _XBOX
  2407. /*
  2408. =======================================================================
  2409. DEBUGGING
  2410. =======================================================================
  2411. */
  2412. /*
  2413. ==================
  2414. CM_DrawDebugSurface
  2415. Called from the renderer
  2416. ==================
  2417. */
  2418. #ifndef BSPC
  2419. void BotDrawDebugPolygons(void (*drawPoly)(int color, int numPoints, float *points), int value);
  2420. #endif
  2421. void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ) {
  2422. #ifndef _XBOX
  2423. static cvar_t *cv;
  2424. const patchCollide_t *pc;
  2425. facet_t *facet;
  2426. winding_t *w;
  2427. int i, j, k, n;
  2428. int curplanenum, planenum, curinward, inward;
  2429. float plane[4];
  2430. vec3_t mins = {-15, -15, -28}, maxs = {15, 15, 28};
  2431. //vec3_t mins = {0, 0, 0}, maxs = {0, 0, 0};
  2432. vec3_t v1, v2;
  2433. if ( !debugPatchCollide ) {
  2434. return;
  2435. }
  2436. #ifndef BSPC
  2437. if ( !cv ) {
  2438. cv = Cvar_Get( "cm_debugSize", "2", 0 );
  2439. }
  2440. #endif
  2441. pc = debugPatchCollide;
  2442. for ( i = 0, facet = pc->facets ; i < pc->numFacets ; i++, facet++ ) {
  2443. for ( k = 0 ; k < facet->numBorders + 1; k++ ) {
  2444. //
  2445. if (k < facet->numBorders) {
  2446. planenum = facet->borderPlanes[k];
  2447. inward = facet->borderInward[k];
  2448. }
  2449. else {
  2450. planenum = facet->surfacePlane;
  2451. inward = qfalse;
  2452. //continue;
  2453. }
  2454. Vector4Copy( pc->planes[ planenum ].plane, plane );
  2455. //planenum = facet->surfacePlane;
  2456. if ( inward ) {
  2457. VectorSubtract( vec3_origin, plane, plane );
  2458. plane[3] = -plane[3];
  2459. }
  2460. plane[3] += cv->value;
  2461. //*
  2462. for (n = 0; n < 3; n++)
  2463. {
  2464. if (plane[n] > 0) v1[n] = maxs[n];
  2465. else v1[n] = mins[n];
  2466. } //end for
  2467. VectorNegate(plane, v2);
  2468. plane[3] += fabs(DotProduct(v1, v2));
  2469. //*/
  2470. w = BaseWindingForPlane( plane, plane[3] );
  2471. for ( j = 0 ; j < facet->numBorders + 1 && w; j++ ) {
  2472. //
  2473. if (j < facet->numBorders) {
  2474. curplanenum = facet->borderPlanes[j];
  2475. curinward = facet->borderInward[j];
  2476. }
  2477. else {
  2478. curplanenum = facet->surfacePlane;
  2479. curinward = qfalse;
  2480. //continue;
  2481. }
  2482. //
  2483. if (curplanenum == planenum) continue;
  2484. Vector4Copy( pc->planes[ curplanenum ].plane, plane );
  2485. if ( !curinward ) {
  2486. VectorSubtract( vec3_origin, plane, plane );
  2487. plane[3] = -plane[3];
  2488. }
  2489. // if ( !facet->borderNoAdjust[j] ) {
  2490. plane[3] -= cv->value;
  2491. // }
  2492. for (n = 0; n < 3; n++)
  2493. {
  2494. if (plane[n] > 0) v1[n] = maxs[n];
  2495. else v1[n] = mins[n];
  2496. } //end for
  2497. VectorNegate(plane, v2);
  2498. plane[3] -= fabs(DotProduct(v1, v2));
  2499. ChopWindingInPlace( &w, plane, plane[3], 0.1f );
  2500. }
  2501. if ( w ) {
  2502. if ( facet == debugFacet ) {
  2503. drawPoly( 4, w->numpoints, w->p[0] );
  2504. //Com_Printf("blue facet has %d border planes\n", facet->numBorders);
  2505. } else {
  2506. drawPoly( 1, w->numpoints, w->p[0] );
  2507. }
  2508. FreeWinding( w );
  2509. }
  2510. else
  2511. Com_Printf("winding chopped away by border planes\n");
  2512. }
  2513. }
  2514. // draw the debug block
  2515. {
  2516. vec3_t v[3];
  2517. VectorCopy( debugBlockPoints[0], v[0] );
  2518. VectorCopy( debugBlockPoints[1], v[1] );
  2519. VectorCopy( debugBlockPoints[2], v[2] );
  2520. drawPoly( 2, 3, v[0] );
  2521. VectorCopy( debugBlockPoints[2], v[0] );
  2522. VectorCopy( debugBlockPoints[3], v[1] );
  2523. VectorCopy( debugBlockPoints[0], v[2] );
  2524. drawPoly( 2, 3, v[0] );
  2525. }
  2526. #if 0
  2527. vec3_t v[4];
  2528. v[0][0] = pc->bounds[1][0];
  2529. v[0][1] = pc->bounds[1][1];
  2530. v[0][2] = pc->bounds[1][2];
  2531. v[1][0] = pc->bounds[1][0];
  2532. v[1][1] = pc->bounds[0][1];
  2533. v[1][2] = pc->bounds[1][2];
  2534. v[2][0] = pc->bounds[0][0];
  2535. v[2][1] = pc->bounds[0][1];
  2536. v[2][2] = pc->bounds[1][2];
  2537. v[3][0] = pc->bounds[0][0];
  2538. v[3][1] = pc->bounds[1][1];
  2539. v[3][2] = pc->bounds[1][2];
  2540. drawPoly( 4, v[0] );
  2541. #endif
  2542. #endif // _XBOX
  2543. }