1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 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 3 of the License, or
- (at your option) any later version.
- Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "qe3.h"
- #include <GL/glu.h>
- #include "../../renderer/tr_local.h"
- #include "../../renderer/model_local.h" // for idRenderModelMD5
- void Brush_UpdateLightPoints(brush_t *b, const idVec3 &offset);
- void Brush_DrawCurve( brush_t *b, bool bSelected, bool cam );
- // globals
- int g_nBrushId = 0;
- bool g_bShowLightVolumes = false;
- bool g_bShowLightTextures = false;
- void GLCircle(float x, float y, float z, float r);
- const int POINTS_PER_KNOT = 50;
- /*
- ================
- DrawRenderModel
- ================
- */
- void DrawRenderModel( idRenderModel *model, idVec3 &origin, idMat3 &axis, bool cameraView ) {
- for ( int i = 0; i < model->NumSurfaces(); i++ ) {
- const modelSurface_t *surf = model->Surface( i );
- const idMaterial *material = surf->shader;
- int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
- if ( cameraView && (nDrawMode == cd_texture || nDrawMode == cd_light) ) {
- material->GetEditorImage()->Bind();
- }
- qglBegin( GL_TRIANGLES );
- const srfTriangles_t *tri = surf->geometry;
- for ( int j = 0; j < tri->numIndexes; j += 3 ) {
- for ( int k = 0; k < 3; k++ ) {
- int index = tri->indexes[j + k];
- idVec3 v;
- v = tri->verts[index].xyz * axis + origin;
- qglTexCoord2f( tri->verts[index].st.x, tri->verts[index].st.y );
- qglVertex3fv( v.ToFloatPtr() );
- }
- }
- qglEnd();
- }
- }
- /*
- ================
- SnapVectorToGrid
- ================
- */
- void SnapVectorToGrid(idVec3 &v) {
- v.x = floor(v.x / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
- v.y = floor(v.y / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
- v.z = floor(v.z / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
- }
- /*
- ================
- Brush_Name
- ================
- */
- 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_Alloc
- ================
- */
- brush_t *Brush_Alloc( void ) {
- brush_t *b = new brush_t;
- b->prev = b->next = NULL;
- b->oprev = b->onext = NULL;
- b->owner = NULL;
- b->mins.Zero();
- b->maxs.Zero();
- b->lightCenter.Zero();
- b->lightRight.Zero();
- b->lightTarget.Zero();
- b->lightUp.Zero();
- b->lightRadius.Zero();
- b->lightOffset.Zero();
- b->lightColor.Zero();
- b->lightStart.Zero();
- b->lightEnd.Zero();
- b->pointLight = false;
- b->startEnd = false;
- b->lightTexture = 0;
- b->trackLightOrigin = false;
- b->entityModel = false;
- b->brush_faces = NULL;
- b->hiddenBrush = false;
- b->pPatch = NULL;
- b->pUndoOwner = NULL;
- b->undoId = 0;
- b->redoId = 0;
- b->ownerId = 0;
- b->numberId = 0;
- b->itemOwner = 0;
- b->bModelFailed = false;
- b->modelHandle = NULL;
- b->forceVisibile = false;
- b->forceWireFrame = false;
- return b;
- }
- /*
- ================
- TextureAxisFromPlane
- ================
- */
- idVec3 baseaxis[18] = {
- idVec3(0, 0, 1),
- idVec3(1, 0, 0),
- idVec3(0, -1, 0),
- // floor
- idVec3(0, 0, -1),
- idVec3(1, 0, 0),
- idVec3(0, -1, 0),
- // ceiling
- idVec3(1, 0, 0),
- idVec3(0, 1, 0),
- idVec3(0, 0, -1),
- // west wall
- idVec3(-1, 0, 0),
- idVec3(0, 1, 0),
- idVec3(0, 0, -1),
- // east wall
- idVec3(0, 1, 0),
- idVec3(1, 0, 0),
- idVec3(0, 0, -1),
- // south wall
- idVec3(0, -1, 0),
- idVec3(1, 0, 0),
- idVec3(0, 0, -1) // north wall
- };
- void TextureAxisFromPlane( const idPlane &pln, idVec3 &xv, idVec3 &yv) {
- int bestaxis;
- float dot, best;
- int i;
- best = 0;
- bestaxis = 0;
- for (i = 0; i < 6; i++) {
- dot = DotProduct(pln, baseaxis[i * 3]);
- if (dot > best) {
- best = dot;
- bestaxis = i;
- }
- }
- VectorCopy(baseaxis[bestaxis * 3 + 1], xv);
- VectorCopy(baseaxis[bestaxis * 3 + 2], yv);
- }
- /*
- ================
- ShadeForNormal
- Light different planes differently to improve recognition
- ================
- */
- float lightaxis[3] = { 0.6f, 0.8f, 1.0f };
- float ShadeForNormal(idVec3 normal) {
- int i;
- float f;
- // axial plane
- for (i = 0; i < 3; i++) {
- if ( idMath::Fabs(normal[i]) > 0.9f ) {
- f = lightaxis[i];
- return f;
- }
- }
- // between two axial planes
- for (i = 0; i < 3; i++) {
- if ( idMath::Fabs(normal[i]) < 0.1f ) {
- f = (lightaxis[(i + 1) % 3] + lightaxis[(i + 2) % 3]) / 2;
- return f;
- }
- }
- // other
- f = (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
- return f;
- }
- /*
- ================
- Face_Alloc
- ================
- */
- face_t *Face_Alloc(void) {
- brushprimit_texdef_t bp;
- face_t *f = (face_t *) Mem_ClearedAlloc(sizeof(*f));
- bp.coords[0][0] = 0.0f;
- bp.coords[1][1] = 0.0f;
- f->brushprimit_texdef = bp;
- f->dirty = true;
- return f;
- }
- /*
- ================
- Face_Free
- ================
- */
- void Face_Free(face_t *f) {
- assert(f != 0);
- if (f->face_winding) {
- delete f->face_winding;
- }
- f->texdef.~texdef_t();
- Mem_Free(f);
- }
- /*
- ================
- Face_Clone
- ================
- */
- face_t *Face_Clone(face_t *f) {
- face_t *n;
- n = Face_Alloc();
- n->texdef = f->texdef;
- n->brushprimit_texdef = f->brushprimit_texdef;
- memcpy(n->planepts, f->planepts, sizeof(n->planepts));
- n->plane = f->plane;
- n->originalPlane = f->originalPlane;
- n->dirty = f->dirty;
- // all other fields are derived, and will be set by Brush_Build
- return n;
- }
- /*
- ================
- Face_FullClone
- Used by Undo.
- Makes an exact copy of the face.
- ================
- */
- face_t *Face_FullClone(face_t *f) {
- face_t *n;
- n = Face_Alloc();
- n->texdef = f->texdef;
- n->brushprimit_texdef = f->brushprimit_texdef;
- memcpy(n->planepts, f->planepts, sizeof(n->planepts));
- n->plane = f->plane;
- n->originalPlane = f->originalPlane;
- n->dirty = f->dirty;
- if (f->face_winding) {
- n->face_winding = f->face_winding->Copy();
- }
- 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, idVec3 delta) {
- idVec3 vX, vY;
- /*
- * #ifdef _DEBUG if (g_PrefsDlg.m_bBrushPrimitMode) common->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 );
- idVec3 vDP, vShift;
- vDP[0] = DotProduct(delta, vX);
- vDP[1] = DotProduct(delta, vY);
- double fAngle = DEG2RAD( f->texdef.rotate );
- 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->GetEditorImage()->uploadWidth);
- Clamp(f->texdef.shift[1], f->d_texture->GetEditorImage()->uploadHeight);
- }
- }
- /*
- ================
- Face_SetColor
- ================
- */
- void Face_SetColor(brush_t *b, face_t *f, float fCurveColor) {
- float shade;
- const idMaterial *q;
- q = f->d_texture;
- // set shading for face
- shade = ShadeForNormal( f->plane.Normal() );
- if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && (b->owner && !b->owner->eclass->fixedsize)) {
- // if (b->curveBrush) shade = fCurveColor;
- f->d_color[0] = f->d_color[1] = f->d_color[2] = shade;
- }
- else if ( f && b && b->owner ) {
- f->d_color[0] = shade * b->owner->eclass->color.x;
- f->d_color[1] = shade * b->owner->eclass->color.y;
- f->d_color[2] = shade * b->owner->eclass->color.z;
- }
- }
- /*
- ================
- Face_TextureVectors
- NOTE: this is never to get called while in brush primitives mode
- ================
- */
- void Face_TextureVectors(face_t *f, float STfromXYZ[2][4]) {
- idVec3 pvecs[2];
- int sv, tv;
- float ang, sinv, cosv;
- float ns, nt;
- int i, j;
- const idMaterial *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) {
- common->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) ? 2 : 1;
- }
- if (!td->scale[1]) {
- td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 2 : 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 = DEG2RAD( td->rotate );
- 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->GetEditorImage()->uploadWidth;
- STfromXYZ[1][j] /= q->GetEditorImage()->uploadHeight;
- }
- }
- /*
- ================
- Face_MakePlane
- ================
- */
- void Face_MakePlane(face_t *f) {
- int j;
- idVec3 t1, t2, t3;
- idPlane oldPlane = f->plane;
- // 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];
- }
- f->plane = t1.Cross( t2 );
- //if ( f->plane.Compare( vec3_origin ) ) {
- // printf("WARNING: brush plane with no normal\n");
- //}
- f->plane.Normalize(false);
- f->plane[3] = - (t3 * f->plane.Normal());
- if ( !f->dirty && !f->plane.Compare( oldPlane, 0.01f ) ) {
- f->dirty = true;
- }
- }
- /*
- ================
- EmitTextureCoordinates
- ================
- */
- void EmitTextureCoordinates(idVec5 &xyzst, const idMaterial *q, face_t *f, bool force) {
- float STfromXYZ[2][4];
- if (g_qeglobals.m_bBrushPrimitMode && !force) {
- EmitBrushPrimitTextureCoordinates(f, f->face_winding);
- }
- else {
- 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) {
- const 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
- }
- if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES)) {
- // draw the angle pointer
- float a = FloatForKey(b->owner, "angle");
- if (a) {
- float s = sin( DEG2RAD( a ) );
- float c = cos( DEG2RAD( a ) );
- idVec3 mid = (b->mins + b->maxs) / 2.0f;
- qglBegin(GL_LINE_STRIP);
- qglVertex3fv(mid.ToFloatPtr());
- mid[0] += c * 8;
- mid[1] += s * 8;
- mid[2] += s * 8;
- qglVertex3fv(mid.ToFloatPtr());
- 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.ToFloatPtr());
- 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.ToFloatPtr());
- 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.ToFloatPtr());
- qglEnd();
- }
- }
- int viewType = g_pParentWnd->ActiveXY()->GetViewType();
- float scale = g_pParentWnd->ActiveXY()->Scale();
- if (g_qeglobals.d_savedinfo.show_names && scale >= 1.0f) {
- name = ValueForKey(b->owner, "name");
- int nameLen = strlen(name);
- if ( nameLen == 0 ) {
- name = ValueForKey(b->owner, "classname");
- nameLen = strlen(name);
- }
- if ( nameLen > 0 ) {
- idVec3 origin = b->owner->origin;
- float halfWidth = ( (nameLen / 2) * (7.0f / scale) );
- float halfHeight = 4.0f / scale;
- switch (viewType) {
- case XY:
- origin.x -= halfWidth;
- origin.y += halfHeight;
- break;
- case XZ:
- origin.x -= halfWidth;
- origin.z += halfHeight;
- break;
- case YZ:
- origin.y -= halfWidth;
- origin.z += halfHeight;
- break;
- }
- qglRasterPos3fv( origin.ToFloatPtr() );
- qglCallLists(nameLen, GL_UNSIGNED_BYTE, name);
- }
- }
- }
- /*
- ================
- Brush_MakeFaceWinding
- returns the visible winding
- ================
- */
- idWinding *Brush_MakeFaceWinding(brush_t *b, face_t *face, bool keepOnPlaneWinding) {
- idWinding *w;
- face_t *clip;
- idPlane plane;
- bool past;
- // get a poly that covers an effectively infinite area
- w = new idWinding( 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, clip->plane) > 0.999f &&
- idMath::Fabs(face->plane[3] - clip->plane[3]) < 0.01f ) { // identical plane, use the later one
- if (past) {
- delete w;
- common->Printf("Unable to create face winding on brush\n");
- return NULL;
- }
- continue;
- }
- // flip the plane, because we want to keep the back side
- VectorSubtract(vec3_origin, clip->plane, plane );
- plane[3] = -clip->plane[3];
- w = w->Clip( plane, ON_EPSILON, keepOnPlaneWinding );
- if ( !w ) {
- return w;
- }
- }
- if ( w->GetNumPoints() < 3) {
- delete w;
- w = NULL;
- }
- if (!w) {
- Sys_Status("Unable to create face winding on brush\n");
- }
- return w;
- }
- /*
- ================
- 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 updateLights) {
- bool bLocalConvert = false;
- #ifdef _DEBUG
- if (!g_qeglobals.m_bBrushPrimitMode && bConvert) {
- common->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, EntityHasModel(b->owner) || b->pPatch, updateLights);
- /* 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 (bMarkMap) {
- Sys_MarkMapModified();
- g_pParentWnd->GetCamera()->MarkWorldDirty();
- }
- 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;
- idVec3 temp;
- b = Brush_Clone(in);
- nf = Face_Clone(f);
- nf->texdef = b->brush_faces->texdef;
- nf->brushprimit_texdef = b->brush_faces->brushprimit_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->brushprimit_texdef = b->brush_faces->brushprimit_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;
- idWinding *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;
- }
- f->face_winding->Split( face->plane, 0.1f, &front, &back );
- if ( !front ) {
- delete back;
- }
- else if ( !back ) {
- delete front;
- }
- else {
- splits++;
- if ( front->IsTiny() ) {
- tinywindings++;
- }
- if ( back->IsTiny() ) {
- tinywindings++;
- }
- delete front;
- delete back;
- }
- }
- 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
- returns true if the brush is 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 ( face1->face_winding->PlanesConcave( *face2->face_winding,
- face1->plane.Normal(), face2->plane.Normal(), -face1->plane[3], -face2->plane[3] ) ) {
- return false;
- }
- }
- }
- return true;
- }
- /*
- ================
- 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
- #define TINY_EPSILON 0.0325f
- int Brush_MoveVertex(brush_t *b, const idVec3 &vertex, const idVec3 &delta, idVec3 &end, bool bSnap) {
- face_t *f, *face, *newface, *lastface, *nextface;
- face_t *movefaces[MAX_MOVE_FACES];
- int movefacepoints[MAX_MOVE_FACES];
- idWinding *w, tmpw(3);
- idVec3 start, mid;
- idPlane plane;
- int i, j, k, nummovefaces, result, done;
- float dot, front, back, frac, smallestfrac;
- result = true;
- tmpw.SetNumPoints( 3 );
- VectorCopy(vertex, start);
- VectorAdd(vertex, delta, end);
- // snap or not?
- //
- if (bSnap) {
- for (i = 0; i < 3; i++) {
- end[i] = floor( end[i] / 0.125f + 0.5f ) * 0.125f;
- }
- }
- VectorCopy(end, mid);
- // if the start and end are the same
- if ( start.Compare( end, TINY_EPSILON ) ) {
- 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->GetNumPoints(); i++) {
- if ( end.Compare( (*w)[i].ToVec3(), TINY_EPSILON ) ) {
- 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->GetNumPoints(); i++) {
- if ( start.Compare( (*w)[i].ToVec3(), TINY_EPSILON ) ) {
- if (face->face_winding->GetNumPoints() <= 3) {
- movefacepoints[nummovefaces] = i;
- movefaces[nummovefaces++] = face;
- break;
- }
- dot = DotProduct(end, face->plane) + face->plane[3];
- // if the end point is in front of the face plane
- //if ( dot > 0.1f ) {
- if ( dot > TINY_EPSILON ) {
- // fanout triangle subdivision
- for (k = i; k < i + w->GetNumPoints() - 3; k++) {
- VectorCopy((*w)[i], tmpw[0]);
- VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[1]);
- VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[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) {
- delete newface->face_winding;
- }
- newface->face_winding = tmpw.Copy();
- // 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)[(i - 2 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[0]);
- VectorCopy((*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[1]);
- VectorCopy((*w)[i], tmpw[2]);
- delete face->face_winding;
- face->face_winding = tmpw.Copy();
- // add the original face to the move faces
- movefacepoints[nummovefaces] = 2;
- movefaces[nummovefaces++] = face;
- }
- else {
- // chop a triangle off the face
- VectorCopy((*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[0]);
- VectorCopy((*w)[i], tmpw[1]);
- VectorCopy((*w)[(i + 1) % w->GetNumPoints()], tmpw[2]);
- // remove the point from the face winding
- w->RemovePoint( i );
- // get texture crap right
- Face_SetColor(b, face, 1.0);
- for (j = 0; j < w->GetNumPoints(); j++) {
- EmitTextureCoordinates( (*w)[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) {
- delete newface->face_winding;
- }
- newface->face_winding = tmpw.Copy();
- // 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));
- }
- else {
- k = movefacepoints[j];
- w = movefaces[j]->face_winding;
- VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[0]);
- VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[1]);
- k = movefacepoints[i];
- w = movefaces[i]->face_winding;
- VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[2]);
- if ( !plane.FromPoints( tmpw[0].ToVec3(), tmpw[1].ToVec3(), tmpw[2].ToVec3(), false ) ) {
- VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[2]);
- if ( !plane.FromPoints( tmpw[0].ToVec3(), tmpw[1].ToVec3(), tmpw[2].ToVec3() ), false ) {
- // this should never happen otherwise the face merge did
- // a crappy job a previous pass
- continue;
- }
- }
- plane[0] = -plane[0];
- plane[1] = -plane[1];
- plane[2] = -plane[2];
- plane[3] = -plane[3];
- }
- // now we've got the plane to check against
- front = DotProduct(start, plane) + plane[3];
- back = DotProduct(end, plane) + plane[3];
- // if the whole move is at one side of the plane
- if (front < TINY_EPSILON && back < TINY_EPSILON) {
- continue;
- }
- if (front > -TINY_EPSILON && back > -TINY_EPSILON) {
- continue;
- }
- // if there's no movement orthogonal to this plane at all
- if ( idMath::Fabs(front - back) < 0.001f ) {
- 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)[movefacepoints[i]] );
- // create new face plane
- for (j = 0; j < 3; j++) {
- VectorCopy( (*movefaces[i]->face_winding)[j], movefaces[i]->planepts[j] );
- }
- Face_MakePlane( movefaces[i] );
- if ( movefaces[i]->plane.Normal().Length() < TINY_EPSILON ) {
- 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)[movefacepoints[i]] );
- // create new face plane
- for (j = 0; j < 3; j++) {
- VectorCopy( (*movefaces[i]->face_winding)[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.0f );
- for (j = 0; j < movefaces[i]->face_winding->GetNumPoints(); j++) {
- EmitTextureCoordinates( (*movefaces[i]->face_winding)[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 ( !face->plane.Compare( face->original->plane, 0.0001f ) ) {
- lastface = face;
- continue;
- }
- w = face->face_winding->TryMerge( *face->original->face_winding, face->plane.Normal(), true );
- if (!w) {
- lastface = face;
- continue;
- }
- delete face->original->face_winding;
- face->original->face_winding = w;
- // get texture crap right
- Face_SetColor( b, face->original, 1.0f );
- for (j = 0; j < face->original->face_winding->GetNumPoints(); j++) {
- EmitTextureCoordinates( (*face->original->face_winding)[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
- Adds a vertex to the brush windings between the given two points.
- ================
- */
- int Brush_InsertVertexBetween(brush_t *b, idVec3 p1, idVec3 p2) {
- face_t *face;
- idWinding *w, *neww;
- idVec3 point;
- int i, insert;
- if ( p1.Compare( p2, TINY_EPSILON ) ) {
- return false;
- }
- VectorAdd( p1, p2, point );
- VectorScale( point, 0.5f, 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->GetNumPoints(); i++) {
- if (! p1.Compare((*w)[i].ToVec3(), TINY_EPSILON)) {
- continue;
- }
- if ( p2.Compare( (*w)[(i + 1) % w->GetNumPoints()].ToVec3(), TINY_EPSILON ) ) {
- neww = new idWinding( *w );
- neww->InsertPoint( point, (i + 1) % w->GetNumPoints() );
- break;
- }
- else if ( p2.Compare( (*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()].ToVec3(), TINY_EPSILON ) ) {
- neww = new idWinding( *w );
- neww->InsertPoint( point, i );
- break;
- }
- }
- if (neww) {
- delete face->face_winding;
- face->face_winding = neww;
- insert = true;
- }
- }
- return insert;
- }
- /*
- ================
- Brush_ResetFaceOriginals
- reset points to original faces to NULL
- ================
- */
- 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
- FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3"
- run before each face parsing. It works, but it's a performance hit
- ================
- */
- brush_t *Brush_Parse(idVec3 origin) {
- brush_t *b;
- face_t *f;
- int i, j;
- idVec3 useOrigin = origin;
- g_qeglobals.d_parsed_brushes++;
- b = Brush_Alloc();
- do {
- if (!GetToken(true)) {
- break;
- }
- if (!strcmp(token, "}")) {
- break;
- }
- // handle "Brush" primitive
- if ( idStr::Icmp(token, "brushDef") == 0 || idStr::Icmp(token, "brushDef2") == 0 || idStr::Icmp(token, "brushDef3") == 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) {
- common->Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
- }
- }
- else {
- // ++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
- common->Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
- }
- bool newFormat = false;
- if ( idStr::Icmp(token, "brushDef2") == 0 ) {
- newFormat = true;
- // useOrigin.Zero();
- }
- else if ( idStr::Icmp(token, "brushDef3") == 0 ) {
- newFormat = true;
- }
- BrushPrimit_Parse(b, newFormat, useOrigin);
- if (newFormat) {
- //Brush_BuildWindings(b, true, true, false, false);
- }
-
- if (b == NULL) {
- Warning("parsing brush primitive");
- return NULL;
- }
- else {
- continue;
- }
- }
- if ( idStr::Icmp(token, "patchDef2") == 0 || idStr::Icmp(token, "patchDef3") == 0 ) {
- Brush_Free(b);
- // double string compare but will go away soon
- b = Patch_Parse( idStr::Icmp(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) {
- common->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;
- }
- }
- }
- // 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);
- //
- // FIXME: idMaterial 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);
- GetToken(false);
- 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->pPatch) {
- Patch_SetEpair(b->pPatch, pKey, pValue);
- }
- else {
- b->epairs.Set(pKey, pValue);
- }
- }
- else {
- Sys_Status("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->pPatch) {
- return Patch_GetKeyValue(b->pPatch, pKey);
- }
- else {
- return b->epairs.GetString(pKey);
- }
- }
- else {
- Sys_Status("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, const idVec3 &origin, bool newFormat) {
- face_t *fa;
- char *pname;
- int i;
- if (b->pPatch) {
- Patch_Write(b->pPatch, f);
- return;
- }
- if (g_qeglobals.m_bBrushPrimitMode) {
- // save brush primitive format
- if (newFormat) {
- WriteFileString(f, "{\nbrushDef3\n{\n");
- }
- else {
- WriteFileString(f, "{\nbrushDef\n{\n");
- }
- // brush epairs
- int count = b->epairs.GetNumKeyVals();
- for (int j = 0; j < count; j++) {
- WriteFileString(f, "\"%s\" \"%s\"\n", b->epairs.GetKeyVal(j)->GetKey().c_str(), b->epairs.GetKeyVal(j)->GetValue().c_str());
- }
- for (fa = b->brush_faces; fa; fa = fa->next) {
- // save planepts
- if (newFormat) {
- idPlane plane;
- if (fa->dirty) {
- fa->planepts[0] -= origin;
- fa->planepts[1] -= origin;
- fa->planepts[2] -= origin;
- plane.FromPoints( fa->planepts[0], fa->planepts[1], fa->planepts[2], false );
- fa->planepts[0] += origin;
- fa->planepts[1] += origin;
- fa->planepts[2] += origin;
- } else {
- plane = fa->originalPlane;
- }
- WriteFileString(f, " ( ");
- for (i = 0; i < 4; i++) {
- if (plane[i] == (int)plane[i]) {
- WriteFileString(f, "%i ", (int)plane[i]);
- }
- else {
- WriteFileString(f, "%f ", plane[i]);
- }
- }
- WriteFileString(f, ") ");
- }
- else {
- for (i = 0; i < 3; i++) {
- WriteFileString(f, "( ");
- for (int j = 0; j < 3; j++) {
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
- WriteFileString(f, "%i ", static_cast<int>(fa->planepts[i][j]));
- }
- else {
- WriteFileString(f, "%f ", fa->planepts[i][j]);
- }
- }
- WriteFileString(f, ") ");
- }
- }
- // save texture coordinates
- WriteFileString(f, "( ( ");
- for (i = 0; i < 3; i++) {
- if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i])) {
- WriteFileString(f, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
- }
- else {
- WriteFileString(f, "%f ", fa->brushprimit_texdef.coords[0][i]);
- }
- }
- WriteFileString(f, ") ( ");
- for (i = 0; i < 3; i++) {
- if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i])) {
- WriteFileString(f, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
- }
- else {
- WriteFileString(f, "%f ", fa->brushprimit_texdef.coords[1][i]);
- }
- }
- WriteFileString(f, ") ) ");
- char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "notexture";
- WriteFileString(f, "\"%s\" ", pName);
- WriteFileString(f, "%i %i %i\n", 0, 0, 0);
- }
- WriteFileString(f, "}\n}\n");
- }
- else {
- WriteFileString(f, "{\n");
- for (fa = b->brush_faces; fa; fa = fa->next) {
- for (i = 0; i < 3; i++) {
- WriteFileString(f, "( ");
- for (int j = 0; j < 3; j++) {
- if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
- WriteFileString(f, "%i ", static_cast<int>(fa->planepts[i][j]));
- }
- else {
- WriteFileString(f, "%f ", fa->planepts[i][j]);
- }
- }
- WriteFileString(f, ") ");
- }
- pname = fa->texdef.name;
- if (pname[0] == 0) {
- pname = "unnamed";
- }
- WriteFileString
- (
- 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]) {
- WriteFileString(f, "%i ", (int)fa->texdef.scale[0]);
- }
- else {
- WriteFileString(f, "%f ", (float)fa->texdef.scale[0]);
- }
- if (fa->texdef.scale[1] == (int)fa->texdef.scale[1]) {
- WriteFileString(f, "%i", (int)fa->texdef.scale[1]);
- }
- else {
- WriteFileString(f, "%f", (float)fa->texdef.scale[1]);
- }
- WriteFileString(f, " %i %i %i",0, 0, 0);
- WriteFileString(f, "\n");
- }
- WriteFileString(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
- save all brushes as Brush primitive format to a CMemFile*
- ================
- */
- void Brush_Write(brush_t *b, CMemFile *pMemFile, const idVec3 &origin, bool newFormat) {
- face_t *fa;
- char *pname;
- int i;
- if (b->pPatch) {
- Patch_Write(b->pPatch, pMemFile);
- return;
- }
- if (g_qeglobals.m_bBrushPrimitMode) {
- // brush primitive format
- if (newFormat) {
- MemFile_fprintf(pMemFile, "{\nBrushDef2\n{\n");
- }
- else {
- MemFile_fprintf(pMemFile, "{\nBrushDef\n{\n");
- }
- // brush epairs
- // brush epairs
- int count = b->epairs.GetNumKeyVals();
- for (int j = 0; j < count; j++) {
- MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", b->epairs.GetKeyVal(j)->GetKey().c_str(), b->epairs.GetKeyVal(j)->GetValue().c_str());
- }
- for (fa = b->brush_faces; fa; fa = fa->next) {
- if (newFormat) {
- // save planepts
- idPlane plane;
- if (fa->dirty) {
- fa->planepts[0] -= origin;
- fa->planepts[1] -= origin;
- fa->planepts[2] -= origin;
- plane.FromPoints( fa->planepts[0], fa->planepts[1], fa->planepts[2], false );
- fa->planepts[0] += origin;
- fa->planepts[1] += origin;
- fa->planepts[2] += origin;
- } else {
- plane = fa->originalPlane;
- }
- MemFile_fprintf(pMemFile, " ( ");
- for (i = 0; i < 4; i++) {
- if (plane[i] == (int)plane[i]) {
- MemFile_fprintf(pMemFile, "%i ", (int)plane[i]);
- }
- else {
- MemFile_fprintf(pMemFile, "%f ", plane[i]);
- }
- }
- MemFile_fprintf(pMemFile, ") ");
- }
- else {
- 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", 0, 0, 0);
- }
- 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, ") ");
- }
- 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", 0, 0, 0);
- 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(idVec3 mins, idVec3 maxs, texdef_t *texdef) {
- int i, j;
- idVec3 pts[4][2];
- face_t *f;
- brush_t *b;
- //
- // brush primitive mode : convert texdef to brushprimit_texdef ? most of the time
- // texdef is empty
- //
- 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->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->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->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_Scale
- =============
- */
- void Brush_Scale(brush_t* b) {
- for ( face_t *f = b->brush_faces; f; f = f->next ) {
- for ( int i = 0; i < 3; i++ ) {
- VectorScale( f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i] );
- }
- }
- }
- /*
- ================
- Brush_CreatePyramid
- Create non-textured pyramid for light entities The brush is NOT linked to any list
- ================
- */
- brush_t *Brush_CreatePyramid(idVec3 mins, idVec3 maxs, texdef_t *texdef) {
- // ++timo handle new brush primitive ? return here ??
- return Brush_Create(mins, maxs, texdef);
- int i;
- for (i = 0; i < 3; i++) {
- if (maxs[i] < mins[i]) {
- Error("Brush_InitSolid: backwards");
- }
- }
- brush_t *b = Brush_Alloc();
- idVec3 corners[4];
- float fMid = idMath::Rint(mins[2] + (idMath::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;
- idVec3 top, bottom;
- top[0] = idMath::Rint(mins[0] + ((maxs[0] - mins[0]) / 2));
- top[1] = idMath::Rint(mins[1] + ((maxs[1] - mins[1]) / 2));
- top[2] = idMath::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->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->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;
- idVec3 mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- idVec3 mid;
- float width;
- float sv, cv;
- if (sides < 3) {
- Sys_Status("Bad sides number", 0);
- return;
- }
- if (sides >= MAX_POINTS_ON_WINDING - 4) {
- Sys_Status("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.5f;
- if (i == axis) {
- continue;
- }
- if ((maxs[i] - mins[i]) * 0.5f > width) {
- width = (maxs[i] - mins[i]) * 0.5f;
- }
- }
- 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.5f);
- f->planepts[0][(axis + 2) % 3] = floor(mid[(axis + 2) % 3] + width * sv + 0.5f);
- 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.5f);
- f->planepts[2][(axis + 2) % 3] = floor(f->planepts[0][(axis + 2) % 3] + width * cv + 0.5f);
- 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
- set bRemoveNode to false to avoid trying to delete the item in group view tree control
- ================
- */
- void Brush_Free(brush_t *b, bool bRemoveNode) {
- face_t *f, *next;
- // free the patch if it's there
- if ( b->pPatch ) {
- Patch_Delete(b->pPatch);
- }
- // free faces
- for ( f = b->brush_faces; f; f = next ) {
- next = f->next;
- Face_Free(f);
- }
- b->epairs.Clear();
- // unlink from active/selected list
- if ( b->next ) {
- Brush_RemoveFromList(b);
- }
- // unlink from entity list
- if ( b->onext ) {
- Entity_UnlinkBrush(b);
- }
- delete b;
- }
- /*
- ================
- Face_MemorySize
- returns the size in memory of the face
- ================
- */
- int Face_MemorySize(face_t *f) {
- int size = 0;
- if ( f->face_winding ) {
- size += sizeof( idWinding ) + f->face_winding->GetNumPoints() * sizeof( (f->face_winding)[0] );
- }
- size += sizeof( face_t );
- return size;
- }
- /*
- ================
- Brush_MemorySize
- returns the size in memory of the brush
- ================
- */
- int Brush_MemorySize( brush_t *b ) {
- face_t *f;
- int size = 0;
- if ( b->pPatch ) {
- size += Patch_MemorySize( b->pPatch );
- }
- for ( f = b->brush_faces; f; f = f->next ) {
- size += Face_MemorySize(f);
- }
- size += sizeof( brush_t ) + b->epairs.Size();
- return size;
- }
- /*
- ================
- Brush_Clone
- does not add the brush to any lists
- ================
- */
- brush_t *Brush_Clone(brush_t *b) {
- brush_t *n = NULL;
- face_t *f, *nf;
- if (b->pPatch) {
- patchMesh_t *p = Patch_Duplicate(b->pPatch);
- Brush_RemoveFromList(p->pSymbiot);
- Entity_UnlinkBrush(p->pSymbiot);
- n = p->pSymbiot;
- }
- else {
- n = Brush_Alloc();
- n->numberId = g_nBrushId++;
- n->owner = b->owner;
- n->lightColor = b->lightColor;
- n->lightEnd = b->lightEnd;
- n->lightOffset = b->lightOffset;
- n->lightRadius = b->lightRadius;
- n->lightRight = b->lightRight;
- n->lightStart = b->lightStart;
- n->lightTarget = b->lightTarget;
- n->lightCenter = b->lightCenter;
- n->lightTexture = b->lightTexture;
- n->lightUp = b->lightUp;
- n->modelHandle = b->modelHandle;
- n->pointLight = b->pointLight;
- 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_FullClone
- Used by Undo.
- Makes an exact copy of the brush.
- 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->pPatch) {
- 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 {
- n = Brush_Alloc();
- n->numberId = g_nBrushId++;
- n->owner = b->owner;
- n->lightColor = b->lightColor;
- n->lightEnd = b->lightEnd;
- n->lightOffset = b->lightOffset;
- n->lightRadius = b->lightRadius;
- n->lightRight = b->lightRight;
- n->lightStart = b->lightStart;
- n->lightTarget = b->lightTarget;
- n->lightCenter = b->lightCenter;
- n->lightTexture = b->lightTexture;
- n->lightUp = b->lightUp;
- n->modelHandle = b->modelHandle;
- n->pointLight = b->pointLight;
- 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.0f );
- if (nf->face_winding) {
- if (g_qeglobals.m_bBrushPrimitMode) {
- EmitBrushPrimitTextureCoordinates(nf, nf->face_winding);
- }
- else {
- for (j = 0; j < nf->face_winding->GetNumPoints(); j++) {
- EmitTextureCoordinates( (*nf->face_winding)[j], nf->d_texture, nf );
- }
- }
- }
- }
- }
- return n;
- }
- extern bool GetMatrixForKey(entity_t *ent, const char *key, idMat3 &mat);
- extern bool Patch_Intersect(patchMesh_t *pm, idVec3 origin, idVec3 direction , float &scale);
- extern bool RayIntersectsTri
- (
- const idVec3 &origin,
- const idVec3 &direction,
- const idVec3 &vert0,
- const idVec3 &vert1,
- const idVec3 &vert2,
- float &scale
- );
- /*
- ================
- RotateVector
- ================
- */
- void RotateVector(idVec3 &v, idVec3 origin, float a, float c, float s) {
- float x = v[0];
- float y = v[1];
- if (a) {
- float x2 = (((x - origin[0]) * c) - ((y - origin[1]) * s)) + origin[0];
- float y2 = (((x - origin[0]) * s) + ((y - origin[1]) * c)) + origin[1];
- x = x2;
- y = y2;
- }
- v[0] = x;
- v[1] = y;
- }
- /*
- ================
- Brush_ModelIntersect
- ================
- */
- bool Brush_ModelIntersect(brush_t *b, idVec3 origin, idVec3 dir,float &scale) {
- idRenderModel *model = b->modelHandle;
- idRenderModel *md5;
-
- if ( !model )
- model = b->owner->eclass->entityModel;
- scale = 0;
- if (model) {
- if ( model->IsDynamicModel() != DM_STATIC ) {
- if ( dynamic_cast<idRenderModelMD5 *>( model ) ) {
- // take care of animated models
- md5 = b->owner->eclass->entityModel;
- const char *classname = ValueForKey( b->owner, "classname" );
- if (stricmp(classname, "func_static") == 0) {
- classname = ValueForKey(b->owner, "animclass");
- }
- const char *anim = ValueForKey( b->owner, "anim" );
- int frame = IntForKey( b->owner, "frame" ) + 1;
- if ( frame < 1 ) {
- frame = 1;
- }
- if ( !anim || !anim[ 0 ] ) {
- anim = "idle";
- }
- model = gameEdit->ANIM_CreateMeshForAnim( md5, classname, anim, frame, false );
- if ( !model ) {
- model = renderModelManager->DefaultModel();
- }
- }
- }
- bool matrix = false;
- idMat3 mat;
- float a, s, c;
- if (GetMatrixForKey(b->owner, "rotation", mat)) {
- matrix = true;
- } else {
- a = FloatForKey(b->owner, "angle");
- if (a) {
- s = sin( DEG2RAD( a ) );
- c = cos( DEG2RAD( a ) );
- }
- else {
- s = c = 0;
- }
- }
- for (int i = 0; i < model->NumSurfaces() ; i++) {
- const modelSurface_t *surf = model->Surface( i );
- srfTriangles_t *tri = surf->geometry;
- for (int j = 0; j < tri->numIndexes; j += 3) {
- idVec3 v1, v2, v3;
- v1 = tri->verts[tri->indexes[j]].xyz;
- v2 = tri->verts[tri->indexes[j + 1]].xyz;
- v3 = tri->verts[tri->indexes[j + 2]].xyz;
- if (matrix) {
- v1 *= b->owner->rotation;
- v1 += b->owner->origin;
- v2 *= b->owner->rotation;
- v2 += b->owner->origin;
- v3 *= b->owner->rotation;
- v3 += b->owner->origin;
- } else {
- v1 += b->owner->origin;
- v2 += b->owner->origin;
- v3 += b->owner->origin;
- RotateVector(v1, b->owner->origin, a, c, s);
- RotateVector(v2, b->owner->origin, a, c, s);
- RotateVector(v3, b->owner->origin, a, c, s);
- }
- if (RayIntersectsTri(origin, dir, v1, v2, v3,scale)) {
- return true;
- }
- }
- }
- }
- return false;
- }
- face_t *Brush_Ray(idVec3 origin, idVec3 dir, brush_t *b, float *dist, bool testPrimitive) {
- face_t *f, *firstface = NULL;
- idVec3 p1, p2;
- float frac, d1, d2;
- int i;
- float scale = HUGE_DISTANCE * 2;
- VectorCopy(origin, p1);
- for (i = 0; i < 3; i++) {
- p2[i] = p1[i] + dir[i] * HUGE_DISTANCE * 2;
- }
- for (f = b->brush_faces; f; f = f->next) {
- d1 = DotProduct(p1, f->plane) + f->plane[3];
- d2 = DotProduct(p2, f->plane) + f->plane[3];
- 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);
- if (testPrimitive && !g_PrefsDlg.m_selectByBoundingBrush) {
- if (b->pPatch) {
- if (!Patch_Intersect(b->pPatch, origin, dir, scale)) {
- *dist = 0;
- return NULL;
- }
- }
- else if ( b->modelHandle != NULL && dynamic_cast<idRenderModelPrt*>( b->modelHandle ) == NULL && dynamic_cast< idRenderModelLiquid*> ( b->modelHandle ) == NULL ) {
- if (!Brush_ModelIntersect(b, origin, dir, scale)) {
- *dist = 0;
- return NULL;
- }
- }
- }
- *dist = d1;
- return firstface;
- }
- /*
- ================
- Brush_Point
- ================
- */
- face_t *Brush_Point(idVec3 origin, brush_t *b) {
- face_t *f;
- float d1;
- for (f = b->brush_faces; f; f = f->next) {
- d1 = DotProduct(origin, f->plane) + f->plane[3];
- if (d1 > 0) {
- return NULL; // point is on front side of face
- }
- }
- return b->brush_faces;
- }
- /*
- ================
- Brush_AddToList
- ================
- */
- 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->pPatch && list == &selected_brushes) {
- Patch_Select(b->pPatch);
- }
- }
- b->list = list;
- b->next = list->next;
- list->next->prev = b;
- list->next = b;
- b->prev = list;
- }
- /*
- ================
- Brush_RemoveFromList
- ================
- */
- void Brush_RemoveFromList(brush_t *b) {
- if (!b->next || !b->prev) {
- Error("Brush_RemoveFromList: not linked");
- }
- if (b->pPatch) {
- Patch_Deselect(b->pPatch);
- // Patch_Deselect(b->nPatchID);
- }
- b->list = NULL;
- b->next->prev = b->prev;
- b->prev->next = b->next;
- b->next = b->prev = NULL;
- }
- /*
- ================
- SetFaceTexdef
- Doesn't set the curve flags.
- NOTE: 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 ) {
- 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
- idVec3 p1, p2, p3; // absolute coordinates
- // compute absolute coordinates
- ComputeAbsolute(f, p1, p2, p3);
- // compute the scale
- idVec3 vx, vy;
- VectorSubtract(p2, p1, vx);
- vx.Normalize();
- VectorSubtract(p3, p1, vy);
- vy.Normalize();
- // 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;
- }
- }
- /*
- ================
- Brush_SetTexture
- ================
- */
- void Brush_SetTexture(brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale) {
- if (b->pPatch) {
- Patch_SetTexture(b->pPatch, texdef);
- }
- else {
- for (face_t * f = b->brush_faces; f; f = f->next) {
- SetFaceTexdef(b, f, texdef, brushprimit_texdef, bFitScale);
- }
- Brush_Build(b);
- }
- }
- /*
- ====================
- Brush_SetTextureName
- ====================
- */
- void Brush_SetTextureName(brush_t *b, const char *name) {
- if (b->pPatch) {
- Patch_SetTextureName(b->pPatch, name);
- }
- else {
- for (face_t * f = b->brush_faces; f; f = f->next) {
- f->texdef.SetName(name);
- }
- Brush_Build(b);
- }
- }
- /*
- ================
- ClipLineToFace
- ================
- */
- bool ClipLineToFace(idVec3 &p1, idVec3 &p2, face_t *f) {
- float d1, d2, fr;
- int i;
- float *v;
- d1 = DotProduct(p1, f->plane) + f->plane[3];
- d2 = DotProduct(p2, f->plane) + f->plane[3];
- 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.ToFloatPtr();
- }
- else {
- v = p2.ToFloatPtr();
- }
- for (i = 0; i < 3; i++) {
- v[i] = p1[i] + fr * (p2[i] - p1[i]);
- }
- return true;
- }
- /*
- ================
- AddPlanept
- ================
- */
- int AddPlanept(idVec3 *f) {
- int i;
- for (i = 0; i < g_qeglobals.d_num_move_points; i++) {
- if (g_qeglobals.d_move_points[i] == f) {
- return 0;
- }
- }
- if (g_qeglobals.d_num_move_points < MAX_MOVE_POINTS) {
- g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
- } else {
- Sys_Status("Trying to move too many points\n");
- return 0;
- }
- return 1;
- }
- /*
- ================
- AddMovePlane
- ================
- */
- void AddMovePlane( idPlane *p ) {
- for (int i = 0; i < g_qeglobals.d_num_move_planes; i++) {
- if (g_qeglobals.d_move_planes[i] == p) {
- return;
- }
- }
- if (g_qeglobals.d_num_move_planes < MAX_MOVE_PLANES) {
- g_qeglobals.d_move_planes[g_qeglobals.d_num_move_planes++] = p;
- } else {
- Sys_Status("Trying to move too many planes\n");
- }
- }
- /*
- ================
- 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, bool shear) {
- int i;
- face_t *f2;
- idWinding *w;
- float d;
- brush_t *b2;
- int c;
- if (b->owner->eclass->fixedsize || EntityHasModel(b->owner)) {
- return;
- }
- c = 0;
- for (i = 0; i < 3; i++) {
- c += AddPlanept(&f->planepts[i]);
- }
- //AddMovePlane(&f->plane);
- 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 (idMath::Fabs(DotProduct(f2->planepts[i], f->plane) + f->plane[3]) > 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, false);
- if (!w) {
- continue;
- }
- // any points on f will become new control points
- for (i = 0; i < w->GetNumPoints(); i++) {
- d = DotProduct( (*w)[i], f->plane ) + f->plane[3];
- if (d > -ON_EPSILON && d < ON_EPSILON) {
- break;
- }
- }
- // if none of the points were on the plane, leave it alone
- if (i != w->GetNumPoints()) {
- if (i == 0) { // see if the first clockwise point was the
- ///
- /// last point on the winding
- d = DotProduct( (*w)[w->GetNumPoints() - 1], f->plane ) + f->plane[3];
- if (d > -ON_EPSILON && d < ON_EPSILON) {
- i = w->GetNumPoints() - 1;
- }
- }
- AddPlanept(&f2->planepts[0]);
- //AddMovePlane(&f2->plane);
- VectorCopy((*w)[i], f2->planepts[0]);
- if (++i == w->GetNumPoints()) {
- i = 0;
- }
- // see if the next point is also on the plane
- d = DotProduct( (*w)[i], f->plane ) + f->plane[3];
- if (d > -ON_EPSILON && d < ON_EPSILON) {
- AddPlanept(&f2->planepts[1]);
- }
- VectorCopy( (*w)[i], f2->planepts[1] );
- if (++i == w->GetNumPoints()) {
- i = 0;
- }
- // the third point is never on the plane
- VectorCopy( (*w)[i], f2->planepts[2] );
- }
- delete 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, idVec3 origin, idVec3 dir, bool shear) {
- face_t *f, *f2;
- idVec3 p1, p2;
- if (g_moveOnly) {
- return;
- }
- // if (b->pPatch) return; Patch_SideSelect(b->nPatchID, origin, dir);
- for (f = b->brush_faces; f; f = f->next) {
- VectorCopy(origin, p1);
- VectorMA(origin, MAX_WORLD_SIZE, dir, p2);
- for (f2 = b->brush_faces; f2; f2 = f2->next) {
- if (f2 == f) {
- continue;
- }
- ClipLineToFace(p1, p2, f2);
- }
- if (f2) {
- continue;
- }
- if ( p1.Compare( origin ) ) {
- continue;
- }
- if (ClipLineToFace(p1, p2, f)) {
- continue;
- }
- Brush_SelectFaceForDragging(b, f, shear);
- }
- }
- extern void UpdateSelectablePoint(brush_t *b, idVec3 v, int type);
- extern void AddSelectablePoint(brush_t *b, idVec3 v, int type, bool priority);
- extern void ClearSelectablePoints(brush_t *b);
- /*
- ================
- Brush_TransformedPoint
- ================
- */
- extern void VectorSnapGrid(idVec3 &v);
- idMat3 Brush_RotationMatrix(brush_t *b) {
- idMat3 mat;
- mat.Identity();
- if (!GetMatrixForKey(b->owner, "light_rotation", mat)) {
- GetMatrixForKey(b->owner, "rotation", mat);
- }
- return mat;
- }
- idVec3 Brush_TransformedPoint(brush_t *b, const idVec3 &in) {
- idVec3 out = in;
- out -= b->owner->origin;
- out *= Brush_RotationMatrix(b);
- out += b->owner->origin;
- return out;
- }
- /*
- ================
- Brush_UpdateLightPoints
- ================
- */
- void Brush_UpdateLightPoints(brush_t *b, const idVec3 &offset) {
- if (!(b->owner->eclass->nShowFlags & ECLASS_LIGHT)) {
- if (b->modelHandle) {
- g_bScreenUpdates = false;
- g_pParentWnd->GetCamera()->BuildEntityRenderState(b->owner, true);
- g_bScreenUpdates = true;
- }
- return;
- }
- if (b->entityModel) {
- return;
- }
- idVec3 vCenter;
- idVec3 *origin = (b->trackLightOrigin) ? &b->owner->lightOrigin : &b->owner->origin;
- if (!GetVectorForKey(b->owner, "_color", b->lightColor)) {
- b->lightColor[0] = b->lightColor[1] = b->lightColor[2] = 1;
- }
- const char *str = ValueForKey(b->owner, "texture");
- b->lightTexture = -1;
- if (str && strlen(str) > 0) {
- const idMaterial *q = Texture_LoadLight(str);
- if (q) {
- b->lightTexture = q->GetEditorImage()->texnum;
- }
- }
- str = ValueForKey(b->owner, "light_right");
- if (str && *str) {
- idVec3 vRight, vUp, vTarget, vTemp;
- if (GetVectorForKey(b->owner, "light_start", b->lightStart)) {
- b->startEnd = true;
- if (!GetVectorForKey(b->owner, "light_end", b->lightEnd)) {
- GetVectorForKey(b->owner, "light_target", b->lightEnd);
- }
- VectorAdd(b->lightEnd, *origin, b->lightEnd);
- VectorAdd(b->lightStart, *origin, b->lightStart);
- VectorAdd(b->lightStart, offset, b->lightStart);
- }
- else {
- b->startEnd = false;
- }
- GetVectorForKey(b->owner, "light_right", vRight);
- GetVectorForKey(b->owner, "light_up", vUp);
- GetVectorForKey(b->owner, "light_target", vTarget);
- if (offset.x || offset.y || offset.z) {
- CString str;
- VectorAdd(vTarget, offset, vTarget);
- SetKeyVec3(b->owner, "light_target", vTarget);
- }
- VectorAdd(vTarget, *origin, b->lightTarget);
- VectorAdd(b->lightTarget, vRight, b->lightRight);
- VectorAdd(b->lightTarget, vUp, b->lightUp);
- UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightUp), LIGHT_UP);
- UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightRight), LIGHT_RIGHT);
- UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightTarget), LIGHT_TARGET);
- UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightStart), LIGHT_START);
- UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightEnd), LIGHT_END);
- b->pointLight = false;
- }
- else {
- b->pointLight = true;
- if (GetVectorForKey(b->owner, "light_center", vCenter)) {
- if (offset.x || offset.y || offset.z) {
- CString str;
- VectorAdd(vCenter, offset, vCenter);
- SetKeyVec3(b->owner, "light_center", vCenter);
- }
- VectorAdd(vCenter, *origin, b->lightCenter);
- UpdateSelectablePoint(b, b->lightCenter, LIGHT_CENTER);
- }
- if (!GetVectorForKey(b->owner, "light_radius", b->lightRadius)) {
- float f = FloatForKey(b->owner, "light");
- if (f == 0) {
- f = 300;
- }
- b->lightRadius[0] = b->lightRadius[1] = b->lightRadius[2] = f;
- }
- else {
- }
- }
- g_bScreenUpdates = false;
- g_pParentWnd->GetCamera()->BuildEntityRenderState(b->owner, true);
- g_bScreenUpdates = true;
- }
- /*
- ================
- Brush_BuildWindings
- ================
- */
- void Brush_BuildWindings(brush_t *b, bool bSnap, bool keepOnPlaneWinding, bool updateLights, bool makeFacePlanes) {
- idWinding *w;
- face_t *face;
- float v;
- // clear the mins/maxs bounds
- b->mins[0] = b->mins[1] = b->mins[2] = 999999;
- b->maxs[0] = b->maxs[1] = b->maxs[2] = -999999;
- if (makeFacePlanes) {
- Brush_MakeFacePlanes(b);
- }
- face = b->brush_faces;
- float fCurveColor = 1.0f;
- for (; face; face = face->next) {
- int i, j;
- delete face->face_winding;
- w = face->face_winding = Brush_MakeFaceWinding(b, face, keepOnPlaneWinding);
- face->d_texture = Texture_ForName(face->texdef.name);
- if (!w) {
- continue;
- }
- for (i = 0; i < w->GetNumPoints(); i++) {
- // add to bounding box
- for (j = 0; j < 3; j++) {
- v = (*w)[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) {
- if (makeFacePlanes) {
- Face_SetColor(b, face, fCurveColor);
- // }
- fCurveColor -= 0.1f;
- if ( fCurveColor <= 0.0f ) {
- fCurveColor = 1.0f;
- }
- // 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->GetNumPoints(); i++) {
- EmitTextureCoordinates((*w)[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->GetNumPoints(); i++) {
- EmitTextureCoordinates((*w)[i], face->d_texture, face);
- }
- }
- }
- }
- if (updateLights) {
- idVec3 offset;
- offset.Zero();
- Brush_UpdateLightPoints(b, offset);
- }
- }
- /*
- ================
- 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;
- }
- }
- }
- /*
- ================
- Brush_SnapToGrid
- ================
- */
- void Brush_SnapToGrid(brush_t *pb) {
- int i;
- for (face_t * f = pb->brush_faces; f; f = f->next) {
- idWinding *w = f->face_winding;
- if (!w) {
- continue; // freed face
- }
- for (i = 0; i < w->GetNumPoints(); i++) {
- SnapVectorToGrid( (*w)[i].ToVec3() );
- }
- for (i = 0; i < 3; i++) {
- f->planepts[i].x = (*w)[i].x;
- f->planepts[i].y = (*w)[i].y;
- f->planepts[i].z = (*w)[i].z;
- }
- }
- idVec3 v;
- idStr str;
- if (GetVectorForKey(pb->owner, "origin", v)) {
- SnapVectorToGrid(pb->owner->origin);
- sprintf(str, "%i %i %i", (int)pb->owner->origin.x, (int)pb->owner->origin.y, (int)pb->owner->origin.z);
- SetKeyValue(pb->owner, "origin", str);
- }
- if (pb->owner->eclass->nShowFlags & ECLASS_LIGHT) {
- if (GetVectorForKey(pb->owner, "light_right", v)) {
- // projected
- SnapVectorToGrid(v);
- pb->lightRight = v;
- SetKeyVec3(pb->owner, "light_right", v);
- GetVectorForKey(pb->owner, "light_up", v);
- SnapVectorToGrid(v);
- pb->lightUp = v;
- SetKeyVec3(pb->owner, "light_up", v);
- GetVectorForKey(pb->owner, "light_target", v);
- SnapVectorToGrid(v);
- pb->lightTarget = v;
- SetKeyVec3(pb->owner, "light_target", v);
- if (GetVectorForKey(pb->owner, "light_start", v)) {
- SnapVectorToGrid(v);
- pb->lightStart = v;
- SetKeyVec3(pb->owner, "light_start", v);
- GetVectorForKey(pb->owner, "light_end", v);
- SnapVectorToGrid(v);
- pb->lightEnd = v;
- SetKeyVec3(pb->owner, "light_end", v);
- }
- } else {
- // point
- if (GetVectorForKey(pb->owner, "light_center", v)) {
- SnapVectorToGrid(v);
- SetKeyVec3(pb->owner, "light_center", v);
- }
- }
- }
- if ( pb->owner->curve ) {
- int c = pb->owner->curve->GetNumValues();
- for ( i = 0; i < c; i++ ) {
- v = pb->owner->curve->GetValue( i );
- SnapVectorToGrid( v );
- pb->owner->curve->SetValue( i, v );
- }
- }
- Brush_Build(pb);
- }
- /*
- ================
- Brush_Rotate
- ================
- */
- void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild) {
- for (face_t * f = b->brush_faces; f; f = f->next) {
- for (int i = 0; i < 3; i++) {
- f->planepts[i] -= origin;
- f->planepts[i] *= matrix;
- f->planepts[i] += origin;
- }
- }
- if (bBuild) {
- Brush_Build(b, false, false);
- }
- }
- extern void VectorRotate3Origin( const idVec3 &vIn, const idVec3 &vRotation, const idVec3 &vOrigin, idVec3 &out );
- /*
- ================
- Brush_Rotate
- ================
- */
- void Brush_Rotate(brush_t *b, idVec3 vAngle, idVec3 vOrigin, bool bBuild) {
- for (face_t * f = b->brush_faces; f; f = f->next) {
- for (int i = 0; i < 3; i++) {
- VectorRotate3Origin(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
- }
- }
- if (bBuild) {
- Brush_Build(b, false, false);
- }
- }
- /*
- ================
- Brush_Center
- ================
- */
- void Brush_Center(brush_t *b, idVec3 vNewCenter) {
- idVec3 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.5f);
- }
- // calc distance between centers
- VectorSubtract(vNewCenter, vMid, vMid);
- Brush_Move(b, vMid, true);
- }
- /*
- ================
- Brush_Resize
- the brush must be a true axial box
- ================
- */
- void Brush_Resize( brush_t *b, idVec3 vMin, idVec3 vMax ) {
- int i, j;
- face_t *f;
- assert( vMin[0] < vMax[0] && vMin[1] < vMax[1] && vMin[2] < vMax[2] );
- Brush_MakeFacePlanes( b );
- for( f = b->brush_faces; f; f = f->next ) {
- for ( i = 0; i < 3; i++ ) {
- if ( f->plane.Normal()[i] >= 0.999f ) {
- for ( j = 0; j < 3; j++ ) {
- f->planepts[j][i] = vMax[i];
- }
- break;
- }
- if ( f->plane.Normal()[i] <= -0.999f ) {
- for ( j = 0; j < 3; j++ ) {
- f->planepts[j][i] = vMin[i];
- }
- break;
- }
- }
- //assert( i < 3 );
- }
- Brush_Build( b, true );
- }
- /*
- ================
- HasModel
- ================
- */
- eclass_t *HasModel(brush_t *b) {
- idVec3 vMin, vMax;
- vMin[0] = vMin[1] = vMin[2] = 999999;
- vMax[0] = vMax[1] = vMax[2] = -999999;
- if (b->owner->md3Class != NULL) {
- return b->owner->md3Class;
- }
- if (b->owner->eclass->modelHandle > 0) {
- 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) {
- const 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);
- b->bModelFailed = false;
- }
- else {
- b->bModelFailed = true;
- }
- }
- }
- return e;
- }
- /*
- ================
- Entity_GetRotationMatrixAngles
- ================
- */
- bool Entity_GetRotationMatrixAngles( entity_t *e, idMat3 &mat, idAngles &angles ) {
- int angle;
- /* the angle keyword is a yaw value, except for two special markers */
- if ( GetMatrixForKey( e, "rotation", mat ) ) {
- angles = mat.ToAngles();
- return true;
- }
- else if ( e->epairs.GetInt( "angle", "0", angle ) ) {
- if ( angle == -1 ) { // up
- angles.Set( 270, 0, 0 );
- }
- else if ( angle == -2 ) { // down
- angles.Set( 90, 0, 0 );
- }
- else {
- angles.Set( 0, angle, 0 );
- }
- mat = angles.ToMat3();
- return true;
- }
- else {
- mat.Identity();
- angles.Zero();
- return false;
- }
- }
- /*
- ================
- FacingVectors
- ================
- */
- static void FacingVectors(entity_t *e, idVec3 &forward, idVec3 &right, idVec3 &up) {
- idAngles angles;
- idMat3 mat;
- Entity_GetRotationMatrixAngles(e, mat, angles);
- angles.ToVectors( &forward, &right, &up);
- }
- /*
- ================
- Brush_DrawFacingAngle
- ================
- */
- void Brush_DrawFacingAngle( brush_t *b, entity_t *e, bool particle ) {
- idVec3 forward, right, up;
- idVec3 endpoint, tip1, tip2;
- idVec3 start;
- float dist;
- VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
- VectorScale(start, 0.5f, start);
- dist = (b->maxs[0] - start[0]) * 2.5f;
- FacingVectors(e, forward, right, up);
- VectorMA(start, dist, ( particle ) ? up : forward, endpoint);
- dist = (b->maxs[0] - start[0]) * 0.5f;
- VectorMA(endpoint, -dist, ( particle ) ? up : forward, tip1);
- VectorMA(tip1, -dist, ( particle ) ? forward : up, tip1);
- VectorMA(tip1, 2 * dist, ( particle ) ? forward : up, tip2);
- globalImages->BindNull();
- qglColor4f(1, 1, 1, 1);
- qglLineWidth(2);
- qglBegin(GL_LINES);
- qglVertex3fv(start.ToFloatPtr());
- qglVertex3fv(endpoint.ToFloatPtr());
- qglVertex3fv(endpoint.ToFloatPtr());
- qglVertex3fv(tip1.ToFloatPtr());
- qglVertex3fv(endpoint.ToFloatPtr());
- qglVertex3fv(tip2.ToFloatPtr());
- qglEnd();
- qglLineWidth(0.5f);
- }
- /*
- ================
- DrawProjectedLight
- ================
- */
- void DrawProjectedLight(brush_t *b, bool bSelected, bool texture) {
- int i;
- idVec3 v1, v2, cross, vieworg, edge[8][2], v[4];
- idVec3 target, start;
- if (!bSelected && !g_bShowLightVolumes) {
- return;
- }
- // use the renderer to get the volume outline
- idPlane lightProject[4];
- idPlane planes[6];
- srfTriangles_t *tri;
- // use the game's epair parsing code so
- // we can use the same renderLight generation
- entity_t *ent = b->owner;
- idDict spawnArgs;
- renderLight_t parms;
- spawnArgs = ent->epairs;
- gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
- R_RenderLightFrustum( parms, planes );
- tri = R_PolytopeSurface(6, planes, NULL);
- qglColor3f(1, 0, 1);
- for (i = 0; i < tri->numIndexes; i += 3) {
- qglBegin(GL_LINE_LOOP);
- glVertex3fv(tri->verts[tri->indexes[i]].xyz.ToFloatPtr());
- glVertex3fv(tri->verts[tri->indexes[i + 1]].xyz.ToFloatPtr());
- glVertex3fv(tri->verts[tri->indexes[i + 2]].xyz.ToFloatPtr());
- qglEnd();
- }
- R_FreeStaticTriSurf(tri);
- // draw different selection points for point lights or projected
- // lights (FIXME: rotate these based on parms!)
- if ( !bSelected ) {
- return;
- }
- idMat3 mat;
- bool transform = GetMatrixForKey(b->owner, "light_rotation", mat);
- if (!transform) {
- transform = GetMatrixForKey(b->owner, "rotation", mat);
- }
- idVec3 tv;
- idVec3 *origin = (b->trackLightOrigin) ? &b->owner->lightOrigin : &b->owner->origin;
- if (b->pointLight) {
- if ( b->lightCenter[0] || b->lightCenter[1] || b->lightCenter[2] ) {
- qglPointSize(8);
- qglColor3f( 1.0f, 0.4f, 0.8f );
- qglBegin(GL_POINTS);
- tv = b->lightCenter;
- if (transform) {
- tv -= *origin;
- tv *= mat;
- tv += *origin;
- }
- qglVertex3fv(tv.ToFloatPtr());
- qglEnd();
- qglPointSize(1);
- }
- return;
- }
- // projected light
- qglPointSize(8);
- qglColor3f( 1.0f, 0.4f, 0.8f );
- qglBegin(GL_POINTS);
- tv = b->lightRight;
- if (transform) {
- tv -= *origin;
- tv *= mat;
- tv += *origin;
- }
- qglVertex3fv(tv.ToFloatPtr());
- tv = b->lightTarget;
- if (transform) {
- tv -= *origin;
- tv *= mat;
- tv += *origin;
- }
- qglVertex3fv(tv.ToFloatPtr());
- tv = b->lightUp;
- if (transform) {
- tv -= *origin;
- tv *= mat;
- tv += *origin;
- }
- qglVertex3fv(tv.ToFloatPtr());
- qglEnd();
- if (b->startEnd) {
- qglColor3f( 0.4f, 1.0f, 0.8f );
- qglBegin(GL_POINTS);
- qglVertex3fv(b->lightStart.ToFloatPtr());
- qglVertex3fv(b->lightEnd.ToFloatPtr());
- qglEnd();
- }
- qglPointSize(1);
- }
- /*
- ================
- GLCircle
- ================
- */
- void GLCircle(float x, float y, float z, float r)
- {
- float ix = 0;
- float iy = r;
- float ig = 3 - 2 * r;
- float idgr = -6;
- float idgd = 4 * r - 10;
- qglPointSize(0.5f);
- qglBegin(GL_POINTS);
- while (ix <= iy) {
- if (ig < 0) {
- ig += idgd;
- idgd -= 8;
- iy--;
- } else {
- ig += idgr;
- idgd -= 4;
- }
- idgr -= 4;
- ix++;
- qglVertex3f(x + ix, y + iy, z);
- qglVertex3f(x - ix, y + iy, z);
- qglVertex3f(x + ix, y - iy, z);
- qglVertex3f(x - ix, y - iy, z);
- qglVertex3f(x + iy, y + ix, z);
- qglVertex3f(x - iy, y + ix, z);
- qglVertex3f(x + iy, y - ix, z);
- qglVertex3f(x - iy, y - ix, z);
- }
- qglEnd();
- }
- /*
- ================
- DrawSpeaker
- ================
- */
- void DrawSpeaker(brush_t *b, bool bSelected, bool twoD) {
- if (!(g_qeglobals.d_savedinfo.showSoundAlways || (g_qeglobals.d_savedinfo.showSoundWhenSelected && bSelected))) {
- return;
- }
-
- // convert to units ( inches )
- float min = FloatForKey(b->owner, "s_mindistance");
- float max = FloatForKey(b->owner, "s_maxdistance");
- const char *s = b->owner->epairs.GetString("s_shader");
- if (s && *s) {
- const idSoundShader *shader = declManager->FindSound( s, false );
- if ( shader ) {
- if ( !min ) {
- min = shader->GetMinDistance();
- }
- if ( !max ) {
- max = shader->GetMaxDistance();
- }
- }
- }
- if (min == 0 && max == 0) {
- return;
- }
-
- // convert from meters to doom units
- min *= METERS_TO_DOOM;
- max *= METERS_TO_DOOM;
- if (twoD) {
- if (bSelected) {
- qglColor4f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z, .5);
- } else {
- qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, .5);
- }
- qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- GLCircle(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z, min);
- if (bSelected) {
- qglColor4f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z, 1);
- } else {
- qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 1);
- }
- GLCircle(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z, max);
- } else {
- qglPushMatrix();
- qglTranslatef(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z );
- qglColor3f( 0.4f, 0.4f, 0.4f );
- qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- GLUquadricObj* qobj = gluNewQuadric();
- gluSphere(qobj, min, 8, 8);
- qglColor3f( 0.8f, 0.8f, 0.8f );
- gluSphere(qobj, max, 8, 8);
- qglEnable(GL_BLEND);
- qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- globalImages->BindNull();
- if (bSelected) {
- qglColor4f( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z, 0.35f );
- } else {
- qglColor4f( b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 0.35f );
- }
- gluSphere(qobj, min, 8, 8);
- if (bSelected) {
- qglColor4f( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z, 0.1f );
- } else {
- qglColor4f( b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 0.1f );
- }
- gluSphere(qobj, max, 8, 8);
- gluDeleteQuadric(qobj);
- qglPopMatrix();
- }
-
- }
- /*
- ================
- DrawLight
- ================
- */
- void DrawLight(brush_t *b, bool bSelected) {
- idVec3 vTriColor;
- bool bTriPaint = false;
- vTriColor[0] = vTriColor[2] = 1.0f;
- vTriColor[1] = 1.0f;
- 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]);
- idVec3 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;
- idVec3 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];
- idVec3 vSave;
- VectorCopy(vTriColor, vSave);
- globalImages->BindNull();
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vTop.ToFloatPtr());
- int i;
- for (i = 0; i <= 3; i++) {
- vTriColor[0] *= 0.95f;
- vTriColor[1] *= 0.95f;
- vTriColor[2] *= 0.95f;
- qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
- qglVertex3fv(vCorners[i].ToFloatPtr());
- }
- qglVertex3fv(vCorners[0].ToFloatPtr());
- qglEnd();
- VectorCopy(vSave, vTriColor);
- vTriColor[0] *= 0.95f;
- vTriColor[1] *= 0.95f;
- vTriColor[2] *= 0.95f;
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vBottom.ToFloatPtr());
- qglVertex3fv(vCorners[0].ToFloatPtr());
- for (i = 3; i >= 0; i--) {
- vTriColor[0] *= 0.95f;
- vTriColor[1] *= 0.95f;
- vTriColor[2] *= 0.95f;
- qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
- qglVertex3fv(vCorners[i].ToFloatPtr());
- }
- qglEnd();
- DrawProjectedLight(b, bSelected, true);
- }
- /*
- ================
- Control_Draw
- ================
- */
- void Control_Draw(brush_t *b) {
- face_t *face;
- int i, order;
- qtexture_t *prev = 0;
- idWinding *w;
- // 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
- }
- qglColor4f(1, 1, .5, 1);
- qglBegin(GL_POLYGON);
- for (i = 0; i < w->GetNumPoints(); i++) {
- qglVertex3fv( (*w)[i].ToFloatPtr() );
- }
- qglEnd();
- }
- }
- /*
- ================
- Brush_DrawModel
- ================
- */
- void Brush_DrawModel( brush_t *b, bool camera, bool bSelected ) {
- idMat3 axis;
- idAngles angles;
- int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
- if ( camera && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME && nDrawMode != cd_wire ) {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- }
- else {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- }
- idRenderModel *model = b->modelHandle;
- if ( model == NULL ) {
- model = b->owner->eclass->entityModel;
- }
- if ( model ) {
- idRenderModel *model2;
- model2 = NULL;
- bool fixedBounds = false;
- if ( model->IsDynamicModel() != DM_STATIC ) {
- if ( dynamic_cast<idRenderModelMD5 *>( model ) ) {
- const char *classname = ValueForKey( b->owner, "classname" );
- if (stricmp(classname, "func_static") == 0) {
- classname = ValueForKey(b->owner, "animclass");
- }
- const char *anim = ValueForKey( b->owner, "anim" );
- int frame = IntForKey( b->owner, "frame" ) + 1;
- if ( frame < 1 ) {
- frame = 1;
- }
- if ( !anim || !anim[ 0 ] ) {
- anim = "idle";
- }
- model2 = gameEdit->ANIM_CreateMeshForAnim( model, classname, anim, frame, false );
- } else if ( dynamic_cast<idRenderModelPrt*>( model ) || dynamic_cast<idRenderModelLiquid*>( model ) ) {
- fixedBounds = true;
- }
- if ( !model2 ) {
- idBounds bounds;
- if (fixedBounds) {
- bounds.Zero();
- bounds.ExpandSelf(12.0f);
- } else {
- bounds = model->Bounds( NULL );
- }
- idVec4 color;
- color.w = 1.0f;
- if (bSelected) {
- color.x = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x;
- color.y = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y;
- color.z = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z;
- } else {
- color.x = b->owner->eclass->color.x;
- color.y = b->owner->eclass->color.y;
- color.z = b->owner->eclass->color.z;
- }
- idVec3 center = bounds.GetCenter();
- glBox(color, b->owner->origin + center, bounds.GetRadius( center ) );
- model = renderModelManager->DefaultModel();
- } else {
- model = model2;
- }
- }
- Entity_GetRotationMatrixAngles( b->owner, axis, angles );
- idVec4 colorSave;
- qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
- if ( bSelected ) {
- qglColor3fv( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr() );
- }
- DrawRenderModel( model, b->owner->origin, axis, camera );
- qglColor4fv( colorSave.ToFloatPtr() );
- if ( bSelected && camera )
- {
- //draw selection tints
- /*
- if ( camera && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME ) {
- qglPolygonMode ( GL_FRONT_AND_BACK , GL_FILL );
- qglColor3fv ( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr () );
- qglEnable ( GL_BLEND );
- qglBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- DrawRenderModel( model, b->owner->origin, axis, camera );
- }
- */
- //draw white triangle outlines
- globalImages->BindNull();
- qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- qglDisable( GL_BLEND );
- qglDisable( GL_DEPTH_TEST );
- qglColor3f( 1.0f, 1.0f, 1.0f );
- qglPolygonOffset( 1.0f, 3.0f );
- DrawRenderModel( model, b->owner->origin, axis, false );
- qglEnable( GL_DEPTH_TEST );
- }
- if ( model2 ) {
- delete model2;
- model2 = NULL;
- }
- }
- if ( bSelected && camera ) {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- }
- else if ( camera ) {
- globalImages->BindNull();
- }
- if ( g_bPatchShowBounds ) {
- for ( face_t *face = b->brush_faces; face; face = face->next ) {
- // only draw polygons facing in a direction we care about
- idWinding *w = face->face_winding;
- if (!w) {
- continue;
- }
- //
- // if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA)) continue;
- // draw the polygon
- //
- qglBegin(GL_LINE_LOOP);
- for (int i = 0; i < w->GetNumPoints(); i++) {
- qglVertex3fv( (*w)[i].ToFloatPtr() );
- }
- qglEnd();
- }
- }
- }
- /*
- ================
- GLTransformedVertex
- ================
- */
- void GLTransformedVertex(float x, float y, float z, idMat3 mat, idVec3 origin, idVec3 color, float maxDist) {
- idVec3 v(x,y,z);
- v -= origin;
- v *= mat;
- v += origin;
- idVec3 n = v - g_pParentWnd->GetCamera()->Camera().origin;
- float max = n.Length() / maxDist;
- if (color.x) {
- color.x = max;
- } else if (color.y) {
- color.y = max;
- } else {
- color.z = max;
- }
- qglColor3f(color.x, color.y, color.z);
- qglVertex3f(v.x, v.y, v.z);
- }
- /*
- ================
- GLTransformedCircle
- ================
- */
- void GLTransformedCircle(int type, idVec3 origin, float r, idMat3 mat, float pointSize, idVec3 color, float maxDist) {
- qglPointSize(pointSize);
- qglBegin(GL_POINTS);
- for (int i = 0; i < 360; i++) {
- float cx = origin.x;
- float cy = origin.y;
- float cz = origin.z;
- switch (type) {
- case 0:
- cx += r * cos((float)i);
- cy += r * sin((float)i);
- break;
- case 1:
- cx += r * cos((float)i);
- cz += r * sin((float)i);
- break;
- case 2:
- cy += r * sin((float)i);
- cz += r * cos((float)i);
- break;
- default:
- break;
- }
- GLTransformedVertex(cx, cy, cz, mat, origin, color, maxDist);
- }
- qglEnd();
- }
- /*
- ================
- Brush_DrawAxis
- ================
- */
- void Brush_DrawAxis(brush_t *b) {
- if ( g_pParentWnd->ActiveXY()->RotateMode() && b->modelHandle ) {
- bool matrix = false;
- idMat3 mat;
- float a, s, c;
- if (GetMatrixForKey(b->owner, "rotation", mat)) {
- matrix = true;
- } else {
- a = FloatForKey(b->owner, "angle");
- if (a) {
- s = sin( DEG2RAD( a ) );
- c = cos( DEG2RAD( a ) );
- }
- else {
- s = c = 0;
- }
- }
- idBounds bo;
- bo.FromTransformedBounds(b->modelHandle->Bounds(), b->owner->origin, b->owner->rotation);
- float dist = (g_pParentWnd->GetCamera()->Camera().origin - bo[0]).Length();
- float dist2 = (g_pParentWnd->GetCamera()->Camera().origin - bo[1]).Length();
- if (dist2 > dist) {
- dist = dist2;
- }
- float xr, yr, zr;
- xr = (b->modelHandle->Bounds()[1].x > b->modelHandle->Bounds()[0].x) ? b->modelHandle->Bounds()[1].x - b->modelHandle->Bounds()[0].x : b->modelHandle->Bounds()[0].x - b->modelHandle->Bounds()[1].x;
- yr = (b->modelHandle->Bounds()[1].y > b->modelHandle->Bounds()[0].y) ? b->modelHandle->Bounds()[1].y - b->modelHandle->Bounds()[0].y : b->modelHandle->Bounds()[0].y - b->modelHandle->Bounds()[1].y;
- zr = (b->modelHandle->Bounds()[1].z > b->modelHandle->Bounds()[0].z) ? b->modelHandle->Bounds()[1].z - b->modelHandle->Bounds()[0].z : b->modelHandle->Bounds()[0].z - b->modelHandle->Bounds()[1].z;
- globalImages->BindNull();
- GLTransformedCircle(0, b->owner->origin, xr, mat, 1.25, idVec3(0, 0, 1), dist);
- GLTransformedCircle(1, b->owner->origin, yr, mat, 1.25, idVec3(0, 1, 0), dist);
- GLTransformedCircle(2, b->owner->origin, zr, mat, 1.25, idVec3(1, 0, 0), dist);
- float wr = xr;
- int type = 0;
- idVec3 org = b->owner->origin;
- if (g_qeglobals.rotateAxis == 0) {
- wr = zr;
- type = 2;
- } else if (g_qeglobals.rotateAxis == 1) {
- wr = yr;
- type = 1;
- }
-
- if (g_qeglobals.flatRotation) {
- if (yr > wr) {
- wr = yr;
- }
- if (zr > wr) {
- wr = zr;
- }
- idVec3 vec = vec3_origin;
- vec[g_qeglobals.rotateAxis] = 1.0f;
- if (g_qeglobals.flatRotation == 1) {
- org = g_pParentWnd->ActiveXY()->RotateOrigin();
- float t = (org - bo.GetCenter()).Length();
- if (t > wr) {
- wr = t;
- }
- } else {
- org = bo.GetCenter();
- }
- idRotation rot(org, vec, 0);
- mat = rot.ToMat3();
- }
- GLTransformedCircle(type, org, wr * 1.03f, mat, 1.45f, idVec3(1, 1, 1), dist);
- }
- }
- /*
- ================
- Brush_DrawModelInfo
- ================
- */
- void Brush_DrawModelInfo(brush_t *b, bool selected) {
- if (b->modelHandle > 0) {
- GLfloat color[4];
- qglGetFloatv(GL_CURRENT_COLOR, &color[0]);
- if (selected) {
- qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr());
- }
- else {
- qglColor3fv(b->owner->eclass->color.ToFloatPtr());
- }
- Brush_DrawModel(b, true, selected);
- qglColor4fv(color);
- if ( selected ) {
- Brush_DrawAxis(b);
- }
- return;
- }
- }
- /*
- ================
- Brush_DrawEmitter
- ================
- */
- void Brush_DrawEmitter(brush_t *b, bool bSelected, bool cam) {
- if ( !( b->owner->eclass->nShowFlags & ECLASS_PARTICLE ) ) {
- return;
- }
-
- if (bSelected) {
- qglColor4f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y, g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z, .5);
- } else {
- qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, .5);
- }
- if ( cam ) {
- Brush_DrawFacingAngle( b, b->owner, true );
- }
- }
- /*
- ================
- Brush_DrawEnv
- ================
- */
- void Brush_DrawEnv( brush_t *b, bool cameraView, bool bSelected ) {
- idVec3 origin, newOrigin;
- idMat3 axis, newAxis;
- idAngles newAngles;
- bool poseIsSet;
- idRenderModel *model = gameEdit->AF_CreateMesh( b->owner->epairs, origin, axis, poseIsSet );
- if ( !poseIsSet ) {
- if ( Entity_GetRotationMatrixAngles( b->owner, newAxis, newAngles ) ) {
- axis = newAxis;
- }
- if ( b->owner->epairs.GetVector( "origin", "0 0 0", newOrigin ) ) {
- origin = newOrigin;
- }
- }
- if ( model ) {
- if ( cameraView && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME ) {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- }
- else {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- }
- idVec4 colorSave;
- qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
- if ( bSelected ) {
- qglColor3fv( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr() );
- } else {
- qglColor3f( 1.f, 1.f, 1.f );
- }
- DrawRenderModel( model, origin, axis, true );
- globalImages->BindNull();
- delete model;
- model = NULL;
- qglColor4fv( colorSave.ToFloatPtr() );
- }
- }
- /*
- ================
- Brush_DrawCombatNode
- ================
- */
- void Brush_DrawCombatNode( brush_t *b, bool cameraView, bool bSelected ) {
- float min_dist = b->owner->epairs.GetFloat( "min" );
- float max_dist = b->owner->epairs.GetFloat( "max" );
- float fov = b->owner->epairs.GetFloat( "fov", "60" );
- float yaw = b->owner->epairs.GetFloat("angle");
- idVec3 offset = b->owner->epairs.GetVector("offset");
- idAngles leftang( 0.0f, yaw + fov * 0.5f - 90.0f, 0.0f );
- idVec3 cone_left = leftang.ToForward();
- idAngles rightang( 0.0f, yaw - fov * 0.5f + 90.0f, 0.0f );
- idVec3 cone_right = rightang.ToForward();
- bool disabled = b->owner->epairs.GetBool( "start_off" );
- idVec4 color;
- if ( bSelected ) {
- color = colorRed;
- } else {
- color = colorBlue;
- }
-
- idVec3 leftDir( -cone_left.y, cone_left.x, 0.0f );
- idVec3 rightDir( cone_right.y, -cone_right.x, 0.0f );
- leftDir.NormalizeFast();
- rightDir.NormalizeFast();
- idMat3 axis = idAngles(0, yaw, 0).ToMat3();
- idVec3 org = b->owner->origin + offset;
- idVec3 entorg = b->owner->origin;
- float cone_dot = cone_right * axis[ 1 ];
- if ( idMath::Fabs( cone_dot ) > 0.1 ) {
- idVec3 pt, pt1, pt2, pt3, pt4;
- float cone_dist = max_dist / cone_dot;
- pt1 = org + leftDir * min_dist;
- pt2 = org + leftDir * cone_dist;
- pt3 = org + rightDir * cone_dist;
- pt4 = org + rightDir * min_dist;
- qglColor4fv(color.ToFloatPtr());
- qglBegin(GL_LINE_STRIP);
- qglVertex3fv( pt1.ToFloatPtr());
- qglVertex3fv( pt2.ToFloatPtr());
- qglVertex3fv( pt3.ToFloatPtr());
- qglVertex3fv( pt4.ToFloatPtr());
- qglVertex3fv( pt1.ToFloatPtr());
- qglEnd();
- qglColor4fv(colorGreen.ToFloatPtr());
- qglBegin(GL_LINE_STRIP);
- qglVertex3fv( entorg.ToFloatPtr());
- pt = (pt1 + pt4) * 0.5f;
- qglVertex3fv( pt.ToFloatPtr());
- pt = (pt2 + pt3) * 0.5f;
- qglVertex3fv( pt.ToFloatPtr());
- idVec3 tip = pt;
- idVec3 dir = ((pt1 + pt2) * 0.5f) - tip;
- dir.Normalize();
- pt = tip + dir * 15.0f;
- qglVertex3fv( pt.ToFloatPtr());
- qglVertex3fv( tip.ToFloatPtr());
- dir = ((pt4 + pt3) * 0.5f) - tip;
- dir.Normalize();
- pt = tip + dir * 15.0f;
- qglVertex3fv( pt.ToFloatPtr());
- qglEnd();
- }
- }
- /*
- ================
- Brush_Draw
- ================
- */
- void Brush_Draw(brush_t *b, bool bSelected) {
- face_t *face;
- int i, order;
- const idMaterial *prev = NULL;
- idWinding *w;
- bool model = false;
- //
- // (TTimo) NOTE: added by build 173, I check after pPlugEnt so it doesn't
- // interfere ?
- //
- if ( b->hiddenBrush ) {
- return;
- }
- Brush_DrawCurve( b, bSelected, true );
- if (b->pPatch) {
- Patch_DrawCam(b->pPatch, bSelected);
- return;
- }
- int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
- if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE)) {
- Brush_DrawFacingAngle(b, b->owner, false);
- }
- if ( b->owner->eclass->fixedsize ) {
- DrawSpeaker( b, bSelected, false );
- if ( g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT) && !(b->modelHandle || b->entityModel) ) {
- DrawLight( b, bSelected );
- return;
- }
- if ( b->owner->eclass->nShowFlags & ECLASS_ENV ) {
- Brush_DrawEnv( b, true, bSelected );
- }
- if ( b->owner->eclass->nShowFlags & ECLASS_COMBATNODE ) {
- Brush_DrawCombatNode( b, true, bSelected );
- }
- }
- if (!(b->owner && (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN))) {
- qglColor4f( 1.0f, 0.0f, 0.0f, 0.8f );
- qglPointSize(4);
- qglBegin(GL_POINTS);
- qglVertex3fv(b->owner->origin.ToFloatPtr());
- qglEnd();
- }
- if ( b->owner->eclass->entityModel ) {
- qglColor3fv( b->owner->eclass->color.ToFloatPtr() );
- Brush_DrawModel( b, true, bSelected );
- return;
- }
- Brush_DrawEmitter( b, bSelected, true );
- if ( b->modelHandle > 0 && !model ) {
- Brush_DrawModelInfo( b, bSelected );
- 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 (g_qeglobals.d_savedinfo.exclude & EXCLUDE_VISPORTALS) {
- if (strstr(face->texdef.name, "visportal")) {
- continue;
- }
- }
- if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_NODRAW) {
- if (strstr(face->texdef.name, "nodraw")) {
- continue;
- }
- }
- if ( (nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev && !b->forceWireFrame ) {
- // set the texture for this face
- prev = face->d_texture;
- face->d_texture->GetEditorImage()->Bind();
- }
- if (model) {
- qglEnable(GL_BLEND);
- qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- qglColor4f( face->d_color.x, face->d_color.y, face->d_color.z, 0.1f );
- } else {
- qglColor4f( face->d_color.x, face->d_color.y, face->d_color.z, face->d_texture->GetEditorAlpha() );
- }
- qglBegin(GL_POLYGON);
- for (i = 0; i < w->GetNumPoints(); i++) {
- if ( !b->forceWireFrame && ( nDrawMode == cd_texture || nDrawMode == cd_light ) ) {
- qglTexCoord2fv( &(*w)[i][3] );
- }
- qglVertex3fv( (*w)[i].ToFloatPtr() );
- }
- qglEnd();
- if (model) {
- qglDisable(GL_BLEND);
- }
- }
- globalImages->BindNull();
- }
- /*
- ================
- Face_Draw
- ================
- */
- void Face_Draw(face_t *f) {
- int i;
- if (f->face_winding == NULL) {
- return;
- }
- qglBegin(GL_POLYGON);
- for (i = 0; i < f->face_winding->GetNumPoints(); i++) {
- qglVertex3fv( (*f->face_winding)[i].ToFloatPtr() );
- }
- qglEnd();
- }
- idSurface_SweptSpline *SplineToSweptSpline( idCurve<idVec3> *curve ) {
- // expects a vec3 curve and creates a vec4 based swept spline
- // must be either nurbs or catmull
- idCurve_Spline<idVec4> *newCurve = NULL;
- if ( dynamic_cast<idCurve_NURBS<idVec3>*>( curve ) ) {
- newCurve = new idCurve_NURBS<idVec4>;
- } else if ( dynamic_cast<idCurve_CatmullRomSpline<idVec3>*>( curve ) ) {
- newCurve = new idCurve_CatmullRomSpline<idVec4>;
- }
- if ( curve == NULL || newCurve == NULL ) {
- return NULL;
- }
- int c = curve->GetNumValues();
- float len = 0.0f;
- for ( int i = 0; i < c; i++ ) {
- idVec3 v = curve->GetValue( i );
- newCurve->AddValue( curve->GetTime( i ), idVec4( v.x, v.y, v.z, len ) );
- if ( i < c - 1 ) {
- len += curve->GetLengthBetweenKnots( i, i + 1 ) * 0.1f;
- }
- }
- idSurface_SweptSpline *ss = new idSurface_SweptSpline;
- ss->SetSpline( newCurve );
- ss->SetSweptCircle( 10.0f );
- ss->Tessellate( newCurve->GetNumValues() * 6, 6 );
- return ss;
- }
- /*
- ================
- Brush_DrawCurve
- ================
- */
- void Brush_DrawCurve( brush_t *b, bool bSelected, bool cam ) {
- if ( b == NULL || b->owner->curve == NULL ) {
- return;
- }
- int maxage = b->owner->curve->GetNumValues();
- int i, time = 0;
- qglColor3f( 0.0f, 0.0f, 1.0f );
- for ( i = 0; i < maxage; i++) {
- if ( bSelected && g_qeglobals.d_select_mode == sel_editpoint ) {
- idVec3 v = b->owner->curve->GetValue( i );
- if ( cam ) {
- glBox( colorBlue, v, 6.0f );
- if ( PointInMoveList( b->owner->curve->GetValueAddress( i ) ) >= 0 ) {
- glBox(colorBlue, v, 8.0f );
- }
- } else {
- qglPointSize( 4.0f );
- qglBegin( GL_POINTS );
- qglVertex3f( v.x, v.y, v.z );
- qglEnd();
- if ( PointInMoveList( b->owner->curve->GetValueAddress( i ) ) >= 0 ) {
- glBox(colorBlue, v, 4.0f );
- }
- }
- }
- /*
- if ( cam ) {
- idSurface_SweptSpline *ss = SplineToSweptSpline( b->owner->curve );
- if ( ss ) {
- idMaterial *mat = declManager->FindMaterial( "_default" );
- mat->GetEditorImage()->Bind();
- qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- qglBegin( GL_TRIANGLES );
- const int *indexes = ss->GetIndexes();
- const idDrawVert *verts = ss->GetVertices();
- for ( j = 0; j < ss->GetNumIndexes(); j += 3 ) {
- for ( k = 0; k < 3; k++ ) {
- int index = indexes[ j + 2 - k ];
- float f = ShadeForNormal( verts[index].normal );
- qglColor3f( f, f, f );
- qglTexCoord2fv( verts[index].st.ToFloatPtr() );
- qglVertex3fv( verts[index].xyz.ToFloatPtr() );
- }
- }
- qglEnd();
- delete ss;
- }
- } else {
- */
- /* qglPointSize( 1.0f );
- qglBegin( GL_POINTS );
- if ( i + 1 < maxage ) {
- int start = b->owner->curve->GetTime( i );
- int end = b->owner->curve->GetTime( i + 1 );
- int inc = (end - start) / POINTS_PER_KNOT;
- for ( int j = 0; j < POINTS_PER_KNOT; j++ ) {
- idVec3 v = b->owner->curve->GetCurrentValue( start );
- qglVertex3f( v.x, v.y, v.z );
- start += inc;
- }
- }*/
- // DHM - _D3XP : Makes it easier to see curve
- qglBegin( GL_LINE_STRIP );
- if ( i + 1 < maxage ) {
- int start = b->owner->curve->GetTime( i );
- int end = b->owner->curve->GetTime( i + 1 );
- int inc = (end - start) / POINTS_PER_KNOT;
- for ( int j = 0; j <= POINTS_PER_KNOT; j++ ) {
- idVec3 v = b->owner->curve->GetCurrentValue( start );
- qglVertex3f( v.x, v.y, v.z );
- start += inc;
- }
- }
- qglEnd();
- /*
- }
- */
- }
- qglPointSize(1);
- }
- /*
- ================
- Brush_DrawXY
- ================
- */
- void Brush_DrawXY(brush_t *b, int nViewType, bool bSelected, bool ignoreViewType) {
- face_t *face;
- int order;
- idWinding *w;
- int i;
- if ( b->hiddenBrush ) {
- return;
- }
- idVec4 colorSave;
- qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
- if (!(b->owner && (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN))) {
- qglColor4f( 1.0f, 0.0f, 0.0f, 0.8f );
- qglPointSize(4);
- qglBegin(GL_POINTS);
- qglVertex3fv(b->owner->origin.ToFloatPtr());
- qglEnd();
- }
- Brush_DrawCurve( b, bSelected, false );
- qglColor4fv(colorSave.ToFloatPtr());
- if (b->pPatch) {
- Patch_DrawXY(b->pPatch);
- if (!g_bPatchShowBounds) {
- return;
- }
- }
- if (b->owner->eclass->fixedsize) {
- DrawSpeaker(b, bSelected, true);
- if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT) && !(b->modelHandle || b->entityModel)) {
- idVec3 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;
- idVec3 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.ToFloatPtr());
- qglVertex3fv(vCorners[0].ToFloatPtr());
- qglVertex3fv(vCorners[1].ToFloatPtr());
- qglVertex3fv(vCorners[2].ToFloatPtr());
- qglVertex3fv(vCorners[3].ToFloatPtr());
- qglVertex3fv(vCorners[0].ToFloatPtr());
- qglEnd();
- qglBegin(GL_TRIANGLE_FAN);
- qglVertex3fv(vBottom.ToFloatPtr());
- qglVertex3fv(vCorners[0].ToFloatPtr());
- qglVertex3fv(vCorners[3].ToFloatPtr());
- qglVertex3fv(vCorners[2].ToFloatPtr());
- qglVertex3fv(vCorners[1].ToFloatPtr());
- qglVertex3fv(vCorners[0].ToFloatPtr());
- qglEnd();
- DrawBrushEntityName(b);
- DrawProjectedLight(b, bSelected, false);
- return;
- } else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL) {
- // if (PaintedModel(b, false)) return;
- } else if (b->owner->eclass->nShowFlags & ECLASS_ENV) {
- Brush_DrawEnv( b, false, bSelected );
- } else if (b->owner->eclass->nShowFlags & ECLASS_COMBATNODE) {
- Brush_DrawCombatNode(b, false, bSelected);
- }
- if (b->owner->eclass->entityModel) {
- Brush_DrawModel( b, false, bSelected );
- DrawBrushEntityName(b);
- qglColor4fv(colorSave.ToFloatPtr());
- return;
- }
- }
- qglColor4fv(colorSave.ToFloatPtr());
- if (b->modelHandle > 0) {
- Brush_DrawEmitter( b, bSelected, false );
- Brush_DrawModel(b, false, bSelected);
- qglColor4fv(colorSave.ToFloatPtr());
- return;
- }
- for (face = b->brush_faces, order = 0; face; face = face->next, order++) {
- // only draw polygons facing in a direction we care about
- if (!ignoreViewType) {
- if (nViewType == XY) {
- if (face->plane[2] <= 0) {
- continue;
- }
- } else {
- if (nViewType == XZ) {
- if (face->plane[1] <= 0) {
- continue;
- }
- } else {
- if (face->plane[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->GetNumPoints(); i++) {
- qglVertex3fv( (*w)[i].ToFloatPtr() );
- }
- qglEnd();
- /*
- for (i = 0; i < 3; i++) {
- glLabeledPoint(idVec4(1, 0, 0, 1), face->planepts[i], 3, va("%i", i));
- }
- */
- }
- DrawBrushEntityName(b);
- }
- /*
- ==================
- PointValueInPointList
- ==================
- */
- static int PointValueInPointList( idVec3 v ) {
- for ( int i = 0; i < g_qeglobals.d_numpoints; i++ ) {
- if ( v == g_qeglobals.d_points[i] ) {
- return i;
- }
- }
- return -1;
- }
- extern bool Sys_KeyDown(int key);
- /*
- ================
- Brush_Move
- ================
- */
- void Brush_Move(brush_t *b, const idVec3 move, bool bSnap, bool updateOrigin) {
- int i;
- face_t *f;
- char text[128];
- for (f = b->brush_faces; f; f = f->next) {
- idVec3 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]);
- }
- }
- bool controlDown = Sys_KeyDown(VK_CONTROL);
- Brush_Build(b, bSnap, true, false, !controlDown);
- if (b->pPatch) {
- Patch_Move(b->pPatch, move);
- }
- if ( b->owner->curve ) {
- b->owner->curve->Translate( move );
- Entity_UpdateCurveData( b->owner );
- }
- idVec3 temp;
- // PGM - keep the origin vector up to date on fixed size entities.
- if (b->owner->eclass->fixedsize || EntityHasModel(b->owner) || (updateOrigin && GetVectorForKey(b->owner, "origin", temp))) {
- // if (!b->entityModel) {
- bool adjustOrigin = true;
- if(b->trackLightOrigin) {
- b->owner->lightOrigin += move;
- sprintf(text, "%i %i %i", (int)b->owner->lightOrigin[0], (int)b->owner->lightOrigin[1], (int)b->owner->lightOrigin[2]);
- SetKeyValue(b->owner, "light_origin", text);
- if (QE_SingleBrush(true, true)) {
- adjustOrigin = false;
- }
- }
- if (adjustOrigin && updateOrigin) {
- b->owner->origin += move;
- if (g_moveOnly) {
- sprintf(text, "%g %g %g", b->owner->origin[0], b->owner->origin[1], b->owner->origin[2]);
- } else {
- sprintf(text, "%i %i %i", (int)b->owner->origin[0], (int)b->owner->origin[1], (int)b->owner->origin[2]);
- }
- SetKeyValue(b->owner, "origin", text);
- }
- // rebuild the light dragging points now that the origin has changed
- idVec3 offset;
- offset.Zero();
- if (controlDown) {
- offset.x = -move.x;
- offset.y = -move.y;
- offset.z = -move.z;
- Brush_UpdateLightPoints(b, offset);
- } else {
- offset.Zero();
- Brush_UpdateLightPoints(b, offset);
- }
- //}
- if (b->owner->eclass->nShowFlags & ECLASS_ENV) {
- const idKeyValue *arg = b->owner->epairs.MatchPrefix( "body ", NULL );
- idStr val;
- idVec3 org;
- idAngles ang;
- while ( arg ) {
- sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
- org += move;
- val = org.ToString(8);
- val += " ";
- val += ang.ToString(8);
- b->owner->epairs.Set(arg->GetKey(), val);
- arg = b->owner->epairs.MatchPrefix( "body ", arg );
- }
- }
- }
- }
- /*
- ================
- Select_AddProjectedLight
- ================
- */
- void Select_AddProjectedLight() {
- idVec3 vTemp;
- CString str;
- // if (!QE_SingleBrush ()) return;
- brush_t *b = selected_brushes.next;
- if (b->owner->eclass->nShowFlags & ECLASS_LIGHT) {
- vTemp[0] = vTemp[1] = 0;
- vTemp[2] = -256;
- str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
- SetKeyValue(b->owner, "light_target", str);
- vTemp[2] = 0;
- vTemp[1] = -128;
- str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
- SetKeyValue(b->owner, "light_up", str);
- vTemp[1] = 0;
- vTemp[0] = -128;
- str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
- SetKeyValue(b->owner, "light_right", str);
- Brush_Build(b);
- }
- }
- /*
- ================
- Brush_Print
- ================
- */
- void Brush_Print(brush_t *b) {
- int nFace = 0;
- for (face_t * f = b->brush_faces; f; f = f->next) {
- common->Printf("Face %i\n", nFace++);
- common->Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
- common->Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
- common->Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
- }
- }
- /*
- ================
- Brush_MakeSidedCone
- Makes the current brush have the given number of 2d sides and turns it into a cone
- ================
- */
- void Brush_MakeSidedCone(int sides) {
- int i;
- idVec3 mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- idVec3 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.5f;
- if (maxs[i] - mins[i] > width) {
- width = maxs[i] - mins[i];
- }
- }
- width *= 0.5f;
- 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 * idMath::TWO_PI / sides);
- cv = cos(i * idMath::TWO_PI / sides);
- f->planepts[0][0] = floor( mid[0] + width * cv + 0.5f );
- f->planepts[0][1] = floor( mid[1] + width * sv + 0.5f );
- 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.5f );
- f->planepts[2][1] = floor( f->planepts[0][1] + width * cv + 0.5f );
- f->planepts[2][2] = maxs[2];
- }
- Brush_AddToList(b, &selected_brushes);
- Entity_LinkBrush(world_entity, b);
- Brush_Build(b);
- Sys_UpdateWindows(W_ALL);
- }
- /*
- ================
- Brush_MakeSidedSphere
- Makes the current brushhave the given number of 2d sides and turns it into a sphere
- ================
- */
- void Brush_MakeSidedSphere(int sides) {
- int i, j;
- idVec3 mins, maxs;
- brush_t *b;
- texdef_t *texdef;
- face_t *f;
- idVec3 mid;
- float radius;
- 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;
- mins = b->mins;
- maxs = b->maxs;
- texdef = &g_qeglobals.d_texturewin.texdef;
- Brush_Free(b);
- // find center of brush
- radius = 8;
- for ( i = 0; i < 3; i++ ) {
- mid[i] = (maxs[i] + mins[i]) * 0.5f;
- if (maxs[i] - mins[i] > radius) {
- radius = maxs[i] - mins[i];
- }
- }
- radius *= 0.5f;
- b = Brush_Alloc();
- for (i = 0; i < sides; i++) {
- for (j = 0; j < sides - 1; j++) {
- f = Face_Alloc();
- f->texdef = *texdef;
- f->next = b->brush_faces;
- b->brush_faces = f;
- f->planepts[0] = idPolar3(radius, idMath::TWO_PI * i / sides, idMath::PI * ((float)(j) / sides - 0.5f) ).ToVec3() + mid;
- f->planepts[1] = idPolar3(radius, idMath::TWO_PI * i / sides, idMath::PI * ((float)(j+1) / sides - 0.5f) ).ToVec3() + mid;
- f->planepts[2] = idPolar3(radius, idMath::TWO_PI * (i+1) / sides, idMath::PI * ((float)(j+1) / sides - 0.5f) ).ToVec3() + mid;
- }
- }
- Brush_AddToList(b, &selected_brushes);
- Entity_LinkBrush(world_entity, b);
- Brush_Build(b);
- Sys_UpdateWindows(W_ALL);
- }
- extern void Face_FitTexture_BrushPrimit(face_t *f, idVec3 mins, idVec3 maxs, float nHeight, float nWidth);
- /*
- ================
- Face_FitTexture
- ================
- */
- void Face_FitTexture(face_t *face, float nHeight, float nWidth) {
- if (g_qeglobals.m_bBrushPrimitMode) {
- idVec3 mins, maxs;
- mins[0] = maxs[0] = 0;
- Face_FitTexture_BrushPrimit(face, mins, maxs, nHeight, nWidth);
- }
- else {
- /*
- * winding_t *w; idBounds bounds; 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;
- * idVec3 vecs[2]; idVec3 coords[4]; texdef_t *td; if (nHeight < 1) { nHeight = 1;
- * } if (nWidth < 1) { nWidth = 1; } bounds.Clear(); td = &face->texdef; w =
- * face->face_winding; if (!w) { return; } for (i=0 ; i<w->numpoints ; i++) {
- * bounds.AddPoint( w->p[i] ); } // // 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(
- * bounds.b[0], vecs[0] ); min_t = DotProduct( bounds.b[0], vecs[1] ); max_s =
- * DotProduct( bounds.b[1], vecs[0] ); max_t = DotProduct( bounds.b[1], 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 = 999999; max_s = max_t = -999999; 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->GetEditorImage()->uploadWidth*nWidth)));
- * td->scale[1] =
- * -(rot_height/((float)(face->d_texture->GetEditorImage()->uploadHeight*nHeight)));
- * td->shift[0] = min_s/td->scale[0]; temp = (int)(td->shift[0] /
- * (face->d_texture->GetEditorImage()->uploadWidth*nWidth)); temp =
- * (temp+1)*face->d_texture->GetEditorImage()->uploadWidth*nWidth; td->shift[0] =
- * (int)(temp -
- * td->shift[0])%(face->d_texture->GetEditorImage()->uploadWidth*nWidth);
- * td->shift[1] = min_t/td->scale[1]; temp = (int)(td->shift[1] /
- * (face->d_texture->GetEditorImage()->uploadHeight*nHeight)); temp =
- * (temp+1)*(face->d_texture->GetEditorImage()->uploadHeight*nHeight);
- * td->shift[1] = (int)(temp -
- * td->shift[1])%(face->d_texture->GetEditorImage()->uploadHeight*nHeight);
- */
- }
- }
- /*
- ================
- Brush_FitTexture
- ================
- */
- void Brush_FitTexture(brush_t *b, float nHeight, float nWidth) {
- face_t *face;
- for (face = b->brush_faces; face; face = face->next) {
- Face_FitTexture(face, nHeight, nWidth);
- }
- }
- void Brush_GetBounds( brush_t *b, idBounds &bo ) {
- if ( b == NULL ) {
- return;
- }
- bo.Clear();
- bo.AddPoint( b->mins );
- bo.AddPoint( b->maxs );
- if ( b->owner->curve ) {
- int c = b->owner->curve->GetNumValues();
- for ( int i = 0; i < c; i++ ) {
- bo.AddPoint ( b->owner->curve->GetValue( i ) );
- }
- }
- }
|