123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596 |
- /*
- ===========================================================================
- Copyright (C) 1999-2005 Id Software, Inc.
- This file is part of Quake III Arena source code.
- Quake III Arena source code is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
- Quake III Arena source code is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Foobar; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- #include "stdafx.h"
- #include <assert.h>
- #include "qe3.h"
- #include "winding.h"
- // globals
- int g_nBrushId = 0;
- const char* Brush_Name(brush_t *b)
- {
- static char cBuff[1024];
- b->numberId = g_nBrushId++;
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- sprintf(cBuff, "Brush %i", b->numberId);
- Brush_SetEpair(b, "Name", cBuff);
- }
- return cBuff;
- }
- brush_t *Brush_Alloc()
- {
- brush_t *b = (brush_t*)qmalloc(sizeof(brush_t));
- return b;
- }
- void PrintWinding (winding_t *w)
- {
- int i;
-
- printf ("-------------\n");
- for (i=0 ; i<w->numpoints ; i++)
- printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0]
- , w->points[i][1], w->points[i][2]);
- }
- void PrintPlane (plane_t *p)
- {
- printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n", p->normal[0], p->normal[1],
- p->normal[2], p->dist);
- }
- void PrintVector (vec3_t v)
- {
- printf ("(%5.2f, %5.2f, %5.2f)\n", v[0], v[1], v[2]);
- }
- /*
- =============================================================================
- TEXTURE COORDINATES
- =============================================================================
- */
- /*
- ==================
- textureAxisFromPlane
- ==================
- */
- vec3_t baseaxis[18] =
- {
- {0,0,1}, {1,0,0}, {0,-1,0}, // floor
- {0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling
- {1,0,0}, {0,1,0}, {0,0,-1}, // west wall
- {-1,0,0}, {0,1,0}, {0,0,-1}, // east wall
- {0,1,0}, {1,0,0}, {0,0,-1}, // south wall
- {0,-1,0}, {1,0,0}, {0,0,-1} // north wall
- };
- void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
- {
- int bestaxis;
- float dot,best;
- int i;
-
- best = 0;
- bestaxis = 0;
-
- for (i=0 ; i<6 ; i++)
- {
- dot = DotProduct (pln->normal, baseaxis[i*3]);
- if (dot > best)
- {
- best = dot;
- bestaxis = i;
- }
- }
-
- VectorCopy (baseaxis[bestaxis*3+1], xv);
- VectorCopy (baseaxis[bestaxis*3+2], yv);
- }
- float lightaxis[3] = {0.6, 0.8, 1.0};
- /*
- ================
- SetShadeForPlane
- Light different planes differently to
- improve recognition
- ================
- */
- float SetShadeForPlane (plane_t *p)
- {
- int i;
- float f;
- // axial plane
- for (i=0 ; i<3 ; i++)
- if (fabs(p->normal[i]) > 0.9)
- {
- f = lightaxis[i];
- return f;
- }
- // between two axial planes
- for (i=0 ; i<3 ; i++)
- if (fabs(p->normal[i]) < 0.1)
- {
- f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2;
- return f;
- }
- // other
- f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
- return f;
- }
- vec3_t vecs[2];
- float shift[2];
- /*
- ================
- Face_Alloc
- ================
- */
- face_t *Face_Alloc( void )
- {
- face_t *f = (face_t*)qmalloc( sizeof( *f ) );
-
- if (g_qeglobals.bSurfacePropertiesPlugin)
- f->pData = static_cast<void *>( g_SurfaceTable.m_pfnTexdefAlloc( f ) );
- return f;
- }
- /*
- ================
- Face_Free
- ================
- */
- void Face_Free( face_t *f )
- {
- assert( f != 0 );
- if ( f->face_winding )
- {
- free( f->face_winding );
- f->face_winding = 0;
- }
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- #ifdef _DEBUG
- if ( !f->pData )
- {
- Sys_Printf("WARNING: unexpected IPluginTexdef is NULL in Face_Free\n");
- }
- else
- #endif
- GETPLUGINTEXDEF(f)->DecRef();
- }
- f->texdef.~texdef_t();;
- free( f );
- }
- /*
- ================
- Face_Clone
- ================
- */
- face_t *Face_Clone (face_t *f)
- {
- face_t *n;
- n = Face_Alloc();
- n->texdef = f->texdef;
- memcpy (n->planepts, f->planepts, sizeof(n->planepts));
- // all other fields are derived, and will be set by Brush_Build
- return n;
- }
- /*
- ================
- Face_FullClone
- makes an exact copy of the face
- ================
- */
- face_t *Face_FullClone (face_t *f)
- {
- face_t *n;
- n = Face_Alloc();
- n->texdef = f->texdef;
- memcpy(n->planepts, f->planepts, sizeof(n->planepts));
- memcpy(&n->plane, &f->plane, sizeof(plane_t));
- if (f->face_winding)
- n->face_winding = Winding_Clone(f->face_winding);
- else
- n->face_winding = NULL;
- n->d_texture = Texture_ForName( n->texdef.name );
- return n;
- }
- /*
- ================
- Clamp
- ================
- */
- void Clamp(float& f, int nClamp)
- {
- float fFrac = f - static_cast<int>(f);
- f = static_cast<int>(f) % nClamp;
- f += fFrac;
- }
- /*
- ================
- Face_MoveTexture
- ================
- */
- void Face_MoveTexture(face_t *f, vec3_t delta)
- {
- vec3_t vX, vY;
- /*
- #ifdef _DEBUG
- if (g_PrefsDlg.m_bBrushPrimitMode)
- Sys_Printf("Warning : Face_MoveTexture not done in brush primitive mode\n");
- #endif
- */
- if (g_qeglobals.m_bBrushPrimitMode)
- Face_MoveTexture_BrushPrimit( f, delta );
- else
- {
- TextureAxisFromPlane(&f->plane, vX, vY);
- vec3_t vDP, vShift;
- vDP[0] = DotProduct(delta, vX);
- vDP[1] = DotProduct(delta, vY);
- double fAngle = f->texdef.rotate / 180 * Q_PI;
- double c = cos(fAngle);
- double s = sin(fAngle);
- vShift[0] = vDP[0] * c - vDP[1] * s;
- vShift[1] = vDP[0] * s + vDP[1] * c;
- if (!f->texdef.scale[0])
- f->texdef.scale[0] = 1;
- if (!f->texdef.scale[1])
- f->texdef.scale[1] = 1;
- f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
- f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
-
- // clamp the shifts
- Clamp(f->texdef.shift[0], f->d_texture->width);
- Clamp(f->texdef.shift[1], f->d_texture->height);
- }
- }
- /*
- ================
- Face_SetColor
- ================
- */
- void Face_SetColor (brush_t *b, face_t *f, float fCurveColor)
- {
- float shade;
- qtexture_t *q;
- q = f->d_texture;
- // set shading for face
- shade = SetShadeForPlane (&f->plane);
- if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && !b->owner->eclass->fixedsize)
- {
- //if (b->curveBrush)
- // shade = fCurveColor;
- f->d_color[0] =
- f->d_color[1] =
- f->d_color[2] = shade;
- }
- else
- {
- f->d_color[0] = shade*q->color[0];
- f->d_color[1] = shade*q->color[1];
- f->d_color[2] = shade*q->color[2];
- }
- }
- /*
- ================
- Face_TextureVectors
- TTimo: NOTE: this is never to get called while in brush primitives mode
- ================
- */
- void Face_TextureVectors (face_t *f, float STfromXYZ[2][4])
- {
- vec3_t pvecs[2];
- int sv, tv;
- float ang, sinv, cosv;
- float ns, nt;
- int i,j;
- qtexture_t *q;
- texdef_t *td;
- #ifdef _DEBUG
- //++timo when playing with patches, this sometimes get called and the Warning is displayed
- // find some way out ..
- if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert)
- Sys_Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
- #endif
- td = &f->texdef;
- q = f->d_texture;
- memset (STfromXYZ, 0, 8*sizeof(float));
- if (!td->scale[0])
- td->scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
- if (!td->scale[1])
- td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
- // get natural texture axis
- TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
- // rotate axis
- if (td->rotate == 0)
- { sinv = 0 ; cosv = 1; }
- else if (td->rotate == 90)
- { sinv = 1 ; cosv = 0; }
- else if (td->rotate == 180)
- { sinv = 0 ; cosv = -1; }
- else if (td->rotate == 270)
- { sinv = -1 ; cosv = 0; }
- else
- {
- ang = td->rotate / 180 * Q_PI;
- sinv = sin(ang);
- cosv = cos(ang);
- }
- if (pvecs[0][0])
- sv = 0;
- else if (pvecs[0][1])
- sv = 1;
- else
- sv = 2;
-
- if (pvecs[1][0])
- tv = 0;
- else if (pvecs[1][1])
- tv = 1;
- else
- tv = 2;
-
- for (i=0 ; i<2 ; i++) {
- ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
- nt = sinv * pvecs[i][sv] + cosv * pvecs[i][tv];
- STfromXYZ[i][sv] = ns;
- STfromXYZ[i][tv] = nt;
- }
- // scale
- for (i=0 ; i<2 ; i++)
- for (j=0 ; j<3 ; j++)
- STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
- // shift
- STfromXYZ[0][3] = td->shift[0];
- STfromXYZ[1][3] = td->shift[1];
- for (j=0 ; j<4 ; j++) {
- STfromXYZ[0][j] /= q->width;
- STfromXYZ[1][j] /= q->height;
- }
- }
- /*
- ================
- Face_MakePlane
- ================
- */
- void Face_MakePlane (face_t *f)
- {
- int j;
- vec3_t t1, t2, t3;
- // convert to a vector / dist plane
- for (j=0 ; j<3 ; j++)
- {
- t1[j] = f->planepts[0][j] - f->planepts[1][j];
- t2[j] = f->planepts[2][j] - f->planepts[1][j];
- t3[j] = f->planepts[1][j];
- }
-
- CrossProduct(t1,t2, f->plane.normal);
- if (VectorCompare (f->plane.normal, vec3_origin))
- printf ("WARNING: brush plane with no normal\n");
- VectorNormalize (f->plane.normal);
- f->plane.dist = DotProduct (t3, f->plane.normal);
- }
- /*
- ================
- EmitTextureCoordinates
- ================
- */
- void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f)
- {
- float STfromXYZ[2][4];
- Face_TextureVectors (f, STfromXYZ);
- xyzst[3] = DotProduct (xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
- xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
- }
- //==========================================================================
- /*
- ================
- Brush_MakeFacePlanes
- ================
- */
- void Brush_MakeFacePlanes (brush_t *b)
- {
- face_t *f;
- for (f=b->brush_faces ; f ; f=f->next)
- {
- Face_MakePlane (f);
- }
- }
- /*
- ================
- DrawBrushEntityName
- ================
- */
- void DrawBrushEntityName (brush_t *b)
- {
- char *name;
- //float a, s, c;
- //vec3_t mid;
- //int i;
- if (!b->owner)
- return; // during contruction
- if (b->owner == world_entity)
- return;
- if (b != b->owner->brushes.onext)
- return; // not key brush
- // MERGEME
- #if 0
- if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES))
- {
- // draw the angle pointer
- a = FloatForKey (b->owner, "angle");
- if (a)
- {
- s = sin (a/180*Q_PI);
- c = cos (a/180*Q_PI);
- for (i=0 ; i<3 ; i++)
- mid[i] = (b->mins[i] + b->maxs[i])*0.5;
- qglBegin (GL_LINE_STRIP);
- qglVertex3fv (mid);
- mid[0] += c*8;
- mid[1] += s*8;
- mid[2] += s*8;
- qglVertex3fv (mid);
- mid[0] -= c*4;
- mid[1] -= s*4;
- mid[2] -= s*4;
- mid[0] -= s*4;
- mid[1] += c*4;
- mid[2] += c*4;
- qglVertex3fv (mid);
- mid[0] += c*4;
- mid[1] += s*4;
- mid[2] += s*4;
- mid[0] += s*4;
- mid[1] -= c*4;
- mid[2] -= c*4;
- qglVertex3fv (mid);
- mid[0] -= c*4;
- mid[1] -= s*4;
- mid[2] -= s*4;
- mid[0] += s*4;
- mid[1] -= c*4;
- mid[2] -= c*4;
- qglVertex3fv (mid);
- qglEnd ();
- }
- }
- #endif
- if (g_qeglobals.d_savedinfo.show_names)
- {
- name = ValueForKey (b->owner, "classname");
- qglRasterPos3f (b->mins[0]+4, b->mins[1]+4, b->mins[2]+4);
- qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
- }
- }
- /*
- =================
- Brush_MakeFaceWinding
- returns the visible polygon on a face
- =================
- */
- winding_t *Brush_MakeFaceWinding (brush_t *b, face_t *face)
- {
- winding_t *w;
- face_t *clip;
- plane_t plane;
- qboolean past;
- // get a poly that covers an effectively infinite area
- w = Winding_BaseForPlane (&face->plane);
- // chop the poly by all of the other faces
- past = false;
- for (clip = b->brush_faces ; clip && w ; clip=clip->next)
- {
- if (clip == face)
- {
- past = true;
- continue;
- }
- if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999
- && fabs(face->plane.dist - clip->plane.dist) < 0.01 )
- { // identical plane, use the later one
- if (past)
- {
- free (w);
- return NULL;
- }
- continue;
- }
- // flip the plane, because we want to keep the back side
- VectorSubtract (vec3_origin,clip->plane.normal, plane.normal);
- plane.dist = -clip->plane.dist;
-
- w = Winding_Clip (w, &plane, false);
- if (!w)
- return w;
- }
-
- if (w->numpoints < 3)
- {
- free(w);
- w = NULL;
- }
- if (!w)
- printf ("unused plane\n");
- return w;
- }
- /*
- =================
- Brush_SnapPlanepts
- =================
- */
- void Brush_SnapPlanepts (brush_t *b)
- {
- int i, j;
- face_t *f;
- if (g_PrefsDlg.m_bNoClamp)
- return;
- for (f=b->brush_faces ; f; f=f->next)
- for (i=0 ; i<3 ; i++)
- for (j=0 ; j<3 ; j++)
- f->planepts[i][j] = floor (f->planepts[i][j] + 0.5);
- }
-
- /*
- ** Brush_Build
- **
- ** Builds a brush rendering data and also sets the min/max bounds
- */
- // TTimo
- // added a bConvert flag to convert between old and new brush texture formats
- // TTimo
- // brush grouping: update the group treeview if necessary
- void Brush_Build( brush_t *b, bool bSnap, bool bMarkMap, bool bConvert )
- {
- bool bLocalConvert;
- #ifdef _DEBUG
- if (!g_qeglobals.m_bBrushPrimitMode && bConvert)
- Sys_Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
- #endif
- // if bConvert is set and g_qeglobals.bNeedConvert is not, that just means we need convert for this brush only
- if (bConvert && !g_qeglobals.bNeedConvert)
- {
- bLocalConvert = true;
- g_qeglobals.bNeedConvert = true;
- }
- /*
- ** build the windings and generate the bounding box
- */
- Brush_BuildWindings(b, bSnap);
- Patch_BuildPoints (b);
- /*
- ** move the points and edges if in select mode
- */
- if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
- SetupVertexSelection ();
- if (b->itemOwner == NULL)
- Group_AddToProperGroup(b);
- if (bMarkMap)
- {
- Sys_MarkMapModified();
- }
- if (bLocalConvert)
- g_qeglobals.bNeedConvert = false;
- }
- /*
- ==============
- Brush_SplitBrushByFace
- The incoming brush is NOT freed.
- The incoming face is NOT left referenced.
- ==============
- */
- void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back)
- {
- brush_t *b;
- face_t *nf;
- vec3_t temp;
- b = Brush_Clone (in);
- nf = Face_Clone (f);
- nf->texdef = b->brush_faces->texdef;
- nf->next = b->brush_faces;
- b->brush_faces = nf;
- Brush_Build( b );
- Brush_RemoveEmptyFaces ( b );
- if ( !b->brush_faces )
- { // completely clipped away
- Brush_Free (b);
- *back = NULL;
- }
- else
- {
- Entity_LinkBrush (in->owner, b);
- *back = b;
- }
- b = Brush_Clone (in);
- nf = Face_Clone (f);
- // swap the plane winding
- VectorCopy (nf->planepts[0], temp);
- VectorCopy (nf->planepts[1], nf->planepts[0]);
- VectorCopy (temp, nf->planepts[1]);
- nf->texdef = b->brush_faces->texdef;
- nf->next = b->brush_faces;
- b->brush_faces = nf;
- Brush_Build( b );
- Brush_RemoveEmptyFaces ( b );
- if ( !b->brush_faces )
- { // completely clipped away
- Brush_Free (b);
- *front = NULL;
- }
- else
- {
- Entity_LinkBrush (in->owner, b);
- *front = b;
- }
- }
- /*
- =================
- Brush_BestSplitFace
- returns the best face to split the brush with.
- return NULL if the brush is convex
- =================
- */
- face_t *Brush_BestSplitFace(brush_t *b)
- {
- face_t *face, *f, *bestface;
- winding_t *front, *back;
- int splits, tinywindings, value, bestvalue;
- bestvalue = 999999;
- bestface = NULL;
- for (face = b->brush_faces; face; face = face->next)
- {
- splits = 0;
- tinywindings = 0;
- for (f = b->brush_faces; f; f = f->next)
- {
- if (f == face) continue;
- //
- Winding_SplitEpsilon(f->face_winding, face->plane.normal, face->plane.dist, 0.1, &front, &back);
- if (!front)
- {
- Winding_Free(back);
- }
- else if (!back)
- {
- Winding_Free(front);
- }
- else
- {
- splits++;
- if (Winding_IsTiny(front)) tinywindings++;
- if (Winding_IsTiny(back)) tinywindings++;
- }
- }
- if (splits)
- {
- value = splits + 50 * tinywindings;
- if (value < bestvalue)
- {
- bestvalue = value;
- bestface = face;
- }
- }
- }
- return bestface;
- }
- /*
- =================
- Brush_MakeConvexBrushes
- MrE FIXME: this doesn't work because the old
- Brush_SplitBrushByFace is used
- Turns the brush into a minimal number of convex brushes.
- If the input brush is convex then it will be returned.
- Otherwise the input brush will be freed.
- NOTE: the input brush should have windings for the faces.
- =================
- */
- brush_t *Brush_MakeConvexBrushes(brush_t *b)
- {
- brush_t *front, *back, *end;
- face_t *face;
- b->next = NULL;
- face = Brush_BestSplitFace(b);
- if (!face) return b;
- Brush_SplitBrushByFace(b, face, &front, &back);
- //this should never happen
- if (!front && !back) return b;
- Brush_Free(b);
- if (!front)
- return Brush_MakeConvexBrushes(back);
- b = Brush_MakeConvexBrushes(front);
- if (back)
- {
- for (end = b; end->next; end = end->next);
- end->next = Brush_MakeConvexBrushes(back);
- }
- return b;
- }
- /*
- =================
- Brush_Convex
- =================
- */
- int Brush_Convex(brush_t *b)
- {
- face_t *face1, *face2;
- for (face1 = b->brush_faces; face1; face1 = face1->next)
- {
- if (!face1->face_winding) continue;
- for (face2 = b->brush_faces; face2; face2 = face2->next)
- {
- if (face1 == face2) continue;
- if (!face2->face_winding) continue;
- if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
- face1->plane.normal, face2->plane.normal,
- face1->plane.dist, face2->plane.dist))
- {
- return false;
- }
- }
- }
- return true;
- }
- /*
- =================
- Brush_MoveVertexes_old1
- - The input brush must have face windings.
- - The input brush must be a brush with faces that do not intersect.
- - The input brush does not have to be convex.
- - The vertex will not be moved if the movement either causes the
- brush to have faces that intersect or causes the brush to be
- flipped inside out.
- (For instance a tetrahedron can easily be flipped inside out
- without having faces that intersect.)
- - The created brush does not have to be convex.
- - Returns true if the vertex movement is performed.
- =================
- */
- #define MAX_MOVE_FACES 64
- #define INTERSECT_EPSILON 0.1
- #define POINT_EPSILON 0.3
- int Brush_MoveVertex_old1(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
- {
- face_t *f, *face, *newface, *lastface, *nextface;
- face_t *movefaces[MAX_MOVE_FACES];
- int movefacepoints[MAX_MOVE_FACES];
- winding_t *w, tmpw;
- int i, j, k, nummovefaces, result;
- float dot;
- result = false;
- //
- tmpw.numpoints = 3;
- tmpw.maxpoints = 3;
- VectorAdd(vertex, delta, end);
- //snap or not?
- if (bSnap)
- for (i = 0; i < 3; i++)
- end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
- //chop off triangles from all brush faces that use the to be moved vertex
- //store pointers to these chopped off triangles in movefaces[]
- nummovefaces = 0;
- for (face = b->brush_faces; face; face = face->next)
- {
- w = face->face_winding;
- if (!w) continue;
- for (i = 0; i < w->numpoints; i++)
- {
- if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
- {
- if (face->face_winding->numpoints <= 3)
- {
- movefacepoints[nummovefaces] = i;
- movefaces[nummovefaces++] = face;
- break;
- }
- dot = DotProduct(end, face->plane.normal) - face->plane.dist;
- //if the end point is in front of the face plane
- if (dot > 0.1)
- {
- //fanout triangle subdivision
- for (k = i; k < i + w->numpoints-3; k++)
- {
- VectorCopy(w->points[i], tmpw.points[0]);
- VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
- //
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //add this new triangle to the move faces
- movefacepoints[nummovefaces] = 0;
- movefaces[nummovefaces++] = newface;
- }
- //give the original face a new winding
- VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[i], tmpw.points[2]);
- Winding_Free(face->face_winding);
- face->face_winding = Winding_Clone(&tmpw);
- //add the original face to the move faces
- movefacepoints[nummovefaces] = 2;
- movefaces[nummovefaces++] = face;
- }
- else
- {
- //chop a triangle off the face
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[i], tmpw.points[1]);
- VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
- //remove the point from the face winding
- Winding_RemovePoint(w, i);
- //get texture crap right
- Face_SetColor(b, face, 1.0);
- for (j = 0; j < w->numpoints; j++)
- EmitTextureCoordinates(w->points[j], face->d_texture, face);
- //make a triangle face
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //
- movefacepoints[nummovefaces] = 1;
- movefaces[nummovefaces++] = newface;
- }
- break;
- }
- }
- }
- //now movefaces contains pointers to triangle faces that
- //contain the to be moved vertex
- //check if the move is valid
- int l;
- vec3_t p1, p2;
- winding_t *w2;
- plane_t plane;
- face = NULL;
- VectorCopy(vertex, tmpw.points[1]);
- VectorCopy(end, tmpw.points[2]);
- for (face = b->brush_faces; face; face = face->next)
- {
- for (i = 0; i < nummovefaces; i++)
- {
- if (face == movefaces[i])
- break;
- }
- if (i < nummovefaces)
- continue;
- //the delta vector may not intersect with any of the not move faces
- if (Winding_VectorIntersect(face->face_winding, &face->plane, vertex, end, INTERSECT_EPSILON))
- break;
- //if the end point of the to be moved vertex is near this not move face
- if (abs(DotProduct(face->plane.normal, end) - face->plane.dist) < 0.5)
- {
- //the end point may not be inside or very close to the not move face winding
- if (Winding_PointInside(face->face_winding, &face->plane, end, 0.5))
- break;
- }
- for (i = 0; i < nummovefaces; i++)
- {
- w = movefaces[i]->face_winding;
- j = movefacepoints[i];
- for (k = -1; k <= 1; k += 2)
- {
- //check if the new edge will not intersect with the not move face
- VectorCopy(w->points[(j + k + w->numpoints) % w->numpoints], tmpw.points[0]);
- if (Winding_VectorIntersect(face->face_winding, &face->plane, tmpw.points[0], end, INTERSECT_EPSILON))
- {
- //ok the new edge instersects with the not move face
- //we can't perform the vertex movement
- //break;
- }
- //check if the not move face intersects the "movement winding"
- Winding_Plane(&tmpw, plane.normal, &plane.dist);
- w2 = face->face_winding;
- for (l = 0; l < w2->numpoints; l++)
- {
- VectorCopy(w2->points[l], p1);
- if (Point_Equal(p1, tmpw.points[0], POINT_EPSILON)) continue;
- VectorCopy(w2->points[(l+1) % w2->numpoints], p2);
- if (Point_Equal(p2, tmpw.points[0], POINT_EPSILON)) continue;
- if (Winding_VectorIntersect(&tmpw, &plane, p1, p2, INTERSECT_EPSILON))
- break;
- }
- if (l < w2->numpoints)
- {
- //ok this not move face intersects the "movement winding"
- //we can't perform the vertex movement
- break;
- }
- }
- if (k <= 1) break;
- }
- if (i < nummovefaces)
- break;
- }
- if (!face)
- {
- //ok the move was valid
- //now move all the vertexes of the movefaces
- for (i = 0; i < nummovefaces; i++)
- {
- VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
- //create new face plane
- for (j = 0; j < 3; j++)
- {
- VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
- }
- Face_MakePlane(movefaces[i]);
- }
- result = true;
- }
- //get texture crap right
- for (i = 0; i < nummovefaces; i++)
- {
- Face_SetColor(b, movefaces[i], 1.0);
- for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
- EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
- }
- //now try to merge faces with their original faces
- lastface = NULL;
- for (face = b->brush_faces; face; face = nextface)
- {
- nextface = face->next;
- if (!face->original)
- {
- lastface = face;
- continue;
- }
- if (!Plane_Equal(&face->plane, &face->original->plane, false))
- {
- lastface = face;
- continue;
- }
- w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
- if (!w)
- {
- lastface = face;
- continue;
- }
- Winding_Free(face->original->face_winding);
- face->original->face_winding = w;
- //get texture crap right
- Face_SetColor(b, face->original, 1.0);
- for (j = 0; j < face->original->face_winding->numpoints; j++)
- EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
- //remove the face that was merged with the original
- if (lastface) lastface->next = face->next;
- else b->brush_faces = face->next;
- Face_Free(face);
- }
- return result;
- }
- /*
- =================
- Brush_MoveVertexes_old2
- - The input brush must be convex
- - The input brush must have face windings.
- - The output brush will be convex.
- - Returns true if the vertex movement is performed.
- =================
- */
- #define MAX_MOVE_FACES 64
- #define INTERSECT_EPSILON 0.1
- #define POINT_EPSILON 0.3
- int Brush_MoveVertex_old2(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
- {
- face_t *f, *face, *newface, *lastface, *nextface;
- face_t *movefaces[MAX_MOVE_FACES];
- int movefacepoints[MAX_MOVE_FACES];
- winding_t *w, tmpw;
- int i, j, k, nummovefaces, result;
- float dot;
- result = true;
- //
- tmpw.numpoints = 3;
- tmpw.maxpoints = 3;
- VectorAdd(vertex, delta, end);
- //snap or not?
- if (bSnap)
- for (i = 0; i < 3; i++)
- end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
- //chop off triangles from all brush faces that use the to be moved vertex
- //store pointers to these chopped off triangles in movefaces[]
- nummovefaces = 0;
- for (face = b->brush_faces; face; face = face->next)
- {
- w = face->face_winding;
- if (!w) continue;
- for (i = 0; i < w->numpoints; i++)
- {
- if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
- {
- if (face->face_winding->numpoints <= 3)
- {
- movefacepoints[nummovefaces] = i;
- movefaces[nummovefaces++] = face;
- break;
- }
- dot = DotProduct(end, face->plane.normal) - face->plane.dist;
- //if the end point is in front of the face plane
- if (dot > 0.1)
- {
- //fanout triangle subdivision
- for (k = i; k < i + w->numpoints-3; k++)
- {
- VectorCopy(w->points[i], tmpw.points[0]);
- VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
- //
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //add this new triangle to the move faces
- movefacepoints[nummovefaces] = 0;
- movefaces[nummovefaces++] = newface;
- }
- //give the original face a new winding
- VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[i], tmpw.points[2]);
- Winding_Free(face->face_winding);
- face->face_winding = Winding_Clone(&tmpw);
- //add the original face to the move faces
- movefacepoints[nummovefaces] = 2;
- movefaces[nummovefaces++] = face;
- }
- else
- {
- //chop a triangle off the face
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[i], tmpw.points[1]);
- VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
- //remove the point from the face winding
- Winding_RemovePoint(w, i);
- //get texture crap right
- Face_SetColor(b, face, 1.0);
- for (j = 0; j < w->numpoints; j++)
- EmitTextureCoordinates(w->points[j], face->d_texture, face);
- //make a triangle face
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //
- movefacepoints[nummovefaces] = 1;
- movefaces[nummovefaces++] = newface;
- }
- break;
- }
- }
- }
- //now movefaces contains pointers to triangle faces that
- //contain the to be moved vertex
- //move the vertex
- for (i = 0; i < nummovefaces; i++)
- {
- //move vertex to end position
- VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
- //create new face plane
- for (j = 0; j < 3; j++)
- {
- VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
- }
- Face_MakePlane(movefaces[i]);
- }
- //if the brush is no longer convex
- if (!Brush_Convex(b))
- {
- for (i = 0; i < nummovefaces; i++)
- {
- //move the vertex back to the initial position
- VectorCopy(vertex, movefaces[i]->face_winding->points[movefacepoints[i]]);
- //create new face plane
- for (j = 0; j < 3; j++)
- {
- VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
- }
- Face_MakePlane(movefaces[i]);
- }
- result = false;
- }
- //get texture crap right
- for (i = 0; i < nummovefaces; i++)
- {
- Face_SetColor(b, movefaces[i], 1.0);
- for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
- EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
- }
- //now try to merge faces with their original faces
- lastface = NULL;
- for (face = b->brush_faces; face; face = nextface)
- {
- nextface = face->next;
- if (!face->original)
- {
- lastface = face;
- continue;
- }
- if (!Plane_Equal(&face->plane, &face->original->plane, false))
- {
- lastface = face;
- continue;
- }
- w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
- if (!w)
- {
- lastface = face;
- continue;
- }
- Winding_Free(face->original->face_winding);
- face->original->face_winding = w;
- //get texture crap right
- Face_SetColor(b, face->original, 1.0);
- for (j = 0; j < face->original->face_winding->numpoints; j++)
- EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
- //remove the face that was merged with the original
- if (lastface) lastface->next = face->next;
- else b->brush_faces = face->next;
- Face_Free(face);
- }
- return result;
- }
- /*
- =================
- Brush_MoveVertexes
- - The input brush must be convex
- - The input brush must have face windings.
- - The output brush will be convex.
- - Returns true if the WHOLE vertex movement is performed.
- =================
- */
- #define MAX_MOVE_FACES 64
- int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
- {
- face_t *f, *face, *newface, *lastface, *nextface;
- face_t *movefaces[MAX_MOVE_FACES];
- int movefacepoints[MAX_MOVE_FACES];
- winding_t *w, tmpw;
- vec3_t start, mid;
- plane_t plane;
- int i, j, k, nummovefaces, result, done;
- float dot, front, back, frac, smallestfrac;
- result = true;
- //
- tmpw.numpoints = 3;
- tmpw.maxpoints = 3;
- VectorCopy(vertex, start);
- VectorAdd(vertex, delta, end);
- //snap or not?
- if (bSnap)
- for (i = 0; i < 3; i++)
- end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
- //
- VectorCopy(end, mid);
- //if the start and end are the same
- if (Point_Equal(start, end, 0.3)) return false;
- //the end point may not be the same as another vertex
- for (face = b->brush_faces; face; face = face->next)
- {
- w = face->face_winding;
- if (!w) continue;
- for (i = 0; i < w->numpoints; i++)
- {
- if (Point_Equal(w->points[i], end, 0.3))
- {
- VectorCopy(vertex, end);
- return false;
- }
- }
- }
- //
- done = false;
- while(!done)
- {
- //chop off triangles from all brush faces that use the to be moved vertex
- //store pointers to these chopped off triangles in movefaces[]
- nummovefaces = 0;
- for (face = b->brush_faces; face; face = face->next)
- {
- w = face->face_winding;
- if (!w) continue;
- for (i = 0; i < w->numpoints; i++)
- {
- if (Point_Equal(w->points[i], start, 0.2))
- {
- if (face->face_winding->numpoints <= 3)
- {
- movefacepoints[nummovefaces] = i;
- movefaces[nummovefaces++] = face;
- break;
- }
- dot = DotProduct(end, face->plane.normal) - face->plane.dist;
- //if the end point is in front of the face plane
- if (dot > 0.1)
- {
- //fanout triangle subdivision
- for (k = i; k < i + w->numpoints-3; k++)
- {
- VectorCopy(w->points[i], tmpw.points[0]);
- VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
- //
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //add this new triangle to the move faces
- movefacepoints[nummovefaces] = 0;
- movefaces[nummovefaces++] = newface;
- }
- //give the original face a new winding
- VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
- VectorCopy(w->points[i], tmpw.points[2]);
- Winding_Free(face->face_winding);
- face->face_winding = Winding_Clone(&tmpw);
- //add the original face to the move faces
- movefacepoints[nummovefaces] = 2;
- movefaces[nummovefaces++] = face;
- }
- else
- {
- //chop a triangle off the face
- VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[i], tmpw.points[1]);
- VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
- //remove the point from the face winding
- Winding_RemovePoint(w, i);
- //get texture crap right
- Face_SetColor(b, face, 1.0);
- for (j = 0; j < w->numpoints; j++)
- EmitTextureCoordinates(w->points[j], face->d_texture, face);
- //make a triangle face
- newface = Face_Clone(face);
- //get the original
- for (f = face; f->original; f = f->original) ;
- newface->original = f;
- //store the new winding
- if (newface->face_winding) Winding_Free(newface->face_winding);
- newface->face_winding = Winding_Clone(&tmpw);
- //get the texture
- newface->d_texture = Texture_ForName( newface->texdef.name );
- //add the face to the brush
- newface->next = b->brush_faces;
- b->brush_faces = newface;
- //
- movefacepoints[nummovefaces] = 1;
- movefaces[nummovefaces++] = newface;
- }
- break;
- }
- }
- }
- //now movefaces contains pointers to triangle faces that
- //contain the to be moved vertex
- //
- done = true;
- VectorCopy(end, mid);
- smallestfrac = 1;
- for (face = b->brush_faces; face; face = face->next)
- {
- //check if there is a move face that has this face as the original
- for (i = 0; i < nummovefaces; i++)
- {
- if (movefaces[i]->original == face) break;
- }
- if (i >= nummovefaces) continue;
- //check if the original is not a move face itself
- for (j = 0; j < nummovefaces; j++)
- {
- if (face == movefaces[j]) break;
- }
- //if the original is not a move face itself
- if (j >= nummovefaces)
- {
- memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
- }
- else
- {
- k = movefacepoints[j];
- w = movefaces[j]->face_winding;
- VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
- VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
- //
- k = movefacepoints[i];
- w = movefaces[i]->face_winding;
- VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
- if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
- {
- VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
- if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
- //this should never happen otherwise the face merge did a crappy job a previous pass
- continue;
- }
- }
- //now we've got the plane to check agains
- front = DotProduct(start, plane.normal) - plane.dist;
- back = DotProduct(end, plane.normal) - plane.dist;
- //if the whole move is at one side of the plane
- if (front < 0.01 && back < 0.01) continue;
- if (front > -0.01 && back > -0.01) continue;
- //if there's no movement orthogonal to this plane at all
- if (fabs(front-back) < 0.001) continue;
- //ok first only move till the plane is hit
- frac = front/(front-back);
- if (frac < smallestfrac)
- {
- mid[0] = start[0] + (end[0] - start[0]) * frac;
- mid[1] = start[1] + (end[1] - start[1]) * frac;
- mid[2] = start[2] + (end[2] - start[2]) * frac;
- smallestfrac = frac;
- }
- //
- done = false;
- }
- //move the vertex
- for (i = 0; i < nummovefaces; i++)
- {
- //move vertex to end position
- VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
- //create new face plane
- for (j = 0; j < 3; j++)
- {
- VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
- }
- Face_MakePlane(movefaces[i]);
- if (VectorLength(movefaces[i]->plane.normal) < 0.1)
- result = false;
- }
- //if the brush is no longer convex
- if (!result || !Brush_Convex(b))
- {
- for (i = 0; i < nummovefaces; i++)
- {
- //move the vertex back to the initial position
- VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
- //create new face plane
- for (j = 0; j < 3; j++)
- {
- VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
- }
- Face_MakePlane(movefaces[i]);
- }
- result = false;
- VectorCopy(start, end);
- done = true;
- }
- else
- {
- VectorCopy(mid, start);
- }
- //get texture crap right
- for (i = 0; i < nummovefaces; i++)
- {
- Face_SetColor(b, movefaces[i], 1.0);
- for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
- EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
- }
- //now try to merge faces with their original faces
- lastface = NULL;
- for (face = b->brush_faces; face; face = nextface)
- {
- nextface = face->next;
- if (!face->original)
- {
- lastface = face;
- continue;
- }
- if (!Plane_Equal(&face->plane, &face->original->plane, false))
- {
- lastface = face;
- continue;
- }
- w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
- if (!w)
- {
- lastface = face;
- continue;
- }
- Winding_Free(face->original->face_winding);
- face->original->face_winding = w;
- //get texture crap right
- Face_SetColor(b, face->original, 1.0);
- for (j = 0; j < face->original->face_winding->numpoints; j++)
- EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
- //remove the face that was merged with the original
- if (lastface) lastface->next = face->next;
- else b->brush_faces = face->next;
- Face_Free(face);
- }
- }
- return result;
- }
- /*
- =================
- Brush_InsertVertexBetween
- =================
- */
- int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
- {
- face_t *face;
- winding_t *w, *neww;
- vec3_t point;
- int i, insert;
- if (Point_Equal(p1, p2, 0.4))
- return false;
- VectorAdd(p1, p2, point);
- VectorScale(point, 0.5, point);
- insert = false;
- //the end point may not be the same as another vertex
- for (face = b->brush_faces; face; face = face->next)
- {
- w = face->face_winding;
- if (!w) continue;
- neww = NULL;
- for (i = 0; i < w->numpoints; i++)
- {
- if (!Point_Equal(w->points[i], p1, 0.1))
- continue;
- if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1))
- {
- neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
- break;
- }
- else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3))
- {
- neww = Winding_InsertPoint(w, point, i);
- break;
- }
- }
- if (neww)
- {
- Winding_Free(face->face_winding);
- face->face_winding = neww;
- insert = true;
- }
- }
- return insert;
- }
- /*
- =================
- Brush_ResetFaceOriginals
- =================
- */
- void Brush_ResetFaceOriginals(brush_t *b)
- {
- face_t *face;
- for (face = b->brush_faces; face; face = face->next)
- {
- face->original = NULL;
- }
- }
- /*
- =================
- Brush_Parse
- The brush is NOT linked to any list
- =================
- */
- //++timo FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3" is ran
- // before each face parsing. It works, but it's a performance hit
- brush_t *Brush_Parse (void)
- {
- brush_t *b;
- face_t *f;
- int i,j;
-
- g_qeglobals.d_parsed_brushes++;
- b = Brush_Alloc();
- do
- {
- if (!GetToken (true))
- break;
- if (!strcmp (token, "}") )
- break;
-
- // handle "Brush" primitive
- if (strcmpi(token, "brushDef") == 0)
- {
- // Timo parsing new brush format
- g_qeglobals.bPrimitBrushes=true;
- // check the map is not mixing the two kinds of brushes
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- if (g_qeglobals.bOldBrushes)
- Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
- }
- //++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
- else
- Sys_Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
-
- BrushPrimit_Parse(b);
- if (b == NULL)
- {
- Warning ("parsing brush primitive");
- return NULL;
- }
- else
- {
- continue;
- }
- }
- if ( strcmpi( token, "terrainDef" ) == 0 )
- {
- free (b);
- b = Terrain_Parse();
- if (b == NULL)
- {
- Warning ("parsing terrain/brush");
- return NULL;
- }
- else
- {
- continue;
- }
- }
- if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
- {
- free (b);
-
- // double string compare but will go away soon
- b = Patch_Parse(strcmpi(token, "patchDef2") == 0);
- if (b == NULL)
- {
- Warning ("parsing patch/brush");
- return NULL;
- }
- else
- {
- continue;
- }
- // handle inline patch
- }
- else
- {
- // Timo parsing old brush format
- g_qeglobals.bOldBrushes=true;
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- // check the map is not mixing the two kinds of brushes
- if (g_qeglobals.bPrimitBrushes)
- Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
- // set the "need" conversion flag
- g_qeglobals.bNeedConvert=true;
- }
-
- f = Face_Alloc();
-
- // add the brush to the end of the chain, so
- // loading and saving a map doesn't reverse the order
-
- f->next = NULL;
- if (!b->brush_faces)
- {
- b->brush_faces = f;
- }
- else
- {
- face_t *scan;
- for (scan=b->brush_faces ; scan->next ; scan=scan->next)
- ;
- scan->next = f;
- }
-
- // read the three point plane definition
- for (i=0 ; i<3 ; i++)
- {
- if (i != 0)
- GetToken (true);
- if (strcmp (token, "(") )
- {
- Warning ("parsing brush");
- return NULL;
- }
-
- for (j=0 ; j<3 ; j++)
- {
- GetToken (false);
- f->planepts[i][j] = atof(token);
- }
-
- GetToken (false);
- if (strcmp (token, ")") )
- {
- Warning ("parsing brush");
- return NULL;
- }
- }
- }
- // Timo
- // if we have a surface plugin, we'll call the plugin parsing
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- GETPLUGINTEXDEF(f)->ParseTexdef();
- }
- else
- {
-
- // read the texturedef
- GetToken (false);
- f->texdef.SetName(token);
- if (token[0] == '(')
- {
- int i = 32;
- }
- GetToken (false);
- f->texdef.shift[0] = atoi(token);
- GetToken (false);
- f->texdef.shift[1] = atoi(token);
- GetToken (false);
- f->texdef.rotate = atoi(token);
- GetToken (false);
- f->texdef.scale[0] = atof(token);
- GetToken (false);
- f->texdef.scale[1] = atof(token);
-
- // the flags and value field aren't necessarily present
- f->d_texture = Texture_ForName( f->texdef.name );
- f->texdef.flags = f->d_texture->flags;
- f->texdef.value = f->d_texture->value;
- f->texdef.contents = f->d_texture->contents;
-
- if (TokenAvailable ())
- {
- GetToken (false);
- f->texdef.contents = atoi(token);
- GetToken (false);
- f->texdef.flags = atoi(token);
- GetToken (false);
- f->texdef.value = atoi(token);
- }
-
- }
- } while (1);
-
- return b;
- }
- /*
- =================
- QERApp_MapPrintf_FILE
- callback for surface properties plugin
- must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
- =================
- */
- // carefully initialize !
- FILE * g_File;
- void WINAPI QERApp_MapPrintf_FILE( char *text, ... )
- {
- va_list argptr;
- char buf[32768];
- va_start (argptr,text);
- vsprintf (buf, text,argptr);
- va_end (argptr);
- fprintf( g_File, buf );
- }
- /*
- ==============
- Brush_SetEpair
- sets an epair for the given brush
- ==============
- */
- void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
- {
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- if (b->patchBrush)
- {
- Patch_SetEpair(b->pPatch, pKey, pValue);
- }
- else if (b->terrainBrush)
- {
- Terrain_SetEpair(b->pTerrain, pKey, pValue);
- }
- else
- {
- SetKeyValue(b->epairs, pKey, pValue);
- }
- }
- else
- {
- Sys_Printf("Can only set key/values in Brush primitive mode\n");
- }
- }
- /*
- =================
- Brush_GetKeyValue
- =================
- */
- const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
- {
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- if (b->patchBrush)
- {
- return Patch_GetKeyValue(b->pPatch, pKey);
- }
- else if (b->terrainBrush)
- {
- return Terrain_GetKeyValue(b->pTerrain, pKey);
- }
- else
- {
- return ValueForKey(b->epairs, pKey);
- }
- }
- else
- {
- Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
- }
- return "";
- }
- /*
- =================
- Brush_Write
- save all brushes as Brush primitive format
- =================
- */
- void Brush_Write (brush_t *b, FILE *f)
- {
- epair_t *ep;
- face_t *fa;
- char *pname;
- int i;
-
- if (b->patchBrush)
- {
- Patch_Write(b->pPatch, f);
- return;
- }
- if ( b->pTerrain )
- {
- Terrain_Write(b->pTerrain, f);
- return;
- }
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- // save brush primitive format
- fprintf (f, "{\nbrushDef\n{\n");
- // brush epairs
- if (b->epairs)
- for (ep = b->epairs ; ep ; ep=ep->next)
- fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
- for (fa=b->brush_faces ; fa ; fa=fa->next)
- {
- // save planepts
- for (i=0 ; i<3 ; i++)
- {
- fprintf(f, "( ");
- for (int j = 0; j < 3; j++)
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
- fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
- else
- fprintf(f, "%f ", fa->planepts[i][j]);
- fprintf(f, ") ");
- }
- // save texture coordinates
- fprintf(f,"( ( ");
- for (i=0 ; i<3 ; i++)
- if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
- fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
- else
- fprintf(f,"%f ",fa->brushprimit_texdef.coords[0][i]);
- fprintf(f,") ( ");
- for (i=0 ; i<3 ; i++)
- if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
- fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
- else
- fprintf(f,"%f ",fa->brushprimit_texdef.coords[1][i]);
- fprintf(f,") ) ");
- // save texture attribs
- //++timo surface properties plugin not implemented for brush primitives
- if (g_qeglobals.bSurfacePropertiesPlugin)
- Sys_Printf("WARNING: surface properties plugin not supported with brush primitives (yet)\n");
- char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
- fprintf(f, "%s ", pName );
- fprintf(f, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
- }
- fprintf (f, "}\n}\n");
- }
- else
- {
- fprintf (f, "{\n");
- for (fa=b->brush_faces ; fa ; fa=fa->next)
- {
- for (i=0 ; i<3 ; i++)
- {
- fprintf(f, "( ");
- for (int j = 0; j < 3; j++)
- {
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
- fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
- else
- fprintf(f, "%f ", fa->planepts[i][j]);
- }
- fprintf(f, ") ");
- }
-
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- g_File = f;
- #ifdef _DEBUG
- if (!fa->pData)
- Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
- else
- #endif
- GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_FILE );
- }
- else
- {
- pname = fa->texdef.name;
- if (pname[0] == 0)
- pname = "unnamed";
-
- fprintf (f, "%s %i %i %i ", pname,
- (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
- (int)fa->texdef.rotate);
-
- if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
- fprintf (f, "%i ", (int)fa->texdef.scale[0]);
- else
- fprintf (f, "%f ", (float)fa->texdef.scale[0]);
- if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
- fprintf (f, "%i", (int)fa->texdef.scale[1]);
- else
- fprintf (f, "%f", (float)fa->texdef.scale[1]);
-
- fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
- }
- fprintf (f, "\n");
- }
- fprintf (f, "}\n");
- }
- }
- /*
- =================
- QERApp_MapPrintf_MEMFILE
- callback for surface properties plugin
- must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
- =================
- */
- // carefully initialize !
- CMemFile * g_pMemFile;
- void WINAPI QERApp_MapPrintf_MEMFILE( char *text, ... )
- {
- va_list argptr;
- char buf[32768];
- va_start (argptr,text);
- vsprintf (buf, text,argptr);
- va_end (argptr);
- MemFile_fprintf( g_pMemFile, buf );
- }
- /*
- =================
- Brush_Write to a CMemFile*
- save all brushes as Brush primitive format
- =================
- */
- void Brush_Write (brush_t *b, CMemFile *pMemFile)
- {
- epair_t *ep;
- face_t *fa;
- char *pname;
- int i;
-
- if (b->patchBrush)
- {
- Patch_Write(b->pPatch, pMemFile);
- return;
- }
- if (b->terrainBrush)
- {
- Terrain_Write(b->pTerrain, pMemFile);
- return;
- }
- //++timo NOTE: it's not very difficult to add since the surface properties plugin
- // writes throught a printf-style function prototype
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- Sys_Printf("WARNING: Brush_Write to a CMemFile and Surface Properties plugin not done\n");
- }
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- // brush primitive format
- MemFile_fprintf (pMemFile, "{\nBrushDef\n{\n");
- // brush epairs
- if (b->epairs)
- for( ep = b->epairs ; ep ; ep=ep->next )
- MemFile_fprintf (pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value );
- for (fa=b->brush_faces ; fa ; fa=fa->next)
- {
- // save planepts
- for (i=0 ; i<3 ; i++)
- {
- MemFile_fprintf(pMemFile, "( ");
- for (int j = 0; j < 3; j++)
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
- MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
- else
- MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
- MemFile_fprintf(pMemFile, ") ");
- }
- // save texture coordinates
- MemFile_fprintf(pMemFile,"( ( ");
- for (i=0 ; i<3 ; i++)
- if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
- MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
- else
- MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[0][i]);
- MemFile_fprintf(pMemFile,") ( ");
- for (i=0 ; i<3 ; i++)
- if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
- MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
- else
- MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[1][i]);
- MemFile_fprintf(pMemFile,") ) ");
- // save texture attribs
- char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
- MemFile_fprintf(pMemFile, "%s ", pName);
- MemFile_fprintf(pMemFile, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
- }
- MemFile_fprintf (pMemFile, "}\n}\n");
- }
- else
- {
- // old brushes format
- // also handle surface properties plugin
- MemFile_fprintf (pMemFile, "{\n");
- for (fa=b->brush_faces ; fa ; fa=fa->next)
- {
- for (i=0 ; i<3 ; i++)
- {
- MemFile_fprintf(pMemFile, "( ");
- for (int j = 0; j < 3; j++)
- {
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
- MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
- else
- MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
- }
- MemFile_fprintf(pMemFile, ") ");
- }
-
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- g_pMemFile = pMemFile;
- #ifdef _DEBUG
- if (!fa->pData)
- Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
- else
- #endif
- GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_MEMFILE );
- }
- else
- {
- pname = fa->texdef.name;
- if (pname[0] == 0)
- pname = "unnamed";
-
- MemFile_fprintf (pMemFile, "%s %i %i %i ", pname,
- (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
- (int)fa->texdef.rotate);
-
- if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
- MemFile_fprintf (pMemFile, "%i ", (int)fa->texdef.scale[0]);
- else
- MemFile_fprintf (pMemFile, "%f ", (float)fa->texdef.scale[0]);
- if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
- MemFile_fprintf (pMemFile, "%i", (int)fa->texdef.scale[1]);
- else
- MemFile_fprintf (pMemFile, "%f", (float)fa->texdef.scale[1]);
-
- MemFile_fprintf (pMemFile, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
- }
- MemFile_fprintf (pMemFile, "\n");
- }
- MemFile_fprintf (pMemFile, "}\n");
- }
-
-
- }
- /*
- =============
- Brush_Create
- Create non-textured blocks for entities
- The brush is NOT linked to any list
- =============
- */
- brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
- {
- int i, j;
- vec3_t pts[4][2];
- face_t *f;
- brush_t *b;
- // brush primitive mode : convert texdef to brushprimit_texdef ?
- // most of the time texdef is empty
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- // check texdef is empty .. if there are cases it's not we need to write some conversion code
- if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
- Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
- }
- for (i=0 ; i<3 ; i++)
- {
- if (maxs[i] < mins[i])
- Error ("Brush_InitSolid: backwards");
- }
- b = Brush_Alloc();
-
- pts[0][0][0] = mins[0];
- pts[0][0][1] = mins[1];
-
- pts[1][0][0] = mins[0];
- pts[1][0][1] = maxs[1];
-
- pts[2][0][0] = maxs[0];
- pts[2][0][1] = maxs[1];
-
- pts[3][0][0] = maxs[0];
- pts[3][0][1] = mins[1];
-
- for (i=0 ; i<4 ; i++)
- {
- pts[i][0][2] = mins[2];
- pts[i][1][0] = pts[i][0][0];
- pts[i][1][1] = pts[i][0][1];
- pts[i][1][2] = maxs[2];
- }
- for (i=0 ; i<4 ; i++)
- {
- f = Face_Alloc();
- f->texdef = *texdef;
- f->texdef.flags &= ~SURF_KEEP;
- f->texdef.contents &= ~CONTENTS_KEEP;
- f->next = b->brush_faces;
- b->brush_faces = f;
- j = (i+1)%4;
- VectorCopy (pts[j][1], f->planepts[0]);
- VectorCopy (pts[i][1], f->planepts[1]);
- VectorCopy (pts[i][0], f->planepts[2]);
- }
-
- f = Face_Alloc();
- f->texdef = *texdef;
- f->texdef.flags &= ~SURF_KEEP;
- f->texdef.contents &= ~CONTENTS_KEEP;
- f->next = b->brush_faces;
- b->brush_faces = f;
- VectorCopy (pts[0][1], f->planepts[0]);
- VectorCopy (pts[1][1], f->planepts[1]);
- VectorCopy (pts[2][1], f->planepts[2]);
- f = Face_Alloc();
- f->texdef = *texdef;
- f->texdef.flags &= ~SURF_KEEP;
- f->texdef.contents &= ~CONTENTS_KEEP;
- f->next = b->brush_faces;
- b->brush_faces = f;
- VectorCopy (pts[2][0], f->planepts[0]);
- VectorCopy (pts[1][0], f->planepts[1]);
- VectorCopy (pts[0][0], f->planepts[2]);
- return b;
- }
- /*
- =============
- Brush_CreatePyramid
- Create non-textured pyramid for light entities
- The brush is NOT linked to any list
- =============
- */
- brush_t *Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
- {
- //++timo handle new brush primitive ? return here ??
- return Brush_Create(mins, maxs, texdef);
- for (int i=0 ; i<3 ; i++)
- if (maxs[i] < mins[i])
- Error ("Brush_InitSolid: backwards");
- brush_t* b = Brush_Alloc();
- vec3_t corners[4];
- float fMid = Q_rint(mins[2] + (Q_rint((maxs[2] - mins[2]) / 2)));
- corners[0][0] = mins[0];
- corners[0][1] = mins[1];
- corners[0][2] = fMid;
- corners[1][0] = mins[0];
- corners[1][1] = maxs[1];
- corners[1][2] = fMid;
- corners[2][0] = maxs[0];
- corners[2][1] = maxs[1];
- corners[2][2] = fMid;
- corners[3][0] = maxs[0];
- corners[3][1] = mins[1];
- corners[3][2] = fMid;
- vec3_t top, bottom;
- top[0] = Q_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
- top[1] = Q_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
- top[2] = Q_rint(maxs[2]);
- VectorCopy(top, bottom);
- bottom[2] = mins[2];
- // sides
- for (i = 0; i < 4; i++)
- {
- face_t* f = Face_Alloc();
- f->texdef = *texdef;
- f->texdef.flags &= ~SURF_KEEP;
- f->texdef.contents &= ~CONTENTS_KEEP;
- f->next = b->brush_faces;
- b->brush_faces = f;
- int j = (i+1)%4;
- VectorCopy (top, f->planepts[0]);
- VectorCopy (corners[i], f->planepts[1]);
- VectorCopy(corners[j], f->planepts[2]);
- f = Face_Alloc();
- f->texdef = *texdef;
- f->texdef.flags &= ~SURF_KEEP;
- f->texdef.contents &= ~CONTENTS_KEEP;
- f->next = b->brush_faces;
- b->brush_faces = f;
- VectorCopy (bottom, f->planepts[2]);
- VectorCopy (corners[i], f->planepts[1]);
- VectorCopy(corners[j], f->planepts[0]);
- }
- return b;
- }
- /*
- =============
- Brush_MakeSided
- Makes the current brush have the given number of 2d sides
- =============
- */
- void Brush_MakeSided (int sides)
- {
- int i, axis;
- vec3_t mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- vec3_t mid;
- float width;
- float sv, cv;
- if (sides < 3)
- {
- Sys_Status ("Bad sides number", 0);
- return;
- }
- if (sides >= MAX_POINTS_ON_WINDING-4)
- {
- Sys_Printf("too many sides.\n");
- return;
- }
- if (!QE_SingleBrush ())
- {
- Sys_Status ("Must have a single brush selected", 0 );
- return;
- }
- b = selected_brushes.next;
- VectorCopy (b->mins, mins);
- VectorCopy (b->maxs, maxs);
- texdef = &g_qeglobals.d_texturewin.texdef;
- Brush_Free (b);
- if (g_pParentWnd->ActiveXY())
- {
- switch(g_pParentWnd->ActiveXY()->GetViewType())
- {
- case XY: axis = 2; break;
- case XZ: axis = 1; break;
- case YZ: axis = 0; break;
- }
- }
- else
- {
- axis = 2;
- }
- // find center of brush
- width = 8;
- for (i = 0; i < 3; i++)
- {
- mid[i] = (maxs[i] + mins[i]) * 0.5;
- if (i == axis) continue;
- if ((maxs[i] - mins[i]) * 0.5 > width)
- width = (maxs[i] - mins[i]) * 0.5;
- }
- b = Brush_Alloc();
-
- // create top face
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- f->planepts[2][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[2][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[2][axis] = maxs[axis];
- f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = maxs[axis];
- f->planepts[0][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[0][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[0][axis] = maxs[axis];
- // create bottom face
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- f->planepts[0][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[0][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[0][axis] = mins[axis];
- f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = mins[axis];
- f->planepts[2][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[2][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[2][axis] = mins[axis];
- for (i=0 ; i<sides ; i++)
- {
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- sv = sin (i*3.14159265*2/sides);
- cv = cos (i*3.14159265*2/sides);
- f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
- f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
- f->planepts[0][axis] = mins[axis];
- f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
- f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
- f->planepts[1][axis] = maxs[axis];
- f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
- f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
- f->planepts[2][axis] = maxs[axis];
- }
- Brush_AddToList (b, &selected_brushes);
- Entity_LinkBrush (world_entity, b);
- Brush_Build( b );
- Sys_UpdateWindows (W_ALL);
- }
- /*
- =============
- Brush_Free
- Frees the brush with all of its faces and display list.
- Unlinks the brush from whichever chain it is in.
- Decrements the owner entity's brushcount.
- Removes owner entity if this was the last brush
- unless owner is the world.
- Removes from groups
- =============
- */
- void Brush_Free (brush_t *b, bool bRemoveNode)
- {
- face_t *f, *next;
- epair_t *ep, *enext;
- // remove from group
- if (bRemoveNode)
- Group_RemoveBrush(b);
- // free the patch if it's there
- if (b->patchBrush)
- {
- Patch_Delete(b->pPatch);
- }
- if( b->terrainBrush )
- {
- Terrain_Delete( b->pTerrain );
- }
- // free faces
- for (f=b->brush_faces ; f ; f=next)
- {
- next = f->next;
- Face_Free( f );
- }
- //Timo : free brush epairs
- for (ep = b->epairs ; ep ; ep=enext )
- {
- enext = ep->next;
- free (ep->key);
- free (ep->value);
- free (ep);
- }
- // unlink from active/selected list
- if (b->next)
- Brush_RemoveFromList (b);
- // unlink from entity list
- if (b->onext)
- Entity_UnlinkBrush (b);
- free (b);
- }
- /*
- =============
- Face_MemorySize
- =============
- */
- int Face_MemorySize(face_t *f )
- {
- int size = 0;
- if (f->face_winding)
- {
- size += _msize(f->face_winding);
- }
- //f->texdef.~texdef_t();;
- size += _msize(f);
- return size;
- }
- /*
- =============
- Brush_MemorySize
- =============
- */
- int Brush_MemorySize(brush_t *b)
- {
- face_t *f;
- epair_t *ep;
- int size = 0;
- //
- if (b->patchBrush)
- {
- size += Patch_MemorySize(b->pPatch);
- }
- if (b->terrainBrush)
- {
- size += Terrain_MemorySize(b->pTerrain);
- }
- //
- for (f = b->brush_faces; f; f = f->next)
- {
- size += Face_MemorySize(f);
- }
- //
- for (ep = b->epairs; ep; ep = ep->next )
- {
- size += _msize(ep->key);
- size += _msize(ep->value);
- size += _msize(ep);
- }
- size += _msize(b);
- return size;
- }
- /*
- ============
- Brush_Clone
- Does NOT add the new brush to any lists
- ============
- */
- brush_t *Brush_Clone (brush_t *b)
- {
- brush_t *n = NULL;
- face_t *f, *nf;
- if (b->patchBrush)
- {
- patchMesh_t *p = Patch_Duplicate(b->pPatch);
- Brush_RemoveFromList(p->pSymbiot);
- Entity_UnlinkBrush(p->pSymbiot);
- n = p->pSymbiot;
- }
- else if (b->terrainBrush)
- {
- terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
- Brush_RemoveFromList(p->pSymbiot);
- Entity_UnlinkBrush(p->pSymbiot);
- n = p->pSymbiot;
- }
- else
- {
- n = Brush_Alloc();
- n->numberId = g_nBrushId++;
- n->owner = b->owner;
- for (f=b->brush_faces ; f ; f=f->next)
- {
- nf = Face_Clone( f );
- nf->next = n->brush_faces;
- n->brush_faces = nf;
- }
- }
- return n;
- }
- /*
- ============
- Brush_Clone
- Does NOT add the new brush to any lists
- ============
- */
- brush_t *Brush_FullClone(brush_t *b)
- {
- brush_t *n = NULL;
- face_t *f, *nf, *f2, *nf2;
- int j;
- if (b->patchBrush)
- {
- patchMesh_t *p = Patch_Duplicate(b->pPatch);
- Brush_RemoveFromList(p->pSymbiot);
- Entity_UnlinkBrush(p->pSymbiot);
- n = p->pSymbiot;
- n->owner = b->owner;
- Brush_Build(n);
- }
- else if (b->terrainBrush)
- {
- terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
- Brush_RemoveFromList(p->pSymbiot);
- Entity_UnlinkBrush(p->pSymbiot);
- n = p->pSymbiot;
- n->owner = b->owner;
- Brush_Build(n);
- }
- else
- {
- n = Brush_Alloc();
- n->numberId = g_nBrushId++;
- n->owner = b->owner;
- VectorCopy(b->mins, n->mins);
- VectorCopy(b->maxs, n->maxs);
- //
- for (f = b->brush_faces; f; f = f->next)
- {
- if (f->original) continue;
- nf = Face_FullClone(f);
- nf->next = n->brush_faces;
- n->brush_faces = nf;
- //copy all faces that have the original set to this face
- for (f2 = b->brush_faces; f2; f2 = f2->next)
- {
- if (f2->original == f)
- {
- nf2 = Face_FullClone(f2);
- nf2->next = n->brush_faces;
- n->brush_faces = nf2;
- //set original
- nf2->original = nf;
- }
- }
- }
- for (nf = n->brush_faces; nf; nf = nf->next)
- {
- Face_SetColor(n, nf, 1.0);
- if (nf->face_winding)
- {
- if (g_qeglobals.m_bBrushPrimitMode)
- EmitBrushPrimitTextureCoordinates(nf,nf->face_winding);
- else
- {
- for (j = 0; j < nf->face_winding->numpoints; j++)
- EmitTextureCoordinates(nf->face_winding->points[j], nf->d_texture, nf);
- }
- }
- }
- }
- return n;
- }
- /*
- ==============
- Brush_Ray
- Itersects a ray with a brush
- Returns the face hit and the distance along the ray the intersection occured at
- Returns NULL and 0 if not hit at all
- ==============
- */
- face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
- {
- face_t *f, *firstface;
- vec3_t p1, p2;
- float frac, d1, d2;
- int i;
- VectorCopy (origin, p1);
- for (i=0 ; i<3 ; i++)
- p2[i] = p1[i] + dir[i]*16384;
- for (f=b->brush_faces ; f ; f=f->next)
- {
- d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
- d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
- if (d1 >= 0 && d2 >= 0)
- {
- *dist = 0;
- return NULL; // ray is on front side of face
- }
- if (d1 <=0 && d2 <= 0)
- continue;
- // clip the ray to the plane
- frac = d1 / (d1 - d2);
- if (d1 > 0)
- {
- firstface = f;
- for (i=0 ; i<3 ; i++)
- p1[i] = p1[i] + frac *(p2[i] - p1[i]);
- }
- else
- {
- for (i=0 ; i<3 ; i++)
- p2[i] = p1[i] + frac *(p2[i] - p1[i]);
- }
- }
- // find distance p1 is along dir
- VectorSubtract (p1, origin, p1);
- d1 = DotProduct (p1, dir);
- *dist = d1;
- return firstface;
- }
- //PGM
- face_t *Brush_Point (vec3_t origin, brush_t *b)
- {
- face_t *f;
- float d1;
- for (f=b->brush_faces ; f ; f=f->next)
- {
- d1 = DotProduct (origin, f->plane.normal) - f->plane.dist;
- if (d1 > 0)
- {
- return NULL; // point is on front side of face
- }
- }
- return b->brush_faces;
- }
- //PGM
- void Brush_AddToList (brush_t *b, brush_t *list)
- {
- if (b->next || b->prev)
- Error ("Brush_AddToList: allready linked");
-
- if (list == &selected_brushes || list == &active_brushes)
- {
- if (b->patchBrush && list == &selected_brushes)
- {
- Patch_Select(b->pPatch);
- }
- if (b->terrainBrush && list == &selected_brushes) {
- Terrain_Select(b->pTerrain);
- }
- }
- b->next = list->next;
- list->next->prev = b;
- list->next = b;
- b->prev = list;
-
- // TTimo messaging
- DispatchRadiantMsg( RADIANT_SELECTION );
- }
- void Brush_RemoveFromList (brush_t *b)
- {
- if (!b->next || !b->prev)
- Error ("Brush_RemoveFromList: not linked");
-
- if (b->patchBrush)
- {
- Patch_Deselect(b->pPatch);
- //Patch_Deselect(b->nPatchID);
- }
- if (b->terrainBrush)
- {
- Terrain_Deselect(b->pTerrain);
- }
- b->next->prev = b->prev;
- b->prev->next = b->next;
- b->next = b->prev = NULL;
- }
- /*
- ===============
- SetFaceTexdef
- Doesn't set the curve flags
- NOTE : ( TTimo )
- never trust f->d_texture here, f->texdef and f->d_texture are out of sync when called by Brush_SetTexture
- use Texture_ForName() to find the right shader
- FIXME : send the right shader ( qtexture_t * ) in the parameters ?
- TTimo: surface plugin, added an IPluginTexdef* parameter
- if not NULL, get ->Copy() of it into the face ( and remember to hook )
- if NULL, ask for a default
- ===============
- */
- void SetFaceTexdef (brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
- int oldFlags;
- int oldContents;
- face_t *tf;
- oldFlags = f->texdef.flags;
- oldContents = f->texdef.contents;
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- f->texdef = *texdef;
- ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, Texture_ForName( f->texdef.name ) );
- }
- else
- if (bFitScale)
- {
- f->texdef = *texdef;
- // fit the scaling of the texture on the actual plane
- vec3_t p1,p2,p3; // absolute coordinates
- // compute absolute coordinates
- ComputeAbsolute(f,p1,p2,p3);
- // compute the scale
- vec3_t vx,vy;
- VectorSubtract(p2,p1,vx);
- VectorNormalize(vx);
- VectorSubtract(p3,p1,vy);
- VectorNormalize(vy);
- // assign scale
- VectorScale(vx,texdef->scale[0],vx);
- VectorScale(vy,texdef->scale[1],vy);
- VectorAdd(p1,vx,p2);
- VectorAdd(p1,vy,p3);
- // compute back shift scale rot
- AbsoluteToLocal(f->plane,f,p1,p2,p3);
- }
- else
- f->texdef = *texdef;
- f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
- f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
- // surface plugin
- if (g_qeglobals.bSurfacePropertiesPlugin)
- {
- #ifdef _DEBUG
- if (!f->pData)
- Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in SetFaceTexdef\n");
- else
- #endif
- GETPLUGINTEXDEF(f)->DecRef();
- IPluginTexdef *pTexdef = NULL;
- if ( pPlugTexdef )
- {
- pTexdef = pPlugTexdef->Copy();
- pTexdef->Hook( f );
- }
- else
- pTexdef = g_SurfaceTable.m_pfnTexdefAlloc( f );
- f->pData = pTexdef;
- }
- // if this is a curve face, set all other curve faces to the same texdef
- if (f->texdef.flags & SURF_CURVE)
- {
- for (tf = b->brush_faces ; tf ; tf = tf->next)
- {
- if (tf->texdef.flags & SURF_CURVE)
- tf->texdef = f->texdef;
- }
- }
- }
- void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
- {
- for (face_t* f = b->brush_faces ; f ; f = f->next)
- {
- SetFaceTexdef (b, f, texdef, brushprimit_texdef, bFitScale, pTexdef);
- }
- Brush_Build( b );
- if (b->patchBrush)
- {
- //++timo clean
- // Sys_Printf("WARNING: Brush_SetTexture needs surface plugin code for patches\n");
- Patch_SetTexture(b->pPatch, texdef, pTexdef );
- }
- if (b->terrainBrush)
- {
- Terrain_SetTexture(b->pTerrain, texdef);
- }
- }
- qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)
- {
- float d1, d2, fr;
- int i;
- float *v;
- d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
- d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
- if (d1 >= 0 && d2 >= 0)
- return false; // totally outside
- if (d1 <= 0 && d2 <= 0)
- return true; // totally inside
- fr = d1 / (d1 - d2);
- if (d1 > 0)
- v = p1;
- else
- v = p2;
- for (i=0 ; i<3 ; i++)
- v[i] = p1[i] + fr*(p2[i] - p1[i]);
- return true;
- }
- int AddPlanept (float *f)
- {
- int i;
- for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
- if (g_qeglobals.d_move_points[i] == f)
- return 0;
- g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
- return 1;
- }
- /*
- ==============
- Brush_SelectFaceForDragging
- Adds the faces planepts to move_points, and
- rotates and adds the planepts of adjacent face if shear is set
- ==============
- */
- void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear)
- {
- int i;
- face_t *f2;
- winding_t *w;
- float d;
- brush_t *b2;
- int c;
- if (b->owner->eclass->fixedsize)
- return;
- c = 0;
- for (i=0 ; i<3 ; i++)
- c += AddPlanept (f->planepts[i]);
- if (c == 0)
- return; // allready completely added
- // select all points on this plane in all brushes the selection
- for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next)
- {
- if (b2 == b)
- continue;
- for (f2=b2->brush_faces ; f2 ; f2=f2->next)
- {
- for (i=0 ; i<3 ; i++)
- if (fabs(DotProduct(f2->planepts[i], f->plane.normal)
- -f->plane.dist) > ON_EPSILON)
- break;
- if (i==3)
- { // move this face as well
- Brush_SelectFaceForDragging (b2, f2, shear);
- break;
- }
- }
- }
- // if shearing, take all the planes adjacent to
- // selected faces and rotate their points so the
- // edge clipped by a selcted face has two of the points
- if (!shear)
- return;
- for (f2=b->brush_faces ; f2 ; f2=f2->next)
- {
- if (f2 == f)
- continue;
- w = Brush_MakeFaceWinding (b, f2);
- if (!w)
- continue;
- // any points on f will become new control points
- for (i=0 ; i<w->numpoints ; i++)
- {
- d = DotProduct (w->points[i], f->plane.normal)
- - f->plane.dist;
- if (d > -ON_EPSILON && d < ON_EPSILON)
- break;
- }
- //
- // if none of the points were on the plane,
- // leave it alone
- //
- if (i != w->numpoints)
- {
- if (i == 0)
- { // see if the first clockwise point was the
- // last point on the winding
- d = DotProduct (w->points[w->numpoints-1]
- , f->plane.normal) - f->plane.dist;
- if (d > -ON_EPSILON && d < ON_EPSILON)
- i = w->numpoints - 1;
- }
- AddPlanept (f2->planepts[0]);
- VectorCopy (w->points[i], f2->planepts[0]);
- if (++i == w->numpoints)
- i = 0;
-
- // see if the next point is also on the plane
- d = DotProduct (w->points[i]
- , f->plane.normal) - f->plane.dist;
- if (d > -ON_EPSILON && d < ON_EPSILON)
- AddPlanept (f2->planepts[1]);
- VectorCopy (w->points[i], f2->planepts[1]);
- if (++i == w->numpoints)
- i = 0;
- // the third point is never on the plane
- VectorCopy (w->points[i], f2->planepts[2]);
- }
- free(w);
- }
- }
- /*
- ==============
- Brush_SideSelect
- The mouse click did not hit the brush, so grab one or more side
- planes for dragging
- ==============
- */
- void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir
- , qboolean shear)
- {
- face_t *f, *f2;
- vec3_t p1, p2;
- //if (b->patchBrush)
- // return;
- //Patch_SideSelect(b->nPatchID, origin, dir);
- for (f=b->brush_faces ; f ; f=f->next)
- {
- VectorCopy (origin, p1);
- VectorMA (origin, 16384, dir, p2);
- for (f2=b->brush_faces ; f2 ; f2=f2->next)
- {
- if (f2 == f)
- continue;
- ClipLineToFace (p1, p2, f2);
- }
- if (f2)
- continue;
- if (VectorCompare (p1, origin))
- continue;
- if (ClipLineToFace (p1, p2, f))
- continue;
- Brush_SelectFaceForDragging (b, f, shear);
- }
-
- }
- void Brush_BuildWindings( brush_t *b, bool bSnap )
- {
- winding_t *w;
- face_t *face;
- vec_t v;
- if (bSnap)
- Brush_SnapPlanepts( b );
- // clear the mins/maxs bounds
- b->mins[0] = b->mins[1] = b->mins[2] = 99999;
- b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999;
- Brush_MakeFacePlanes (b);
- face = b->brush_faces;
- float fCurveColor = 1.0;
- for ( ; face ; face=face->next)
- {
- int i, j;
- free(face->face_winding);
- w = face->face_winding = Brush_MakeFaceWinding (b, face);
- face->d_texture = Texture_ForName( face->texdef.name );
- if (!w)
- continue;
-
- for (i=0 ; i<w->numpoints ; i++)
- {
- // add to bounding box
- for (j=0 ; j<3 ; j++)
- {
- v = w->points[i][j];
- if (v > b->maxs[j])
- b->maxs[j] = v;
- if (v < b->mins[j])
- b->mins[j] = v;
- }
- }
- // setup s and t vectors, and set color
- //if (!g_PrefsDlg.m_bGLLighting)
- //{
- Face_SetColor (b, face, fCurveColor);
- //}
- fCurveColor -= .10;
- if (fCurveColor <= 0)
- fCurveColor = 1.0;
- // computing ST coordinates for the windings
- if (g_qeglobals.m_bBrushPrimitMode)
- {
- if (g_qeglobals.bNeedConvert)
- {
- // we have parsed old brushes format and need conversion
- // convert old brush texture representation to new format
- FaceToBrushPrimitFace(face);
- #ifdef _DEBUG
- // use old texture coordinates code to check against
- for (i=0 ; i<w->numpoints ; i++)
- EmitTextureCoordinates( w->points[i], face->d_texture, face);
- #endif
- }
- // use new texture representation to compute texture coordinates
- // in debug mode we will check against old code and warn if there are differences
- EmitBrushPrimitTextureCoordinates(face,w);
- }
- else
- {
- for (i=0 ; i<w->numpoints ; i++)
- EmitTextureCoordinates( w->points[i], face->d_texture, face);
- }
- }
- }
- /*
- ==================
- Brush_RemoveEmptyFaces
- Frees any overconstraining faces
- ==================
- */
- void Brush_RemoveEmptyFaces ( brush_t *b )
- {
- face_t *f, *next;
- f = b->brush_faces;
- b->brush_faces = NULL;
- for ( ; f ; f=next)
- {
- next = f->next;
- if (!f->face_winding)
- Face_Free (f);
- else
- {
- f->next = b->brush_faces;
- b->brush_faces = f;
- }
- }
- }
- void Brush_SnapToGrid(brush_t *pb)
- {
- for (face_t *f = pb->brush_faces ; f; f = f->next)
- {
- for (int i = 0 ;i < 3 ;i++)
- {
- for (int j = 0 ;j < 3 ; j++)
- {
- f->planepts[i][j] = floor (f->planepts[i][j] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
- }
- }
- }
- Brush_Build(pb);
- }
- void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild)
- {
- for (face_t* f=b->brush_faces ; f ; f=f->next)
- {
- for (int i=0 ; i<3 ; i++)
- {
- VectorRotate(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
- }
- }
- if (bBuild)
- {
- Brush_Build(b, false, false);
- }
- }
- void Brush_Center(brush_t *b, vec3_t vNewCenter)
- {
- vec3_t vMid;
- // get center of the brush
- for (int j = 0; j < 3; j++)
- {
- vMid[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
- }
- // calc distance between centers
- VectorSubtract(vNewCenter, vMid, vMid);
- Brush_Move(b, vMid, true);
- }
- // only designed for fixed size entity brushes
- void Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax)
- {
- brush_t *b2 = Brush_Create(vMin, vMax, &b->brush_faces->texdef);
- face_t *next;
- for (face_t *f=b->brush_faces ; f ; f=next)
- {
- next = f->next;
- Face_Free( f );
- }
- b->brush_faces = b2->brush_faces;
- // unlink from active/selected list
- if (b2->next)
- Brush_RemoveFromList (b2);
- free(b2);
- Brush_Build(b, true);
- }
- eclass_t* HasModel(brush_t *b)
- {
- vec3_t vMin, vMax;
- vMin[0] = vMin[1] = vMin[2] = 9999;
- vMax[0] = vMax[1] = vMax[2] = -9999;
- if (b->owner->md3Class != NULL)
- {
- return b->owner->md3Class;
- }
- if (Eclass_hasModel(b->owner->eclass, vMin, vMax))
- {
- return b->owner->eclass;
- }
- eclass_t *e = NULL;
- // FIXME: entity needs to track whether a cache hit failed and not ask again
- if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
- {
- char *pModel = ValueForKey(b->owner, "model");
- if (pModel != NULL && strlen(pModel) > 0)
- {
- e = GetCachedModel(b->owner, pModel, vMin, vMax);
- if (e != NULL)
- {
- // we need to scale the brush to the proper size based on the model load
- // recreate brush just like in load/save
- VectorAdd (vMin, b->owner->origin, vMin);
- VectorAdd (vMax, b->owner->origin, vMax);
- Brush_Resize(b, vMin, vMax);
- /*
- //
- vec3_t vTemp, vTemp2;
- VectorSubtract(b->maxs, b->mins, vTemp);
- VectorSubtract(vMax, vMin, vTemp2);
- for (int i = 0; i < 3; i++)
- {
- if (vTemp[i] != 0)
- {
- vTemp2[i] /= vTemp[i];
- }
- }
- vec3_t vMid, vMid2;
- vMid[0] = vMid[1] = vMid[2] = 0.0;
- vMid2[0] = vMid2[1] = vMid2[2] = 0.0;
- for (int j = 0; j < 3; j++)
- {
- vMid2[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
- }
- //VectorSubtract(vMid2, vMid, vMid2);
- for (face_t* f=b->brush_faces ; f ; f=f->next)
- {
- for (int i=0 ; i<3 ; i++)
- {
- // scale
- VectorSubtract(f->planepts[i], vMid2, f->planepts[i]);
- f->planepts[i][0] *= vTemp2[0];
- f->planepts[i][1] *= vTemp2[1];
- f->planepts[i][2] *= vTemp2[2];
- VectorAdd(f->planepts[i], vMid2, f->planepts[i]);
- }
- }
- //Brush_Center(b, b->owner->origin);
- //Brush_SnapToGrid(b);
- /*
- float a = FloatForKey (b->owner, "angle");
- if (a)
- {
- vec3_t vAngle;
- vAngle[0] = vAngle[1] = 0;
- vAngle[2] = a;
- Brush_Rotate(b, vAngle, b->owner->origin);
- }
- else
- {
- Brush_Build(b, true);
- */
- // }
- b->bModelFailed = false;
- }
- else
- {
- b->bModelFailed = true;
- }
- }
- }
- return e;
- }
- static bool g_bInPaintedModel = false;
- static bool g_bDoIt = false;
- bool PaintedModel(brush_t *b, bool bOkToTexture)
- {
- if (g_bInPaintedModel)
- {
- return true;
- }
-
- if (g_PrefsDlg.m_nEntityShowState == ENTITY_BOX || b->bModelFailed)
- {
- return false;
- }
- else if (!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY))
- {
- return false;
- }
- g_bInPaintedModel = true;
- bool bReturn = false;
- eclass_t *pEclass = HasModel(b);
- if (pEclass)
- {
- qglPushAttrib(GL_ALL_ATTRIB_BITS);
- entitymodel *model = pEclass->model;
- float a = FloatForKey (b->owner, "angle");
- while (model != NULL)
- {
- if (bOkToTexture == false || g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME || model->nTextureBind == -1) // skinned
- {
- qglDisable( GL_CULL_FACE );
- qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- qglDisable(GL_TEXTURE_2D);
- qglColor3fv(pEclass->color);
- }
- else
- {
- qglColor3f(1, 1, 1);
- qglEnable(GL_TEXTURE_2D);
- qglBindTexture( GL_TEXTURE_2D, model->nTextureBind );
- }
- vec3_t v;
-
- int i,j;
- VectorAdd(b->maxs, b->mins, v);
- VectorScale(v, 0.5, v);
- VectorCopy(b->owner->origin, v);
-
- //for (i = 0; i < 3; i++)
- //{
- // v[i] -= (pEclass->mins[i] - b->mins[i]);
- //}
- //if (model->nModelPosition)
- //{
- //v[2] = b->mins[2] - (pEclass->mins[2]);
- //}
- float s, c;
- if (a)
- {
- s = sin (a/180*Q_PI);
- c = cos (a/180*Q_PI);
- }
- vec3_t vSin;
- vec3_t vCos;
- VectorClear(vSin);
- VectorClear(vCos);
- for ( j = 0; j < 3; j++)
- {
- if (b->owner->vRotation[j])
- {
- vSin[j] = sin(b->owner->vRotation[j]/180*Q_PI);
- vCos[j] = cos(b->owner->vRotation[j]/180*Q_PI);
- }
- }
- qglBegin (GL_TRIANGLES);
- vec5_t vTest[3];
- for (i = 0; i < model->nTriCount; i++)
- {
- for (j = 0; j < 3; j++)
- {
- #if 1
- float x = model->pTriList[i].v[j][0] + v[0];
- float y = model->pTriList[i].v[j][1] + v[1];
- if (a)
- {
- float x2 = (((x - v[0]) * c) - ((y - v[1]) * s)) + v[0];
- float y2 = (((x - v[0]) * s) + ((y - v[1]) * c)) + v[1];
- x = x2;
- y = y2;
- }
- //qglTexCoord2f (pEclass->pTriList[i].st[j][0] / pEclass->nSkinWidth, pEclass->pTriList[i].st[j][1] / pEclass->nSkinHeight);
- qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
- qglVertex3f(x, y, model->pTriList[i].v[j][2] + v[2]);
- #else
- float x = model->pTriList[i].v[j][0] + v[0];
- float y = model->pTriList[i].v[j][1] + v[1];
- float z = model->pTriList[i].v[j][2] + v[2];
- if (b->owner->vRotation[0])
- {
- float y2 = (((y - v[1]) * vCos[0]) - ((z - v[2]) * vSin[0])) + v[1];
- float z2 = (((y - v[1]) * vSin[0]) + ((z - v[2]) * vCos[0])) + v[2];
- y = y2;
- z = z2;
- }
- if (b->owner->vRotation[1])
- {
- float z2 = (((z - v[2]) * vCos[1]) - ((x - v[0]) * vSin[1])) + v[2];
- float x2 = (((z - v[2]) * vSin[1]) + ((x - v[0]) * vCos[1])) + v[0];
- x = x2;
- z = z2;
- }
- if (b->owner->vRotation[2])
- {
- float x2 = (((x - v[0]) * vCos[2]) - ((y - v[1]) * vSin[2])) + v[0];
- float y2 = (((x - v[0]) * vSin[2]) + ((y - v[1]) * vCos[2])) + v[1];
- x = x2;
- y = y2;
- }
- qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
- qglVertex3f(x, y, z);
- #endif
- if (g_bDoIt)
- {
- vTest[j][0] = x;
- vTest[j][1] = y;
- vTest[j][2] = model->pTriList[i].v[j][2] + v[2];
- vTest[j][3] = model->pTriList[i].st[j][0];
- vTest[j][4] = model->pTriList[i].st[j][1];
- }
- }
- if (g_bDoIt)
- {
- Patch_FromTriangle(vTest[0], vTest[1], vTest[2]);
- }
- }
- qglEnd();
- if (g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME) // skinned
- {
- qglEnable(GL_CULL_FACE );
- qglEnable(GL_TEXTURE_2D);
- qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
- }
- else
- {
- qglDisable(GL_TEXTURE_2D);
- }
- model = model->pNext;
- }
- if (g_bDoIt)
- {
- g_bDoIt = false;
- }
- vec3_t vColor;
- VectorScale(pEclass->color, 0.50, vColor);
- vec3_t vCenter, vMin, vMax;
- VectorCopy(b->owner->origin, vCenter);
- qglColor3fv(vColor);
- qglPointSize(4);
- qglBegin(GL_POINTS);
- qglVertex3fv(b->owner->origin);
- qglEnd();
- qglBegin(GL_LINES);
- vCenter[0] -= 8;
- qglVertex3fv(vCenter);
- vCenter[0] += 16;
- qglVertex3fv(vCenter);
- vCenter[0] -= 8;
- vCenter[1] -= 8;
- qglVertex3fv(vCenter);
- vCenter[1] += 16;
- qglVertex3fv(vCenter);
- vCenter[1] -= 8;
- vCenter[2] -= 8;
- qglVertex3fv(vCenter);
- vCenter[2] += 16;
- qglVertex3fv(vCenter);
- vCenter[2] -= 8;
- qglEnd();
- VectorCopy(vCenter, vMin);
- VectorCopy(vCenter, vMax);
- vMin[0] -= 4;
- vMin[1] -= 4;
- vMin[2] -= 4;
- vMax[0] += 4;
- vMax[1] += 4;
- vMax[2] += 4;
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(vMin[0],vMin[1],vMin[2]);
- qglVertex3f(vMax[0],vMin[1],vMin[2]);
- qglVertex3f(vMax[0],vMax[1],vMin[2]);
- qglVertex3f(vMin[0],vMax[1],vMin[2]);
- qglEnd();
-
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(vMin[0],vMin[1],vMax[2]);
- qglVertex3f(vMax[0],vMin[1],vMax[2]);
- qglVertex3f(vMax[0],vMax[1],vMax[2]);
- qglVertex3f(vMin[0],vMax[1],vMax[2]);
- qglEnd();
- qglBegin(GL_LINES);
- qglVertex3f(vMin[0],vMin[1],vMin[2]);
- qglVertex3f(vMin[0],vMin[1],vMax[2]);
- qglVertex3f(vMin[0],vMax[1],vMax[2]);
- qglVertex3f(vMin[0],vMax[1],vMin[2]);
- qglVertex3f(vMax[0],vMin[1],vMin[2]);
- qglVertex3f(vMax[0],vMin[1],vMax[2]);
- qglVertex3f(vMax[0],vMax[1],vMax[2]);
- qglVertex3f(vMax[0],vMax[1],vMin[2]);
- qglEnd();
- if (g_PrefsDlg.m_nEntityShowState & ENTITY_BOXED)
- {
- qglColor3fv(pEclass->color);
- vec3_t mins, maxs;
- VectorCopy(b->mins, mins);
- VectorCopy(b->maxs, maxs);
- /*
- if (a)
- {
- vec3_t vAngle;
- vAngle[0] = vAngle[1] = 0;
- vAngle[2] = a;
- VectorRotate(mins, vAngle, b->owner->origin, mins);
- VectorRotate(maxs, vAngle, b->owner->origin, maxs);
- }
- */
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(mins[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],maxs[1],mins[2]);
- qglVertex3f(mins[0],maxs[1],mins[2]);
- qglEnd();
-
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(mins[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],maxs[2]);
- qglEnd();
- qglBegin(GL_LINES);
- qglVertex3f(mins[0],mins[1],mins[2]);
- qglVertex3f(mins[0],mins[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],mins[2]);
- qglEnd();
- }
- qglPopAttrib();
- bReturn = true;
- }
- else
- {
- b->bModelFailed = true;
- }
- g_bInPaintedModel = false;
- return bReturn;
- }
- /*
- //++timo moved out to mahlib.h
- //++timo remove
- void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
- {
- float angle;
- static float sr, sp, sy, cr, cp, cy;
- // static to help MS compiler fp bugs
- angle = angles[YAW] * Q_PI / 180;
- sy = sin(angle);
- cy = cos(angle);
- angle = angles[PITCH] * Q_PI / 180;
- sp = sin(angle);
- cp = cos(angle);
- angle = angles[ROLL] * Q_PI / 180;
- sr = sin(angle);
- cr = cos(angle);
- if (forward)
- {
- forward[0] = cp*cy;
- forward[1] = cp*sy;
- forward[2] = -sp;
- }
- if (right)
- {
- right[0] = (-1*sr*sp*cy+-1*cr*-sy);
- right[1] = (-1*sr*sp*sy+-1*cr*cy);
- right[2] = -1*sr*cp;
- }
- if (up)
- {
- up[0] = (cr*sp*cy+-sr*-sy);
- up[1] = (cr*sp*sy+-sr*cy);
- up[2] = cr*cp;
- }
- }
- */
- void FacingVectors (entity_t *e, vec3_t forward, vec3_t right, vec3_t up)
- {
- int angleVal;
- vec3_t angles;
- angleVal = IntForKey(e, "angle");
- if (angleVal == -1) // up
- {
- VectorSet(angles, 270, 0, 0);
- }
- else if(angleVal == -2) // down
- {
- VectorSet(angles, 90, 0, 0);
- }
- else
- {
- VectorSet(angles, 0, angleVal, 0);
- }
- AngleVectors(angles, forward, right, up);
- }
- void Brush_DrawFacingAngle (brush_t *b, entity_t *e)
- {
- vec3_t forward, right, up;
- vec3_t endpoint, tip1, tip2;
- vec3_t start;
- float dist;
- VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
- VectorScale(start, 0.5, start);
- dist = (b->maxs[0] - start[0]) * 2.5;
- FacingVectors (e, forward, right, up);
- VectorMA (start, dist, forward, endpoint);
- dist = (b->maxs[0] - start[0]) * 0.5;
- VectorMA (endpoint, -dist, forward, tip1);
- VectorMA (tip1, -dist, up, tip1);
- VectorMA (tip1, 2*dist, up, tip2);
- qglColor4f (1, 1, 1, 1);
- qglLineWidth (4);
- qglBegin (GL_LINES);
- qglVertex3fv (start);
- qglVertex3fv (endpoint);
- qglVertex3fv (endpoint);
- qglVertex3fv (tip1);
- qglVertex3fv (endpoint);
- qglVertex3fv (tip2);
- qglEnd ();
- qglLineWidth (1);
- }
- void DrawLight(brush_t *b)
- {
- vec3_t vTriColor;
- bool bTriPaint = false;
- vTriColor[0] = vTriColor[2] = 1.0;
- vTriColor[1] = 1.0;
- bTriPaint = true;
- CString strColor = ValueForKey(b->owner, "_color");
- if (strColor.GetLength() > 0)
- {
- float fR, fG, fB;
- int n = sscanf(strColor,"%f %f %f", &fR, &fG, &fB);
- if (n == 3)
- {
- vTriColor[0] = fR;
- vTriColor[1] = fG;
- vTriColor[2] = fB;
- }
- }
- qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
- vec3_t vCorners[4];
- float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
- vCorners[0][0] = b->mins[0];
- vCorners[0][1] = b->mins[1];
- vCorners[0][2] = fMid;
- vCorners[1][0] = b->mins[0];
- vCorners[1][1] = b->maxs[1];
- vCorners[1][2] = fMid;
- vCorners[2][0] = b->maxs[0];
- vCorners[2][1] = b->maxs[1];
- vCorners[2][2] = fMid;
- vCorners[3][0] = b->maxs[0];
- vCorners[3][1] = b->mins[1];
- vCorners[3][2] = fMid;
- vec3_t vTop, vBottom;
- vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
- vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
- vTop[2] = b->maxs[2];
- VectorCopy(vTop, vBottom);
- vBottom[2] = b->mins[2];
- vec3_t vSave;
- VectorCopy(vTriColor, vSave);
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vTop);
- for (int i = 0; i <= 3; i++)
- {
- vTriColor[0] *= 0.95;
- vTriColor[1] *= 0.95;
- vTriColor[2] *= 0.95;
- qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
- qglVertex3fv(vCorners[i]);
- }
- qglVertex3fv(vCorners[0]);
- qglEnd();
-
- VectorCopy(vSave, vTriColor);
- vTriColor[0] *= 0.95;
- vTriColor[1] *= 0.95;
- vTriColor[2] *= 0.95;
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vBottom);
- qglVertex3fv(vCorners[0]);
- for (i = 3; i >= 0; i--)
- {
- vTriColor[0] *= 0.95;
- vTriColor[1] *= 0.95;
- vTriColor[2] *= 0.95;
- qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
- qglVertex3fv(vCorners[i]);
- }
- qglEnd();
- // check for DOOM lights
- CString str = ValueForKey(b->owner, "light_right");
- if (str.GetLength() > 0) {
- vec3_t vRight, vUp, vTarget, vTemp;
- GetVectorForKey (b->owner, "light_right", vRight);
- GetVectorForKey (b->owner, "light_up", vUp);
- GetVectorForKey (b->owner, "light_target", vTarget);
- qglColor3f(0, 1, 0);
- qglBegin(GL_LINE_LOOP);
- VectorAdd(vTarget, b->owner->origin, vTemp);
- VectorAdd(vTemp, vRight, vTemp);
- VectorAdd(vTemp, vUp, vTemp);
- qglVertex3fv(b->owner->origin);
- qglVertex3fv(vTemp);
- VectorAdd(vTarget, b->owner->origin, vTemp);
- VectorAdd(vTemp, vUp, vTemp);
- VectorSubtract(vTemp, vRight, vTemp);
- qglVertex3fv(b->owner->origin);
- qglVertex3fv(vTemp);
- VectorAdd(vTarget, b->owner->origin, vTemp);
- VectorAdd(vTemp, vRight, vTemp);
- VectorSubtract(vTemp, vUp, vTemp);
- qglVertex3fv(b->owner->origin);
- qglVertex3fv(vTemp);
- VectorAdd(vTarget, b->owner->origin, vTemp);
- VectorSubtract(vTemp, vUp, vTemp);
- VectorSubtract(vTemp, vRight, vTemp);
- qglVertex3fv(b->owner->origin);
- qglVertex3fv(vTemp);
- qglEnd();
- }
- }
- void Brush_Draw( brush_t *b )
- {
- face_t *face;
- int i, order;
- qtexture_t *prev = 0;
- winding_t *w;
- if ( b->owner && ( b->owner->eclass->nShowFlags & ECLASS_PLUGINENTITY ) )
- {
- b->owner->pPlugEnt->CamRender();
- return;
- }
-
- // (TTimo) NOTE: added by build 173, I check after pPlugEnt so it doesn't interfere ?
- if (b->hiddenBrush)
- {
- return;
- }
- if (b->patchBrush)
- {
- //Patch_DrawCam(b->nPatchID);
- Patch_DrawCam(b->pPatch);
- //if (!g_bPatchShowBounds)
- return;
- }
-
- if (b->terrainBrush)
- {
- Terrain_DrawCam(b->pTerrain);
- return;
- }
- int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
-
- if (b->owner->eclass->fixedsize)
- {
-
- if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE))
- {
- Brush_DrawFacingAngle(b, b->owner);
- }
-
- if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
- {
- DrawLight(b);
- return;
- }
- if (nDrawMode == cd_texture || nDrawMode == cd_light)
- qglDisable (GL_TEXTURE_2D);
-
- // if we are wireframing models
- bool bp = (b->bModelFailed) ? false : PaintedModel(b, true);
-
- if (nDrawMode == cd_texture || nDrawMode == cd_light)
- qglEnable (GL_TEXTURE_2D);
-
- if (bp)
- return;
- }
-
- // guarantee the texture will be set first
- prev = NULL;
- for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
- {
- w = face->face_winding;
- if (!w)
- {
- continue; // freed face
- }
-
- if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
- {
- if (strstr(face->texdef.name, "caulk"))
- {
- continue;
- }
- }
-
- #if 0
- if (b->alphaBrush)
- {
- if (!(face->texdef.flags & SURF_ALPHA))
- continue;
- //--qglPushAttrib(GL_ALL_ATTRIB_BITS);
- qglDisable(GL_CULL_FACE);
- //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- //--qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- //--qglDisable(GL_DEPTH_TEST);
- //--qglBlendFunc (GL_SRC_ALPHA, GL_DST_ALPHA);
- //--qglEnable (GL_BLEND);
- }
- #endif
-
- if ((nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
- {
- // set the texture for this face
- prev = face->d_texture;
- qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
- }
-
-
-
- if (!b->patchBrush)
- {
- if (face->texdef.flags & SURF_TRANS33)
- qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.33 );
- else if ( face->texdef.flags & SURF_TRANS66)
- qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.66 );
- else
- qglColor3fv( face->d_color );
- }
- else
- {
- qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.13 );
- }
-
- // shader drawing stuff
- if (face->d_texture->bFromShader)
- {
- // setup shader drawing
- qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], face->d_texture->fTrans );
-
- }
-
- // draw the polygon
-
- //if (nDrawMode == cd_light)
- //{
- if (g_PrefsDlg.m_bGLLighting)
- {
- qglNormal3fv(face->plane.normal);
- }
- //}
-
- qglBegin(GL_POLYGON);
- //if (nDrawMode == cd_light)
-
- for (i=0 ; i<w->numpoints ; i++)
- {
- if (nDrawMode == cd_texture || nDrawMode == cd_light)
- qglTexCoord2fv( &w->points[i][3] );
- qglVertex3fv(w->points[i]);
- }
- qglEnd();
- }
-
- #if 0
- if (b->alphaBrush)
- {
- //--qglPopAttrib();
- qglEnable(GL_CULL_FACE);
- //--qglDisable (GL_BLEND);
- //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- #endif
-
- if (b->owner->eclass->fixedsize && (nDrawMode == cd_texture || nDrawMode == cd_light))
- qglEnable (GL_TEXTURE_2D);
-
- qglBindTexture( GL_TEXTURE_2D, 0 );
- }
- void Face_Draw( face_t *f )
- {
- int i;
- if ( f->face_winding == 0 )
- return;
- qglBegin( GL_POLYGON );
- for ( i = 0 ; i < f->face_winding->numpoints; i++)
- qglVertex3fv( f->face_winding->points[i] );
- qglEnd();
- }
- void Brush_DrawXY(brush_t *b, int nViewType)
- {
- face_t *face;
- int order;
- winding_t *w;
- int i;
- if (b->hiddenBrush)
- {
- return;
- }
- if (b->patchBrush)
- {
- //Patch_DrawXY(b->nPatchID);
- Patch_DrawXY(b->pPatch);
- if (!g_bPatchShowBounds)
- return;
- }
- if (b->terrainBrush)
- {
- Terrain_DrawXY(b->pTerrain, b->owner);
- }
-
- if (b->owner->eclass->fixedsize)
- {
- if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
- {
- vec3_t vCorners[4];
- float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
- vCorners[0][0] = b->mins[0];
- vCorners[0][1] = b->mins[1];
- vCorners[0][2] = fMid;
- vCorners[1][0] = b->mins[0];
- vCorners[1][1] = b->maxs[1];
- vCorners[1][2] = fMid;
- vCorners[2][0] = b->maxs[0];
- vCorners[2][1] = b->maxs[1];
- vCorners[2][2] = fMid;
- vCorners[3][0] = b->maxs[0];
- vCorners[3][1] = b->mins[1];
- vCorners[3][2] = fMid;
- vec3_t vTop, vBottom;
- vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
- vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
- vTop[2] = b->maxs[2];
- VectorCopy(vTop, vBottom);
- vBottom[2] = b->mins[2];
- qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vTop);
- qglVertex3fv(vCorners[0]);
- qglVertex3fv(vCorners[1]);
- qglVertex3fv(vCorners[2]);
- qglVertex3fv(vCorners[3]);
- qglVertex3fv(vCorners[0]);
- qglEnd();
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vBottom);
- qglVertex3fv(vCorners[0]);
- qglVertex3fv(vCorners[3]);
- qglVertex3fv(vCorners[2]);
- qglVertex3fv(vCorners[1]);
- qglVertex3fv(vCorners[0]);
- qglEnd();
- DrawBrushEntityName (b);
- return;
- }
- else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
- {
- if (PaintedModel(b, false))
- return;
- }
- }
- for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
- {
- // only draw polygons facing in a direction we care about
- if (nViewType == XY)
- {
- if (face->plane.normal[2] <= 0)
- continue;
- }
- else
- {
- if (nViewType == XZ)
- {
- if (face->plane.normal[1] <= 0)
- continue;
- }
- else
- {
- if (face->plane.normal[0] <= 0)
- continue;
- }
- }
- w = face->face_winding;
- if (!w)
- continue;
- //if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA))
- // continue;
- // draw the polygon
- qglBegin(GL_LINE_LOOP);
- for (i=0 ; i<w->numpoints ; i++)
- qglVertex3fv(w->points[i]);
- qglEnd();
- }
- DrawBrushEntityName (b);
- }
- /*
- ============
- Brush_Move
- ============
- */
- void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
- {
- int i;
- face_t *f;
- for (f=b->brush_faces ; f ; f=f->next)
- {
- vec3_t vTemp;
- VectorCopy(move, vTemp);
- if (g_PrefsDlg.m_bTextureLock)
- Face_MoveTexture(f, vTemp);
-
- for (i=0 ; i<3 ; i++)
- VectorAdd (f->planepts[i], move, f->planepts[i]);
- }
- Brush_Build( b, bSnap );
- if (b->patchBrush)
- {
- //Patch_Move(b->nPatchID, move);
- Patch_Move(b->pPatch, move);
- }
- if (b->terrainBrush)
- {
- Terrain_Move(b->pTerrain, move);
- }
- // PGM - keep the origin vector up to date on fixed size entities.
- if(b->owner->eclass->fixedsize)
- {
- VectorAdd(b->owner->origin, move, b->owner->origin);
- //VectorAdd(b->maxs, b->mins, b->owner->origin);
- //VectorScale(b->owner->origin, 0.5, b->owner->origin);
- }
- }
- void Brush_Print(brush_t* b)
- {
- int nFace = 0;
- for (face_t* f = b->brush_faces ; f ; f=f->next)
- {
- Sys_Printf("Face %i\n", nFace++);
- Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
- Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
- Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
- }
- }
- /*
- =============
- Brush_MakeSided
- Makes the current brushhave the given number of 2d sides and turns it into a cone
- =============
- */
- void Brush_MakeSidedCone(int sides)
- {
- int i;
- vec3_t mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- vec3_t mid;
- float width;
- float sv, cv;
- if (sides < 3)
- {
- Sys_Status ("Bad sides number", 0);
- return;
- }
- if (!QE_SingleBrush ())
- {
- Sys_Status ("Must have a single brush selected", 0 );
- return;
- }
- b = selected_brushes.next;
- VectorCopy (b->mins, mins);
- VectorCopy (b->maxs, maxs);
- texdef = &g_qeglobals.d_texturewin.texdef;
- Brush_Free (b);
- // find center of brush
- width = 8;
- for (i=0 ; i<2 ; i++)
- {
- mid[i] = (maxs[i] + mins[i])*0.5;
- if (maxs[i] - mins[i] > width)
- width = maxs[i] - mins[i];
- }
- width /= 2;
- b = Brush_Alloc();
- // create bottom face
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
- f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
- f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
- for (i=0 ; i<sides ; i++)
- {
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- sv = sin (i*3.14159265*2/sides);
- cv = cos (i*3.14159265*2/sides);
- f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
- f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
- f->planepts[0][2] = mins[2];
- f->planepts[1][0] = mid[0];
- f->planepts[1][1] = mid[1];
- f->planepts[1][2] = maxs[2];
- f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
- f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
- f->planepts[2][2] = maxs[2];
- }
- Brush_AddToList (b, &selected_brushes);
- Entity_LinkBrush (world_entity, b);
- Brush_Build( b );
- Sys_UpdateWindows (W_ALL);
- }
- /*
- =============
- Brush_MakeSided
- Makes the current brushhave the given number of 2d sides and turns it into a sphere
- =============
- */
- void Brush_MakeSidedSphere(int sides)
- {
- int i,j;
- vec3_t mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- vec3_t mid;
- if (sides < 4)
- {
- Sys_Status ("Bad sides number", 0);
- return;
- }
- if (!QE_SingleBrush ())
- {
- Sys_Status ("Must have a single brush selected", 0 );
- return;
- }
- b = selected_brushes.next;
- VectorCopy (b->mins, mins);
- VectorCopy (b->maxs, maxs);
- texdef = &g_qeglobals.d_texturewin.texdef;
- Brush_Free (b);
- // find center of brush
- float radius = 8;
- for (i=0 ; i<2 ; i++)
- {
- mid[i] = (maxs[i] + mins[i])*0.5;
- if (maxs[i] - mins[i] > radius)
- radius = maxs[i] - mins[i];
- }
- radius /= 2;
- b = Brush_Alloc();
- float dt = float(2 * Q_PI / sides);
- float dp = float(Q_PI / sides);
- float t,p;
- for(i=0; i <= sides-1; i++)
- {
- for(j=0;j <= sides-2; j++)
- {
- t = i * dt;
- p = float(j * dp - Q_PI / 2);
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- VectorPolar(f->planepts[0], radius, t, p);
- VectorPolar(f->planepts[1], radius, t, p + dp);
- VectorPolar(f->planepts[2], radius, t + dt, p + dp);
- for (int k = 0; k < 3; k++)
- VectorAdd(f->planepts[k], mid, f->planepts[k]);
- }
- }
- p = float((sides - 1) * dp - Q_PI / 2);
- for(i = 0; i <= sides-1; i++)
- {
- t = i * dt;
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- VectorPolar(f->planepts[0], radius, t, p);
- VectorPolar(f->planepts[1], radius, t + dt, p + dp);
- VectorPolar(f->planepts[2], radius, t + dt, p);
- for (int k = 0; k < 3; k++)
- VectorAdd(f->planepts[k], mid, f->planepts[k]);
- }
- Brush_AddToList (b, &selected_brushes);
- Entity_LinkBrush (world_entity, b);
- Brush_Build( b );
- Sys_UpdateWindows (W_ALL);
- }
- void Face_FitTexture( face_t * face, int nHeight, int nWidth )
- {
- winding_t *w;
- vec3_t mins,maxs;
- int i;
- float width, height, temp;
- float rot_width, rot_height;
- float cosv,sinv,ang;
- float min_t, min_s, max_t, max_s;
- float s,t;
- vec3_t vecs[2];
- vec3_t coords[4];
- texdef_t *td;
- if (nHeight < 1)
- {
- nHeight = 1;
- }
- if (nWidth < 1)
- {
- nWidth = 1;
- }
- ClearBounds (mins, maxs);
- td = &face->texdef;
- w = face->face_winding;
- if (!w)
- {
- return;
- }
- for (i=0 ; i<w->numpoints ; i++)
- {
- AddPointToBounds( w->points[i], mins, maxs );
- }
- //
- // get the current angle
- //
- ang = td->rotate / 180 * Q_PI;
- sinv = sin(ang);
- cosv = cos(ang);
- // get natural texture axis
- TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
- min_s = DotProduct( mins, vecs[0] );
- min_t = DotProduct( mins, vecs[1] );
- max_s = DotProduct( maxs, vecs[0] );
- max_t = DotProduct( maxs, vecs[1] );
- width = max_s - min_s;
- height = max_t - min_t;
- coords[0][0] = min_s;
- coords[0][1] = min_t;
- coords[1][0] = max_s;
- coords[1][1] = min_t;
- coords[2][0] = min_s;
- coords[2][1] = max_t;
- coords[3][0] = max_s;
- coords[3][1] = max_t;
- min_s = min_t = 99999;
- max_s = max_t = -99999;
- for (i=0; i<4; i++)
- {
- s = cosv * coords[i][0] - sinv * coords[i][1];
- t = sinv * coords[i][0] + cosv * coords[i][1];
- if (i&1)
- {
- if (s > max_s)
- {
- max_s = s;
- }
- }
- else
- {
- if (s < min_s)
- {
- min_s = s;
- }
- if (i<2)
- {
- if (t < min_t)
- {
- min_t = t;
- }
- }
- else
- {
- if (t > max_t)
- {
- max_t = t;
- }
- }
- }
- }
- rot_width = (max_s - min_s);
- rot_height = (max_t - min_t);
- td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
- td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
- td->shift[0] = min_s/td->scale[0];
- temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
- temp = (temp+1)*face->d_texture->width*nWidth;
- td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
- td->shift[1] = min_t/td->scale[1];
- temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
- temp = (temp+1)*(face->d_texture->height*nHeight);
- td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
- }
- void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
- {
- face_t *face;
- for (face = b->brush_faces ; face ; face=face->next)
- {
- Face_FitTexture( face, nHeight, nWidth );
- }
- }
|