123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931 |
- #include "cm_local.h"
- #include "cm_patch.h"
- //#define CULL_BBOX
- /*
- This file does not reference any globals, and has these entry points:
- void CM_ClearLevelPatches( void );
- struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points );
- void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
- qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
- void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) );
- Issues for collision against curved surfaces:
- Surface edges need to be handled differently than surface planes
- Plane expansion causes raw surfaces to expand past expanded bounding box
- Position test of a volume against a surface is tricky.
- Position test of a point against a surface is not well defined, because the surface has no volume.
- Tracing leading edge points instead of volumes?
- Position test by tracing corner to corner? (8*7 traces -- ouch)
- coplanar edges
- triangulated patches
- degenerate patches
- endcaps
- degenerate
- WARNING: this may misbehave with meshes that have rows or columns that only
- degenerate a few triangles. Completely degenerate rows and columns are handled
- properly.
- */
- /*
- #define MAX_FACETS 1024
- #define MAX_PATCH_PLANES 2048
- typedef struct {
- float plane[4];
- int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision
- } patchPlane_t;
- typedef struct {
- int surfacePlane;
- int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels
- int borderPlanes[4+6+16];
- int borderInward[4+6+16];
- qboolean borderNoAdjust[4+6+16];
- } facet_t;
- typedef struct patchCollide_s {
- vec3_t bounds[2];
- int numPlanes; // surface planes plus edge planes
- patchPlane_t *planes;
- int numFacets;
- facet_t *facets;
- } patchCollide_t;
- #define MAX_GRID_SIZE 129
- typedef struct {
- int width;
- int height;
- qboolean wrapWidth;
- qboolean wrapHeight;
- vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height]
- } cGrid_t;
- #define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve
- #define PLANE_TRI_EPSILON 0.1
- #define WRAP_POINT_EPSILON 0.1
- */
- #define ADDBEVELS
- int c_totalPatchBlocks;
- int c_totalPatchSurfaces;
- int c_totalPatchEdges;
- static const patchCollide_t *debugPatchCollide;
- static const facet_t *debugFacet;
- static qboolean debugBlock;
- static vec3_t debugBlockPoints[4];
- /*
- =================
- CM_ClearLevelPatches
- =================
- */
- void CM_ClearLevelPatches( void ) {
- debugPatchCollide = NULL;
- debugFacet = NULL;
- }
- /*
- =================
- CM_SignbitsForNormal
- =================
- */
- static int CM_SignbitsForNormal( vec3_t normal ) {
- int bits, j;
- bits = 0;
- for (j=0 ; j<3 ; j++) {
- if ( normal[j] < 0 ) {
- bits |= 1<<j;
- }
- }
- return bits;
- }
- /*
- =====================
- CM_PlaneFromPoints
- Returns false if the triangle is degenrate.
- The normal will point out of the clock for clockwise ordered points
- =====================
- */
- static qboolean CM_PlaneFromPoints( vec4_t plane, vec3_t a, vec3_t b, vec3_t c ) {
- vec3_t d1, d2;
- VectorSubtract( b, a, d1 );
- VectorSubtract( c, a, d2 );
- CrossProduct( d2, d1, plane );
- if ( VectorNormalize( plane ) == 0 ) {
- return qfalse;
- }
- plane[3] = DotProduct( a, plane );
- return qtrue;
- }
- /*
- ================================================================================
- GRID SUBDIVISION
- ================================================================================
- */
- /*
- =================
- CM_NeedsSubdivision
- Returns true if the given quadratic curve is not flat enough for our
- collision detection purposes
- =================
- */
- static qboolean CM_NeedsSubdivision( vec3_t a, vec3_t b, vec3_t c ) {
- vec3_t cmid;
- vec3_t lmid;
- vec3_t delta;
- float dist;
- int i;
- // calculate the linear midpoint
- for ( i = 0 ; i < 3 ; i++ ) {
- lmid[i] = 0.5*(a[i] + c[i]);
- }
- // calculate the exact curve midpoint
- for ( i = 0 ; i < 3 ; i++ ) {
- cmid[i] = 0.5 * ( 0.5*(a[i] + b[i]) + 0.5*(b[i] + c[i]) );
- }
- // see if the curve is far enough away from the linear mid
- VectorSubtract( cmid, lmid, delta );
- dist = VectorLengthSquared( delta );
-
- return dist >= SUBDIVIDE_DISTANCE * SUBDIVIDE_DISTANCE;
- }
- /*
- ===============
- CM_Subdivide
- a, b, and c are control points.
- the subdivided sequence will be: a, out1, out2, out3, c
- ===============
- */
- static void CM_Subdivide( vec3_t a, vec3_t b, vec3_t c, vec3_t out1, vec3_t out2, vec3_t out3 ) {
- int i;
- for ( i = 0 ; i < 3 ; i++ ) {
- out1[i] = 0.5 * (a[i] + b[i]);
- out3[i] = 0.5 * (b[i] + c[i]);
- out2[i] = 0.5 * (out1[i] + out3[i]);
- }
- }
- /*
- =================
- CM_TransposeGrid
- Swaps the rows and columns in place
- =================
- */
- static void CM_TransposeGrid( cGrid_t *grid ) {
- int i, j, l;
- vec3_t temp;
- qboolean tempWrap;
- if ( grid->width > grid->height ) {
- for ( i = 0 ; i < grid->height ; i++ ) {
- for ( j = i + 1 ; j < grid->width ; j++ ) {
- if ( j < grid->height ) {
- // swap the value
- VectorCopy( grid->points[i][j], temp );
- VectorCopy( grid->points[j][i], grid->points[i][j] );
- VectorCopy( temp, grid->points[j][i] );
- } else {
- // just copy
- VectorCopy( grid->points[j][i], grid->points[i][j] );
- }
- }
- }
- } else {
- for ( i = 0 ; i < grid->width ; i++ ) {
- for ( j = i + 1 ; j < grid->height ; j++ ) {
- if ( j < grid->width ) {
- // swap the value
- VectorCopy( grid->points[j][i], temp );
- VectorCopy( grid->points[i][j], grid->points[j][i] );
- VectorCopy( temp, grid->points[i][j] );
- } else {
- // just copy
- VectorCopy( grid->points[i][j], grid->points[j][i] );
- }
- }
- }
- }
- l = grid->width;
- grid->width = grid->height;
- grid->height = l;
- tempWrap = grid->wrapWidth;
- grid->wrapWidth = grid->wrapHeight;
- grid->wrapHeight = tempWrap;
- }
- /*
- ===================
- CM_SetGridWrapWidth
- If the left and right columns are exactly equal, set grid->wrapWidth qtrue
- ===================
- */
- static void CM_SetGridWrapWidth( cGrid_t *grid ) {
- int i, j;
- float d;
- for ( i = 0 ; i < grid->height ; i++ ) {
- for ( j = 0 ; j < 3 ; j++ ) {
- d = grid->points[0][i][j] - grid->points[grid->width-1][i][j];
- if ( d < -WRAP_POINT_EPSILON || d > WRAP_POINT_EPSILON ) {
- break;
- }
- }
- if ( j != 3 ) {
- break;
- }
- }
- if ( i == grid->height ) {
- grid->wrapWidth = qtrue;
- } else {
- grid->wrapWidth = qfalse;
- }
- }
- /*
- =================
- CM_SubdivideGridColumns
- Adds columns as necessary to the grid until
- all the aproximating points are within SUBDIVIDE_DISTANCE
- from the true curve
- =================
- */
- static void CM_SubdivideGridColumns( cGrid_t *grid ) {
- int i, j, k;
- for ( i = 0 ; i < grid->width - 2 ; ) {
- // grid->points[i][x] is an interpolating control point
- // grid->points[i+1][x] is an aproximating control point
- // grid->points[i+2][x] is an interpolating control point
- //
- // first see if we can collapse the aproximating collumn away
- //
- for ( j = 0 ; j < grid->height ; j++ ) {
- if ( CM_NeedsSubdivision( grid->points[i][j], grid->points[i+1][j], grid->points[i+2][j] ) ) {
- break;
- }
- }
- if ( j == grid->height ) {
- // all of the points were close enough to the linear midpoints
- // that we can collapse the entire column away
- for ( j = 0 ; j < grid->height ; j++ ) {
- // remove the column
- for ( k = i + 2 ; k < grid->width ; k++ ) {
- VectorCopy( grid->points[k][j], grid->points[k-1][j] );
- }
- }
- grid->width--;
- // go to the next curve segment
- i++;
- continue;
- }
- //
- // we need to subdivide the curve
- //
- for ( j = 0 ; j < grid->height ; j++ ) {
- vec3_t prev, mid, next;
- // save the control points now
- VectorCopy( grid->points[i][j], prev );
- VectorCopy( grid->points[i+1][j], mid );
- VectorCopy( grid->points[i+2][j], next );
- // make room for two additional columns in the grid
- // columns i+1 will be replaced, column i+2 will become i+4
- // i+1, i+2, and i+3 will be generated
- for ( k = grid->width - 1 ; k > i + 1 ; k-- ) {
- VectorCopy( grid->points[k][j], grid->points[k+2][j] );
- }
- // generate the subdivided points
- CM_Subdivide( prev, mid, next, grid->points[i+1][j], grid->points[i+2][j], grid->points[i+3][j] );
- }
- grid->width += 2;
- // the new aproximating point at i+1 may need to be removed
- // or subdivided farther, so don't advance i
- }
- }
- #define POINT_EPSILON 0.1
- /*
- ======================
- CM_ComparePoints
- ======================
- */
- static qboolean CM_ComparePoints( float *a, float *b ) {
- float d;
- d = a[0] - b[0];
- if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
- return qfalse;
- }
- d = a[1] - b[1];
- if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
- return qfalse;
- }
- d = a[2] - b[2];
- if ( d < -POINT_EPSILON || d > POINT_EPSILON ) {
- return qfalse;
- }
- return qtrue;
- }
- /*
- =================
- CM_RemoveDegenerateColumns
- If there are any identical columns, remove them
- =================
- */
- static void CM_RemoveDegenerateColumns( cGrid_t *grid ) {
- int i, j, k;
- for ( i = 0 ; i < grid->width - 1 ; i++ ) {
- for ( j = 0 ; j < grid->height ; j++ ) {
- if ( !CM_ComparePoints( grid->points[i][j], grid->points[i+1][j] ) ) {
- break;
- }
- }
- if ( j != grid->height ) {
- continue; // not degenerate
- }
- for ( j = 0 ; j < grid->height ; j++ ) {
- // remove the column
- for ( k = i + 2 ; k < grid->width ; k++ ) {
- VectorCopy( grid->points[k][j], grid->points[k-1][j] );
- }
- }
- grid->width--;
- // check against the next column
- i--;
- }
- }
- /*
- ================================================================================
- PATCH COLLIDE GENERATION
- ================================================================================
- */
- static int numPlanes;
- #ifdef _XBOX
- static patchPlane_t *planes = NULL;
- void CM_TempPatchPlanesAlloc(void)
- {
- if(!planes) {
- planes = (patchPlane_t*)Z_Malloc(MAX_PATCH_PLANES*sizeof(patchPlane_t),
- TAG_TEMP_WORKSPACE, qfalse);
- }
- }
- void CM_TempPatchPlanesDealloc(void)
- {
- if(planes) {
- Z_Free(planes);
- planes = NULL;
- }
- }
- #else
- static patchPlane_t planes[MAX_PATCH_PLANES];
- #endif
- //static int numFacets;
- // static facet_t facets[MAX_PATCH_PLANES]; //maybe MAX_FACETS ??
- //static facet_t facets[MAX_FACETS]; // Switched to MAX_FACETS = VV_FIXME, allocate these only during use
- static facet_t *facets = NULL;
- #define NORMAL_EPSILON 0.0001
- #define DIST_EPSILON 0.02
- int CM_PlaneEqual(patchPlane_t *p, float plane[4], int *flipped) {
- float invplane[4];
- if (
- Q_fabs(p->plane[0] - plane[0]) < NORMAL_EPSILON
- && Q_fabs(p->plane[1] - plane[1]) < NORMAL_EPSILON
- && Q_fabs(p->plane[2] - plane[2]) < NORMAL_EPSILON
- && Q_fabs(p->plane[3] - plane[3]) < DIST_EPSILON )
- {
- *flipped = qfalse;
- return qtrue;
- }
- VectorNegate(plane, invplane);
- invplane[3] = -plane[3];
- if (
- Q_fabs(p->plane[0] - invplane[0]) < NORMAL_EPSILON
- && Q_fabs(p->plane[1] - invplane[1]) < NORMAL_EPSILON
- && Q_fabs(p->plane[2] - invplane[2]) < NORMAL_EPSILON
- && Q_fabs(p->plane[3] - invplane[3]) < DIST_EPSILON )
- {
- *flipped = qtrue;
- return qtrue;
- }
- return qfalse;
- }
- void CM_SnapVector(vec3_t normal) {
- int i;
- for (i=0 ; i<3 ; i++)
- {
- if ( Q_fabs(normal[i] - 1) < NORMAL_EPSILON )
- {
- VectorClear (normal);
- normal[i] = 1;
- break;
- }
- if ( Q_fabs(normal[i] - -1) < NORMAL_EPSILON )
- {
- VectorClear (normal);
- normal[i] = -1;
- break;
- }
- }
- }
- int CM_FindPlane2(float plane[4], int *flipped) {
- int i;
- // see if the points are close enough to an existing plane
- for ( i = 0 ; i < numPlanes ; i++ ) {
- if (CM_PlaneEqual(&planes[i], plane, flipped)) return i;
- }
- // add a new plane
- if ( numPlanes == MAX_PATCH_PLANES ) {
- Com_Error( ERR_DROP, "MAX_PATCH_PLANES reached (%d)", MAX_PATCH_PLANES );
- }
- Vector4Copy( plane, planes[numPlanes].plane );
- planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
- numPlanes++;
- *flipped = qfalse;
- return numPlanes-1;
- }
- /*
- ==================
- CM_FindPlane
- ==================
- */
- static int CM_FindPlane( float *p1, float *p2, float *p3 ) {
- float plane[4];
- int i;
- float d;
- if ( !CM_PlaneFromPoints( plane, p1, p2, p3 ) ) {
- return -1;
- }
- // see if the points are close enough to an existing plane
- for ( i = 0 ; i < numPlanes ; i++ ) {
- if ( DotProduct( plane, planes[i].plane ) < 0 ) {
- continue; // allow backwards planes?
- }
- d = DotProduct( p1, planes[i].plane ) - planes[i].plane[3];
- if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
- continue;
- }
- d = DotProduct( p2, planes[i].plane ) - planes[i].plane[3];
- if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
- continue;
- }
- d = DotProduct( p3, planes[i].plane ) - planes[i].plane[3];
- if ( d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON ) {
- continue;
- }
- // found it
- return i;
- }
- // add a new plane
- if ( numPlanes == MAX_PATCH_PLANES ) {
- Com_Error( ERR_DROP, "MAX_PATCH_PLANES" );
- }
- Vector4Copy( plane, planes[numPlanes].plane );
- planes[numPlanes].signbits = CM_SignbitsForNormal( plane );
- numPlanes++;
- return numPlanes-1;
- }
- /*
- ==================
- CM_PointOnPlaneSide
- ==================
- */
- static int CM_PointOnPlaneSide( float *p, int planeNum ) {
- float *plane;
- float d;
- if ( planeNum == -1 ) {
- return SIDE_ON;
- }
- plane = planes[ planeNum ].plane;
- d = DotProduct( p, plane ) - plane[3];
- if ( d > PLANE_TRI_EPSILON ) {
- return SIDE_FRONT;
- }
- if ( d < -PLANE_TRI_EPSILON ) {
- return SIDE_BACK;
- }
- return SIDE_ON;
- }
- #ifdef _XBOX
- static int CM_GridPlane( int* gridPlanes, int i, int j, int tri ) {
- int p;
- p = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+tri];
- if ( p != -1 ) {
- return p;
- }
- p = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+(!tri)];
- if ( p != -1 ) {
- return p;
- }
- // should never happen
- Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
- return -1;
- }
- #else // _XBOX
- static int CM_GridPlane( int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2], int i, int j, int tri ) {
- int p;
- p = gridPlanes[i][j][tri];
- if ( p != -1 ) {
- return p;
- }
- p = gridPlanes[i][j][!tri];
- if ( p != -1 ) {
- return p;
- }
- // should never happen
- Com_Printf( "WARNING: CM_GridPlane unresolvable\n" );
- return -1;
- }
- #endif // _XBOX
- /*
- ==================
- CM_EdgePlaneNum
- ==================
- */
- #ifdef _XBOX
- static int CM_EdgePlaneNum( cGrid_t *grid, int* gridPlanes/*[PATCH_MAX_GRID_SIZE][PATCH_MAX_GRID_SIZE][2]*/, int i, int j, int k ) {
- float *p1, *p2;
- vec3_t up;
- int p;
- switch ( k ) {
- case 0: // top border
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 2: // bottom border
- p1 = grid->points[i][j+1];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p2, p1, up );
- case 3: // left border
- p1 = grid->points[i][j];
- p2 = grid->points[i][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p2, p1, up );
- case 1: // right border
- p1 = grid->points[i+1][j];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 4: // diagonal out of triangle 0
- p1 = grid->points[i+1][j+1];
- p2 = grid->points[i][j];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 5: // diagonal out of triangle 1
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- }
- Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
- return -1;
- }
- #else
- static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2], int i, int j, int k ) {
- float *p1, *p2;
- vec3_t up;
- int p;
- switch ( k ) {
- case 0: // top border
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 2: // bottom border
- p1 = grid->points[i][j+1];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p2, p1, up );
- case 3: // left border
- p1 = grid->points[i][j];
- p2 = grid->points[i][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p2, p1, up );
- case 1: // right border
- p1 = grid->points[i+1][j];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 4: // diagonal out of triangle 0
- p1 = grid->points[i+1][j+1];
- p2 = grid->points[i][j];
- p = CM_GridPlane( gridPlanes, i, j, 0 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- case 5: // diagonal out of triangle 1
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j+1];
- p = CM_GridPlane( gridPlanes, i, j, 1 );
- VectorMA( p1, 4, planes[ p ].plane, up );
- return CM_FindPlane( p1, p2, up );
- }
- Com_Error( ERR_DROP, "CM_EdgePlaneNum: bad k" );
- return -1;
- }
- #endif
- /*
- ===================
- CM_SetBorderInward
- ===================
- */
- #ifdef _XBOX
- static void CM_SetBorderInward( facetLoad_t *facet, cGrid_t *grid,
- int i, int j, int which ) {
- int k, l;
- float *points[4];
- int numPoints;
- switch ( which ) {
- case -1:
- points[0] = grid->points[i][j];
- points[1] = grid->points[i+1][j];
- points[2] = grid->points[i+1][j+1];
- points[3] = grid->points[i][j+1];
- numPoints = 4;
- break;
- case 0:
- points[0] = grid->points[i][j];
- points[1] = grid->points[i+1][j];
- points[2] = grid->points[i+1][j+1];
- numPoints = 3;
- break;
- case 1:
- points[0] = grid->points[i+1][j+1];
- points[1] = grid->points[i][j+1];
- points[2] = grid->points[i][j];
- numPoints = 3;
- break;
- default:
- Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
- numPoints = 0;
- break;
- }
- for ( k = 0 ; k < facet->numBorders ; k++ ) {
- int front, back;
- front = 0;
- back = 0;
- for ( l = 0 ; l < numPoints ; l++ ) {
- int side;
- side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
- if ( side == SIDE_FRONT ) {
- front++;
- } if ( side == SIDE_BACK ) {
- back++;
- }
- }
- if ( front && !back ) {
- facet->borderInward[k] = qtrue;
- } else if ( back && !front ) {
- facet->borderInward[k] = qfalse;
- } else if ( !front && !back ) {
- // flat side border
- facet->borderPlanes[k] = -1;
- } else {
- // bisecting side border
- Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
- facet->borderInward[k] = qfalse;
- if ( !debugBlock ) {
- debugBlock = qtrue;
- VectorCopy( grid->points[i][j], debugBlockPoints[0] );
- VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
- VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
- VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
- }
- }
- }
- }
- #else // _XBOX
- static void CM_SetBorderInward( facet_t *facet, cGrid_t *grid, int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2],
- int i, int j, int which ) {
- int k, l;
- float *points[4];
- int numPoints;
- switch ( which ) {
- case -1:
- points[0] = grid->points[i][j];
- points[1] = grid->points[i+1][j];
- points[2] = grid->points[i+1][j+1];
- points[3] = grid->points[i][j+1];
- numPoints = 4;
- break;
- case 0:
- points[0] = grid->points[i][j];
- points[1] = grid->points[i+1][j];
- points[2] = grid->points[i+1][j+1];
- numPoints = 3;
- break;
- case 1:
- points[0] = grid->points[i+1][j+1];
- points[1] = grid->points[i][j+1];
- points[2] = grid->points[i][j];
- numPoints = 3;
- break;
- default:
- Com_Error( ERR_FATAL, "CM_SetBorderInward: bad parameter" );
- numPoints = 0;
- break;
- }
- for ( k = 0 ; k < facet->numBorders ; k++ ) {
- int front, back;
- front = 0;
- back = 0;
- for ( l = 0 ; l < numPoints ; l++ ) {
- int side;
- side = CM_PointOnPlaneSide( points[l], facet->borderPlanes[k] );
- if ( side == SIDE_FRONT ) {
- front++;
- } if ( side == SIDE_BACK ) {
- back++;
- }
- }
- if ( front && !back ) {
- facet->borderInward[k] = qtrue;
- } else if ( back && !front ) {
- facet->borderInward[k] = qfalse;
- } else if ( !front && !back ) {
- // flat side border
- facet->borderPlanes[k] = -1;
- } else {
- // bisecting side border
- Com_DPrintf( "WARNING: CM_SetBorderInward: mixed plane sides\n" );
- facet->borderInward[k] = qfalse;
- if ( !debugBlock ) {
- debugBlock = qtrue;
- VectorCopy( grid->points[i][j], debugBlockPoints[0] );
- VectorCopy( grid->points[i+1][j], debugBlockPoints[1] );
- VectorCopy( grid->points[i+1][j+1], debugBlockPoints[2] );
- VectorCopy( grid->points[i][j+1], debugBlockPoints[3] );
- }
- }
- }
- }
- #endif
- /*
- ==================
- CM_ValidateFacet
- If the facet isn't bounded by its borders, we screwed up.
- ==================
- */
- #ifdef _XBOX
- static qboolean CM_ValidateFacet( facetLoad_t *facet ) {
- float plane[4];
- int j;
- winding_t *w;
- vec3_t bounds[2];
- if ( facet->surfacePlane == -1 ) {
- return qfalse;
- }
- Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
- w = BaseWindingForPlane( plane, plane[3] );
- for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
- if ( facet->borderPlanes[j] == -1 ) {
- FreeWinding(w);
- return qfalse;
- }
- Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
- if ( !facet->borderInward[j] ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- ChopWindingInPlace( &w, plane, plane[3], 0.1f );
- }
- if ( !w ) {
- return qfalse; // winding was completely chopped away
- }
- // see if the facet is unreasonably large
- WindingBounds( w, bounds[0], bounds[1] );
- FreeWinding( w );
-
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
- return qfalse; // we must be missing a plane
- }
- if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
- return qfalse;
- }
- if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
- return qfalse;
- }
- }
- return qtrue; // winding is fine
- }
- #else // _XBOX
- static qboolean CM_ValidateFacet( facet_t *facet ) {
- float plane[4];
- int j;
- winding_t *w;
- vec3_t bounds[2];
- if ( facet->surfacePlane == -1 ) {
- return qfalse;
- }
- Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
- w = BaseWindingForPlane( plane, plane[3] );
- for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
- if ( facet->borderPlanes[j] == -1 ) {
- FreeWinding(w);
- return qfalse;
- }
- Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
- if ( !facet->borderInward[j] ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- ChopWindingInPlace( &w, plane, plane[3], 0.1f );
- }
- if ( !w ) {
- return qfalse; // winding was completely chopped away
- }
- // see if the facet is unreasonably large
- WindingBounds( w, bounds[0], bounds[1] );
- FreeWinding( w );
-
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
- return qfalse; // we must be missing a plane
- }
- if ( bounds[0][j] >= MAX_MAP_BOUNDS ) {
- return qfalse;
- }
- if ( bounds[1][j] <= -MAX_MAP_BOUNDS ) {
- return qfalse;
- }
- }
- return qtrue; // winding is fine
- }
- #endif // _XBOX
- /*
- ==================
- CM_AddFacetBevels
- ==================
- */
- #ifdef _XBOX
- void CM_AddFacetBevels( facetLoad_t *facet ) {
- int i, j, k, l;
- int axis, dir, order, flipped;
- float plane[4], d, newplane[4];
- winding_t *w, *w2;
- vec3_t mins, maxs, vec, vec2;
- #ifndef ADDBEVELS
- return;
- #endif
- Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
- w = BaseWindingForPlane( plane, plane[3] );
- for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
- if (facet->borderPlanes[j] == facet->surfacePlane) continue;
- Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
- if ( !facet->borderInward[j] ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- ChopWindingInPlace( &w, plane, plane[3], 0.1f );
- }
- if ( !w ) {
- return;
- }
- WindingBounds(w, mins, maxs);
- // add the axial planes
- order = 0;
- for ( axis = 0 ; axis < 3 ; axis++ )
- {
- for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
- {
- VectorClear(plane);
- plane[axis] = dir;
- if (dir == 1) {
- plane[3] = maxs[axis];
- }
- else {
- plane[3] = -mins[axis];
- }
- //if it's the surface plane
- if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
- continue;
- }
- // see if the plane is allready present
- for ( i = 0 ; i < facet->numBorders ; i++ ) {
- if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
- break;
- }
- if ( i == facet->numBorders ) {
- if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
- int num = CM_FindPlane2(plane, &flipped);
- assert(num > -32768 && num < 32768);
- facet->borderPlanes[facet->numBorders] = num;
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = flipped;
- facet->numBorders++;
- }
- }
- }
- //
- // add the edge bevels
- //
- // test the non-axial plane edges
- for ( j = 0 ; j < w->numpoints ; j++ )
- {
- k = (j+1)%w->numpoints;
- VectorSubtract (w->p[j], w->p[k], vec);
- //if it's a degenerate edge
- if (VectorNormalize (vec) < 0.5)
- continue;
- CM_SnapVector(vec);
- for ( k = 0; k < 3 ; k++ )
- if ( vec[k] == -1 || vec[k] == 1 )
- break; // axial
- if ( k < 3 )
- continue; // only test non-axial edges
- // try the six possible slanted axials from this edge
- for ( axis = 0 ; axis < 3 ; axis++ )
- {
- for ( dir = -1 ; dir <= 1 ; dir += 2 )
- {
- // construct a plane
- VectorClear (vec2);
- vec2[axis] = dir;
- CrossProduct (vec, vec2, plane);
- if (VectorNormalize (plane) < 0.5)
- continue;
- plane[3] = DotProduct (w->p[j], plane);
- // if all the points of the facet winding are
- // behind this plane, it is a proper edge bevel
- for ( l = 0 ; l < w->numpoints ; l++ )
- {
- d = DotProduct (w->p[l], plane) - plane[3];
- if (d > 0.1)
- break; // point in front
- }
- if ( l < w->numpoints )
- continue;
- //if it's the surface plane
- if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
- continue;
- }
- // see if the plane is allready present
- for ( i = 0 ; i < facet->numBorders ; i++ ) {
- if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
- break;
- }
- }
- if ( i == facet->numBorders ) {
- if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
- int num = CM_FindPlane2(plane, &flipped);
- assert(num > -32768 && num < 32768);
- facet->borderPlanes[facet->numBorders] = num;
- for ( k = 0 ; k < facet->numBorders ; k++ ) {
- if (facet->borderPlanes[facet->numBorders] ==
- facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
- }
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = flipped;
- //
- w2 = CopyWinding(w);
- Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
- if (!facet->borderInward[facet->numBorders])
- {
- VectorNegate(newplane, newplane);
- newplane[3] = -newplane[3];
- } //end if
- ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
- if (!w2) {
- Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
- continue;
- }
- else {
- FreeWinding(w2);
- }
- //
- facet->numBorders++;
- //already got a bevel
- // break;
- }
- }
- }
- }
- FreeWinding( w );
- #ifndef BSPC
- //add opposite plane
- assert(facet->surfacePlane > -32768 && facet->surfacePlane < 32768);
- facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = qtrue;
- facet->numBorders++;
- #endif //BSPC
- }
- #else // _XBOX
- void CM_AddFacetBevels( facet_t *facet ) {
- int i, j, k, l;
- int axis, dir, order, flipped;
- float plane[4], d, newplane[4];
- winding_t *w, *w2;
- vec3_t mins, maxs, vec, vec2;
- #ifndef ADDBEVELS
- return;
- #endif
- Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
- w = BaseWindingForPlane( plane, plane[3] );
- for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
- if (facet->borderPlanes[j] == facet->surfacePlane) continue;
- Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
- if ( !facet->borderInward[j] ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- ChopWindingInPlace( &w, plane, plane[3], 0.1f );
- }
- if ( !w ) {
- return;
- }
- WindingBounds(w, mins, maxs);
- // add the axial planes
- order = 0;
- for ( axis = 0 ; axis < 3 ; axis++ )
- {
- for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
- {
- VectorClear(plane);
- plane[axis] = dir;
- if (dir == 1) {
- plane[3] = maxs[axis];
- }
- else {
- plane[3] = -mins[axis];
- }
- //if it's the surface plane
- if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
- continue;
- }
- // see if the plane is allready present
- for ( i = 0 ; i < facet->numBorders ; i++ ) {
- if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
- break;
- }
- if ( i == facet->numBorders ) {
- if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
- facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = flipped;
- facet->numBorders++;
- }
- }
- }
- //
- // add the edge bevels
- //
- // test the non-axial plane edges
- for ( j = 0 ; j < w->numpoints ; j++ )
- {
- k = (j+1)%w->numpoints;
- VectorSubtract (w->p[j], w->p[k], vec);
- //if it's a degenerate edge
- if (VectorNormalize (vec) < 0.5)
- continue;
- CM_SnapVector(vec);
- for ( k = 0; k < 3 ; k++ )
- if ( vec[k] == -1 || vec[k] == 1 )
- break; // axial
- if ( k < 3 )
- continue; // only test non-axial edges
- // try the six possible slanted axials from this edge
- for ( axis = 0 ; axis < 3 ; axis++ )
- {
- for ( dir = -1 ; dir <= 1 ; dir += 2 )
- {
- // construct a plane
- VectorClear (vec2);
- vec2[axis] = dir;
- CrossProduct (vec, vec2, plane);
- if (VectorNormalize (plane) < 0.5)
- continue;
- plane[3] = DotProduct (w->p[j], plane);
- // if all the points of the facet winding are
- // behind this plane, it is a proper edge bevel
- for ( l = 0 ; l < w->numpoints ; l++ )
- {
- d = DotProduct (w->p[l], plane) - plane[3];
- if (d > 0.1)
- break; // point in front
- }
- if ( l < w->numpoints )
- continue;
- //if it's the surface plane
- if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
- continue;
- }
- // see if the plane is allready present
- for ( i = 0 ; i < facet->numBorders ; i++ ) {
- if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
- break;
- }
- }
- if ( i == facet->numBorders ) {
- if (facet->numBorders > 4 + 6 + 16) Com_Printf(S_COLOR_RED"ERROR: too many bevels\n");
- facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
- for ( k = 0 ; k < facet->numBorders ; k++ ) {
- if (facet->borderPlanes[facet->numBorders] ==
- facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
- }
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = flipped;
- //
- w2 = CopyWinding(w);
- Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
- if (!facet->borderInward[facet->numBorders])
- {
- VectorNegate(newplane, newplane);
- newplane[3] = -newplane[3];
- } //end if
- ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
- if (!w2) {
- Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
- continue;
- }
- else {
- FreeWinding(w2);
- }
- //
- facet->numBorders++;
- //already got a bevel
- // break;
- }
- }
- }
- }
- FreeWinding( w );
- #ifndef BSPC
- //add opposite plane
- facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
- facet->borderNoAdjust[facet->numBorders] = 0;
- facet->borderInward[facet->numBorders] = qtrue;
- facet->numBorders++;
- #endif //BSPC
- }
- #endif // _XBOX
- typedef enum {
- EN_TOP,
- EN_RIGHT,
- EN_BOTTOM,
- EN_LEFT
- } edgeName_t;
- #ifdef _XBOX
- facetLoad_t* cm_facets = 0;
- int* cm_gridPlanes = 0;
- void CM_PatchCollideFromGridTempAlloc()
- {
- if (!cm_facets)
- {
- cm_facets = (facetLoad_t*)Z_Malloc(MAX_PATCH_PLANES*sizeof(facetLoad_t), TAG_TEMP_WORKSPACE, qfalse);
- }
- if (!cm_gridPlanes)
- {
- cm_gridPlanes = (int*)Z_Malloc(CM_MAX_GRID_SIZE*CM_MAX_GRID_SIZE*2*sizeof(int), TAG_TEMP_WORKSPACE, qfalse);
- }
- }
- void CM_PatchCollideFromGridTempDealloc()
- {
- Z_Free(cm_gridPlanes);
- Z_Free(cm_facets);
- cm_gridPlanes = 0;
- cm_facets = 0;
- }
- #endif
- /*
- ==================
- CM_PatchCollideFromGrid
- ==================
- */
- #ifdef _XBOX
- int min1 = 0, max1 = 0, min2 = 0, max2 = 0;
- static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf,
- facetLoad_t *facetbuf, int *gridbuf ) {
- int i, j;
- float *p1, *p2, *p3;
- int *gridPlanes;
- facetLoad_t *facet;
- int borders[4];
- int noAdjust[4];
- facetLoad_t *facets;
- int numFacets;
- facets = cm_facets;
- if (facets == 0)
- {
- facets = facetbuf;
- }
- gridPlanes = cm_gridPlanes;
- if (gridPlanes == 0)
- {
- gridPlanes = gridbuf;
- }
-
- numPlanes = 0;
- numFacets = 0;
- // find the planes for each triangle of the grid
- for ( i = 0 ; i < grid->width - 1 ; i++ ) {
- for ( j = 0 ; j < grid->height - 1 ; j++ ) {
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j];
- p3 = grid->points[i+1][j+1];
- gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] = CM_FindPlane( p1, p2, p3 );
- p1 = grid->points[i+1][j+1];
- p2 = grid->points[i][j+1];
- p3 = grid->points[i][j];
- gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] = CM_FindPlane( p1, p2, p3 );
- }
- }
- // create the borders for each facet
- for ( i = 0 ; i < grid->width - 1 ; i++ ) {
- for ( j = 0 ; j < grid->height - 1 ; j++ ) {
-
- borders[EN_TOP] = -1;
- if ( j > 0 ) {
- borders[EN_TOP] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(j-1)*2+1];
- } else if ( grid->wrapHeight ) {
- borders[EN_TOP] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(grid->height-2)*2+1];
- }
- noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] );
- if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
- borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
- }
- borders[EN_BOTTOM] = -1;
- if ( j < grid->height - 2 ) {
- borders[EN_BOTTOM] = gridPlanes[i*CM_MAX_GRID_SIZE*2+(j+1)*2+0];
- } else if ( grid->wrapHeight ) {
- borders[EN_BOTTOM] = gridPlanes[i*CM_MAX_GRID_SIZE*2+0*2+0];
- }
- noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] );
- if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
- borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
- }
- borders[EN_LEFT] = -1;
- if ( i > 0 ) {
- borders[EN_LEFT] = gridPlanes[(i-1)*CM_MAX_GRID_SIZE*2+j*2+0];
- } else if ( grid->wrapWidth ) {
- borders[EN_LEFT] = gridPlanes[(grid->width-2)*CM_MAX_GRID_SIZE*2+j*2+0];
- }
- noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] );
- if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
- borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
- }
- borders[EN_RIGHT] = -1;
- if ( i < grid->width - 2 ) {
- borders[EN_RIGHT] = gridPlanes[(i+1)*CM_MAX_GRID_SIZE*2+j*2+1];
- } else if ( grid->wrapWidth ) {
- borders[EN_RIGHT] = gridPlanes[0*CM_MAX_GRID_SIZE*2+j*2+1];
- }
- noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] );
- if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
- borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
- }
- if ( numFacets == MAX_FACETS ) {
- Com_Error( ERR_DROP, "MAX_FACETS" );
- }
- facet = &facets[numFacets];
- memset( facet, 0, sizeof( *facet ) );
- if ( gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] == gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] ) {
- if ( gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] == -1 ) {
- continue; // degenrate
- }
- facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
- facet->numBorders = 4;
- facet->borderPlanes[0] = borders[EN_TOP];
- assert(borders[EN_TOP] > -32768 && borders[EN_TOP] < 32768);
- facet->borderNoAdjust[0] = noAdjust[EN_TOP];
- assert(noAdjust[EN_TOP] >= 0 && noAdjust[EN_TOP] < 256);
- facet->borderPlanes[1] = borders[EN_RIGHT];
- assert(borders[EN_RIGHT] > -32768 && borders[EN_RIGHT] < 32768);
- facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
- assert(noAdjust[EN_RIGHT] >= 0 && noAdjust[EN_RIGHT] < 256);
- facet->borderPlanes[2] = borders[EN_BOTTOM];
- assert(borders[EN_BOTTOM] > -32768 &&
- borders[EN_BOTTOM] < 32768);
- facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
- assert(noAdjust[EN_BOTTOM] >= 0 && noAdjust[EN_BOTTOM] < 256);
- facet->borderPlanes[3] = borders[EN_LEFT];
- assert(borders[EN_LEFT] > -32768 && borders[EN_LEFT] < 32768);
- facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
- assert(noAdjust[EN_LEFT] >= 0 && noAdjust[EN_LEFT] < 256);
- CM_SetBorderInward( facet, grid, i, j, -1 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- } else {
- // two seperate triangles
- facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
- facet->numBorders = 3;
- facet->borderPlanes[0] = borders[EN_TOP];
- assert(borders[EN_TOP] > -32768 && borders[EN_TOP] < 32768);
- assert(noAdjust[EN_TOP] >= 0 && noAdjust[EN_TOP] < 256);
- facet->borderNoAdjust[0] = noAdjust[EN_TOP];
- facet->borderPlanes[1] = borders[EN_RIGHT];
- assert(borders[EN_RIGHT] > -32768 && borders[EN_RIGHT] < 32768);
- facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
- assert(noAdjust[EN_RIGHT] >= 0 && noAdjust[EN_RIGHT] < 256);
- facet->borderPlanes[2] = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1];
- assert(gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] > -32768 &&
- gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1] < 32768);
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = borders[EN_BOTTOM];
- assert(borders[EN_BOTTOM] > -32768 &&
- borders[EN_BOTTOM] < 32768);
- if ( facet->borderPlanes[2] == -1 ) {
- int num = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
- assert(num > -32768 && num < 32768);
- facet->borderPlanes[2] = num;
- }
- }
- CM_SetBorderInward( facet, grid, i, j, 0 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- if ( numFacets == MAX_FACETS ) {
- Com_Error( ERR_DROP, "MAX_FACETS" );
- }
- facet = &facets[numFacets];
- memset( facet, 0, sizeof( *facet ) );
- facet->surfacePlane = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+1];
- facet->numBorders = 3;
- facet->borderPlanes[0] = borders[EN_BOTTOM];
- assert(borders[EN_BOTTOM] > -32768 &&
- borders[EN_BOTTOM] < 32768);
- facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
- assert(noAdjust[EN_BOTTOM] >= 0 && noAdjust[EN_BOTTOM] < 256);
- facet->borderPlanes[1] = borders[EN_LEFT];
- assert(borders[EN_LEFT] > -32768 && borders[EN_LEFT] < 32768);
- facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
- assert(noAdjust[EN_LEFT] >= 0 && noAdjust[EN_LEFT] < 256);
- facet->borderPlanes[2] = gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0];
- assert(gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] > -32768 &&
- gridPlanes[i*CM_MAX_GRID_SIZE*2+j*2+0] < 32768);
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = borders[EN_TOP];
- assert(borders[EN_TOP] > -32768 &&
- borders[EN_TOP] < 32768);
- if ( facet->borderPlanes[2] == -1 ) {
- int num = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
- assert(num > -32768 && num < 32768);
- facet->borderPlanes[2] = num;
- }
- }
- CM_SetBorderInward( facet, grid, i, j, 1 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- }
- }
- }
- // copy the results out
- pf->numPlanes = numPlanes;
- pf->numFacets = numFacets;
- if (numFacets)
- {
- pf->facets = (facet_t *) Z_Malloc( numFacets * sizeof( *pf->facets ), TAG_BSP, qfalse);
- for(i=0; i<numFacets; i++) {
- pf->facets[i].data = (char*)Z_Malloc(facets[i].numBorders * 4,
- TAG_BSP, qfalse);
- pf->facets[i].surfacePlane = facets[i].surfacePlane;
- pf->facets[i].numBorders = facets[i].numBorders;
- short *bp = pf->facets[i].GetBorderPlanes();
- char *bi = pf->facets[i].GetBorderInward();
- char *bna = pf->facets[i].GetBorderNoAdjust();
- for(j=0; j<facets[i].numBorders; j++) {
- bp[j] = facets[i].borderPlanes[j];
- bi[j] = facets[i].borderInward[j];
- bna[j] = facets[i].borderNoAdjust[j];
- }
- }
- }
- else
- {
- pf->facets = 0;
- }
- pf->planes = (patchPlane_t *) Z_Malloc( numPlanes * sizeof( *pf->planes ), TAG_BSP, qfalse);
- memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
- }
- #else
- static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf ) {
- int i, j;
- float *p1, *p2, *p3;
- MAC_STATIC int gridPlanes[CM_MAX_GRID_SIZE][CM_MAX_GRID_SIZE][2];
- facet_t *facet;
- int borders[4];
- int noAdjust[4];
- int numFacets;
- facets = (facet_t*) Z_Malloc(MAX_FACETS*sizeof(facet_t), TAG_TEMP_WORKSPACE, qfalse, 4);
- numPlanes = 0;
- numFacets = 0;
- // find the planes for each triangle of the grid
- for ( i = 0 ; i < grid->width - 1 ; i++ ) {
- for ( j = 0 ; j < grid->height - 1 ; j++ ) {
- p1 = grid->points[i][j];
- p2 = grid->points[i+1][j];
- p3 = grid->points[i+1][j+1];
- gridPlanes[i][j][0] = CM_FindPlane( p1, p2, p3 );
- p1 = grid->points[i+1][j+1];
- p2 = grid->points[i][j+1];
- p3 = grid->points[i][j];
- gridPlanes[i][j][1] = CM_FindPlane( p1, p2, p3 );
- }
- }
- // create the borders for each facet
- for ( i = 0 ; i < grid->width - 1 ; i++ ) {
- for ( j = 0 ; j < grid->height - 1 ; j++ ) {
-
- borders[EN_TOP] = -1;
- if ( j > 0 ) {
- borders[EN_TOP] = gridPlanes[i][j-1][1];
- } else if ( grid->wrapHeight ) {
- borders[EN_TOP] = gridPlanes[i][grid->height-2][1];
- }
- noAdjust[EN_TOP] = ( borders[EN_TOP] == gridPlanes[i][j][0] );
- if ( borders[EN_TOP] == -1 || noAdjust[EN_TOP] ) {
- borders[EN_TOP] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 0 );
- }
- borders[EN_BOTTOM] = -1;
- if ( j < grid->height - 2 ) {
- borders[EN_BOTTOM] = gridPlanes[i][j+1][0];
- } else if ( grid->wrapHeight ) {
- borders[EN_BOTTOM] = gridPlanes[i][0][0];
- }
- noAdjust[EN_BOTTOM] = ( borders[EN_BOTTOM] == gridPlanes[i][j][1] );
- if ( borders[EN_BOTTOM] == -1 || noAdjust[EN_BOTTOM] ) {
- borders[EN_BOTTOM] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 2 );
- }
- borders[EN_LEFT] = -1;
- if ( i > 0 ) {
- borders[EN_LEFT] = gridPlanes[i-1][j][0];
- } else if ( grid->wrapWidth ) {
- borders[EN_LEFT] = gridPlanes[grid->width-2][j][0];
- }
- noAdjust[EN_LEFT] = ( borders[EN_LEFT] == gridPlanes[i][j][1] );
- if ( borders[EN_LEFT] == -1 || noAdjust[EN_LEFT] ) {
- borders[EN_LEFT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 3 );
- }
- borders[EN_RIGHT] = -1;
- if ( i < grid->width - 2 ) {
- borders[EN_RIGHT] = gridPlanes[i+1][j][1];
- } else if ( grid->wrapWidth ) {
- borders[EN_RIGHT] = gridPlanes[0][j][1];
- }
- noAdjust[EN_RIGHT] = ( borders[EN_RIGHT] == gridPlanes[i][j][0] );
- if ( borders[EN_RIGHT] == -1 || noAdjust[EN_RIGHT] ) {
- borders[EN_RIGHT] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 1 );
- }
- if ( numFacets == MAX_FACETS ) {
- Com_Error( ERR_DROP, "MAX_FACETS" );
- }
- facet = &facets[numFacets];
- memset( facet, 0, sizeof( *facet ) );
- if ( gridPlanes[i][j][0] == gridPlanes[i][j][1] ) {
- if ( gridPlanes[i][j][0] == -1 ) {
- continue; // degenrate
- }
- facet->surfacePlane = gridPlanes[i][j][0];
- facet->numBorders = 4;
- facet->borderPlanes[0] = borders[EN_TOP];
- facet->borderNoAdjust[0] = noAdjust[EN_TOP];
- facet->borderPlanes[1] = borders[EN_RIGHT];
- facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
- facet->borderPlanes[2] = borders[EN_BOTTOM];
- facet->borderNoAdjust[2] = noAdjust[EN_BOTTOM];
- facet->borderPlanes[3] = borders[EN_LEFT];
- facet->borderNoAdjust[3] = noAdjust[EN_LEFT];
- CM_SetBorderInward( facet, grid, gridPlanes, i, j, -1 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- } else {
- // two seperate triangles
- facet->surfacePlane = gridPlanes[i][j][0];
- facet->numBorders = 3;
- facet->borderPlanes[0] = borders[EN_TOP];
- facet->borderNoAdjust[0] = noAdjust[EN_TOP];
- facet->borderPlanes[1] = borders[EN_RIGHT];
- facet->borderNoAdjust[1] = noAdjust[EN_RIGHT];
- facet->borderPlanes[2] = gridPlanes[i][j][1];
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = borders[EN_BOTTOM];
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 4 );
- }
- }
- CM_SetBorderInward( facet, grid, gridPlanes, i, j, 0 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- if ( numFacets == MAX_FACETS ) {
- Com_Error( ERR_DROP, "MAX_FACETS" );
- }
- facet = &facets[numFacets];
- memset( facet, 0, sizeof( *facet ) );
- facet->surfacePlane = gridPlanes[i][j][1];
- facet->numBorders = 3;
- facet->borderPlanes[0] = borders[EN_BOTTOM];
- facet->borderNoAdjust[0] = noAdjust[EN_BOTTOM];
- facet->borderPlanes[1] = borders[EN_LEFT];
- facet->borderNoAdjust[1] = noAdjust[EN_LEFT];
- facet->borderPlanes[2] = gridPlanes[i][j][0];
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = borders[EN_TOP];
- if ( facet->borderPlanes[2] == -1 ) {
- facet->borderPlanes[2] = CM_EdgePlaneNum( grid, gridPlanes, i, j, 5 );
- }
- }
- CM_SetBorderInward( facet, grid, gridPlanes, i, j, 1 );
- if ( CM_ValidateFacet( facet ) ) {
- CM_AddFacetBevels( facet );
- numFacets++;
- }
- }
- }
- }
- // copy the results out
- pf->numPlanes = numPlanes;
- pf->numFacets = numFacets;
- if (numFacets)
- {
- pf->facets = (facet_t *) Z_Malloc( numFacets * sizeof( *pf->facets ), TAG_BSP, qfalse);
- memcpy( pf->facets, facets, numFacets * sizeof( *pf->facets ) );
- }
- else
- {
- pf->facets = 0;
- }
- pf->planes = (patchPlane_t *) Z_Malloc( numPlanes * sizeof( *pf->planes ), TAG_BSP, qfalse);
- memcpy( pf->planes, planes, numPlanes * sizeof( *pf->planes ) );
- Z_Free(facets);
- }
- #endif // _XBOX
- static patchCollide_t *pfScratch = 0;
- void CM_PreparePatchCollide(int num)
- {
- pfScratch = (patchCollide_t *) Z_Malloc( sizeof( *pfScratch ) * num, TAG_BSP, qfalse );
- }
- cGrid_t *cm_grid = 0;
- void CM_GridAlloc()
- {
- if (cm_grid) return;
- cm_grid = (cGrid_t*)Z_Malloc(sizeof(cGrid_t), TAG_TEMP_WORKSPACE, qfalse);
- }
- void CM_GridDealloc()
- {
- Z_Free(cm_grid);
- cm_grid = 0;
- }
- /*
- ===================
- CM_GeneratePatchCollide
- Creates an internal structure that will be used to perform
- collision detection with a patch mesh.
- Points is packed as concatenated rows.
- ===================
- */
- #ifdef _XBOX
- struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points,
- facetLoad_t *facetbuf, int *gridbuf ) {
- patchCollide_t *pf;
- // --AAA--AAA--
- // cGrid_t *grid = new cGrid_t;
- cGrid_t *grid = cm_grid;
- // --AAA--AAA--
- int i, j;
- memset(grid, 0, sizeof(cGrid_t));
- if ( width <= 2 || height <= 2 || !points ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
- width, height, points );
- }
- if ( !(width & 1) || !(height & 1) ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
- }
- if ( width > CM_MAX_GRID_SIZE || height > CM_MAX_GRID_SIZE ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > CM_MAX_GRID_SIZE" );
- }
- // build a grid
- grid->width = width;
- grid->height = height;
- grid->wrapWidth = qfalse;
- grid->wrapHeight = qfalse;
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 0 ; j < height ; j++ ) {
- VectorCopy( points[j*width + i], grid->points[i][j] );
- }
- }
- // subdivide the grid
- CM_SetGridWrapWidth( grid );
- CM_SubdivideGridColumns( grid );
- CM_RemoveDegenerateColumns( grid );
- CM_TransposeGrid( grid );
- CM_SetGridWrapWidth( grid );
- CM_SubdivideGridColumns( grid );
- CM_RemoveDegenerateColumns( grid );
- // we now have a grid of points exactly on the curve
- // the aproximate surface defined by these points will be
- // collided against
-
- // --AAA--AAA--
- // pf = (patchCollide_t *) Z_Malloc( sizeof( *pf ), TAG_BSP, qfalse );
- pf = pfScratch++;
- // --AAA--AAA--
-
- ClearBounds( pf->bounds[0], pf->bounds[1] );
- for ( i = 0 ; i < grid->width ; i++ ) {
- for ( j = 0 ; j < grid->height ; j++ ) {
- AddPointToBounds( grid->points[i][j], pf->bounds[0], pf->bounds[1] );
- }
- }
- c_totalPatchBlocks += ( grid->width - 1 ) * ( grid->height - 1 );
- // generate a bsp tree for the surface
- CM_PatchCollideFromGrid( grid, pf, facetbuf, gridbuf );
- // expand by one unit for epsilon purposes
- pf->bounds[0][0] -= 1;
- pf->bounds[0][1] -= 1;
- pf->bounds[0][2] -= 1;
- pf->bounds[1][0] += 1;
- pf->bounds[1][1] += 1;
- pf->bounds[1][2] += 1;
- // --AAA--AAA--
- // delete grid;
- // --AAA--AAA--
- return pf;
- }
- #else
- struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ) {
- patchCollide_t *pf;
- MAC_STATIC cGrid_t grid;
- int i, j;
- if ( width <= 2 || height <= 2 || !points ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: bad parameters: (%i, %i, %p)",
- width, height, points );
- }
- if ( !(width & 1) || !(height & 1) ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: even sizes are invalid for quadratic meshes" );
- }
- if ( width > CM_MAX_GRID_SIZE || height > CM_MAX_GRID_SIZE ) {
- Com_Error( ERR_DROP, "CM_GeneratePatchFacets: source is > CM_MAX_GRID_SIZE" );
- }
- // build a grid
- grid.width = width;
- grid.height = height;
- grid.wrapWidth = qfalse;
- grid.wrapHeight = qfalse;
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 0 ; j < height ; j++ ) {
- VectorCopy( points[j*width + i], grid.points[i][j] );
- }
- }
- // subdivide the grid
- CM_SetGridWrapWidth( &grid );
- CM_SubdivideGridColumns( &grid );
- CM_RemoveDegenerateColumns( &grid );
- CM_TransposeGrid( &grid );
- CM_SetGridWrapWidth( &grid );
- CM_SubdivideGridColumns( &grid );
- CM_RemoveDegenerateColumns( &grid );
- // we now have a grid of points exactly on the curve
- // the aproximate surface defined by these points will be
- // collided against
- pf = (patchCollide_t *) Z_Malloc( sizeof( *pf ), TAG_BSP, qfalse );
- ClearBounds( pf->bounds[0], pf->bounds[1] );
- for ( i = 0 ; i < grid.width ; i++ ) {
- for ( j = 0 ; j < grid.height ; j++ ) {
- AddPointToBounds( grid.points[i][j], pf->bounds[0], pf->bounds[1] );
- }
- }
- c_totalPatchBlocks += ( grid.width - 1 ) * ( grid.height - 1 );
- // generate a bsp tree for the surface
- CM_PatchCollideFromGrid( &grid, pf );
- // expand by one unit for epsilon purposes
- pf->bounds[0][0] -= 1;
- pf->bounds[0][1] -= 1;
- pf->bounds[0][2] -= 1;
- pf->bounds[1][0] += 1;
- pf->bounds[1][1] += 1;
- pf->bounds[1][2] += 1;
- return pf;
- }
- #endif // _XBOX
- /*
- ================================================================================
- TRACE TESTING
- ================================================================================
- */
- /*
- ====================
- CM_TraceThroughPatchCollide
- Modifies tr->tr if any of the facets effect the trace
- ====================
- */
- /*
- void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
- {
- int i, j, n;
- float d1, d2, offset, planedist, fraction;
- vec3_t v1, v2, normal, point;
- patchPlane_t *planes;
- facet_t *facet;
- //
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ )
- {
- planes = &pc->planes[ facet->surfacePlane ];
- VectorCopy(planes->plane, normal);
- for (n = 0; n < 3; n++)
- {
- if (normal[n] > 0) v1[n] = tw->size[0][n];
- else v1[n] = tw->size[1][n];
- } //end for
- VectorNegate(normal, v2);
- offset = DotProduct(v1, v2);
- //offset = 0;
- //
- planedist = planes->plane[3] + offset;
- //
- d1 = DotProduct( tw->start, normal ) - planedist;
- d2 = DotProduct( tw->end, normal ) - planedist;
- // if completely in front of face, no intersection with the entire patch
- if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
- continue;
- }
- // if it doesn't cross the plane, the plane isn't relevent
- if (d1 <= 0 && d2 <= 0 ) {
- continue;
- }
- // crosses face
- if (d1 > d2) { // enter
- fraction = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
- if ( fraction < 0 ) {
- fraction = 0;
- }
- for (j = 0; j < 3; j++)
- point[j] = tw->start[j] + (tw->end[j] - tw->start[j]) * fraction;
- }
- else {
- continue;
- }
- //
- for (j = 0; j < facet->numBorders; j++)
- {
- planes = &pc->planes[ facet->borderPlanes[j] ];
- if (!facet->borderInward[j])
- {
- VectorNegate(planes->plane, normal);
- planedist = -planes->plane[3];
- } //end if
- else
- {
- VectorCopy(planes->plane, normal);
- planedist = planes->plane[3];
- } //end else
- for (n = 0; n < 3; n++)
- {
- if (normal[n] > 0) v1[n] = tw->size[0][n];
- else v1[n] = tw->size[1][n];
- } //end for
- VectorNegate(normal, v2);
- offset = DotProduct(v1, v2);
- //offset = 0;
- planedist -= offset;
- //the hit point should be in front of the (inward facing) border plane
- if (DotProduct(point, normal) - planedist < -ON_EPSILON) break;
- } //end for
- if (j < facet->numBorders) continue;
- //
- if (fraction < tw->trace.fraction)
- {
- debugPatchCollide = pc;
- debugFacet = facet;
- tw->trace.fraction = fraction;
- planes = &pc->planes[ facet->surfacePlane ];
- VectorCopy( planes->plane, tw->trace.plane.normal );
- tw->trace.plane.dist = planes->plane[3];
- } //end if
- } //end for
- } //end of the function CM_TraceThroughPatchCollide*/
- /*
- ====================
- CM_TracePointThroughPatchCollide
- special case for point traces because the patch collide "brushes" have no volume
- ====================
- */
- #ifdef _XBOX
- void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
- qboolean frontFacing[MAX_PATCH_PLANES];
- float intersection[MAX_PATCH_PLANES];
- float intersect;
- const patchPlane_t *planes;
- const facet_t *facet;
- int i, j, k;
- float offset;
- float d1, d2;
- #ifndef BSPC
- static cvar_t *cv;
- #endif //BSPC
- #ifndef BSPC
- if ( !cm_playerCurveClip->integer && !tw->isPoint ) {
- return; // FIXME: until I get player sized clipping working right
- }
- #endif
- if (!pc->numFacets)
- { //not gonna do anything anyhow?
- return;
- }
- // determine the trace's relationship to all planes
- planes = pc->planes;
- for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
- offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
- d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
- d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
- if ( d1 <= 0 ) {
- frontFacing[i] = qfalse;
- } else {
- frontFacing[i] = qtrue;
- }
- if ( d1 == d2 ) {
- intersection[i] = WORLD_SIZE;
- } else {
- intersection[i] = d1 / ( d1 - d2 );
- if ( intersection[i] <= 0 ) {
- intersection[i] = WORLD_SIZE;
- }
- }
- }
- // see if any of the surface planes are intersected
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- if ( !frontFacing[facet->surfacePlane] ) {
- continue;
- }
- intersect = intersection[facet->surfacePlane];
- if ( intersect < 0 ) {
- continue; // surface is behind the starting point
- }
- if ( intersect > tw->trace.fraction ) {
- continue; // already hit something closer
- }
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- k = facet->GetBorderPlanes()[j];
- if ( frontFacing[k] ^ facet->GetBorderInward()[j] ) {
- if ( intersection[k] > intersect ) {
- break;
- }
- } else {
- if ( intersection[k] < intersect ) {
- break;
- }
- }
- }
- if ( j == facet->numBorders ) {
- // we hit this facet
- #ifndef BSPC
- if (!cv) {
- cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
- }
- if (cv->integer) {
- debugPatchCollide = pc;
- debugFacet = facet;
- }
- #endif //BSPC
- planes = &pc->planes[facet->surfacePlane];
- // calculate intersection with a slight pushoff
- offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
- d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
- d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
- tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
- if ( tw->trace.fraction < 0 ) {
- tw->trace.fraction = 0;
- }
- VectorCopy( planes->plane, tw->trace.plane.normal );
- tw->trace.plane.dist = planes->plane[3];
- }
- }
- }
- #else // _XBOX
- void CM_TracePointThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
- qboolean frontFacing[MAX_PATCH_PLANES];
- float intersection[MAX_PATCH_PLANES];
- float intersect;
- const patchPlane_t *planes;
- const facet_t *facet;
- int i, j, k;
- float offset;
- float d1, d2;
- #ifndef BSPC
- static cvar_t *cv;
- #endif //BSPC
- #ifndef BSPC
- if ( !cm_playerCurveClip->integer && !tw->isPoint ) {
- return; // FIXME: until I get player sized clipping working right
- }
- #endif
- if (!pc->numFacets)
- { //not gonna do anything anyhow?
- return;
- }
- // determine the trace's relationship to all planes
- planes = pc->planes;
- for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
- offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
- d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
- d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
- if ( d1 <= 0 ) {
- frontFacing[i] = qfalse;
- } else {
- frontFacing[i] = qtrue;
- }
- if ( d1 == d2 ) {
- intersection[i] = WORLD_SIZE;
- } else {
- intersection[i] = d1 / ( d1 - d2 );
- if ( intersection[i] <= 0 ) {
- intersection[i] = WORLD_SIZE;
- }
- }
- }
- // see if any of the surface planes are intersected
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- if ( !frontFacing[facet->surfacePlane] ) {
- continue;
- }
- intersect = intersection[facet->surfacePlane];
- if ( intersect < 0 ) {
- continue; // surface is behind the starting point
- }
- if ( intersect > tw->trace.fraction ) {
- continue; // already hit something closer
- }
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- k = facet->borderPlanes[j];
- if ( frontFacing[k] ^ facet->borderInward[j] ) {
- if ( intersection[k] > intersect ) {
- break;
- }
- } else {
- if ( intersection[k] < intersect ) {
- break;
- }
- }
- }
- if ( j == facet->numBorders ) {
- // we hit this facet
- #ifndef BSPC
- if (!cv) {
- cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
- }
- if (cv->integer) {
- debugPatchCollide = pc;
- debugFacet = facet;
- }
- #endif //BSPC
- planes = &pc->planes[facet->surfacePlane];
- // calculate intersection with a slight pushoff
- offset = DotProduct( tw->offsets[ planes->signbits ], planes->plane );
- d1 = DotProduct( tw->start, planes->plane ) - planes->plane[3] + offset;
- d2 = DotProduct( tw->end, planes->plane ) - planes->plane[3] + offset;
- tw->trace.fraction = ( d1 - SURFACE_CLIP_EPSILON ) / ( d1 - d2 );
- if ( tw->trace.fraction < 0 ) {
- tw->trace.fraction = 0;
- }
- VectorCopy( planes->plane, tw->trace.plane.normal );
- tw->trace.plane.dist = planes->plane[3];
- }
- }
- }
- #endif
- /*
- ====================
- CM_CheckFacetPlane
- ====================
- */
- int CM_CheckFacetPlane(float *plane, vec3_t start, vec3_t end, float *enterFrac, float *leaveFrac, int *hit) {
- float d1, d2, f;
- *hit = qfalse;
- d1 = DotProduct( start, plane ) - plane[3];
- d2 = DotProduct( end, plane ) - plane[3];
- // if completely in front of face, no intersection with the entire facet
- if (d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ) ) {
- return qfalse;
- }
- // if it doesn't cross the plane, the plane isn't relevent
- if (d1 <= 0 && d2 <= 0 ) {
- return qtrue;
- }
- // crosses face
- if (d1 > d2) { // enter
- f = (d1-SURFACE_CLIP_EPSILON) / (d1-d2);
- if ( f < 0 ) {
- f = 0;
- }
- //always favor previous plane hits and thus also the surface plane hit
- if (f > *enterFrac) {
- *enterFrac = f;
- *hit = qtrue;
- }
- } else { // leave
- f = (d1+SURFACE_CLIP_EPSILON) / (d1-d2);
- if ( f > 1 ) {
- f = 1;
- }
- if (f < *leaveFrac) {
- *leaveFrac = f;
- }
- }
- return qtrue;
- }
- /*
- ====================
- CM_TraceThroughPatchCollide
- ====================
- */
- #ifdef _XBOX
- void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
- {
- int i, j, hit, hitnum;
- float offset, enterFrac, leaveFrac, t;
- patchPlane_t *planes;
- facet_t *facet;
- float plane[4], bestplane[4];
- vec3_t startp, endp;
- #ifndef BSPC
- static cvar_t *cv;
- #endif //BSPC
- #ifndef CULL_BBOX
- // I'm not sure if test is strictly correct. Are all
- // bboxes axis aligned? Do I care? It seems to work
- // good enough...
- for ( i = 0 ; i < 3 ; i++ ) {
- if ( tw->bounds[0][i] > pc->bounds[1][i]
- || tw->bounds[1][i] < pc->bounds[0][i] ) {
- return;
- }
- }
- #endif
- if (tw->isPoint) {
- CM_TracePointThroughPatchCollide( tw, pc );
- return;
- }
- #ifndef ADDBEVELS
- CM_TracePointThroughPatchCollide( tw, pc );
- return;
- #endif
- //
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- enterFrac = -1.0;
- leaveFrac = 1.0;
- hitnum = -1;
- //
- planes = &pc->planes[ facet->surfacePlane ];
- VectorCopy(planes->plane, plane);
- plane[3] = planes->plane[3];
- if ( tw->sphere.use ) {
- // adjust the plane distance apropriately for radius
- plane[3] += tw->sphere.radius;
- // find the closest point on the capsule to the plane
- t = DotProduct( plane, tw->sphere.offset );
- if ( t > 0.0f )
- {
- VectorSubtract( tw->start, tw->sphere.offset, startp );
- VectorSubtract( tw->end, tw->sphere.offset, endp );
- }
- else
- {
- VectorAdd( tw->start, tw->sphere.offset, startp );
- VectorAdd( tw->end, tw->sphere.offset, endp );
- }
- }
- else {
- offset = DotProduct( tw->offsets[ planes->signbits ], plane);
- plane[3] -= offset;
- VectorCopy( tw->start, startp );
- VectorCopy( tw->end, endp );
- }
- if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
- continue;
- }
- if (hit) {
- Vector4Copy(plane, bestplane);
- }
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- planes = &pc->planes[ facet->GetBorderPlanes()[j] ];
- if (facet->GetBorderInward()[j]) {
- VectorNegate(planes->plane, plane);
- plane[3] = -planes->plane[3];
- }
- else {
- VectorCopy(planes->plane, plane);
- plane[3] = planes->plane[3];
- }
- if ( tw->sphere.use ) {
- // adjust the plane distance apropriately for radius
- plane[3] += tw->sphere.radius;
- // find the closest point on the capsule to the plane
- t = DotProduct( plane, tw->sphere.offset );
- if ( t > 0.0f )
- {
- VectorSubtract( tw->start, tw->sphere.offset, startp );
- VectorSubtract( tw->end, tw->sphere.offset, endp );
- }
- else
- {
- VectorAdd( tw->start, tw->sphere.offset, startp );
- VectorAdd( tw->end, tw->sphere.offset, endp );
- }
- }
- else {
- // NOTE: this works even though the plane might be flipped because the bbox is centered
- offset = DotProduct( tw->offsets[ planes->signbits ], plane);
- plane[3] += Q_fabs(offset);
- VectorCopy( tw->start, startp );
- VectorCopy( tw->end, endp );
- }
- if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
- break;
- }
- if (hit) {
- hitnum = j;
- Vector4Copy(plane, bestplane);
- }
- }
- if (j < facet->numBorders) continue;
- //never clip against the back side
- if (hitnum == facet->numBorders - 1) continue;
- if (enterFrac < leaveFrac && enterFrac >= 0) {
- if (enterFrac < tw->trace.fraction) {
- if (enterFrac < 0) {
- enterFrac = 0;
- }
- #ifndef BSPC
- if (!cv) {
- cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
- }
- if (cv && cv->integer) {
- debugPatchCollide = pc;
- debugFacet = facet;
- }
- #endif // BSPC
- tw->trace.fraction = enterFrac;
- VectorCopy( bestplane, tw->trace.plane.normal );
- tw->trace.plane.dist = bestplane[3];
- }
- }
- }
- }
- #else // _XBOX
- void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc )
- {
- int i, j, hit, hitnum;
- float offset, enterFrac, leaveFrac, t;
- patchPlane_t *planes;
- facet_t *facet;
- float plane[4], bestplane[4];
- vec3_t startp, endp;
- #ifndef BSPC
- static cvar_t *cv;
- #endif //BSPC
- if (tw->isPoint) {
- CM_TracePointThroughPatchCollide( tw, pc );
- return;
- }
- #ifndef ADDBEVELS
- CM_TracePointThroughPatchCollide( tw, pc );
- return;
- #endif
- //
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- enterFrac = -1.0;
- leaveFrac = 1.0;
- hitnum = -1;
- //
- planes = &pc->planes[ facet->surfacePlane ];
- VectorCopy(planes->plane, plane);
- plane[3] = planes->plane[3];
- if ( tw->sphere.use ) {
- // adjust the plane distance apropriately for radius
- plane[3] += tw->sphere.radius;
- // find the closest point on the capsule to the plane
- t = DotProduct( plane, tw->sphere.offset );
- if ( t > 0.0f )
- {
- VectorSubtract( tw->start, tw->sphere.offset, startp );
- VectorSubtract( tw->end, tw->sphere.offset, endp );
- }
- else
- {
- VectorAdd( tw->start, tw->sphere.offset, startp );
- VectorAdd( tw->end, tw->sphere.offset, endp );
- }
- }
- else {
- offset = DotProduct( tw->offsets[ planes->signbits ], plane);
- plane[3] -= offset;
- VectorCopy( tw->start, startp );
- VectorCopy( tw->end, endp );
- }
- if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
- continue;
- }
- if (hit) {
- Vector4Copy(plane, bestplane);
- }
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- planes = &pc->planes[ facet->borderPlanes[j] ];
- if (facet->borderInward[j]) {
- VectorNegate(planes->plane, plane);
- plane[3] = -planes->plane[3];
- }
- else {
- VectorCopy(planes->plane, plane);
- plane[3] = planes->plane[3];
- }
- if ( tw->sphere.use ) {
- // adjust the plane distance apropriately for radius
- plane[3] += tw->sphere.radius;
- // find the closest point on the capsule to the plane
- t = DotProduct( plane, tw->sphere.offset );
- if ( t > 0.0f )
- {
- VectorSubtract( tw->start, tw->sphere.offset, startp );
- VectorSubtract( tw->end, tw->sphere.offset, endp );
- }
- else
- {
- VectorAdd( tw->start, tw->sphere.offset, startp );
- VectorAdd( tw->end, tw->sphere.offset, endp );
- }
- }
- else {
- // NOTE: this works even though the plane might be flipped because the bbox is centered
- offset = DotProduct( tw->offsets[ planes->signbits ], plane);
- plane[3] += fabs(offset);
- VectorCopy( tw->start, startp );
- VectorCopy( tw->end, endp );
- }
- if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) {
- break;
- }
- if (hit) {
- hitnum = j;
- Vector4Copy(plane, bestplane);
- }
- }
- if (j < facet->numBorders) continue;
- //never clip against the back side
- if (hitnum == facet->numBorders - 1) continue;
- if (enterFrac < leaveFrac && enterFrac >= 0) {
- if (enterFrac < tw->trace.fraction) {
- if (enterFrac < 0) {
- enterFrac = 0;
- }
- #ifndef BSPC
- if (!cv) {
- cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
- }
- if (cv && cv->integer) {
- debugPatchCollide = pc;
- debugFacet = facet;
- }
- #endif // BSPC
- tw->trace.fraction = enterFrac;
- VectorCopy( bestplane, tw->trace.plane.normal );
- tw->trace.plane.dist = bestplane[3];
- }
- }
- }
- }
- #endif // _XBOX
- /*
- =======================================================================
- POSITION TEST
- =======================================================================
- */
- #define BOX_FRONT 0
- #define BOX_BACK 1
- #define BOX_CROSS 2
- /*
- ====================
- CM_PositionTestInPatchCollide
- Modifies tr->tr if any of the facets effect the trace
- ====================
- */
- #ifdef _XBOX
- qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
- int cross[MAX_PATCH_PLANES];
- const patchPlane_t *planes;
- const facet_t *facet;
- int i, j, k;
- float offset;
- float d;
- //return qfalse;
- #ifndef CULL_BBOX
- for ( i = 0 ; i < 3 ; i++ ) {
- if ( tw->bounds[0][i] > pc->bounds[1][i]
- || tw->bounds[1][i] < pc->bounds[0][i] ) {
- return qfalse;
- }
- }
- #endif
- // determine if the box is in front, behind, or crossing each plane
- planes = pc->planes;
- for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
- d = DotProduct( tw->start, planes->plane ) - planes->plane[3];
- offset = Q_fabs( DotProduct( tw->offsets[ planes->signbits ], planes->plane ) );
- if ( d < -offset ) {
- cross[i] = BOX_FRONT;
- } else if ( d > offset ) {
- cross[i] = BOX_BACK;
- } else {
- cross[i] = BOX_CROSS;
- }
- }
- // see if any of the surface planes are intersected
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- // the facet plane must be in a cross state
- if ( cross[facet->surfacePlane] != BOX_CROSS ) {
- continue;
- }
- // all of the boundaries must be either cross or back
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- k = facet->GetBorderPlanes()[j];
- if ( cross[ k ] == BOX_CROSS ) {
- continue;
- }
- if ( cross[k] ^ facet->GetBorderInward()[j] ) {
- break;
- }
- }
- // if we passed all borders, we are definately in this facet
- if ( j == facet->numBorders ) {
- return qtrue;
- }
- }
- return qfalse;
- }
- #else // _XBOX
- qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) {
- int cross[MAX_PATCH_PLANES];
- const patchPlane_t *planes;
- const facet_t *facet;
- int i, j, k;
- float offset;
- float d;
- //return qfalse;
- #ifndef CULL_BBOX
- for ( i = 0 ; i < 3 ; i++ ) {
- if ( tw->bounds[0][i] > pc->bounds[1][i]
- || tw->bounds[1][i] < pc->bounds[0][i] ) {
- return qfalse;
- }
- }
- #endif
- // determine if the box is in front, behind, or crossing each plane
- planes = pc->planes;
- for ( i = 0 ; i < pc->numPlanes ; i++, planes++ ) {
- d = DotProduct( tw->start, planes->plane ) - planes->plane[3];
- offset = fabs( DotProduct( tw->offsets[ planes->signbits ], planes->plane ) );
- if ( d < -offset ) {
- cross[i] = BOX_FRONT;
- } else if ( d > offset ) {
- cross[i] = BOX_BACK;
- } else {
- cross[i] = BOX_CROSS;
- }
- }
- // see if any of the surface planes are intersected
- facet = pc->facets;
- for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
- // the facet plane must be in a cross state
- if ( cross[facet->surfacePlane] != BOX_CROSS ) {
- continue;
- }
- // all of the boundaries must be either cross or back
- for ( j = 0 ; j < facet->numBorders ; j++ ) {
- k = facet->borderPlanes[j];
- if ( cross[ k ] == BOX_CROSS ) {
- continue;
- }
- if ( cross[k] ^ facet->borderInward[j] ) {
- break;
- }
- }
- // if we passed all borders, we are definately in this facet
- if ( j == facet->numBorders ) {
- return qtrue;
- }
- }
- return qfalse;
- }
- #endif // _XBOX
- /*
- =======================================================================
- DEBUGGING
- =======================================================================
- */
- /*
- ==================
- CM_DrawDebugSurface
- Called from the renderer
- ==================
- */
- #ifndef BSPC
- void BotDrawDebugPolygons(void (*drawPoly)(int color, int numPoints, float *points), int value);
- #endif
- void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ) {
- #ifndef _XBOX
- static cvar_t *cv;
- const patchCollide_t *pc;
- facet_t *facet;
- winding_t *w;
- int i, j, k, n;
- int curplanenum, planenum, curinward, inward;
- float plane[4];
- vec3_t mins = {-15, -15, -28}, maxs = {15, 15, 28};
- //vec3_t mins = {0, 0, 0}, maxs = {0, 0, 0};
- vec3_t v1, v2;
- if ( !debugPatchCollide ) {
- return;
- }
- #ifndef BSPC
- if ( !cv ) {
- cv = Cvar_Get( "cm_debugSize", "2", 0 );
- }
- #endif
- pc = debugPatchCollide;
- for ( i = 0, facet = pc->facets ; i < pc->numFacets ; i++, facet++ ) {
- for ( k = 0 ; k < facet->numBorders + 1; k++ ) {
- //
- if (k < facet->numBorders) {
- planenum = facet->borderPlanes[k];
- inward = facet->borderInward[k];
- }
- else {
- planenum = facet->surfacePlane;
- inward = qfalse;
- //continue;
- }
- Vector4Copy( pc->planes[ planenum ].plane, plane );
- //planenum = facet->surfacePlane;
- if ( inward ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- plane[3] += cv->value;
- //*
- for (n = 0; n < 3; n++)
- {
- if (plane[n] > 0) v1[n] = maxs[n];
- else v1[n] = mins[n];
- } //end for
- VectorNegate(plane, v2);
- plane[3] += fabs(DotProduct(v1, v2));
- //*/
- w = BaseWindingForPlane( plane, plane[3] );
- for ( j = 0 ; j < facet->numBorders + 1 && w; j++ ) {
- //
- if (j < facet->numBorders) {
- curplanenum = facet->borderPlanes[j];
- curinward = facet->borderInward[j];
- }
- else {
- curplanenum = facet->surfacePlane;
- curinward = qfalse;
- //continue;
- }
- //
- if (curplanenum == planenum) continue;
- Vector4Copy( pc->planes[ curplanenum ].plane, plane );
- if ( !curinward ) {
- VectorSubtract( vec3_origin, plane, plane );
- plane[3] = -plane[3];
- }
- // if ( !facet->borderNoAdjust[j] ) {
- plane[3] -= cv->value;
- // }
- for (n = 0; n < 3; n++)
- {
- if (plane[n] > 0) v1[n] = maxs[n];
- else v1[n] = mins[n];
- } //end for
- VectorNegate(plane, v2);
- plane[3] -= fabs(DotProduct(v1, v2));
- ChopWindingInPlace( &w, plane, plane[3], 0.1f );
- }
- if ( w ) {
- if ( facet == debugFacet ) {
- drawPoly( 4, w->numpoints, w->p[0] );
- //Com_Printf("blue facet has %d border planes\n", facet->numBorders);
- } else {
- drawPoly( 1, w->numpoints, w->p[0] );
- }
- FreeWinding( w );
- }
- else
- Com_Printf("winding chopped away by border planes\n");
- }
- }
- // draw the debug block
- {
- vec3_t v[3];
- VectorCopy( debugBlockPoints[0], v[0] );
- VectorCopy( debugBlockPoints[1], v[1] );
- VectorCopy( debugBlockPoints[2], v[2] );
- drawPoly( 2, 3, v[0] );
- VectorCopy( debugBlockPoints[2], v[0] );
- VectorCopy( debugBlockPoints[3], v[1] );
- VectorCopy( debugBlockPoints[0], v[2] );
- drawPoly( 2, 3, v[0] );
- }
- #if 0
- vec3_t v[4];
- v[0][0] = pc->bounds[1][0];
- v[0][1] = pc->bounds[1][1];
- v[0][2] = pc->bounds[1][2];
- v[1][0] = pc->bounds[1][0];
- v[1][1] = pc->bounds[0][1];
- v[1][2] = pc->bounds[1][2];
- v[2][0] = pc->bounds[0][0];
- v[2][1] = pc->bounds[0][1];
- v[2][2] = pc->bounds[1][2];
- v[3][0] = pc->bounds[0][0];
- v[3][1] = pc->bounds[1][1];
- v[3][2] = pc->bounds[1][2];
- drawPoly( 4, v[0] );
- #endif
- #endif // _XBOX
- }
|