EditorBrush.cpp 120 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "qe3.h"
  23. #include <GL/glu.h>
  24. #include "../../renderer/tr_local.h"
  25. #include "../../renderer/model_local.h" // for idRenderModelMD5
  26. void Brush_UpdateLightPoints(brush_t *b, const idVec3 &offset);
  27. void Brush_DrawCurve( brush_t *b, bool bSelected, bool cam );
  28. // globals
  29. int g_nBrushId = 0;
  30. bool g_bShowLightVolumes = false;
  31. bool g_bShowLightTextures = false;
  32. void GLCircle(float x, float y, float z, float r);
  33. const int POINTS_PER_KNOT = 50;
  34. /*
  35. ================
  36. DrawRenderModel
  37. ================
  38. */
  39. void DrawRenderModel( idRenderModel *model, idVec3 &origin, idMat3 &axis, bool cameraView ) {
  40. for ( int i = 0; i < model->NumSurfaces(); i++ ) {
  41. const modelSurface_t *surf = model->Surface( i );
  42. const idMaterial *material = surf->shader;
  43. int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  44. if ( cameraView && (nDrawMode == cd_texture || nDrawMode == cd_light) ) {
  45. material->GetEditorImage()->Bind();
  46. }
  47. qglBegin( GL_TRIANGLES );
  48. const srfTriangles_t *tri = surf->geometry;
  49. for ( int j = 0; j < tri->numIndexes; j += 3 ) {
  50. for ( int k = 0; k < 3; k++ ) {
  51. int index = tri->indexes[j + k];
  52. idVec3 v;
  53. v = tri->verts[index].xyz * axis + origin;
  54. qglTexCoord2f( tri->verts[index].st.x, tri->verts[index].st.y );
  55. qglVertex3fv( v.ToFloatPtr() );
  56. }
  57. }
  58. qglEnd();
  59. }
  60. }
  61. /*
  62. ================
  63. SnapVectorToGrid
  64. ================
  65. */
  66. void SnapVectorToGrid(idVec3 &v) {
  67. v.x = floor(v.x / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
  68. v.y = floor(v.y / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
  69. v.z = floor(v.z / g_qeglobals.d_gridsize + 0.5f) * g_qeglobals.d_gridsize;
  70. }
  71. /*
  72. ================
  73. Brush_Name
  74. ================
  75. */
  76. const char *Brush_Name( brush_t *b ) {
  77. static char cBuff[1024];
  78. b->numberId = g_nBrushId++;
  79. if (g_qeglobals.m_bBrushPrimitMode) {
  80. sprintf(cBuff, "Brush %i", b->numberId);
  81. Brush_SetEpair(b, "Name", cBuff);
  82. }
  83. return cBuff;
  84. }
  85. /*
  86. ================
  87. Brush_Alloc
  88. ================
  89. */
  90. brush_t *Brush_Alloc( void ) {
  91. brush_t *b = new brush_t;
  92. b->prev = b->next = NULL;
  93. b->oprev = b->onext = NULL;
  94. b->owner = NULL;
  95. b->mins.Zero();
  96. b->maxs.Zero();
  97. b->lightCenter.Zero();
  98. b->lightRight.Zero();
  99. b->lightTarget.Zero();
  100. b->lightUp.Zero();
  101. b->lightRadius.Zero();
  102. b->lightOffset.Zero();
  103. b->lightColor.Zero();
  104. b->lightStart.Zero();
  105. b->lightEnd.Zero();
  106. b->pointLight = false;
  107. b->startEnd = false;
  108. b->lightTexture = 0;
  109. b->trackLightOrigin = false;
  110. b->entityModel = false;
  111. b->brush_faces = NULL;
  112. b->hiddenBrush = false;
  113. b->pPatch = NULL;
  114. b->pUndoOwner = NULL;
  115. b->undoId = 0;
  116. b->redoId = 0;
  117. b->ownerId = 0;
  118. b->numberId = 0;
  119. b->itemOwner = 0;
  120. b->bModelFailed = false;
  121. b->modelHandle = NULL;
  122. b->forceVisibile = false;
  123. b->forceWireFrame = false;
  124. return b;
  125. }
  126. /*
  127. ================
  128. TextureAxisFromPlane
  129. ================
  130. */
  131. idVec3 baseaxis[18] = {
  132. idVec3(0, 0, 1),
  133. idVec3(1, 0, 0),
  134. idVec3(0, -1, 0),
  135. // floor
  136. idVec3(0, 0, -1),
  137. idVec3(1, 0, 0),
  138. idVec3(0, -1, 0),
  139. // ceiling
  140. idVec3(1, 0, 0),
  141. idVec3(0, 1, 0),
  142. idVec3(0, 0, -1),
  143. // west wall
  144. idVec3(-1, 0, 0),
  145. idVec3(0, 1, 0),
  146. idVec3(0, 0, -1),
  147. // east wall
  148. idVec3(0, 1, 0),
  149. idVec3(1, 0, 0),
  150. idVec3(0, 0, -1),
  151. // south wall
  152. idVec3(0, -1, 0),
  153. idVec3(1, 0, 0),
  154. idVec3(0, 0, -1) // north wall
  155. };
  156. void TextureAxisFromPlane( const idPlane &pln, idVec3 &xv, idVec3 &yv) {
  157. int bestaxis;
  158. float dot, best;
  159. int i;
  160. best = 0;
  161. bestaxis = 0;
  162. for (i = 0; i < 6; i++) {
  163. dot = DotProduct(pln, baseaxis[i * 3]);
  164. if (dot > best) {
  165. best = dot;
  166. bestaxis = i;
  167. }
  168. }
  169. VectorCopy(baseaxis[bestaxis * 3 + 1], xv);
  170. VectorCopy(baseaxis[bestaxis * 3 + 2], yv);
  171. }
  172. /*
  173. ================
  174. ShadeForNormal
  175. Light different planes differently to improve recognition
  176. ================
  177. */
  178. float lightaxis[3] = { 0.6f, 0.8f, 1.0f };
  179. float ShadeForNormal(idVec3 normal) {
  180. int i;
  181. float f;
  182. // axial plane
  183. for (i = 0; i < 3; i++) {
  184. if ( idMath::Fabs(normal[i]) > 0.9f ) {
  185. f = lightaxis[i];
  186. return f;
  187. }
  188. }
  189. // between two axial planes
  190. for (i = 0; i < 3; i++) {
  191. if ( idMath::Fabs(normal[i]) < 0.1f ) {
  192. f = (lightaxis[(i + 1) % 3] + lightaxis[(i + 2) % 3]) / 2;
  193. return f;
  194. }
  195. }
  196. // other
  197. f = (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
  198. return f;
  199. }
  200. /*
  201. ================
  202. Face_Alloc
  203. ================
  204. */
  205. face_t *Face_Alloc(void) {
  206. brushprimit_texdef_t bp;
  207. face_t *f = (face_t *) Mem_ClearedAlloc(sizeof(*f));
  208. bp.coords[0][0] = 0.0f;
  209. bp.coords[1][1] = 0.0f;
  210. f->brushprimit_texdef = bp;
  211. f->dirty = true;
  212. return f;
  213. }
  214. /*
  215. ================
  216. Face_Free
  217. ================
  218. */
  219. void Face_Free(face_t *f) {
  220. assert(f != 0);
  221. if (f->face_winding) {
  222. delete f->face_winding;
  223. }
  224. f->texdef.~texdef_t();
  225. Mem_Free(f);
  226. }
  227. /*
  228. ================
  229. Face_Clone
  230. ================
  231. */
  232. face_t *Face_Clone(face_t *f) {
  233. face_t *n;
  234. n = Face_Alloc();
  235. n->texdef = f->texdef;
  236. n->brushprimit_texdef = f->brushprimit_texdef;
  237. memcpy(n->planepts, f->planepts, sizeof(n->planepts));
  238. n->plane = f->plane;
  239. n->originalPlane = f->originalPlane;
  240. n->dirty = f->dirty;
  241. // all other fields are derived, and will be set by Brush_Build
  242. return n;
  243. }
  244. /*
  245. ================
  246. Face_FullClone
  247. Used by Undo.
  248. Makes an exact copy of the face.
  249. ================
  250. */
  251. face_t *Face_FullClone(face_t *f) {
  252. face_t *n;
  253. n = Face_Alloc();
  254. n->texdef = f->texdef;
  255. n->brushprimit_texdef = f->brushprimit_texdef;
  256. memcpy(n->planepts, f->planepts, sizeof(n->planepts));
  257. n->plane = f->plane;
  258. n->originalPlane = f->originalPlane;
  259. n->dirty = f->dirty;
  260. if (f->face_winding) {
  261. n->face_winding = f->face_winding->Copy();
  262. }
  263. else {
  264. n->face_winding = NULL;
  265. }
  266. n->d_texture = Texture_ForName(n->texdef.name);
  267. return n;
  268. }
  269. /*
  270. ================
  271. Clamp
  272. ================
  273. */
  274. void Clamp(float &f, int nClamp) {
  275. float fFrac = f - static_cast<int>(f);
  276. f = static_cast<int>(f) % nClamp;
  277. f += fFrac;
  278. }
  279. /*
  280. ================
  281. Face_MoveTexture
  282. ================
  283. */
  284. void Face_MoveTexture(face_t *f, idVec3 delta) {
  285. idVec3 vX, vY;
  286. /*
  287. * #ifdef _DEBUG if (g_PrefsDlg.m_bBrushPrimitMode) common->Printf("Warning :
  288. * Face_MoveTexture not done in brush primitive mode\n"); #endif
  289. */
  290. if (g_qeglobals.m_bBrushPrimitMode) {
  291. Face_MoveTexture_BrushPrimit(f, delta);
  292. }
  293. else {
  294. TextureAxisFromPlane( f->plane, vX, vY );
  295. idVec3 vDP, vShift;
  296. vDP[0] = DotProduct(delta, vX);
  297. vDP[1] = DotProduct(delta, vY);
  298. double fAngle = DEG2RAD( f->texdef.rotate );
  299. double c = cos(fAngle);
  300. double s = sin(fAngle);
  301. vShift[0] = vDP[0] * c - vDP[1] * s;
  302. vShift[1] = vDP[0] * s + vDP[1] * c;
  303. if (!f->texdef.scale[0]) {
  304. f->texdef.scale[0] = 1;
  305. }
  306. if (!f->texdef.scale[1]) {
  307. f->texdef.scale[1] = 1;
  308. }
  309. f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
  310. f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
  311. // clamp the shifts
  312. Clamp(f->texdef.shift[0], f->d_texture->GetEditorImage()->uploadWidth);
  313. Clamp(f->texdef.shift[1], f->d_texture->GetEditorImage()->uploadHeight);
  314. }
  315. }
  316. /*
  317. ================
  318. Face_SetColor
  319. ================
  320. */
  321. void Face_SetColor(brush_t *b, face_t *f, float fCurveColor) {
  322. float shade;
  323. const idMaterial *q;
  324. q = f->d_texture;
  325. // set shading for face
  326. shade = ShadeForNormal( f->plane.Normal() );
  327. if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && (b->owner && !b->owner->eclass->fixedsize)) {
  328. // if (b->curveBrush) shade = fCurveColor;
  329. f->d_color[0] = f->d_color[1] = f->d_color[2] = shade;
  330. }
  331. else if ( f && b && b->owner ) {
  332. f->d_color[0] = shade * b->owner->eclass->color.x;
  333. f->d_color[1] = shade * b->owner->eclass->color.y;
  334. f->d_color[2] = shade * b->owner->eclass->color.z;
  335. }
  336. }
  337. /*
  338. ================
  339. Face_TextureVectors
  340. NOTE: this is never to get called while in brush primitives mode
  341. ================
  342. */
  343. void Face_TextureVectors(face_t *f, float STfromXYZ[2][4]) {
  344. idVec3 pvecs[2];
  345. int sv, tv;
  346. float ang, sinv, cosv;
  347. float ns, nt;
  348. int i, j;
  349. const idMaterial *q;
  350. texdef_t *td;
  351. #ifdef _DEBUG
  352. //
  353. // ++timo when playing with patches, this sometimes get called and the Warning is
  354. // displayed find some way out ..
  355. //
  356. if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert) {
  357. common->Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
  358. }
  359. #endif
  360. td = &f->texdef;
  361. q = f->d_texture;
  362. memset(STfromXYZ, 0, 8 * sizeof (float));
  363. if (!td->scale[0]) {
  364. td->scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 2 : 1;
  365. }
  366. if (!td->scale[1]) {
  367. td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 2 : 1;
  368. }
  369. // get natural texture axis
  370. TextureAxisFromPlane( f->plane, pvecs[0], pvecs[1]);
  371. // rotate axis
  372. if (td->rotate == 0) {
  373. sinv = 0;
  374. cosv = 1;
  375. }
  376. else if (td->rotate == 90) {
  377. sinv = 1;
  378. cosv = 0;
  379. }
  380. else if (td->rotate == 180) {
  381. sinv = 0;
  382. cosv = -1;
  383. }
  384. else if (td->rotate == 270) {
  385. sinv = -1;
  386. cosv = 0;
  387. }
  388. else {
  389. ang = DEG2RAD( td->rotate );
  390. sinv = sin(ang);
  391. cosv = cos(ang);
  392. }
  393. if (pvecs[0][0]) {
  394. sv = 0;
  395. }
  396. else if (pvecs[0][1]) {
  397. sv = 1;
  398. }
  399. else {
  400. sv = 2;
  401. }
  402. if (pvecs[1][0]) {
  403. tv = 0;
  404. }
  405. else if (pvecs[1][1]) {
  406. tv = 1;
  407. }
  408. else {
  409. tv = 2;
  410. }
  411. for (i = 0; i < 2; i++) {
  412. ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
  413. nt = sinv * pvecs[i][sv] + cosv * pvecs[i][tv];
  414. STfromXYZ[i][sv] = ns;
  415. STfromXYZ[i][tv] = nt;
  416. }
  417. // scale
  418. for (i = 0; i < 2; i++) {
  419. for (j = 0; j < 3; j++) {
  420. STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
  421. }
  422. }
  423. // shift
  424. STfromXYZ[0][3] = td->shift[0];
  425. STfromXYZ[1][3] = td->shift[1];
  426. for (j = 0; j < 4; j++) {
  427. STfromXYZ[0][j] /= q->GetEditorImage()->uploadWidth;
  428. STfromXYZ[1][j] /= q->GetEditorImage()->uploadHeight;
  429. }
  430. }
  431. /*
  432. ================
  433. Face_MakePlane
  434. ================
  435. */
  436. void Face_MakePlane(face_t *f) {
  437. int j;
  438. idVec3 t1, t2, t3;
  439. idPlane oldPlane = f->plane;
  440. // convert to a vector / dist plane
  441. for (j = 0; j < 3; j++) {
  442. t1[j] = f->planepts[0][j] - f->planepts[1][j];
  443. t2[j] = f->planepts[2][j] - f->planepts[1][j];
  444. t3[j] = f->planepts[1][j];
  445. }
  446. f->plane = t1.Cross( t2 );
  447. //if ( f->plane.Compare( vec3_origin ) ) {
  448. // printf("WARNING: brush plane with no normal\n");
  449. //}
  450. f->plane.Normalize(false);
  451. f->plane[3] = - (t3 * f->plane.Normal());
  452. if ( !f->dirty && !f->plane.Compare( oldPlane, 0.01f ) ) {
  453. f->dirty = true;
  454. }
  455. }
  456. /*
  457. ================
  458. EmitTextureCoordinates
  459. ================
  460. */
  461. void EmitTextureCoordinates(idVec5 &xyzst, const idMaterial *q, face_t *f, bool force) {
  462. float STfromXYZ[2][4];
  463. if (g_qeglobals.m_bBrushPrimitMode && !force) {
  464. EmitBrushPrimitTextureCoordinates(f, f->face_winding);
  465. }
  466. else {
  467. Face_TextureVectors(f, STfromXYZ);
  468. xyzst[3] = DotProduct(xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
  469. xyzst[4] = DotProduct(xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
  470. }
  471. }
  472. /*
  473. ================
  474. Brush_MakeFacePlanes
  475. ================
  476. */
  477. void Brush_MakeFacePlanes(brush_t *b) {
  478. face_t *f;
  479. for (f = b->brush_faces; f; f = f->next) {
  480. Face_MakePlane(f);
  481. }
  482. }
  483. /*
  484. ================
  485. DrawBrushEntityName
  486. ================
  487. */
  488. void DrawBrushEntityName(brush_t *b) {
  489. const char *name;
  490. // float a, s, c; vec3_t mid; int i;
  491. if (!b->owner) {
  492. return; // during contruction
  493. }
  494. if (b->owner == world_entity) {
  495. return;
  496. }
  497. if (b != b->owner->brushes.onext) {
  498. return; // not key brush
  499. }
  500. if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES)) {
  501. // draw the angle pointer
  502. float a = FloatForKey(b->owner, "angle");
  503. if (a) {
  504. float s = sin( DEG2RAD( a ) );
  505. float c = cos( DEG2RAD( a ) );
  506. idVec3 mid = (b->mins + b->maxs) / 2.0f;
  507. qglBegin(GL_LINE_STRIP);
  508. qglVertex3fv(mid.ToFloatPtr());
  509. mid[0] += c * 8;
  510. mid[1] += s * 8;
  511. mid[2] += s * 8;
  512. qglVertex3fv(mid.ToFloatPtr());
  513. mid[0] -= c * 4;
  514. mid[1] -= s * 4;
  515. mid[2] -= s * 4;
  516. mid[0] -= s * 4;
  517. mid[1] += c * 4;
  518. mid[2] += c * 4;
  519. qglVertex3fv(mid.ToFloatPtr());
  520. mid[0] += c * 4;
  521. mid[1] += s * 4;
  522. mid[2] += s * 4;
  523. mid[0] += s * 4;
  524. mid[1] -= c * 4;
  525. mid[2] -= c * 4;
  526. qglVertex3fv(mid.ToFloatPtr());
  527. mid[0] -= c * 4;
  528. mid[1] -= s * 4;
  529. mid[2] -= s * 4;
  530. mid[0] += s * 4;
  531. mid[1] -= c * 4;
  532. mid[2] -= c * 4;
  533. qglVertex3fv(mid.ToFloatPtr());
  534. qglEnd();
  535. }
  536. }
  537. int viewType = g_pParentWnd->ActiveXY()->GetViewType();
  538. float scale = g_pParentWnd->ActiveXY()->Scale();
  539. if (g_qeglobals.d_savedinfo.show_names && scale >= 1.0f) {
  540. name = ValueForKey(b->owner, "name");
  541. int nameLen = strlen(name);
  542. if ( nameLen == 0 ) {
  543. name = ValueForKey(b->owner, "classname");
  544. nameLen = strlen(name);
  545. }
  546. if ( nameLen > 0 ) {
  547. idVec3 origin = b->owner->origin;
  548. float halfWidth = ( (nameLen / 2) * (7.0f / scale) );
  549. float halfHeight = 4.0f / scale;
  550. switch (viewType) {
  551. case XY:
  552. origin.x -= halfWidth;
  553. origin.y += halfHeight;
  554. break;
  555. case XZ:
  556. origin.x -= halfWidth;
  557. origin.z += halfHeight;
  558. break;
  559. case YZ:
  560. origin.y -= halfWidth;
  561. origin.z += halfHeight;
  562. break;
  563. }
  564. qglRasterPos3fv( origin.ToFloatPtr() );
  565. qglCallLists(nameLen, GL_UNSIGNED_BYTE, name);
  566. }
  567. }
  568. }
  569. /*
  570. ================
  571. Brush_MakeFaceWinding
  572. returns the visible winding
  573. ================
  574. */
  575. idWinding *Brush_MakeFaceWinding(brush_t *b, face_t *face, bool keepOnPlaneWinding) {
  576. idWinding *w;
  577. face_t *clip;
  578. idPlane plane;
  579. bool past;
  580. // get a poly that covers an effectively infinite area
  581. w = new idWinding( face->plane );
  582. // chop the poly by all of the other faces
  583. past = false;
  584. for (clip = b->brush_faces; clip && w; clip = clip->next) {
  585. if (clip == face) {
  586. past = true;
  587. continue;
  588. }
  589. if ( DotProduct(face->plane, clip->plane) > 0.999f &&
  590. idMath::Fabs(face->plane[3] - clip->plane[3]) < 0.01f ) { // identical plane, use the later one
  591. if (past) {
  592. delete w;
  593. common->Printf("Unable to create face winding on brush\n");
  594. return NULL;
  595. }
  596. continue;
  597. }
  598. // flip the plane, because we want to keep the back side
  599. VectorSubtract(vec3_origin, clip->plane, plane );
  600. plane[3] = -clip->plane[3];
  601. w = w->Clip( plane, ON_EPSILON, keepOnPlaneWinding );
  602. if ( !w ) {
  603. return w;
  604. }
  605. }
  606. if ( w->GetNumPoints() < 3) {
  607. delete w;
  608. w = NULL;
  609. }
  610. if (!w) {
  611. Sys_Status("Unable to create face winding on brush\n");
  612. }
  613. return w;
  614. }
  615. /*
  616. ================
  617. Brush_Build
  618. Builds a brush rendering data and also sets the min/max bounds
  619. TTimo added a bConvert flag to convert between old and new brush texture formats
  620. TTimo brush grouping: update the group treeview if necessary
  621. ================
  622. */
  623. void Brush_Build(brush_t *b, bool bSnap, bool bMarkMap, bool bConvert, bool updateLights) {
  624. bool bLocalConvert = false;
  625. #ifdef _DEBUG
  626. if (!g_qeglobals.m_bBrushPrimitMode && bConvert) {
  627. common->Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
  628. }
  629. #endif
  630. //
  631. // if bConvert is set and g_qeglobals.bNeedConvert is not, that just means we need
  632. // convert for this brush only
  633. //
  634. if (bConvert && !g_qeglobals.bNeedConvert) {
  635. bLocalConvert = true;
  636. g_qeglobals.bNeedConvert = true;
  637. }
  638. /* build the windings and generate the bounding box */
  639. Brush_BuildWindings(b, bSnap, EntityHasModel(b->owner) || b->pPatch, updateLights);
  640. /* move the points and edges if in select mode */
  641. if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge) {
  642. SetupVertexSelection();
  643. }
  644. if (bMarkMap) {
  645. Sys_MarkMapModified();
  646. g_pParentWnd->GetCamera()->MarkWorldDirty();
  647. }
  648. if (bLocalConvert) {
  649. g_qeglobals.bNeedConvert = false;
  650. }
  651. }
  652. /*
  653. ================
  654. Brush_SplitBrushByFace
  655. The incoming brush is NOT freed. The incoming face is NOT left referenced.
  656. ================
  657. */
  658. void Brush_SplitBrushByFace(brush_t *in, face_t *f, brush_t **front, brush_t **back) {
  659. brush_t *b;
  660. face_t *nf;
  661. idVec3 temp;
  662. b = Brush_Clone(in);
  663. nf = Face_Clone(f);
  664. nf->texdef = b->brush_faces->texdef;
  665. nf->brushprimit_texdef = b->brush_faces->brushprimit_texdef;
  666. nf->next = b->brush_faces;
  667. b->brush_faces = nf;
  668. Brush_Build(b);
  669. Brush_RemoveEmptyFaces(b);
  670. if (!b->brush_faces) { // completely clipped away
  671. Brush_Free(b);
  672. *back = NULL;
  673. }
  674. else {
  675. Entity_LinkBrush(in->owner, b);
  676. *back = b;
  677. }
  678. b = Brush_Clone(in);
  679. nf = Face_Clone(f);
  680. // swap the plane winding
  681. VectorCopy(nf->planepts[0], temp);
  682. VectorCopy(nf->planepts[1], nf->planepts[0]);
  683. VectorCopy(temp, nf->planepts[1]);
  684. nf->texdef = b->brush_faces->texdef;
  685. nf->brushprimit_texdef = b->brush_faces->brushprimit_texdef;
  686. nf->next = b->brush_faces;
  687. b->brush_faces = nf;
  688. Brush_Build(b);
  689. Brush_RemoveEmptyFaces(b);
  690. if (!b->brush_faces) { // completely clipped away
  691. Brush_Free(b);
  692. *front = NULL;
  693. }
  694. else {
  695. Entity_LinkBrush(in->owner, b);
  696. *front = b;
  697. }
  698. }
  699. /*
  700. ================
  701. Brush_BestSplitFace
  702. returns the best face to split the brush with. return NULL if the brush is convex
  703. ================
  704. */
  705. face_t *Brush_BestSplitFace(brush_t *b) {
  706. face_t *face, *f, *bestface;
  707. idWinding *front, *back;
  708. int splits, tinywindings, value, bestvalue;
  709. bestvalue = 999999;
  710. bestface = NULL;
  711. for ( face = b->brush_faces; face; face = face->next ) {
  712. splits = 0;
  713. tinywindings = 0;
  714. for ( f = b->brush_faces; f; f = f->next ) {
  715. if ( f == face ) {
  716. continue;
  717. }
  718. f->face_winding->Split( face->plane, 0.1f, &front, &back );
  719. if ( !front ) {
  720. delete back;
  721. }
  722. else if ( !back ) {
  723. delete front;
  724. }
  725. else {
  726. splits++;
  727. if ( front->IsTiny() ) {
  728. tinywindings++;
  729. }
  730. if ( back->IsTiny() ) {
  731. tinywindings++;
  732. }
  733. delete front;
  734. delete back;
  735. }
  736. }
  737. if ( splits ) {
  738. value = splits + 50 * tinywindings;
  739. if ( value < bestvalue ) {
  740. bestvalue = value;
  741. bestface = face;
  742. }
  743. }
  744. }
  745. return bestface;
  746. }
  747. /*
  748. ================
  749. Brush_MakeConvexBrushes
  750. MrE FIXME: this doesn't work because the old Brush_SplitBrushByFace is used
  751. Turns the brush into a minimal number of convex brushes.
  752. If the input brush is convex then it will be returned. Otherwise the input
  753. brush will be freed.
  754. NOTE: the input brush should have windings for the faces.
  755. ================
  756. */
  757. brush_t *Brush_MakeConvexBrushes(brush_t *b) {
  758. brush_t *front, *back, *end;
  759. face_t *face;
  760. b->next = NULL;
  761. face = Brush_BestSplitFace(b);
  762. if (!face) {
  763. return b;
  764. }
  765. Brush_SplitBrushByFace(b, face, &front, &back);
  766. // this should never happen
  767. if (!front && !back) {
  768. return b;
  769. }
  770. Brush_Free(b);
  771. if (!front) {
  772. return Brush_MakeConvexBrushes(back);
  773. }
  774. b = Brush_MakeConvexBrushes(front);
  775. if (back) {
  776. for (end = b; end->next; end = end->next);
  777. end->next = Brush_MakeConvexBrushes(back);
  778. }
  779. return b;
  780. }
  781. /*
  782. ================
  783. Brush_Convex
  784. returns true if the brush is convex
  785. ================
  786. */
  787. int Brush_Convex(brush_t *b) {
  788. face_t *face1, *face2;
  789. for (face1 = b->brush_faces; face1; face1 = face1->next) {
  790. if (!face1->face_winding) {
  791. continue;
  792. }
  793. for (face2 = b->brush_faces; face2; face2 = face2->next) {
  794. if (face1 == face2) {
  795. continue;
  796. }
  797. if (!face2->face_winding) {
  798. continue;
  799. }
  800. if ( face1->face_winding->PlanesConcave( *face2->face_winding,
  801. face1->plane.Normal(), face2->plane.Normal(), -face1->plane[3], -face2->plane[3] ) ) {
  802. return false;
  803. }
  804. }
  805. }
  806. return true;
  807. }
  808. /*
  809. ================
  810. Brush_MoveVertexes
  811. The input brush must be convex.
  812. The input brush must have face windings.
  813. The output brush will be convex.
  814. Returns true if the WHOLE vertex movement is performed.
  815. ================
  816. */
  817. #define MAX_MOVE_FACES 64
  818. #define TINY_EPSILON 0.0325f
  819. int Brush_MoveVertex(brush_t *b, const idVec3 &vertex, const idVec3 &delta, idVec3 &end, bool bSnap) {
  820. face_t *f, *face, *newface, *lastface, *nextface;
  821. face_t *movefaces[MAX_MOVE_FACES];
  822. int movefacepoints[MAX_MOVE_FACES];
  823. idWinding *w, tmpw(3);
  824. idVec3 start, mid;
  825. idPlane plane;
  826. int i, j, k, nummovefaces, result, done;
  827. float dot, front, back, frac, smallestfrac;
  828. result = true;
  829. tmpw.SetNumPoints( 3 );
  830. VectorCopy(vertex, start);
  831. VectorAdd(vertex, delta, end);
  832. // snap or not?
  833. //
  834. if (bSnap) {
  835. for (i = 0; i < 3; i++) {
  836. end[i] = floor( end[i] / 0.125f + 0.5f ) * 0.125f;
  837. }
  838. }
  839. VectorCopy(end, mid);
  840. // if the start and end are the same
  841. if ( start.Compare( end, TINY_EPSILON ) ) {
  842. return false;
  843. }
  844. // the end point may not be the same as another vertex
  845. for ( face = b->brush_faces; face; face = face->next ) {
  846. w = face->face_winding;
  847. if (!w) {
  848. continue;
  849. }
  850. for (i = 0; i < w->GetNumPoints(); i++) {
  851. if ( end.Compare( (*w)[i].ToVec3(), TINY_EPSILON ) ) {
  852. VectorCopy(vertex, end);
  853. return false;
  854. }
  855. }
  856. }
  857. done = false;
  858. while (!done) {
  859. //
  860. // chop off triangles from all brush faces that use the to be moved vertex store
  861. // pointers to these chopped off triangles in movefaces[]
  862. //
  863. nummovefaces = 0;
  864. for (face = b->brush_faces; face; face = face->next) {
  865. w = face->face_winding;
  866. if (!w) {
  867. continue;
  868. }
  869. for (i = 0; i < w->GetNumPoints(); i++) {
  870. if ( start.Compare( (*w)[i].ToVec3(), TINY_EPSILON ) ) {
  871. if (face->face_winding->GetNumPoints() <= 3) {
  872. movefacepoints[nummovefaces] = i;
  873. movefaces[nummovefaces++] = face;
  874. break;
  875. }
  876. dot = DotProduct(end, face->plane) + face->plane[3];
  877. // if the end point is in front of the face plane
  878. //if ( dot > 0.1f ) {
  879. if ( dot > TINY_EPSILON ) {
  880. // fanout triangle subdivision
  881. for (k = i; k < i + w->GetNumPoints() - 3; k++) {
  882. VectorCopy((*w)[i], tmpw[0]);
  883. VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[1]);
  884. VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[2]);
  885. newface = Face_Clone(face);
  886. // get the original
  887. for (f = face; f->original; f = f->original) {};
  888. newface->original = f;
  889. // store the new winding
  890. if (newface->face_winding) {
  891. delete newface->face_winding;
  892. }
  893. newface->face_winding = tmpw.Copy();
  894. // get the texture
  895. newface->d_texture = Texture_ForName(newface->texdef.name);
  896. // add the face to the brush
  897. newface->next = b->brush_faces;
  898. b->brush_faces = newface;
  899. // add this new triangle to the move faces
  900. movefacepoints[nummovefaces] = 0;
  901. movefaces[nummovefaces++] = newface;
  902. }
  903. // give the original face a new winding
  904. VectorCopy((*w)[(i - 2 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[0]);
  905. VectorCopy((*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[1]);
  906. VectorCopy((*w)[i], tmpw[2]);
  907. delete face->face_winding;
  908. face->face_winding = tmpw.Copy();
  909. // add the original face to the move faces
  910. movefacepoints[nummovefaces] = 2;
  911. movefaces[nummovefaces++] = face;
  912. }
  913. else {
  914. // chop a triangle off the face
  915. VectorCopy((*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()], tmpw[0]);
  916. VectorCopy((*w)[i], tmpw[1]);
  917. VectorCopy((*w)[(i + 1) % w->GetNumPoints()], tmpw[2]);
  918. // remove the point from the face winding
  919. w->RemovePoint( i );
  920. // get texture crap right
  921. Face_SetColor(b, face, 1.0);
  922. for (j = 0; j < w->GetNumPoints(); j++) {
  923. EmitTextureCoordinates( (*w)[j], face->d_texture, face );
  924. }
  925. // make a triangle face
  926. newface = Face_Clone(face);
  927. // get the original
  928. for (f = face; f->original; f = f->original) {};
  929. newface->original = f;
  930. // store the new winding
  931. if (newface->face_winding) {
  932. delete newface->face_winding;
  933. }
  934. newface->face_winding = tmpw.Copy();
  935. // get the texture
  936. newface->d_texture = Texture_ForName(newface->texdef.name);
  937. // add the face to the brush
  938. newface->next = b->brush_faces;
  939. b->brush_faces = newface;
  940. movefacepoints[nummovefaces] = 1;
  941. movefaces[nummovefaces++] = newface;
  942. }
  943. break;
  944. }
  945. }
  946. }
  947. //
  948. // now movefaces contains pointers to triangle faces that contain the to be moved
  949. // vertex
  950. //
  951. done = true;
  952. VectorCopy(end, mid);
  953. smallestfrac = 1;
  954. for (face = b->brush_faces; face; face = face->next) {
  955. // check if there is a move face that has this face as the original
  956. for (i = 0; i < nummovefaces; i++) {
  957. if (movefaces[i]->original == face) {
  958. break;
  959. }
  960. }
  961. if (i >= nummovefaces) {
  962. continue;
  963. }
  964. // check if the original is not a move face itself
  965. for (j = 0; j < nummovefaces; j++) {
  966. if (face == movefaces[j]) {
  967. break;
  968. }
  969. }
  970. // if the original is not a move face itself
  971. if (j >= nummovefaces) {
  972. memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane));
  973. }
  974. else {
  975. k = movefacepoints[j];
  976. w = movefaces[j]->face_winding;
  977. VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[0]);
  978. VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[1]);
  979. k = movefacepoints[i];
  980. w = movefaces[i]->face_winding;
  981. VectorCopy((*w)[(k + 1) % w->GetNumPoints()], tmpw[2]);
  982. if ( !plane.FromPoints( tmpw[0].ToVec3(), tmpw[1].ToVec3(), tmpw[2].ToVec3(), false ) ) {
  983. VectorCopy((*w)[(k + 2) % w->GetNumPoints()], tmpw[2]);
  984. if ( !plane.FromPoints( tmpw[0].ToVec3(), tmpw[1].ToVec3(), tmpw[2].ToVec3() ), false ) {
  985. // this should never happen otherwise the face merge did
  986. // a crappy job a previous pass
  987. continue;
  988. }
  989. }
  990. plane[0] = -plane[0];
  991. plane[1] = -plane[1];
  992. plane[2] = -plane[2];
  993. plane[3] = -plane[3];
  994. }
  995. // now we've got the plane to check against
  996. front = DotProduct(start, plane) + plane[3];
  997. back = DotProduct(end, plane) + plane[3];
  998. // if the whole move is at one side of the plane
  999. if (front < TINY_EPSILON && back < TINY_EPSILON) {
  1000. continue;
  1001. }
  1002. if (front > -TINY_EPSILON && back > -TINY_EPSILON) {
  1003. continue;
  1004. }
  1005. // if there's no movement orthogonal to this plane at all
  1006. if ( idMath::Fabs(front - back) < 0.001f ) {
  1007. continue;
  1008. }
  1009. // ok first only move till the plane is hit
  1010. frac = front / (front - back);
  1011. if (frac < smallestfrac) {
  1012. mid[0] = start[0] + (end[0] - start[0]) * frac;
  1013. mid[1] = start[1] + (end[1] - start[1]) * frac;
  1014. mid[2] = start[2] + (end[2] - start[2]) * frac;
  1015. smallestfrac = frac;
  1016. }
  1017. done = false;
  1018. }
  1019. // move the vertex
  1020. for (i = 0; i < nummovefaces; i++) {
  1021. // move vertex to end position
  1022. VectorCopy( mid, (*movefaces[i]->face_winding)[movefacepoints[i]] );
  1023. // create new face plane
  1024. for (j = 0; j < 3; j++) {
  1025. VectorCopy( (*movefaces[i]->face_winding)[j], movefaces[i]->planepts[j] );
  1026. }
  1027. Face_MakePlane( movefaces[i] );
  1028. if ( movefaces[i]->plane.Normal().Length() < TINY_EPSILON ) {
  1029. result = false;
  1030. }
  1031. }
  1032. // if the brush is no longer convex
  1033. if (!result || !Brush_Convex(b)) {
  1034. for (i = 0; i < nummovefaces; i++) {
  1035. // move the vertex back to the initial position
  1036. VectorCopy( start, (*movefaces[i]->face_winding)[movefacepoints[i]] );
  1037. // create new face plane
  1038. for (j = 0; j < 3; j++) {
  1039. VectorCopy( (*movefaces[i]->face_winding)[j], movefaces[i]->planepts[j] );
  1040. }
  1041. Face_MakePlane(movefaces[i]);
  1042. }
  1043. result = false;
  1044. VectorCopy(start, end);
  1045. done = true;
  1046. }
  1047. else {
  1048. VectorCopy(mid, start);
  1049. }
  1050. // get texture crap right
  1051. for (i = 0; i < nummovefaces; i++) {
  1052. Face_SetColor( b, movefaces[i], 1.0f );
  1053. for (j = 0; j < movefaces[i]->face_winding->GetNumPoints(); j++) {
  1054. EmitTextureCoordinates( (*movefaces[i]->face_winding)[j], movefaces[i]->d_texture, movefaces[i] );
  1055. }
  1056. }
  1057. // now try to merge faces with their original faces
  1058. lastface = NULL;
  1059. for (face = b->brush_faces; face; face = nextface) {
  1060. nextface = face->next;
  1061. if (!face->original) {
  1062. lastface = face;
  1063. continue;
  1064. }
  1065. if ( !face->plane.Compare( face->original->plane, 0.0001f ) ) {
  1066. lastface = face;
  1067. continue;
  1068. }
  1069. w = face->face_winding->TryMerge( *face->original->face_winding, face->plane.Normal(), true );
  1070. if (!w) {
  1071. lastface = face;
  1072. continue;
  1073. }
  1074. delete face->original->face_winding;
  1075. face->original->face_winding = w;
  1076. // get texture crap right
  1077. Face_SetColor( b, face->original, 1.0f );
  1078. for (j = 0; j < face->original->face_winding->GetNumPoints(); j++) {
  1079. EmitTextureCoordinates( (*face->original->face_winding)[j], face->original->d_texture, face->original);
  1080. }
  1081. // remove the face that was merged with the original
  1082. if (lastface) {
  1083. lastface->next = face->next;
  1084. }
  1085. else {
  1086. b->brush_faces = face->next;
  1087. }
  1088. Face_Free(face);
  1089. }
  1090. }
  1091. return result;
  1092. }
  1093. /*
  1094. ================
  1095. Brush_InsertVertexBetween
  1096. Adds a vertex to the brush windings between the given two points.
  1097. ================
  1098. */
  1099. int Brush_InsertVertexBetween(brush_t *b, idVec3 p1, idVec3 p2) {
  1100. face_t *face;
  1101. idWinding *w, *neww;
  1102. idVec3 point;
  1103. int i, insert;
  1104. if ( p1.Compare( p2, TINY_EPSILON ) ) {
  1105. return false;
  1106. }
  1107. VectorAdd( p1, p2, point );
  1108. VectorScale( point, 0.5f, point );
  1109. insert = false;
  1110. // the end point may not be the same as another vertex
  1111. for (face = b->brush_faces; face; face = face->next) {
  1112. w = face->face_winding;
  1113. if (!w) {
  1114. continue;
  1115. }
  1116. neww = NULL;
  1117. for (i = 0; i < w->GetNumPoints(); i++) {
  1118. if (! p1.Compare((*w)[i].ToVec3(), TINY_EPSILON)) {
  1119. continue;
  1120. }
  1121. if ( p2.Compare( (*w)[(i + 1) % w->GetNumPoints()].ToVec3(), TINY_EPSILON ) ) {
  1122. neww = new idWinding( *w );
  1123. neww->InsertPoint( point, (i + 1) % w->GetNumPoints() );
  1124. break;
  1125. }
  1126. else if ( p2.Compare( (*w)[(i - 1 + w->GetNumPoints()) % w->GetNumPoints()].ToVec3(), TINY_EPSILON ) ) {
  1127. neww = new idWinding( *w );
  1128. neww->InsertPoint( point, i );
  1129. break;
  1130. }
  1131. }
  1132. if (neww) {
  1133. delete face->face_winding;
  1134. face->face_winding = neww;
  1135. insert = true;
  1136. }
  1137. }
  1138. return insert;
  1139. }
  1140. /*
  1141. ================
  1142. Brush_ResetFaceOriginals
  1143. reset points to original faces to NULL
  1144. ================
  1145. */
  1146. void Brush_ResetFaceOriginals(brush_t *b) {
  1147. face_t *face;
  1148. for (face = b->brush_faces; face; face = face->next) {
  1149. face->original = NULL;
  1150. }
  1151. }
  1152. /*
  1153. ================
  1154. Brush_Parse
  1155. The brush is NOT linked to any list
  1156. FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3"
  1157. run before each face parsing. It works, but it's a performance hit
  1158. ================
  1159. */
  1160. brush_t *Brush_Parse(idVec3 origin) {
  1161. brush_t *b;
  1162. face_t *f;
  1163. int i, j;
  1164. idVec3 useOrigin = origin;
  1165. g_qeglobals.d_parsed_brushes++;
  1166. b = Brush_Alloc();
  1167. do {
  1168. if (!GetToken(true)) {
  1169. break;
  1170. }
  1171. if (!strcmp(token, "}")) {
  1172. break;
  1173. }
  1174. // handle "Brush" primitive
  1175. if ( idStr::Icmp(token, "brushDef") == 0 || idStr::Icmp(token, "brushDef2") == 0 || idStr::Icmp(token, "brushDef3") == 0 ) {
  1176. // Timo parsing new brush format
  1177. g_qeglobals.bPrimitBrushes = true;
  1178. // check the map is not mixing the two kinds of brushes
  1179. if (g_qeglobals.m_bBrushPrimitMode) {
  1180. if (g_qeglobals.bOldBrushes) {
  1181. common->Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
  1182. }
  1183. }
  1184. else {
  1185. // ++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
  1186. common->Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
  1187. }
  1188. bool newFormat = false;
  1189. if ( idStr::Icmp(token, "brushDef2") == 0 ) {
  1190. newFormat = true;
  1191. // useOrigin.Zero();
  1192. }
  1193. else if ( idStr::Icmp(token, "brushDef3") == 0 ) {
  1194. newFormat = true;
  1195. }
  1196. BrushPrimit_Parse(b, newFormat, useOrigin);
  1197. if (newFormat) {
  1198. //Brush_BuildWindings(b, true, true, false, false);
  1199. }
  1200. if (b == NULL) {
  1201. Warning("parsing brush primitive");
  1202. return NULL;
  1203. }
  1204. else {
  1205. continue;
  1206. }
  1207. }
  1208. if ( idStr::Icmp(token, "patchDef2") == 0 || idStr::Icmp(token, "patchDef3") == 0 ) {
  1209. Brush_Free(b);
  1210. // double string compare but will go away soon
  1211. b = Patch_Parse( idStr::Icmp(token, "patchDef2") == 0 );
  1212. if (b == NULL) {
  1213. Warning("parsing patch/brush");
  1214. return NULL;
  1215. }
  1216. else {
  1217. continue;
  1218. }
  1219. // handle inline patch
  1220. }
  1221. else {
  1222. // Timo parsing old brush format
  1223. g_qeglobals.bOldBrushes = true;
  1224. if (g_qeglobals.m_bBrushPrimitMode) {
  1225. // check the map is not mixing the two kinds of brushes
  1226. if (g_qeglobals.bPrimitBrushes) {
  1227. common->Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
  1228. }
  1229. // set the "need" conversion flag
  1230. g_qeglobals.bNeedConvert = true;
  1231. }
  1232. f = Face_Alloc();
  1233. //
  1234. // add the brush to the end of the chain, so loading and saving a map doesn't
  1235. // reverse the order
  1236. //
  1237. f->next = NULL;
  1238. if (!b->brush_faces) {
  1239. b->brush_faces = f;
  1240. }
  1241. else {
  1242. face_t *scan;
  1243. for (scan = b->brush_faces; scan->next; scan = scan->next)
  1244. ;
  1245. scan->next = f;
  1246. }
  1247. // read the three point plane definition
  1248. for (i = 0; i < 3; i++) {
  1249. if (i != 0) {
  1250. GetToken(true);
  1251. }
  1252. if (strcmp(token, "(")) {
  1253. Warning("parsing brush");
  1254. return NULL;
  1255. }
  1256. for (j = 0; j < 3; j++) {
  1257. GetToken(false);
  1258. f->planepts[i][j] = atof(token);
  1259. }
  1260. GetToken(false);
  1261. if (strcmp(token, ")")) {
  1262. Warning("parsing brush");
  1263. return NULL;
  1264. }
  1265. }
  1266. }
  1267. // read the texturedef
  1268. GetToken(false);
  1269. f->texdef.SetName(token);
  1270. if (token[0] == '(') {
  1271. int i = 32;
  1272. }
  1273. GetToken(false);
  1274. f->texdef.shift[0] = atoi(token);
  1275. GetToken(false);
  1276. f->texdef.shift[1] = atoi(token);
  1277. GetToken(false);
  1278. f->texdef.rotate = atoi(token);
  1279. GetToken(false);
  1280. f->texdef.scale[0] = atof(token);
  1281. GetToken(false);
  1282. f->texdef.scale[1] = atof(token);
  1283. // the flags and value field aren't necessarily present
  1284. f->d_texture = Texture_ForName(f->texdef.name);
  1285. //
  1286. // FIXME: idMaterial f->texdef.flags = f->d_texture->flags; f->texdef.value =
  1287. // f->d_texture->value; f->texdef.contents = f->d_texture->contents;
  1288. //
  1289. if (TokenAvailable()) {
  1290. GetToken(false);
  1291. GetToken(false);
  1292. GetToken(false);
  1293. f->texdef.value = atoi(token);
  1294. }
  1295. } while (1);
  1296. return b;
  1297. }
  1298. /*
  1299. ================
  1300. QERApp_MapPrintf_FILE
  1301. callback for surface properties plugin must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
  1302. carefully initialize !
  1303. ================
  1304. */
  1305. FILE *g_File;
  1306. void WINAPI QERApp_MapPrintf_FILE(char *text, ...) {
  1307. va_list argptr;
  1308. char buf[32768];
  1309. va_start(argptr, text);
  1310. vsprintf(buf, text, argptr);
  1311. va_end(argptr);
  1312. fprintf(g_File, buf);
  1313. }
  1314. /*
  1315. ================
  1316. Brush_SetEpair
  1317. sets an epair for the given brush
  1318. ================
  1319. */
  1320. void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue) {
  1321. if (g_qeglobals.m_bBrushPrimitMode) {
  1322. if (b->pPatch) {
  1323. Patch_SetEpair(b->pPatch, pKey, pValue);
  1324. }
  1325. else {
  1326. b->epairs.Set(pKey, pValue);
  1327. }
  1328. }
  1329. else {
  1330. Sys_Status("Can only set key/values in Brush primitive mode\n");
  1331. }
  1332. }
  1333. /*
  1334. ================
  1335. Brush_GetKeyValue
  1336. ================
  1337. */
  1338. const char *Brush_GetKeyValue(brush_t *b, const char *pKey) {
  1339. if (g_qeglobals.m_bBrushPrimitMode) {
  1340. if (b->pPatch) {
  1341. return Patch_GetKeyValue(b->pPatch, pKey);
  1342. }
  1343. else {
  1344. return b->epairs.GetString(pKey);
  1345. }
  1346. }
  1347. else {
  1348. Sys_Status("Can only set brush/patch key/values in Brush primitive mode\n");
  1349. }
  1350. return "";
  1351. }
  1352. /*
  1353. ================
  1354. Brush_Write
  1355. save all brushes as Brush primitive format
  1356. ================
  1357. */
  1358. void Brush_Write(brush_t *b, FILE *f, const idVec3 &origin, bool newFormat) {
  1359. face_t *fa;
  1360. char *pname;
  1361. int i;
  1362. if (b->pPatch) {
  1363. Patch_Write(b->pPatch, f);
  1364. return;
  1365. }
  1366. if (g_qeglobals.m_bBrushPrimitMode) {
  1367. // save brush primitive format
  1368. if (newFormat) {
  1369. WriteFileString(f, "{\nbrushDef3\n{\n");
  1370. }
  1371. else {
  1372. WriteFileString(f, "{\nbrushDef\n{\n");
  1373. }
  1374. // brush epairs
  1375. int count = b->epairs.GetNumKeyVals();
  1376. for (int j = 0; j < count; j++) {
  1377. WriteFileString(f, "\"%s\" \"%s\"\n", b->epairs.GetKeyVal(j)->GetKey().c_str(), b->epairs.GetKeyVal(j)->GetValue().c_str());
  1378. }
  1379. for (fa = b->brush_faces; fa; fa = fa->next) {
  1380. // save planepts
  1381. if (newFormat) {
  1382. idPlane plane;
  1383. if (fa->dirty) {
  1384. fa->planepts[0] -= origin;
  1385. fa->planepts[1] -= origin;
  1386. fa->planepts[2] -= origin;
  1387. plane.FromPoints( fa->planepts[0], fa->planepts[1], fa->planepts[2], false );
  1388. fa->planepts[0] += origin;
  1389. fa->planepts[1] += origin;
  1390. fa->planepts[2] += origin;
  1391. } else {
  1392. plane = fa->originalPlane;
  1393. }
  1394. WriteFileString(f, " ( ");
  1395. for (i = 0; i < 4; i++) {
  1396. if (plane[i] == (int)plane[i]) {
  1397. WriteFileString(f, "%i ", (int)plane[i]);
  1398. }
  1399. else {
  1400. WriteFileString(f, "%f ", plane[i]);
  1401. }
  1402. }
  1403. WriteFileString(f, ") ");
  1404. }
  1405. else {
  1406. for (i = 0; i < 3; i++) {
  1407. WriteFileString(f, "( ");
  1408. for (int j = 0; j < 3; j++) {
  1409. if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
  1410. WriteFileString(f, "%i ", static_cast<int>(fa->planepts[i][j]));
  1411. }
  1412. else {
  1413. WriteFileString(f, "%f ", fa->planepts[i][j]);
  1414. }
  1415. }
  1416. WriteFileString(f, ") ");
  1417. }
  1418. }
  1419. // save texture coordinates
  1420. WriteFileString(f, "( ( ");
  1421. for (i = 0; i < 3; i++) {
  1422. if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i])) {
  1423. WriteFileString(f, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
  1424. }
  1425. else {
  1426. WriteFileString(f, "%f ", fa->brushprimit_texdef.coords[0][i]);
  1427. }
  1428. }
  1429. WriteFileString(f, ") ( ");
  1430. for (i = 0; i < 3; i++) {
  1431. if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i])) {
  1432. WriteFileString(f, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
  1433. }
  1434. else {
  1435. WriteFileString(f, "%f ", fa->brushprimit_texdef.coords[1][i]);
  1436. }
  1437. }
  1438. WriteFileString(f, ") ) ");
  1439. char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "notexture";
  1440. WriteFileString(f, "\"%s\" ", pName);
  1441. WriteFileString(f, "%i %i %i\n", 0, 0, 0);
  1442. }
  1443. WriteFileString(f, "}\n}\n");
  1444. }
  1445. else {
  1446. WriteFileString(f, "{\n");
  1447. for (fa = b->brush_faces; fa; fa = fa->next) {
  1448. for (i = 0; i < 3; i++) {
  1449. WriteFileString(f, "( ");
  1450. for (int j = 0; j < 3; j++) {
  1451. if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
  1452. WriteFileString(f, "%i ", static_cast<int>(fa->planepts[i][j]));
  1453. }
  1454. else {
  1455. WriteFileString(f, "%f ", fa->planepts[i][j]);
  1456. }
  1457. }
  1458. WriteFileString(f, ") ");
  1459. }
  1460. pname = fa->texdef.name;
  1461. if (pname[0] == 0) {
  1462. pname = "unnamed";
  1463. }
  1464. WriteFileString
  1465. (
  1466. f,
  1467. "%s %i %i %i ",
  1468. pname,
  1469. (int)fa->texdef.shift[0],
  1470. (int)fa->texdef.shift[1],
  1471. (int)fa->texdef.rotate
  1472. );
  1473. if (fa->texdef.scale[0] == (int)fa->texdef.scale[0]) {
  1474. WriteFileString(f, "%i ", (int)fa->texdef.scale[0]);
  1475. }
  1476. else {
  1477. WriteFileString(f, "%f ", (float)fa->texdef.scale[0]);
  1478. }
  1479. if (fa->texdef.scale[1] == (int)fa->texdef.scale[1]) {
  1480. WriteFileString(f, "%i", (int)fa->texdef.scale[1]);
  1481. }
  1482. else {
  1483. WriteFileString(f, "%f", (float)fa->texdef.scale[1]);
  1484. }
  1485. WriteFileString(f, " %i %i %i",0, 0, 0);
  1486. WriteFileString(f, "\n");
  1487. }
  1488. WriteFileString(f, "}\n");
  1489. }
  1490. }
  1491. /*
  1492. ================
  1493. QERApp_MapPrintf_MEMFILE
  1494. callback for surface properties plugin must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
  1495. carefully initialize !
  1496. ================
  1497. */
  1498. CMemFile *g_pMemFile;
  1499. void WINAPI QERApp_MapPrintf_MEMFILE(char *text, ...) {
  1500. va_list argptr;
  1501. char buf[32768];
  1502. va_start(argptr, text);
  1503. vsprintf(buf, text, argptr);
  1504. va_end(argptr);
  1505. MemFile_fprintf(g_pMemFile, buf);
  1506. }
  1507. /*
  1508. ================
  1509. Brush_Write
  1510. save all brushes as Brush primitive format to a CMemFile*
  1511. ================
  1512. */
  1513. void Brush_Write(brush_t *b, CMemFile *pMemFile, const idVec3 &origin, bool newFormat) {
  1514. face_t *fa;
  1515. char *pname;
  1516. int i;
  1517. if (b->pPatch) {
  1518. Patch_Write(b->pPatch, pMemFile);
  1519. return;
  1520. }
  1521. if (g_qeglobals.m_bBrushPrimitMode) {
  1522. // brush primitive format
  1523. if (newFormat) {
  1524. MemFile_fprintf(pMemFile, "{\nBrushDef2\n{\n");
  1525. }
  1526. else {
  1527. MemFile_fprintf(pMemFile, "{\nBrushDef\n{\n");
  1528. }
  1529. // brush epairs
  1530. // brush epairs
  1531. int count = b->epairs.GetNumKeyVals();
  1532. for (int j = 0; j < count; j++) {
  1533. MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", b->epairs.GetKeyVal(j)->GetKey().c_str(), b->epairs.GetKeyVal(j)->GetValue().c_str());
  1534. }
  1535. for (fa = b->brush_faces; fa; fa = fa->next) {
  1536. if (newFormat) {
  1537. // save planepts
  1538. idPlane plane;
  1539. if (fa->dirty) {
  1540. fa->planepts[0] -= origin;
  1541. fa->planepts[1] -= origin;
  1542. fa->planepts[2] -= origin;
  1543. plane.FromPoints( fa->planepts[0], fa->planepts[1], fa->planepts[2], false );
  1544. fa->planepts[0] += origin;
  1545. fa->planepts[1] += origin;
  1546. fa->planepts[2] += origin;
  1547. } else {
  1548. plane = fa->originalPlane;
  1549. }
  1550. MemFile_fprintf(pMemFile, " ( ");
  1551. for (i = 0; i < 4; i++) {
  1552. if (plane[i] == (int)plane[i]) {
  1553. MemFile_fprintf(pMemFile, "%i ", (int)plane[i]);
  1554. }
  1555. else {
  1556. MemFile_fprintf(pMemFile, "%f ", plane[i]);
  1557. }
  1558. }
  1559. MemFile_fprintf(pMemFile, ") ");
  1560. }
  1561. else {
  1562. for (i = 0; i < 3; i++) {
  1563. MemFile_fprintf(pMemFile, "( ");
  1564. for (int j = 0; j < 3; j++) {
  1565. if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
  1566. MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
  1567. }
  1568. else {
  1569. MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
  1570. }
  1571. }
  1572. MemFile_fprintf(pMemFile, ") ");
  1573. }
  1574. }
  1575. // save texture coordinates
  1576. MemFile_fprintf(pMemFile, "( ( ");
  1577. for (i = 0; i < 3; i++) {
  1578. if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i])) {
  1579. MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
  1580. }
  1581. else {
  1582. MemFile_fprintf(pMemFile, "%f ", fa->brushprimit_texdef.coords[0][i]);
  1583. }
  1584. }
  1585. MemFile_fprintf(pMemFile, ") ( ");
  1586. for (i = 0; i < 3; i++) {
  1587. if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i])) {
  1588. MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
  1589. }
  1590. else {
  1591. MemFile_fprintf(pMemFile, "%f ", fa->brushprimit_texdef.coords[1][i]);
  1592. }
  1593. }
  1594. MemFile_fprintf(pMemFile, ") ) ");
  1595. // save texture attribs
  1596. char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
  1597. MemFile_fprintf(pMemFile, "\"%s\" ", pName);
  1598. MemFile_fprintf(pMemFile, "%i %i %i\n", 0, 0, 0);
  1599. }
  1600. MemFile_fprintf(pMemFile, "}\n}\n");
  1601. }
  1602. else {
  1603. // old brushes format also handle surface properties plugin
  1604. MemFile_fprintf(pMemFile, "{\n");
  1605. for (fa = b->brush_faces; fa; fa = fa->next) {
  1606. for (i = 0; i < 3; i++) {
  1607. MemFile_fprintf(pMemFile, "( ");
  1608. for (int j = 0; j < 3; j++) {
  1609. if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j])) {
  1610. MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
  1611. }
  1612. else {
  1613. MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
  1614. }
  1615. }
  1616. MemFile_fprintf(pMemFile, ") ");
  1617. }
  1618. pname = fa->texdef.name;
  1619. if (pname[0] == 0) {
  1620. pname = "unnamed";
  1621. }
  1622. MemFile_fprintf
  1623. (
  1624. pMemFile,
  1625. "%s %i %i %i ",
  1626. pname,
  1627. (int)fa->texdef.shift[0],
  1628. (int)fa->texdef.shift[1],
  1629. (int)fa->texdef.rotate
  1630. );
  1631. if (fa->texdef.scale[0] == (int)fa->texdef.scale[0]) {
  1632. MemFile_fprintf(pMemFile, "%i ", (int)fa->texdef.scale[0]);
  1633. }
  1634. else {
  1635. MemFile_fprintf(pMemFile, "%f ", (float)fa->texdef.scale[0]);
  1636. }
  1637. if (fa->texdef.scale[1] == (int)fa->texdef.scale[1]) {
  1638. MemFile_fprintf(pMemFile, "%i", (int)fa->texdef.scale[1]);
  1639. }
  1640. else {
  1641. MemFile_fprintf(pMemFile, "%f", (float)fa->texdef.scale[1]);
  1642. }
  1643. MemFile_fprintf(pMemFile, " %i %i %i", 0, 0, 0);
  1644. MemFile_fprintf(pMemFile, "\n");
  1645. }
  1646. MemFile_fprintf(pMemFile, "}\n");
  1647. }
  1648. }
  1649. /*
  1650. ================
  1651. Brush_Create
  1652. Create non-textured blocks for entities The brush is NOT linked to any list
  1653. ================
  1654. */
  1655. brush_t *Brush_Create(idVec3 mins, idVec3 maxs, texdef_t *texdef) {
  1656. int i, j;
  1657. idVec3 pts[4][2];
  1658. face_t *f;
  1659. brush_t *b;
  1660. //
  1661. // brush primitive mode : convert texdef to brushprimit_texdef ? most of the time
  1662. // texdef is empty
  1663. //
  1664. for (i = 0; i < 3; i++) {
  1665. if (maxs[i] < mins[i]) {
  1666. Error("Brush_InitSolid: backwards");
  1667. }
  1668. }
  1669. b = Brush_Alloc();
  1670. pts[0][0][0] = mins[0];
  1671. pts[0][0][1] = mins[1];
  1672. pts[1][0][0] = mins[0];
  1673. pts[1][0][1] = maxs[1];
  1674. pts[2][0][0] = maxs[0];
  1675. pts[2][0][1] = maxs[1];
  1676. pts[3][0][0] = maxs[0];
  1677. pts[3][0][1] = mins[1];
  1678. for (i = 0; i < 4; i++) {
  1679. pts[i][0][2] = mins[2];
  1680. pts[i][1][0] = pts[i][0][0];
  1681. pts[i][1][1] = pts[i][0][1];
  1682. pts[i][1][2] = maxs[2];
  1683. }
  1684. for (i = 0; i < 4; i++) {
  1685. f = Face_Alloc();
  1686. f->texdef = *texdef;
  1687. f->next = b->brush_faces;
  1688. b->brush_faces = f;
  1689. j = (i + 1) % 4;
  1690. VectorCopy(pts[j][1], f->planepts[0]);
  1691. VectorCopy(pts[i][1], f->planepts[1]);
  1692. VectorCopy(pts[i][0], f->planepts[2]);
  1693. }
  1694. f = Face_Alloc();
  1695. f->texdef = *texdef;
  1696. f->next = b->brush_faces;
  1697. b->brush_faces = f;
  1698. VectorCopy(pts[0][1], f->planepts[0]);
  1699. VectorCopy(pts[1][1], f->planepts[1]);
  1700. VectorCopy(pts[2][1], f->planepts[2]);
  1701. f = Face_Alloc();
  1702. f->texdef = *texdef;
  1703. f->next = b->brush_faces;
  1704. b->brush_faces = f;
  1705. VectorCopy(pts[2][0], f->planepts[0]);
  1706. VectorCopy(pts[1][0], f->planepts[1]);
  1707. VectorCopy(pts[0][0], f->planepts[2]);
  1708. return b;
  1709. }
  1710. /*
  1711. =============
  1712. Brush_Scale
  1713. =============
  1714. */
  1715. void Brush_Scale(brush_t* b) {
  1716. for ( face_t *f = b->brush_faces; f; f = f->next ) {
  1717. for ( int i = 0; i < 3; i++ ) {
  1718. VectorScale( f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i] );
  1719. }
  1720. }
  1721. }
  1722. /*
  1723. ================
  1724. Brush_CreatePyramid
  1725. Create non-textured pyramid for light entities The brush is NOT linked to any list
  1726. ================
  1727. */
  1728. brush_t *Brush_CreatePyramid(idVec3 mins, idVec3 maxs, texdef_t *texdef) {
  1729. // ++timo handle new brush primitive ? return here ??
  1730. return Brush_Create(mins, maxs, texdef);
  1731. int i;
  1732. for (i = 0; i < 3; i++) {
  1733. if (maxs[i] < mins[i]) {
  1734. Error("Brush_InitSolid: backwards");
  1735. }
  1736. }
  1737. brush_t *b = Brush_Alloc();
  1738. idVec3 corners[4];
  1739. float fMid = idMath::Rint(mins[2] + (idMath::Rint((maxs[2] - mins[2]) / 2)));
  1740. corners[0][0] = mins[0];
  1741. corners[0][1] = mins[1];
  1742. corners[0][2] = fMid;
  1743. corners[1][0] = mins[0];
  1744. corners[1][1] = maxs[1];
  1745. corners[1][2] = fMid;
  1746. corners[2][0] = maxs[0];
  1747. corners[2][1] = maxs[1];
  1748. corners[2][2] = fMid;
  1749. corners[3][0] = maxs[0];
  1750. corners[3][1] = mins[1];
  1751. corners[3][2] = fMid;
  1752. idVec3 top, bottom;
  1753. top[0] = idMath::Rint(mins[0] + ((maxs[0] - mins[0]) / 2));
  1754. top[1] = idMath::Rint(mins[1] + ((maxs[1] - mins[1]) / 2));
  1755. top[2] = idMath::Rint(maxs[2]);
  1756. VectorCopy(top, bottom);
  1757. bottom[2] = mins[2];
  1758. // sides
  1759. for (i = 0; i < 4; i++) {
  1760. face_t *f = Face_Alloc();
  1761. f->texdef = *texdef;
  1762. f->next = b->brush_faces;
  1763. b->brush_faces = f;
  1764. int j = (i + 1) % 4;
  1765. VectorCopy(top, f->planepts[0]);
  1766. VectorCopy(corners[i], f->planepts[1]);
  1767. VectorCopy(corners[j], f->planepts[2]);
  1768. f = Face_Alloc();
  1769. f->texdef = *texdef;
  1770. f->next = b->brush_faces;
  1771. b->brush_faces = f;
  1772. VectorCopy(bottom, f->planepts[2]);
  1773. VectorCopy(corners[i], f->planepts[1]);
  1774. VectorCopy(corners[j], f->planepts[0]);
  1775. }
  1776. return b;
  1777. }
  1778. /*
  1779. ================
  1780. Brush_MakeSided
  1781. Makes the current brush have the given number of 2d sides
  1782. ================
  1783. */
  1784. void Brush_MakeSided(int sides) {
  1785. int i, axis;
  1786. idVec3 mins, maxs;
  1787. brush_t *b;
  1788. texdef_t *texdef;
  1789. face_t *f;
  1790. idVec3 mid;
  1791. float width;
  1792. float sv, cv;
  1793. if (sides < 3) {
  1794. Sys_Status("Bad sides number", 0);
  1795. return;
  1796. }
  1797. if (sides >= MAX_POINTS_ON_WINDING - 4) {
  1798. Sys_Status("too many sides.\n");
  1799. return;
  1800. }
  1801. if (!QE_SingleBrush()) {
  1802. Sys_Status("Must have a single brush selected", 0);
  1803. return;
  1804. }
  1805. b = selected_brushes.next;
  1806. VectorCopy(b->mins, mins);
  1807. VectorCopy(b->maxs, maxs);
  1808. texdef = &g_qeglobals.d_texturewin.texdef;
  1809. Brush_Free(b);
  1810. if (g_pParentWnd->ActiveXY()) {
  1811. switch (g_pParentWnd->ActiveXY()->GetViewType())
  1812. {
  1813. case XY:
  1814. axis = 2;
  1815. break;
  1816. case XZ:
  1817. axis = 1;
  1818. break;
  1819. case YZ:
  1820. axis = 0;
  1821. break;
  1822. }
  1823. }
  1824. else {
  1825. axis = 2;
  1826. }
  1827. // find center of brush
  1828. width = 8;
  1829. for (i = 0; i < 3; i++) {
  1830. mid[i] = (maxs[i] + mins[i]) * 0.5f;
  1831. if (i == axis) {
  1832. continue;
  1833. }
  1834. if ((maxs[i] - mins[i]) * 0.5f > width) {
  1835. width = (maxs[i] - mins[i]) * 0.5f;
  1836. }
  1837. }
  1838. b = Brush_Alloc();
  1839. // create top face
  1840. f = Face_Alloc();
  1841. f->texdef = *texdef;
  1842. f->next = b->brush_faces;
  1843. b->brush_faces = f;
  1844. f->planepts[2][(axis + 1) % 3] = mins[(axis + 1) % 3];
  1845. f->planepts[2][(axis + 2) % 3] = mins[(axis + 2) % 3];
  1846. f->planepts[2][axis] = maxs[axis];
  1847. f->planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3];
  1848. f->planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3];
  1849. f->planepts[1][axis] = maxs[axis];
  1850. f->planepts[0][(axis + 1) % 3] = maxs[(axis + 1) % 3];
  1851. f->planepts[0][(axis + 2) % 3] = maxs[(axis + 2) % 3];
  1852. f->planepts[0][axis] = maxs[axis];
  1853. // create bottom face
  1854. f = Face_Alloc();
  1855. f->texdef = *texdef;
  1856. f->next = b->brush_faces;
  1857. b->brush_faces = f;
  1858. f->planepts[0][(axis + 1) % 3] = mins[(axis + 1) % 3];
  1859. f->planepts[0][(axis + 2) % 3] = mins[(axis + 2) % 3];
  1860. f->planepts[0][axis] = mins[axis];
  1861. f->planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3];
  1862. f->planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3];
  1863. f->planepts[1][axis] = mins[axis];
  1864. f->planepts[2][(axis + 1) % 3] = maxs[(axis + 1) % 3];
  1865. f->planepts[2][(axis + 2) % 3] = maxs[(axis + 2) % 3];
  1866. f->planepts[2][axis] = mins[axis];
  1867. for (i = 0; i < sides; i++) {
  1868. f = Face_Alloc();
  1869. f->texdef = *texdef;
  1870. f->next = b->brush_faces;
  1871. b->brush_faces = f;
  1872. sv = sin(i * 3.14159265 * 2 / sides);
  1873. cv = cos(i * 3.14159265 * 2 / sides);
  1874. f->planepts[0][(axis + 1) % 3] = floor(mid[(axis + 1) % 3] + width * cv + 0.5f);
  1875. f->planepts[0][(axis + 2) % 3] = floor(mid[(axis + 2) % 3] + width * sv + 0.5f);
  1876. f->planepts[0][axis] = mins[axis];
  1877. f->planepts[1][(axis + 1) % 3] = f->planepts[0][(axis + 1) % 3];
  1878. f->planepts[1][(axis + 2) % 3] = f->planepts[0][(axis + 2) % 3];
  1879. f->planepts[1][axis] = maxs[axis];
  1880. f->planepts[2][(axis + 1) % 3] = floor(f->planepts[0][(axis + 1) % 3] - width * sv + 0.5f);
  1881. f->planepts[2][(axis + 2) % 3] = floor(f->planepts[0][(axis + 2) % 3] + width * cv + 0.5f);
  1882. f->planepts[2][axis] = maxs[axis];
  1883. }
  1884. Brush_AddToList(b, &selected_brushes);
  1885. Entity_LinkBrush(world_entity, b);
  1886. Brush_Build(b);
  1887. Sys_UpdateWindows(W_ALL);
  1888. }
  1889. /*
  1890. ================
  1891. Brush_Free
  1892. Frees the brush with all of its faces and display list.
  1893. Unlinks the brush from whichever chain it is in.
  1894. Decrements the owner entity's brushcount.
  1895. Removes owner entity if this was the last brush unless owner is the world.
  1896. Removes from groups
  1897. set bRemoveNode to false to avoid trying to delete the item in group view tree control
  1898. ================
  1899. */
  1900. void Brush_Free(brush_t *b, bool bRemoveNode) {
  1901. face_t *f, *next;
  1902. // free the patch if it's there
  1903. if ( b->pPatch ) {
  1904. Patch_Delete(b->pPatch);
  1905. }
  1906. // free faces
  1907. for ( f = b->brush_faces; f; f = next ) {
  1908. next = f->next;
  1909. Face_Free(f);
  1910. }
  1911. b->epairs.Clear();
  1912. // unlink from active/selected list
  1913. if ( b->next ) {
  1914. Brush_RemoveFromList(b);
  1915. }
  1916. // unlink from entity list
  1917. if ( b->onext ) {
  1918. Entity_UnlinkBrush(b);
  1919. }
  1920. delete b;
  1921. }
  1922. /*
  1923. ================
  1924. Face_MemorySize
  1925. returns the size in memory of the face
  1926. ================
  1927. */
  1928. int Face_MemorySize(face_t *f) {
  1929. int size = 0;
  1930. if ( f->face_winding ) {
  1931. size += sizeof( idWinding ) + f->face_winding->GetNumPoints() * sizeof( (f->face_winding)[0] );
  1932. }
  1933. size += sizeof( face_t );
  1934. return size;
  1935. }
  1936. /*
  1937. ================
  1938. Brush_MemorySize
  1939. returns the size in memory of the brush
  1940. ================
  1941. */
  1942. int Brush_MemorySize( brush_t *b ) {
  1943. face_t *f;
  1944. int size = 0;
  1945. if ( b->pPatch ) {
  1946. size += Patch_MemorySize( b->pPatch );
  1947. }
  1948. for ( f = b->brush_faces; f; f = f->next ) {
  1949. size += Face_MemorySize(f);
  1950. }
  1951. size += sizeof( brush_t ) + b->epairs.Size();
  1952. return size;
  1953. }
  1954. /*
  1955. ================
  1956. Brush_Clone
  1957. does not add the brush to any lists
  1958. ================
  1959. */
  1960. brush_t *Brush_Clone(brush_t *b) {
  1961. brush_t *n = NULL;
  1962. face_t *f, *nf;
  1963. if (b->pPatch) {
  1964. patchMesh_t *p = Patch_Duplicate(b->pPatch);
  1965. Brush_RemoveFromList(p->pSymbiot);
  1966. Entity_UnlinkBrush(p->pSymbiot);
  1967. n = p->pSymbiot;
  1968. }
  1969. else {
  1970. n = Brush_Alloc();
  1971. n->numberId = g_nBrushId++;
  1972. n->owner = b->owner;
  1973. n->lightColor = b->lightColor;
  1974. n->lightEnd = b->lightEnd;
  1975. n->lightOffset = b->lightOffset;
  1976. n->lightRadius = b->lightRadius;
  1977. n->lightRight = b->lightRight;
  1978. n->lightStart = b->lightStart;
  1979. n->lightTarget = b->lightTarget;
  1980. n->lightCenter = b->lightCenter;
  1981. n->lightTexture = b->lightTexture;
  1982. n->lightUp = b->lightUp;
  1983. n->modelHandle = b->modelHandle;
  1984. n->pointLight = b->pointLight;
  1985. for (f = b->brush_faces; f; f = f->next) {
  1986. nf = Face_Clone(f);
  1987. nf->next = n->brush_faces;
  1988. n->brush_faces = nf;
  1989. }
  1990. }
  1991. return n;
  1992. }
  1993. /*
  1994. ================
  1995. Brush_FullClone
  1996. Used by Undo.
  1997. Makes an exact copy of the brush.
  1998. Does NOT add the new brush to any lists.
  1999. ================
  2000. */
  2001. brush_t *Brush_FullClone(brush_t *b) {
  2002. brush_t *n = NULL;
  2003. face_t *f, *nf, *f2, *nf2;
  2004. int j;
  2005. if (b->pPatch) {
  2006. patchMesh_t *p = Patch_Duplicate(b->pPatch);
  2007. Brush_RemoveFromList(p->pSymbiot);
  2008. Entity_UnlinkBrush(p->pSymbiot);
  2009. n = p->pSymbiot;
  2010. n->owner = b->owner;
  2011. Brush_Build(n);
  2012. }
  2013. else {
  2014. n = Brush_Alloc();
  2015. n->numberId = g_nBrushId++;
  2016. n->owner = b->owner;
  2017. n->lightColor = b->lightColor;
  2018. n->lightEnd = b->lightEnd;
  2019. n->lightOffset = b->lightOffset;
  2020. n->lightRadius = b->lightRadius;
  2021. n->lightRight = b->lightRight;
  2022. n->lightStart = b->lightStart;
  2023. n->lightTarget = b->lightTarget;
  2024. n->lightCenter = b->lightCenter;
  2025. n->lightTexture = b->lightTexture;
  2026. n->lightUp = b->lightUp;
  2027. n->modelHandle = b->modelHandle;
  2028. n->pointLight = b->pointLight;
  2029. VectorCopy(b->mins, n->mins);
  2030. VectorCopy(b->maxs, n->maxs);
  2031. for (f = b->brush_faces; f; f = f->next) {
  2032. if (f->original) {
  2033. continue;
  2034. }
  2035. nf = Face_FullClone(f);
  2036. nf->next = n->brush_faces;
  2037. n->brush_faces = nf;
  2038. // copy all faces that have the original set to this face
  2039. for (f2 = b->brush_faces; f2; f2 = f2->next) {
  2040. if (f2->original == f) {
  2041. nf2 = Face_FullClone(f2);
  2042. nf2->next = n->brush_faces;
  2043. n->brush_faces = nf2;
  2044. // set original
  2045. nf2->original = nf;
  2046. }
  2047. }
  2048. }
  2049. for (nf = n->brush_faces; nf; nf = nf->next) {
  2050. Face_SetColor( n, nf, 1.0f );
  2051. if (nf->face_winding) {
  2052. if (g_qeglobals.m_bBrushPrimitMode) {
  2053. EmitBrushPrimitTextureCoordinates(nf, nf->face_winding);
  2054. }
  2055. else {
  2056. for (j = 0; j < nf->face_winding->GetNumPoints(); j++) {
  2057. EmitTextureCoordinates( (*nf->face_winding)[j], nf->d_texture, nf );
  2058. }
  2059. }
  2060. }
  2061. }
  2062. }
  2063. return n;
  2064. }
  2065. extern bool GetMatrixForKey(entity_t *ent, const char *key, idMat3 &mat);
  2066. extern bool Patch_Intersect(patchMesh_t *pm, idVec3 origin, idVec3 direction , float &scale);
  2067. extern bool RayIntersectsTri
  2068. (
  2069. const idVec3 &origin,
  2070. const idVec3 &direction,
  2071. const idVec3 &vert0,
  2072. const idVec3 &vert1,
  2073. const idVec3 &vert2,
  2074. float &scale
  2075. );
  2076. /*
  2077. ================
  2078. RotateVector
  2079. ================
  2080. */
  2081. void RotateVector(idVec3 &v, idVec3 origin, float a, float c, float s) {
  2082. float x = v[0];
  2083. float y = v[1];
  2084. if (a) {
  2085. float x2 = (((x - origin[0]) * c) - ((y - origin[1]) * s)) + origin[0];
  2086. float y2 = (((x - origin[0]) * s) + ((y - origin[1]) * c)) + origin[1];
  2087. x = x2;
  2088. y = y2;
  2089. }
  2090. v[0] = x;
  2091. v[1] = y;
  2092. }
  2093. /*
  2094. ================
  2095. Brush_ModelIntersect
  2096. ================
  2097. */
  2098. bool Brush_ModelIntersect(brush_t *b, idVec3 origin, idVec3 dir,float &scale) {
  2099. idRenderModel *model = b->modelHandle;
  2100. idRenderModel *md5;
  2101. if ( !model )
  2102. model = b->owner->eclass->entityModel;
  2103. scale = 0;
  2104. if (model) {
  2105. if ( model->IsDynamicModel() != DM_STATIC ) {
  2106. if ( dynamic_cast<idRenderModelMD5 *>( model ) ) {
  2107. // take care of animated models
  2108. md5 = b->owner->eclass->entityModel;
  2109. const char *classname = ValueForKey( b->owner, "classname" );
  2110. if (stricmp(classname, "func_static") == 0) {
  2111. classname = ValueForKey(b->owner, "animclass");
  2112. }
  2113. const char *anim = ValueForKey( b->owner, "anim" );
  2114. int frame = IntForKey( b->owner, "frame" ) + 1;
  2115. if ( frame < 1 ) {
  2116. frame = 1;
  2117. }
  2118. if ( !anim || !anim[ 0 ] ) {
  2119. anim = "idle";
  2120. }
  2121. model = gameEdit->ANIM_CreateMeshForAnim( md5, classname, anim, frame, false );
  2122. if ( !model ) {
  2123. model = renderModelManager->DefaultModel();
  2124. }
  2125. }
  2126. }
  2127. bool matrix = false;
  2128. idMat3 mat;
  2129. float a, s, c;
  2130. if (GetMatrixForKey(b->owner, "rotation", mat)) {
  2131. matrix = true;
  2132. } else {
  2133. a = FloatForKey(b->owner, "angle");
  2134. if (a) {
  2135. s = sin( DEG2RAD( a ) );
  2136. c = cos( DEG2RAD( a ) );
  2137. }
  2138. else {
  2139. s = c = 0;
  2140. }
  2141. }
  2142. for (int i = 0; i < model->NumSurfaces() ; i++) {
  2143. const modelSurface_t *surf = model->Surface( i );
  2144. srfTriangles_t *tri = surf->geometry;
  2145. for (int j = 0; j < tri->numIndexes; j += 3) {
  2146. idVec3 v1, v2, v3;
  2147. v1 = tri->verts[tri->indexes[j]].xyz;
  2148. v2 = tri->verts[tri->indexes[j + 1]].xyz;
  2149. v3 = tri->verts[tri->indexes[j + 2]].xyz;
  2150. if (matrix) {
  2151. v1 *= b->owner->rotation;
  2152. v1 += b->owner->origin;
  2153. v2 *= b->owner->rotation;
  2154. v2 += b->owner->origin;
  2155. v3 *= b->owner->rotation;
  2156. v3 += b->owner->origin;
  2157. } else {
  2158. v1 += b->owner->origin;
  2159. v2 += b->owner->origin;
  2160. v3 += b->owner->origin;
  2161. RotateVector(v1, b->owner->origin, a, c, s);
  2162. RotateVector(v2, b->owner->origin, a, c, s);
  2163. RotateVector(v3, b->owner->origin, a, c, s);
  2164. }
  2165. if (RayIntersectsTri(origin, dir, v1, v2, v3,scale)) {
  2166. return true;
  2167. }
  2168. }
  2169. }
  2170. }
  2171. return false;
  2172. }
  2173. face_t *Brush_Ray(idVec3 origin, idVec3 dir, brush_t *b, float *dist, bool testPrimitive) {
  2174. face_t *f, *firstface = NULL;
  2175. idVec3 p1, p2;
  2176. float frac, d1, d2;
  2177. int i;
  2178. float scale = HUGE_DISTANCE * 2;
  2179. VectorCopy(origin, p1);
  2180. for (i = 0; i < 3; i++) {
  2181. p2[i] = p1[i] + dir[i] * HUGE_DISTANCE * 2;
  2182. }
  2183. for (f = b->brush_faces; f; f = f->next) {
  2184. d1 = DotProduct(p1, f->plane) + f->plane[3];
  2185. d2 = DotProduct(p2, f->plane) + f->plane[3];
  2186. if (d1 >= 0 && d2 >= 0) {
  2187. *dist = 0;
  2188. return NULL; // ray is on front side of face
  2189. }
  2190. if (d1 <= 0 && d2 <= 0) {
  2191. continue;
  2192. }
  2193. // clip the ray to the plane
  2194. frac = d1 / (d1 - d2);
  2195. if (d1 > 0) {
  2196. firstface = f;
  2197. for (i = 0; i < 3; i++) {
  2198. p1[i] = p1[i] + frac * (p2[i] - p1[i]);
  2199. }
  2200. }
  2201. else {
  2202. for (i = 0; i < 3; i++) {
  2203. p2[i] = p1[i] + frac * (p2[i] - p1[i]);
  2204. }
  2205. }
  2206. }
  2207. // find distance p1 is along dir
  2208. VectorSubtract(p1, origin, p1);
  2209. d1 = DotProduct(p1, dir);
  2210. if (testPrimitive && !g_PrefsDlg.m_selectByBoundingBrush) {
  2211. if (b->pPatch) {
  2212. if (!Patch_Intersect(b->pPatch, origin, dir, scale)) {
  2213. *dist = 0;
  2214. return NULL;
  2215. }
  2216. }
  2217. else if ( b->modelHandle != NULL && dynamic_cast<idRenderModelPrt*>( b->modelHandle ) == NULL && dynamic_cast< idRenderModelLiquid*> ( b->modelHandle ) == NULL ) {
  2218. if (!Brush_ModelIntersect(b, origin, dir, scale)) {
  2219. *dist = 0;
  2220. return NULL;
  2221. }
  2222. }
  2223. }
  2224. *dist = d1;
  2225. return firstface;
  2226. }
  2227. /*
  2228. ================
  2229. Brush_Point
  2230. ================
  2231. */
  2232. face_t *Brush_Point(idVec3 origin, brush_t *b) {
  2233. face_t *f;
  2234. float d1;
  2235. for (f = b->brush_faces; f; f = f->next) {
  2236. d1 = DotProduct(origin, f->plane) + f->plane[3];
  2237. if (d1 > 0) {
  2238. return NULL; // point is on front side of face
  2239. }
  2240. }
  2241. return b->brush_faces;
  2242. }
  2243. /*
  2244. ================
  2245. Brush_AddToList
  2246. ================
  2247. */
  2248. void Brush_AddToList(brush_t *b, brush_t *list) {
  2249. if (b->next || b->prev) {
  2250. Error("Brush_AddToList: allready linked");
  2251. }
  2252. if (list == &selected_brushes || list == &active_brushes) {
  2253. if (b->pPatch && list == &selected_brushes) {
  2254. Patch_Select(b->pPatch);
  2255. }
  2256. }
  2257. b->list = list;
  2258. b->next = list->next;
  2259. list->next->prev = b;
  2260. list->next = b;
  2261. b->prev = list;
  2262. }
  2263. /*
  2264. ================
  2265. Brush_RemoveFromList
  2266. ================
  2267. */
  2268. void Brush_RemoveFromList(brush_t *b) {
  2269. if (!b->next || !b->prev) {
  2270. Error("Brush_RemoveFromList: not linked");
  2271. }
  2272. if (b->pPatch) {
  2273. Patch_Deselect(b->pPatch);
  2274. // Patch_Deselect(b->nPatchID);
  2275. }
  2276. b->list = NULL;
  2277. b->next->prev = b->prev;
  2278. b->prev->next = b->next;
  2279. b->next = b->prev = NULL;
  2280. }
  2281. /*
  2282. ================
  2283. SetFaceTexdef
  2284. Doesn't set the curve flags.
  2285. NOTE: never trust f->d_texture here, f->texdef and f->d_texture are out of sync when
  2286. called by Brush_SetTexture use Texture_ForName() to find the right shader
  2287. FIXME: send the right shader ( qtexture_t * ) in the parameters ?
  2288. TTimo: surface plugin, added an IPluginTexdef* parameter if not NULL,
  2289. get ->Copy() of it into the face ( and remember to hook ) if NULL, ask for a default
  2290. ================
  2291. */
  2292. void SetFaceTexdef( brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale ) {
  2293. if (g_qeglobals.m_bBrushPrimitMode) {
  2294. f->texdef = *texdef;
  2295. ConvertTexMatWithQTexture(brushprimit_texdef, NULL, &f->brushprimit_texdef, Texture_ForName(f->texdef.name));
  2296. }
  2297. else if (bFitScale) {
  2298. f->texdef = *texdef;
  2299. // fit the scaling of the texture on the actual plane
  2300. idVec3 p1, p2, p3; // absolute coordinates
  2301. // compute absolute coordinates
  2302. ComputeAbsolute(f, p1, p2, p3);
  2303. // compute the scale
  2304. idVec3 vx, vy;
  2305. VectorSubtract(p2, p1, vx);
  2306. vx.Normalize();
  2307. VectorSubtract(p3, p1, vy);
  2308. vy.Normalize();
  2309. // assign scale
  2310. VectorScale(vx, texdef->scale[0], vx);
  2311. VectorScale(vy, texdef->scale[1], vy);
  2312. VectorAdd(p1, vx, p2);
  2313. VectorAdd(p1, vy, p3);
  2314. // compute back shift scale rot
  2315. AbsoluteToLocal(f->plane, f, p1, p2, p3);
  2316. }
  2317. else {
  2318. f->texdef = *texdef;
  2319. }
  2320. }
  2321. /*
  2322. ================
  2323. Brush_SetTexture
  2324. ================
  2325. */
  2326. void Brush_SetTexture(brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale) {
  2327. if (b->pPatch) {
  2328. Patch_SetTexture(b->pPatch, texdef);
  2329. }
  2330. else {
  2331. for (face_t * f = b->brush_faces; f; f = f->next) {
  2332. SetFaceTexdef(b, f, texdef, brushprimit_texdef, bFitScale);
  2333. }
  2334. Brush_Build(b);
  2335. }
  2336. }
  2337. /*
  2338. ====================
  2339. Brush_SetTextureName
  2340. ====================
  2341. */
  2342. void Brush_SetTextureName(brush_t *b, const char *name) {
  2343. if (b->pPatch) {
  2344. Patch_SetTextureName(b->pPatch, name);
  2345. }
  2346. else {
  2347. for (face_t * f = b->brush_faces; f; f = f->next) {
  2348. f->texdef.SetName(name);
  2349. }
  2350. Brush_Build(b);
  2351. }
  2352. }
  2353. /*
  2354. ================
  2355. ClipLineToFace
  2356. ================
  2357. */
  2358. bool ClipLineToFace(idVec3 &p1, idVec3 &p2, face_t *f) {
  2359. float d1, d2, fr;
  2360. int i;
  2361. float *v;
  2362. d1 = DotProduct(p1, f->plane) + f->plane[3];
  2363. d2 = DotProduct(p2, f->plane) + f->plane[3];
  2364. if (d1 >= 0 && d2 >= 0) {
  2365. return false; // totally outside
  2366. }
  2367. if (d1 <= 0 && d2 <= 0) {
  2368. return true; // totally inside
  2369. }
  2370. fr = d1 / (d1 - d2);
  2371. if (d1 > 0) {
  2372. v = p1.ToFloatPtr();
  2373. }
  2374. else {
  2375. v = p2.ToFloatPtr();
  2376. }
  2377. for (i = 0; i < 3; i++) {
  2378. v[i] = p1[i] + fr * (p2[i] - p1[i]);
  2379. }
  2380. return true;
  2381. }
  2382. /*
  2383. ================
  2384. AddPlanept
  2385. ================
  2386. */
  2387. int AddPlanept(idVec3 *f) {
  2388. int i;
  2389. for (i = 0; i < g_qeglobals.d_num_move_points; i++) {
  2390. if (g_qeglobals.d_move_points[i] == f) {
  2391. return 0;
  2392. }
  2393. }
  2394. if (g_qeglobals.d_num_move_points < MAX_MOVE_POINTS) {
  2395. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
  2396. } else {
  2397. Sys_Status("Trying to move too many points\n");
  2398. return 0;
  2399. }
  2400. return 1;
  2401. }
  2402. /*
  2403. ================
  2404. AddMovePlane
  2405. ================
  2406. */
  2407. void AddMovePlane( idPlane *p ) {
  2408. for (int i = 0; i < g_qeglobals.d_num_move_planes; i++) {
  2409. if (g_qeglobals.d_move_planes[i] == p) {
  2410. return;
  2411. }
  2412. }
  2413. if (g_qeglobals.d_num_move_planes < MAX_MOVE_PLANES) {
  2414. g_qeglobals.d_move_planes[g_qeglobals.d_num_move_planes++] = p;
  2415. } else {
  2416. Sys_Status("Trying to move too many planes\n");
  2417. }
  2418. }
  2419. /*
  2420. ================
  2421. Brush_SelectFaceForDragging
  2422. Adds the faces planepts to move_points, and rotates and adds the planepts of adjacent face if shear is set
  2423. ================
  2424. */
  2425. void Brush_SelectFaceForDragging(brush_t *b, face_t *f, bool shear) {
  2426. int i;
  2427. face_t *f2;
  2428. idWinding *w;
  2429. float d;
  2430. brush_t *b2;
  2431. int c;
  2432. if (b->owner->eclass->fixedsize || EntityHasModel(b->owner)) {
  2433. return;
  2434. }
  2435. c = 0;
  2436. for (i = 0; i < 3; i++) {
  2437. c += AddPlanept(&f->planepts[i]);
  2438. }
  2439. //AddMovePlane(&f->plane);
  2440. if (c == 0) {
  2441. return; // allready completely added
  2442. }
  2443. // select all points on this plane in all brushes the selection
  2444. for (b2 = selected_brushes.next; b2 != &selected_brushes; b2 = b2->next) {
  2445. if (b2 == b) {
  2446. continue;
  2447. }
  2448. for (f2 = b2->brush_faces; f2; f2 = f2->next) {
  2449. for (i = 0; i < 3; i++) {
  2450. if (idMath::Fabs(DotProduct(f2->planepts[i], f->plane) + f->plane[3]) > ON_EPSILON) {
  2451. break;
  2452. }
  2453. }
  2454. if (i == 3) { // move this face as well
  2455. Brush_SelectFaceForDragging(b2, f2, shear);
  2456. break;
  2457. }
  2458. }
  2459. }
  2460. //
  2461. // if shearing, take all the planes adjacent to selected faces and rotate their
  2462. // points so the edge clipped by a selcted face has two of the points
  2463. //
  2464. if (!shear) {
  2465. return;
  2466. }
  2467. for (f2 = b->brush_faces; f2; f2 = f2->next) {
  2468. if (f2 == f) {
  2469. continue;
  2470. }
  2471. w = Brush_MakeFaceWinding(b, f2, false);
  2472. if (!w) {
  2473. continue;
  2474. }
  2475. // any points on f will become new control points
  2476. for (i = 0; i < w->GetNumPoints(); i++) {
  2477. d = DotProduct( (*w)[i], f->plane ) + f->plane[3];
  2478. if (d > -ON_EPSILON && d < ON_EPSILON) {
  2479. break;
  2480. }
  2481. }
  2482. // if none of the points were on the plane, leave it alone
  2483. if (i != w->GetNumPoints()) {
  2484. if (i == 0) { // see if the first clockwise point was the
  2485. ///
  2486. /// last point on the winding
  2487. d = DotProduct( (*w)[w->GetNumPoints() - 1], f->plane ) + f->plane[3];
  2488. if (d > -ON_EPSILON && d < ON_EPSILON) {
  2489. i = w->GetNumPoints() - 1;
  2490. }
  2491. }
  2492. AddPlanept(&f2->planepts[0]);
  2493. //AddMovePlane(&f2->plane);
  2494. VectorCopy((*w)[i], f2->planepts[0]);
  2495. if (++i == w->GetNumPoints()) {
  2496. i = 0;
  2497. }
  2498. // see if the next point is also on the plane
  2499. d = DotProduct( (*w)[i], f->plane ) + f->plane[3];
  2500. if (d > -ON_EPSILON && d < ON_EPSILON) {
  2501. AddPlanept(&f2->planepts[1]);
  2502. }
  2503. VectorCopy( (*w)[i], f2->planepts[1] );
  2504. if (++i == w->GetNumPoints()) {
  2505. i = 0;
  2506. }
  2507. // the third point is never on the plane
  2508. VectorCopy( (*w)[i], f2->planepts[2] );
  2509. }
  2510. delete w;
  2511. }
  2512. }
  2513. /*
  2514. ================
  2515. Brush_SideSelect
  2516. The mouse click did not hit the brush, so grab one or more side planes for dragging.
  2517. ================
  2518. */
  2519. void Brush_SideSelect(brush_t *b, idVec3 origin, idVec3 dir, bool shear) {
  2520. face_t *f, *f2;
  2521. idVec3 p1, p2;
  2522. if (g_moveOnly) {
  2523. return;
  2524. }
  2525. // if (b->pPatch) return; Patch_SideSelect(b->nPatchID, origin, dir);
  2526. for (f = b->brush_faces; f; f = f->next) {
  2527. VectorCopy(origin, p1);
  2528. VectorMA(origin, MAX_WORLD_SIZE, dir, p2);
  2529. for (f2 = b->brush_faces; f2; f2 = f2->next) {
  2530. if (f2 == f) {
  2531. continue;
  2532. }
  2533. ClipLineToFace(p1, p2, f2);
  2534. }
  2535. if (f2) {
  2536. continue;
  2537. }
  2538. if ( p1.Compare( origin ) ) {
  2539. continue;
  2540. }
  2541. if (ClipLineToFace(p1, p2, f)) {
  2542. continue;
  2543. }
  2544. Brush_SelectFaceForDragging(b, f, shear);
  2545. }
  2546. }
  2547. extern void UpdateSelectablePoint(brush_t *b, idVec3 v, int type);
  2548. extern void AddSelectablePoint(brush_t *b, idVec3 v, int type, bool priority);
  2549. extern void ClearSelectablePoints(brush_t *b);
  2550. /*
  2551. ================
  2552. Brush_TransformedPoint
  2553. ================
  2554. */
  2555. extern void VectorSnapGrid(idVec3 &v);
  2556. idMat3 Brush_RotationMatrix(brush_t *b) {
  2557. idMat3 mat;
  2558. mat.Identity();
  2559. if (!GetMatrixForKey(b->owner, "light_rotation", mat)) {
  2560. GetMatrixForKey(b->owner, "rotation", mat);
  2561. }
  2562. return mat;
  2563. }
  2564. idVec3 Brush_TransformedPoint(brush_t *b, const idVec3 &in) {
  2565. idVec3 out = in;
  2566. out -= b->owner->origin;
  2567. out *= Brush_RotationMatrix(b);
  2568. out += b->owner->origin;
  2569. return out;
  2570. }
  2571. /*
  2572. ================
  2573. Brush_UpdateLightPoints
  2574. ================
  2575. */
  2576. void Brush_UpdateLightPoints(brush_t *b, const idVec3 &offset) {
  2577. if (!(b->owner->eclass->nShowFlags & ECLASS_LIGHT)) {
  2578. if (b->modelHandle) {
  2579. g_bScreenUpdates = false;
  2580. g_pParentWnd->GetCamera()->BuildEntityRenderState(b->owner, true);
  2581. g_bScreenUpdates = true;
  2582. }
  2583. return;
  2584. }
  2585. if (b->entityModel) {
  2586. return;
  2587. }
  2588. idVec3 vCenter;
  2589. idVec3 *origin = (b->trackLightOrigin) ? &b->owner->lightOrigin : &b->owner->origin;
  2590. if (!GetVectorForKey(b->owner, "_color", b->lightColor)) {
  2591. b->lightColor[0] = b->lightColor[1] = b->lightColor[2] = 1;
  2592. }
  2593. const char *str = ValueForKey(b->owner, "texture");
  2594. b->lightTexture = -1;
  2595. if (str && strlen(str) > 0) {
  2596. const idMaterial *q = Texture_LoadLight(str);
  2597. if (q) {
  2598. b->lightTexture = q->GetEditorImage()->texnum;
  2599. }
  2600. }
  2601. str = ValueForKey(b->owner, "light_right");
  2602. if (str && *str) {
  2603. idVec3 vRight, vUp, vTarget, vTemp;
  2604. if (GetVectorForKey(b->owner, "light_start", b->lightStart)) {
  2605. b->startEnd = true;
  2606. if (!GetVectorForKey(b->owner, "light_end", b->lightEnd)) {
  2607. GetVectorForKey(b->owner, "light_target", b->lightEnd);
  2608. }
  2609. VectorAdd(b->lightEnd, *origin, b->lightEnd);
  2610. VectorAdd(b->lightStart, *origin, b->lightStart);
  2611. VectorAdd(b->lightStart, offset, b->lightStart);
  2612. }
  2613. else {
  2614. b->startEnd = false;
  2615. }
  2616. GetVectorForKey(b->owner, "light_right", vRight);
  2617. GetVectorForKey(b->owner, "light_up", vUp);
  2618. GetVectorForKey(b->owner, "light_target", vTarget);
  2619. if (offset.x || offset.y || offset.z) {
  2620. CString str;
  2621. VectorAdd(vTarget, offset, vTarget);
  2622. SetKeyVec3(b->owner, "light_target", vTarget);
  2623. }
  2624. VectorAdd(vTarget, *origin, b->lightTarget);
  2625. VectorAdd(b->lightTarget, vRight, b->lightRight);
  2626. VectorAdd(b->lightTarget, vUp, b->lightUp);
  2627. UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightUp), LIGHT_UP);
  2628. UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightRight), LIGHT_RIGHT);
  2629. UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightTarget), LIGHT_TARGET);
  2630. UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightStart), LIGHT_START);
  2631. UpdateSelectablePoint(b, Brush_TransformedPoint(b, b->lightEnd), LIGHT_END);
  2632. b->pointLight = false;
  2633. }
  2634. else {
  2635. b->pointLight = true;
  2636. if (GetVectorForKey(b->owner, "light_center", vCenter)) {
  2637. if (offset.x || offset.y || offset.z) {
  2638. CString str;
  2639. VectorAdd(vCenter, offset, vCenter);
  2640. SetKeyVec3(b->owner, "light_center", vCenter);
  2641. }
  2642. VectorAdd(vCenter, *origin, b->lightCenter);
  2643. UpdateSelectablePoint(b, b->lightCenter, LIGHT_CENTER);
  2644. }
  2645. if (!GetVectorForKey(b->owner, "light_radius", b->lightRadius)) {
  2646. float f = FloatForKey(b->owner, "light");
  2647. if (f == 0) {
  2648. f = 300;
  2649. }
  2650. b->lightRadius[0] = b->lightRadius[1] = b->lightRadius[2] = f;
  2651. }
  2652. else {
  2653. }
  2654. }
  2655. g_bScreenUpdates = false;
  2656. g_pParentWnd->GetCamera()->BuildEntityRenderState(b->owner, true);
  2657. g_bScreenUpdates = true;
  2658. }
  2659. /*
  2660. ================
  2661. Brush_BuildWindings
  2662. ================
  2663. */
  2664. void Brush_BuildWindings(brush_t *b, bool bSnap, bool keepOnPlaneWinding, bool updateLights, bool makeFacePlanes) {
  2665. idWinding *w;
  2666. face_t *face;
  2667. float v;
  2668. // clear the mins/maxs bounds
  2669. b->mins[0] = b->mins[1] = b->mins[2] = 999999;
  2670. b->maxs[0] = b->maxs[1] = b->maxs[2] = -999999;
  2671. if (makeFacePlanes) {
  2672. Brush_MakeFacePlanes(b);
  2673. }
  2674. face = b->brush_faces;
  2675. float fCurveColor = 1.0f;
  2676. for (; face; face = face->next) {
  2677. int i, j;
  2678. delete face->face_winding;
  2679. w = face->face_winding = Brush_MakeFaceWinding(b, face, keepOnPlaneWinding);
  2680. face->d_texture = Texture_ForName(face->texdef.name);
  2681. if (!w) {
  2682. continue;
  2683. }
  2684. for (i = 0; i < w->GetNumPoints(); i++) {
  2685. // add to bounding box
  2686. for (j = 0; j < 3; j++) {
  2687. v = (*w)[i][j];
  2688. if (v > b->maxs[j]) {
  2689. b->maxs[j] = v;
  2690. }
  2691. if (v < b->mins[j]) {
  2692. b->mins[j] = v;
  2693. }
  2694. }
  2695. }
  2696. // setup s and t vectors, and set color if (!g_PrefsDlg.m_bGLLighting) {
  2697. if (makeFacePlanes) {
  2698. Face_SetColor(b, face, fCurveColor);
  2699. // }
  2700. fCurveColor -= 0.1f;
  2701. if ( fCurveColor <= 0.0f ) {
  2702. fCurveColor = 1.0f;
  2703. }
  2704. // computing ST coordinates for the windings
  2705. if (g_qeglobals.m_bBrushPrimitMode) {
  2706. if (g_qeglobals.bNeedConvert) {
  2707. //
  2708. // we have parsed old brushes format and need conversion convert old brush texture
  2709. // representation to new format
  2710. //
  2711. FaceToBrushPrimitFace(face);
  2712. #ifdef _DEBUG
  2713. // use old texture coordinates code to check against
  2714. for (i = 0; i < w->GetNumPoints(); i++) {
  2715. EmitTextureCoordinates((*w)[i], face->d_texture, face);
  2716. }
  2717. #endif
  2718. }
  2719. //
  2720. // use new texture representation to compute texture coordinates in debug mode we
  2721. // will check against old code and warn if there are differences
  2722. //
  2723. EmitBrushPrimitTextureCoordinates(face, w);
  2724. }
  2725. else {
  2726. for (i = 0; i < w->GetNumPoints(); i++) {
  2727. EmitTextureCoordinates((*w)[i], face->d_texture, face);
  2728. }
  2729. }
  2730. }
  2731. }
  2732. if (updateLights) {
  2733. idVec3 offset;
  2734. offset.Zero();
  2735. Brush_UpdateLightPoints(b, offset);
  2736. }
  2737. }
  2738. /*
  2739. ================
  2740. Brush_RemoveEmptyFaces
  2741. Frees any overconstraining faces
  2742. ================
  2743. */
  2744. void Brush_RemoveEmptyFaces(brush_t *b) {
  2745. face_t *f, *next;
  2746. f = b->brush_faces;
  2747. b->brush_faces = NULL;
  2748. for (; f; f = next) {
  2749. next = f->next;
  2750. if (!f->face_winding) {
  2751. Face_Free(f);
  2752. }
  2753. else {
  2754. f->next = b->brush_faces;
  2755. b->brush_faces = f;
  2756. }
  2757. }
  2758. }
  2759. /*
  2760. ================
  2761. Brush_SnapToGrid
  2762. ================
  2763. */
  2764. void Brush_SnapToGrid(brush_t *pb) {
  2765. int i;
  2766. for (face_t * f = pb->brush_faces; f; f = f->next) {
  2767. idWinding *w = f->face_winding;
  2768. if (!w) {
  2769. continue; // freed face
  2770. }
  2771. for (i = 0; i < w->GetNumPoints(); i++) {
  2772. SnapVectorToGrid( (*w)[i].ToVec3() );
  2773. }
  2774. for (i = 0; i < 3; i++) {
  2775. f->planepts[i].x = (*w)[i].x;
  2776. f->planepts[i].y = (*w)[i].y;
  2777. f->planepts[i].z = (*w)[i].z;
  2778. }
  2779. }
  2780. idVec3 v;
  2781. idStr str;
  2782. if (GetVectorForKey(pb->owner, "origin", v)) {
  2783. SnapVectorToGrid(pb->owner->origin);
  2784. sprintf(str, "%i %i %i", (int)pb->owner->origin.x, (int)pb->owner->origin.y, (int)pb->owner->origin.z);
  2785. SetKeyValue(pb->owner, "origin", str);
  2786. }
  2787. if (pb->owner->eclass->nShowFlags & ECLASS_LIGHT) {
  2788. if (GetVectorForKey(pb->owner, "light_right", v)) {
  2789. // projected
  2790. SnapVectorToGrid(v);
  2791. pb->lightRight = v;
  2792. SetKeyVec3(pb->owner, "light_right", v);
  2793. GetVectorForKey(pb->owner, "light_up", v);
  2794. SnapVectorToGrid(v);
  2795. pb->lightUp = v;
  2796. SetKeyVec3(pb->owner, "light_up", v);
  2797. GetVectorForKey(pb->owner, "light_target", v);
  2798. SnapVectorToGrid(v);
  2799. pb->lightTarget = v;
  2800. SetKeyVec3(pb->owner, "light_target", v);
  2801. if (GetVectorForKey(pb->owner, "light_start", v)) {
  2802. SnapVectorToGrid(v);
  2803. pb->lightStart = v;
  2804. SetKeyVec3(pb->owner, "light_start", v);
  2805. GetVectorForKey(pb->owner, "light_end", v);
  2806. SnapVectorToGrid(v);
  2807. pb->lightEnd = v;
  2808. SetKeyVec3(pb->owner, "light_end", v);
  2809. }
  2810. } else {
  2811. // point
  2812. if (GetVectorForKey(pb->owner, "light_center", v)) {
  2813. SnapVectorToGrid(v);
  2814. SetKeyVec3(pb->owner, "light_center", v);
  2815. }
  2816. }
  2817. }
  2818. if ( pb->owner->curve ) {
  2819. int c = pb->owner->curve->GetNumValues();
  2820. for ( i = 0; i < c; i++ ) {
  2821. v = pb->owner->curve->GetValue( i );
  2822. SnapVectorToGrid( v );
  2823. pb->owner->curve->SetValue( i, v );
  2824. }
  2825. }
  2826. Brush_Build(pb);
  2827. }
  2828. /*
  2829. ================
  2830. Brush_Rotate
  2831. ================
  2832. */
  2833. void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild) {
  2834. for (face_t * f = b->brush_faces; f; f = f->next) {
  2835. for (int i = 0; i < 3; i++) {
  2836. f->planepts[i] -= origin;
  2837. f->planepts[i] *= matrix;
  2838. f->planepts[i] += origin;
  2839. }
  2840. }
  2841. if (bBuild) {
  2842. Brush_Build(b, false, false);
  2843. }
  2844. }
  2845. extern void VectorRotate3Origin( const idVec3 &vIn, const idVec3 &vRotation, const idVec3 &vOrigin, idVec3 &out );
  2846. /*
  2847. ================
  2848. Brush_Rotate
  2849. ================
  2850. */
  2851. void Brush_Rotate(brush_t *b, idVec3 vAngle, idVec3 vOrigin, bool bBuild) {
  2852. for (face_t * f = b->brush_faces; f; f = f->next) {
  2853. for (int i = 0; i < 3; i++) {
  2854. VectorRotate3Origin(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
  2855. }
  2856. }
  2857. if (bBuild) {
  2858. Brush_Build(b, false, false);
  2859. }
  2860. }
  2861. /*
  2862. ================
  2863. Brush_Center
  2864. ================
  2865. */
  2866. void Brush_Center(brush_t *b, idVec3 vNewCenter) {
  2867. idVec3 vMid;
  2868. // get center of the brush
  2869. for (int j = 0; j < 3; j++) {
  2870. vMid[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5f);
  2871. }
  2872. // calc distance between centers
  2873. VectorSubtract(vNewCenter, vMid, vMid);
  2874. Brush_Move(b, vMid, true);
  2875. }
  2876. /*
  2877. ================
  2878. Brush_Resize
  2879. the brush must be a true axial box
  2880. ================
  2881. */
  2882. void Brush_Resize( brush_t *b, idVec3 vMin, idVec3 vMax ) {
  2883. int i, j;
  2884. face_t *f;
  2885. assert( vMin[0] < vMax[0] && vMin[1] < vMax[1] && vMin[2] < vMax[2] );
  2886. Brush_MakeFacePlanes( b );
  2887. for( f = b->brush_faces; f; f = f->next ) {
  2888. for ( i = 0; i < 3; i++ ) {
  2889. if ( f->plane.Normal()[i] >= 0.999f ) {
  2890. for ( j = 0; j < 3; j++ ) {
  2891. f->planepts[j][i] = vMax[i];
  2892. }
  2893. break;
  2894. }
  2895. if ( f->plane.Normal()[i] <= -0.999f ) {
  2896. for ( j = 0; j < 3; j++ ) {
  2897. f->planepts[j][i] = vMin[i];
  2898. }
  2899. break;
  2900. }
  2901. }
  2902. //assert( i < 3 );
  2903. }
  2904. Brush_Build( b, true );
  2905. }
  2906. /*
  2907. ================
  2908. HasModel
  2909. ================
  2910. */
  2911. eclass_t *HasModel(brush_t *b) {
  2912. idVec3 vMin, vMax;
  2913. vMin[0] = vMin[1] = vMin[2] = 999999;
  2914. vMax[0] = vMax[1] = vMax[2] = -999999;
  2915. if (b->owner->md3Class != NULL) {
  2916. return b->owner->md3Class;
  2917. }
  2918. if (b->owner->eclass->modelHandle > 0) {
  2919. return b->owner->eclass;
  2920. }
  2921. eclass_t *e = NULL;
  2922. // FIXME: entity needs to track whether a cache hit failed and not ask again
  2923. if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL) {
  2924. const char *pModel = ValueForKey(b->owner, "model");
  2925. if (pModel != NULL && strlen(pModel) > 0) {
  2926. e = GetCachedModel(b->owner, pModel, vMin, vMax);
  2927. if (e != NULL) {
  2928. //
  2929. // we need to scale the brush to the proper size based on the model load recreate
  2930. // brush just like in load/save
  2931. //
  2932. VectorAdd(vMin, b->owner->origin, vMin);
  2933. VectorAdd(vMax, b->owner->origin, vMax);
  2934. Brush_Resize(b, vMin, vMax);
  2935. b->bModelFailed = false;
  2936. }
  2937. else {
  2938. b->bModelFailed = true;
  2939. }
  2940. }
  2941. }
  2942. return e;
  2943. }
  2944. /*
  2945. ================
  2946. Entity_GetRotationMatrixAngles
  2947. ================
  2948. */
  2949. bool Entity_GetRotationMatrixAngles( entity_t *e, idMat3 &mat, idAngles &angles ) {
  2950. int angle;
  2951. /* the angle keyword is a yaw value, except for two special markers */
  2952. if ( GetMatrixForKey( e, "rotation", mat ) ) {
  2953. angles = mat.ToAngles();
  2954. return true;
  2955. }
  2956. else if ( e->epairs.GetInt( "angle", "0", angle ) ) {
  2957. if ( angle == -1 ) { // up
  2958. angles.Set( 270, 0, 0 );
  2959. }
  2960. else if ( angle == -2 ) { // down
  2961. angles.Set( 90, 0, 0 );
  2962. }
  2963. else {
  2964. angles.Set( 0, angle, 0 );
  2965. }
  2966. mat = angles.ToMat3();
  2967. return true;
  2968. }
  2969. else {
  2970. mat.Identity();
  2971. angles.Zero();
  2972. return false;
  2973. }
  2974. }
  2975. /*
  2976. ================
  2977. FacingVectors
  2978. ================
  2979. */
  2980. static void FacingVectors(entity_t *e, idVec3 &forward, idVec3 &right, idVec3 &up) {
  2981. idAngles angles;
  2982. idMat3 mat;
  2983. Entity_GetRotationMatrixAngles(e, mat, angles);
  2984. angles.ToVectors( &forward, &right, &up);
  2985. }
  2986. /*
  2987. ================
  2988. Brush_DrawFacingAngle
  2989. ================
  2990. */
  2991. void Brush_DrawFacingAngle( brush_t *b, entity_t *e, bool particle ) {
  2992. idVec3 forward, right, up;
  2993. idVec3 endpoint, tip1, tip2;
  2994. idVec3 start;
  2995. float dist;
  2996. VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
  2997. VectorScale(start, 0.5f, start);
  2998. dist = (b->maxs[0] - start[0]) * 2.5f;
  2999. FacingVectors(e, forward, right, up);
  3000. VectorMA(start, dist, ( particle ) ? up : forward, endpoint);
  3001. dist = (b->maxs[0] - start[0]) * 0.5f;
  3002. VectorMA(endpoint, -dist, ( particle ) ? up : forward, tip1);
  3003. VectorMA(tip1, -dist, ( particle ) ? forward : up, tip1);
  3004. VectorMA(tip1, 2 * dist, ( particle ) ? forward : up, tip2);
  3005. globalImages->BindNull();
  3006. qglColor4f(1, 1, 1, 1);
  3007. qglLineWidth(2);
  3008. qglBegin(GL_LINES);
  3009. qglVertex3fv(start.ToFloatPtr());
  3010. qglVertex3fv(endpoint.ToFloatPtr());
  3011. qglVertex3fv(endpoint.ToFloatPtr());
  3012. qglVertex3fv(tip1.ToFloatPtr());
  3013. qglVertex3fv(endpoint.ToFloatPtr());
  3014. qglVertex3fv(tip2.ToFloatPtr());
  3015. qglEnd();
  3016. qglLineWidth(0.5f);
  3017. }
  3018. /*
  3019. ================
  3020. DrawProjectedLight
  3021. ================
  3022. */
  3023. void DrawProjectedLight(brush_t *b, bool bSelected, bool texture) {
  3024. int i;
  3025. idVec3 v1, v2, cross, vieworg, edge[8][2], v[4];
  3026. idVec3 target, start;
  3027. if (!bSelected && !g_bShowLightVolumes) {
  3028. return;
  3029. }
  3030. // use the renderer to get the volume outline
  3031. idPlane lightProject[4];
  3032. idPlane planes[6];
  3033. srfTriangles_t *tri;
  3034. // use the game's epair parsing code so
  3035. // we can use the same renderLight generation
  3036. entity_t *ent = b->owner;
  3037. idDict spawnArgs;
  3038. renderLight_t parms;
  3039. spawnArgs = ent->epairs;
  3040. gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
  3041. R_RenderLightFrustum( parms, planes );
  3042. tri = R_PolytopeSurface(6, planes, NULL);
  3043. qglColor3f(1, 0, 1);
  3044. for (i = 0; i < tri->numIndexes; i += 3) {
  3045. qglBegin(GL_LINE_LOOP);
  3046. glVertex3fv(tri->verts[tri->indexes[i]].xyz.ToFloatPtr());
  3047. glVertex3fv(tri->verts[tri->indexes[i + 1]].xyz.ToFloatPtr());
  3048. glVertex3fv(tri->verts[tri->indexes[i + 2]].xyz.ToFloatPtr());
  3049. qglEnd();
  3050. }
  3051. R_FreeStaticTriSurf(tri);
  3052. // draw different selection points for point lights or projected
  3053. // lights (FIXME: rotate these based on parms!)
  3054. if ( !bSelected ) {
  3055. return;
  3056. }
  3057. idMat3 mat;
  3058. bool transform = GetMatrixForKey(b->owner, "light_rotation", mat);
  3059. if (!transform) {
  3060. transform = GetMatrixForKey(b->owner, "rotation", mat);
  3061. }
  3062. idVec3 tv;
  3063. idVec3 *origin = (b->trackLightOrigin) ? &b->owner->lightOrigin : &b->owner->origin;
  3064. if (b->pointLight) {
  3065. if ( b->lightCenter[0] || b->lightCenter[1] || b->lightCenter[2] ) {
  3066. qglPointSize(8);
  3067. qglColor3f( 1.0f, 0.4f, 0.8f );
  3068. qglBegin(GL_POINTS);
  3069. tv = b->lightCenter;
  3070. if (transform) {
  3071. tv -= *origin;
  3072. tv *= mat;
  3073. tv += *origin;
  3074. }
  3075. qglVertex3fv(tv.ToFloatPtr());
  3076. qglEnd();
  3077. qglPointSize(1);
  3078. }
  3079. return;
  3080. }
  3081. // projected light
  3082. qglPointSize(8);
  3083. qglColor3f( 1.0f, 0.4f, 0.8f );
  3084. qglBegin(GL_POINTS);
  3085. tv = b->lightRight;
  3086. if (transform) {
  3087. tv -= *origin;
  3088. tv *= mat;
  3089. tv += *origin;
  3090. }
  3091. qglVertex3fv(tv.ToFloatPtr());
  3092. tv = b->lightTarget;
  3093. if (transform) {
  3094. tv -= *origin;
  3095. tv *= mat;
  3096. tv += *origin;
  3097. }
  3098. qglVertex3fv(tv.ToFloatPtr());
  3099. tv = b->lightUp;
  3100. if (transform) {
  3101. tv -= *origin;
  3102. tv *= mat;
  3103. tv += *origin;
  3104. }
  3105. qglVertex3fv(tv.ToFloatPtr());
  3106. qglEnd();
  3107. if (b->startEnd) {
  3108. qglColor3f( 0.4f, 1.0f, 0.8f );
  3109. qglBegin(GL_POINTS);
  3110. qglVertex3fv(b->lightStart.ToFloatPtr());
  3111. qglVertex3fv(b->lightEnd.ToFloatPtr());
  3112. qglEnd();
  3113. }
  3114. qglPointSize(1);
  3115. }
  3116. /*
  3117. ================
  3118. GLCircle
  3119. ================
  3120. */
  3121. void GLCircle(float x, float y, float z, float r)
  3122. {
  3123. float ix = 0;
  3124. float iy = r;
  3125. float ig = 3 - 2 * r;
  3126. float idgr = -6;
  3127. float idgd = 4 * r - 10;
  3128. qglPointSize(0.5f);
  3129. qglBegin(GL_POINTS);
  3130. while (ix <= iy) {
  3131. if (ig < 0) {
  3132. ig += idgd;
  3133. idgd -= 8;
  3134. iy--;
  3135. } else {
  3136. ig += idgr;
  3137. idgd -= 4;
  3138. }
  3139. idgr -= 4;
  3140. ix++;
  3141. qglVertex3f(x + ix, y + iy, z);
  3142. qglVertex3f(x - ix, y + iy, z);
  3143. qglVertex3f(x + ix, y - iy, z);
  3144. qglVertex3f(x - ix, y - iy, z);
  3145. qglVertex3f(x + iy, y + ix, z);
  3146. qglVertex3f(x - iy, y + ix, z);
  3147. qglVertex3f(x + iy, y - ix, z);
  3148. qglVertex3f(x - iy, y - ix, z);
  3149. }
  3150. qglEnd();
  3151. }
  3152. /*
  3153. ================
  3154. DrawSpeaker
  3155. ================
  3156. */
  3157. void DrawSpeaker(brush_t *b, bool bSelected, bool twoD) {
  3158. if (!(g_qeglobals.d_savedinfo.showSoundAlways || (g_qeglobals.d_savedinfo.showSoundWhenSelected && bSelected))) {
  3159. return;
  3160. }
  3161. // convert to units ( inches )
  3162. float min = FloatForKey(b->owner, "s_mindistance");
  3163. float max = FloatForKey(b->owner, "s_maxdistance");
  3164. const char *s = b->owner->epairs.GetString("s_shader");
  3165. if (s && *s) {
  3166. const idSoundShader *shader = declManager->FindSound( s, false );
  3167. if ( shader ) {
  3168. if ( !min ) {
  3169. min = shader->GetMinDistance();
  3170. }
  3171. if ( !max ) {
  3172. max = shader->GetMaxDistance();
  3173. }
  3174. }
  3175. }
  3176. if (min == 0 && max == 0) {
  3177. return;
  3178. }
  3179. // convert from meters to doom units
  3180. min *= METERS_TO_DOOM;
  3181. max *= METERS_TO_DOOM;
  3182. if (twoD) {
  3183. if (bSelected) {
  3184. 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);
  3185. } else {
  3186. qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, .5);
  3187. }
  3188. qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
  3189. GLCircle(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z, min);
  3190. if (bSelected) {
  3191. 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);
  3192. } else {
  3193. qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 1);
  3194. }
  3195. GLCircle(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z, max);
  3196. } else {
  3197. qglPushMatrix();
  3198. qglTranslatef(b->owner->origin.x, b->owner->origin.y, b->owner->origin.z );
  3199. qglColor3f( 0.4f, 0.4f, 0.4f );
  3200. qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
  3201. GLUquadricObj* qobj = gluNewQuadric();
  3202. gluSphere(qobj, min, 8, 8);
  3203. qglColor3f( 0.8f, 0.8f, 0.8f );
  3204. gluSphere(qobj, max, 8, 8);
  3205. qglEnable(GL_BLEND);
  3206. qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  3207. qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  3208. globalImages->BindNull();
  3209. if (bSelected) {
  3210. 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 );
  3211. } else {
  3212. qglColor4f( b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 0.35f );
  3213. }
  3214. gluSphere(qobj, min, 8, 8);
  3215. if (bSelected) {
  3216. 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 );
  3217. } else {
  3218. qglColor4f( b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, 0.1f );
  3219. }
  3220. gluSphere(qobj, max, 8, 8);
  3221. gluDeleteQuadric(qobj);
  3222. qglPopMatrix();
  3223. }
  3224. }
  3225. /*
  3226. ================
  3227. DrawLight
  3228. ================
  3229. */
  3230. void DrawLight(brush_t *b, bool bSelected) {
  3231. idVec3 vTriColor;
  3232. bool bTriPaint = false;
  3233. vTriColor[0] = vTriColor[2] = 1.0f;
  3234. vTriColor[1] = 1.0f;
  3235. bTriPaint = true;
  3236. CString strColor = ValueForKey(b->owner, "_color");
  3237. if (strColor.GetLength() > 0) {
  3238. float fR, fG, fB;
  3239. int n = sscanf(strColor, "%f %f %f", &fR, &fG, &fB);
  3240. if (n == 3) {
  3241. vTriColor[0] = fR;
  3242. vTriColor[1] = fG;
  3243. vTriColor[2] = fB;
  3244. }
  3245. }
  3246. qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3247. idVec3 vCorners[4];
  3248. float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
  3249. vCorners[0][0] = b->mins[0];
  3250. vCorners[0][1] = b->mins[1];
  3251. vCorners[0][2] = fMid;
  3252. vCorners[1][0] = b->mins[0];
  3253. vCorners[1][1] = b->maxs[1];
  3254. vCorners[1][2] = fMid;
  3255. vCorners[2][0] = b->maxs[0];
  3256. vCorners[2][1] = b->maxs[1];
  3257. vCorners[2][2] = fMid;
  3258. vCorners[3][0] = b->maxs[0];
  3259. vCorners[3][1] = b->mins[1];
  3260. vCorners[3][2] = fMid;
  3261. idVec3 vTop, vBottom;
  3262. vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
  3263. vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
  3264. vTop[2] = b->maxs[2];
  3265. VectorCopy(vTop, vBottom);
  3266. vBottom[2] = b->mins[2];
  3267. idVec3 vSave;
  3268. VectorCopy(vTriColor, vSave);
  3269. globalImages->BindNull();
  3270. qglBegin(GL_TRIANGLE_FAN);
  3271. qglVertex3fv(vTop.ToFloatPtr());
  3272. int i;
  3273. for (i = 0; i <= 3; i++) {
  3274. vTriColor[0] *= 0.95f;
  3275. vTriColor[1] *= 0.95f;
  3276. vTriColor[2] *= 0.95f;
  3277. qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3278. qglVertex3fv(vCorners[i].ToFloatPtr());
  3279. }
  3280. qglVertex3fv(vCorners[0].ToFloatPtr());
  3281. qglEnd();
  3282. VectorCopy(vSave, vTriColor);
  3283. vTriColor[0] *= 0.95f;
  3284. vTriColor[1] *= 0.95f;
  3285. vTriColor[2] *= 0.95f;
  3286. qglBegin(GL_TRIANGLE_FAN);
  3287. qglVertex3fv(vBottom.ToFloatPtr());
  3288. qglVertex3fv(vCorners[0].ToFloatPtr());
  3289. for (i = 3; i >= 0; i--) {
  3290. vTriColor[0] *= 0.95f;
  3291. vTriColor[1] *= 0.95f;
  3292. vTriColor[2] *= 0.95f;
  3293. qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3294. qglVertex3fv(vCorners[i].ToFloatPtr());
  3295. }
  3296. qglEnd();
  3297. DrawProjectedLight(b, bSelected, true);
  3298. }
  3299. /*
  3300. ================
  3301. Control_Draw
  3302. ================
  3303. */
  3304. void Control_Draw(brush_t *b) {
  3305. face_t *face;
  3306. int i, order;
  3307. qtexture_t *prev = 0;
  3308. idWinding *w;
  3309. // guarantee the texture will be set first
  3310. prev = NULL;
  3311. for ( face = b->brush_faces, order = 0; face; face = face->next, order++ ) {
  3312. w = face->face_winding;
  3313. if (!w) {
  3314. continue; // freed face
  3315. }
  3316. qglColor4f(1, 1, .5, 1);
  3317. qglBegin(GL_POLYGON);
  3318. for (i = 0; i < w->GetNumPoints(); i++) {
  3319. qglVertex3fv( (*w)[i].ToFloatPtr() );
  3320. }
  3321. qglEnd();
  3322. }
  3323. }
  3324. /*
  3325. ================
  3326. Brush_DrawModel
  3327. ================
  3328. */
  3329. void Brush_DrawModel( brush_t *b, bool camera, bool bSelected ) {
  3330. idMat3 axis;
  3331. idAngles angles;
  3332. int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  3333. if ( camera && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME && nDrawMode != cd_wire ) {
  3334. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  3335. }
  3336. else {
  3337. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  3338. }
  3339. idRenderModel *model = b->modelHandle;
  3340. if ( model == NULL ) {
  3341. model = b->owner->eclass->entityModel;
  3342. }
  3343. if ( model ) {
  3344. idRenderModel *model2;
  3345. model2 = NULL;
  3346. bool fixedBounds = false;
  3347. if ( model->IsDynamicModel() != DM_STATIC ) {
  3348. if ( dynamic_cast<idRenderModelMD5 *>( model ) ) {
  3349. const char *classname = ValueForKey( b->owner, "classname" );
  3350. if (stricmp(classname, "func_static") == 0) {
  3351. classname = ValueForKey(b->owner, "animclass");
  3352. }
  3353. const char *anim = ValueForKey( b->owner, "anim" );
  3354. int frame = IntForKey( b->owner, "frame" ) + 1;
  3355. if ( frame < 1 ) {
  3356. frame = 1;
  3357. }
  3358. if ( !anim || !anim[ 0 ] ) {
  3359. anim = "idle";
  3360. }
  3361. model2 = gameEdit->ANIM_CreateMeshForAnim( model, classname, anim, frame, false );
  3362. } else if ( dynamic_cast<idRenderModelPrt*>( model ) || dynamic_cast<idRenderModelLiquid*>( model ) ) {
  3363. fixedBounds = true;
  3364. }
  3365. if ( !model2 ) {
  3366. idBounds bounds;
  3367. if (fixedBounds) {
  3368. bounds.Zero();
  3369. bounds.ExpandSelf(12.0f);
  3370. } else {
  3371. bounds = model->Bounds( NULL );
  3372. }
  3373. idVec4 color;
  3374. color.w = 1.0f;
  3375. if (bSelected) {
  3376. color.x = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].x;
  3377. color.y = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].y;
  3378. color.z = g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].z;
  3379. } else {
  3380. color.x = b->owner->eclass->color.x;
  3381. color.y = b->owner->eclass->color.y;
  3382. color.z = b->owner->eclass->color.z;
  3383. }
  3384. idVec3 center = bounds.GetCenter();
  3385. glBox(color, b->owner->origin + center, bounds.GetRadius( center ) );
  3386. model = renderModelManager->DefaultModel();
  3387. } else {
  3388. model = model2;
  3389. }
  3390. }
  3391. Entity_GetRotationMatrixAngles( b->owner, axis, angles );
  3392. idVec4 colorSave;
  3393. qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
  3394. if ( bSelected ) {
  3395. qglColor3fv( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr() );
  3396. }
  3397. DrawRenderModel( model, b->owner->origin, axis, camera );
  3398. qglColor4fv( colorSave.ToFloatPtr() );
  3399. if ( bSelected && camera )
  3400. {
  3401. //draw selection tints
  3402. /*
  3403. if ( camera && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME ) {
  3404. qglPolygonMode ( GL_FRONT_AND_BACK , GL_FILL );
  3405. qglColor3fv ( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr () );
  3406. qglEnable ( GL_BLEND );
  3407. qglBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  3408. DrawRenderModel( model, b->owner->origin, axis, camera );
  3409. }
  3410. */
  3411. //draw white triangle outlines
  3412. globalImages->BindNull();
  3413. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  3414. qglDisable( GL_BLEND );
  3415. qglDisable( GL_DEPTH_TEST );
  3416. qglColor3f( 1.0f, 1.0f, 1.0f );
  3417. qglPolygonOffset( 1.0f, 3.0f );
  3418. DrawRenderModel( model, b->owner->origin, axis, false );
  3419. qglEnable( GL_DEPTH_TEST );
  3420. }
  3421. if ( model2 ) {
  3422. delete model2;
  3423. model2 = NULL;
  3424. }
  3425. }
  3426. if ( bSelected && camera ) {
  3427. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  3428. }
  3429. else if ( camera ) {
  3430. globalImages->BindNull();
  3431. }
  3432. if ( g_bPatchShowBounds ) {
  3433. for ( face_t *face = b->brush_faces; face; face = face->next ) {
  3434. // only draw polygons facing in a direction we care about
  3435. idWinding *w = face->face_winding;
  3436. if (!w) {
  3437. continue;
  3438. }
  3439. //
  3440. // if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA)) continue;
  3441. // draw the polygon
  3442. //
  3443. qglBegin(GL_LINE_LOOP);
  3444. for (int i = 0; i < w->GetNumPoints(); i++) {
  3445. qglVertex3fv( (*w)[i].ToFloatPtr() );
  3446. }
  3447. qglEnd();
  3448. }
  3449. }
  3450. }
  3451. /*
  3452. ================
  3453. GLTransformedVertex
  3454. ================
  3455. */
  3456. void GLTransformedVertex(float x, float y, float z, idMat3 mat, idVec3 origin, idVec3 color, float maxDist) {
  3457. idVec3 v(x,y,z);
  3458. v -= origin;
  3459. v *= mat;
  3460. v += origin;
  3461. idVec3 n = v - g_pParentWnd->GetCamera()->Camera().origin;
  3462. float max = n.Length() / maxDist;
  3463. if (color.x) {
  3464. color.x = max;
  3465. } else if (color.y) {
  3466. color.y = max;
  3467. } else {
  3468. color.z = max;
  3469. }
  3470. qglColor3f(color.x, color.y, color.z);
  3471. qglVertex3f(v.x, v.y, v.z);
  3472. }
  3473. /*
  3474. ================
  3475. GLTransformedCircle
  3476. ================
  3477. */
  3478. void GLTransformedCircle(int type, idVec3 origin, float r, idMat3 mat, float pointSize, idVec3 color, float maxDist) {
  3479. qglPointSize(pointSize);
  3480. qglBegin(GL_POINTS);
  3481. for (int i = 0; i < 360; i++) {
  3482. float cx = origin.x;
  3483. float cy = origin.y;
  3484. float cz = origin.z;
  3485. switch (type) {
  3486. case 0:
  3487. cx += r * cos((float)i);
  3488. cy += r * sin((float)i);
  3489. break;
  3490. case 1:
  3491. cx += r * cos((float)i);
  3492. cz += r * sin((float)i);
  3493. break;
  3494. case 2:
  3495. cy += r * sin((float)i);
  3496. cz += r * cos((float)i);
  3497. break;
  3498. default:
  3499. break;
  3500. }
  3501. GLTransformedVertex(cx, cy, cz, mat, origin, color, maxDist);
  3502. }
  3503. qglEnd();
  3504. }
  3505. /*
  3506. ================
  3507. Brush_DrawAxis
  3508. ================
  3509. */
  3510. void Brush_DrawAxis(brush_t *b) {
  3511. if ( g_pParentWnd->ActiveXY()->RotateMode() && b->modelHandle ) {
  3512. bool matrix = false;
  3513. idMat3 mat;
  3514. float a, s, c;
  3515. if (GetMatrixForKey(b->owner, "rotation", mat)) {
  3516. matrix = true;
  3517. } else {
  3518. a = FloatForKey(b->owner, "angle");
  3519. if (a) {
  3520. s = sin( DEG2RAD( a ) );
  3521. c = cos( DEG2RAD( a ) );
  3522. }
  3523. else {
  3524. s = c = 0;
  3525. }
  3526. }
  3527. idBounds bo;
  3528. bo.FromTransformedBounds(b->modelHandle->Bounds(), b->owner->origin, b->owner->rotation);
  3529. float dist = (g_pParentWnd->GetCamera()->Camera().origin - bo[0]).Length();
  3530. float dist2 = (g_pParentWnd->GetCamera()->Camera().origin - bo[1]).Length();
  3531. if (dist2 > dist) {
  3532. dist = dist2;
  3533. }
  3534. float xr, yr, zr;
  3535. 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;
  3536. 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;
  3537. 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;
  3538. globalImages->BindNull();
  3539. GLTransformedCircle(0, b->owner->origin, xr, mat, 1.25, idVec3(0, 0, 1), dist);
  3540. GLTransformedCircle(1, b->owner->origin, yr, mat, 1.25, idVec3(0, 1, 0), dist);
  3541. GLTransformedCircle(2, b->owner->origin, zr, mat, 1.25, idVec3(1, 0, 0), dist);
  3542. float wr = xr;
  3543. int type = 0;
  3544. idVec3 org = b->owner->origin;
  3545. if (g_qeglobals.rotateAxis == 0) {
  3546. wr = zr;
  3547. type = 2;
  3548. } else if (g_qeglobals.rotateAxis == 1) {
  3549. wr = yr;
  3550. type = 1;
  3551. }
  3552. if (g_qeglobals.flatRotation) {
  3553. if (yr > wr) {
  3554. wr = yr;
  3555. }
  3556. if (zr > wr) {
  3557. wr = zr;
  3558. }
  3559. idVec3 vec = vec3_origin;
  3560. vec[g_qeglobals.rotateAxis] = 1.0f;
  3561. if (g_qeglobals.flatRotation == 1) {
  3562. org = g_pParentWnd->ActiveXY()->RotateOrigin();
  3563. float t = (org - bo.GetCenter()).Length();
  3564. if (t > wr) {
  3565. wr = t;
  3566. }
  3567. } else {
  3568. org = bo.GetCenter();
  3569. }
  3570. idRotation rot(org, vec, 0);
  3571. mat = rot.ToMat3();
  3572. }
  3573. GLTransformedCircle(type, org, wr * 1.03f, mat, 1.45f, idVec3(1, 1, 1), dist);
  3574. }
  3575. }
  3576. /*
  3577. ================
  3578. Brush_DrawModelInfo
  3579. ================
  3580. */
  3581. void Brush_DrawModelInfo(brush_t *b, bool selected) {
  3582. if (b->modelHandle > 0) {
  3583. GLfloat color[4];
  3584. qglGetFloatv(GL_CURRENT_COLOR, &color[0]);
  3585. if (selected) {
  3586. qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr());
  3587. }
  3588. else {
  3589. qglColor3fv(b->owner->eclass->color.ToFloatPtr());
  3590. }
  3591. Brush_DrawModel(b, true, selected);
  3592. qglColor4fv(color);
  3593. if ( selected ) {
  3594. Brush_DrawAxis(b);
  3595. }
  3596. return;
  3597. }
  3598. }
  3599. /*
  3600. ================
  3601. Brush_DrawEmitter
  3602. ================
  3603. */
  3604. void Brush_DrawEmitter(brush_t *b, bool bSelected, bool cam) {
  3605. if ( !( b->owner->eclass->nShowFlags & ECLASS_PARTICLE ) ) {
  3606. return;
  3607. }
  3608. if (bSelected) {
  3609. 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);
  3610. } else {
  3611. qglColor4f(b->owner->eclass->color.x, b->owner->eclass->color.y, b->owner->eclass->color.z, .5);
  3612. }
  3613. if ( cam ) {
  3614. Brush_DrawFacingAngle( b, b->owner, true );
  3615. }
  3616. }
  3617. /*
  3618. ================
  3619. Brush_DrawEnv
  3620. ================
  3621. */
  3622. void Brush_DrawEnv( brush_t *b, bool cameraView, bool bSelected ) {
  3623. idVec3 origin, newOrigin;
  3624. idMat3 axis, newAxis;
  3625. idAngles newAngles;
  3626. bool poseIsSet;
  3627. idRenderModel *model = gameEdit->AF_CreateMesh( b->owner->epairs, origin, axis, poseIsSet );
  3628. if ( !poseIsSet ) {
  3629. if ( Entity_GetRotationMatrixAngles( b->owner, newAxis, newAngles ) ) {
  3630. axis = newAxis;
  3631. }
  3632. if ( b->owner->epairs.GetVector( "origin", "0 0 0", newOrigin ) ) {
  3633. origin = newOrigin;
  3634. }
  3635. }
  3636. if ( model ) {
  3637. if ( cameraView && g_PrefsDlg.m_nEntityShowState != ENTITY_WIREFRAME ) {
  3638. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  3639. }
  3640. else {
  3641. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  3642. }
  3643. idVec4 colorSave;
  3644. qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
  3645. if ( bSelected ) {
  3646. qglColor3fv( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr() );
  3647. } else {
  3648. qglColor3f( 1.f, 1.f, 1.f );
  3649. }
  3650. DrawRenderModel( model, origin, axis, true );
  3651. globalImages->BindNull();
  3652. delete model;
  3653. model = NULL;
  3654. qglColor4fv( colorSave.ToFloatPtr() );
  3655. }
  3656. }
  3657. /*
  3658. ================
  3659. Brush_DrawCombatNode
  3660. ================
  3661. */
  3662. void Brush_DrawCombatNode( brush_t *b, bool cameraView, bool bSelected ) {
  3663. float min_dist = b->owner->epairs.GetFloat( "min" );
  3664. float max_dist = b->owner->epairs.GetFloat( "max" );
  3665. float fov = b->owner->epairs.GetFloat( "fov", "60" );
  3666. float yaw = b->owner->epairs.GetFloat("angle");
  3667. idVec3 offset = b->owner->epairs.GetVector("offset");
  3668. idAngles leftang( 0.0f, yaw + fov * 0.5f - 90.0f, 0.0f );
  3669. idVec3 cone_left = leftang.ToForward();
  3670. idAngles rightang( 0.0f, yaw - fov * 0.5f + 90.0f, 0.0f );
  3671. idVec3 cone_right = rightang.ToForward();
  3672. bool disabled = b->owner->epairs.GetBool( "start_off" );
  3673. idVec4 color;
  3674. if ( bSelected ) {
  3675. color = colorRed;
  3676. } else {
  3677. color = colorBlue;
  3678. }
  3679. idVec3 leftDir( -cone_left.y, cone_left.x, 0.0f );
  3680. idVec3 rightDir( cone_right.y, -cone_right.x, 0.0f );
  3681. leftDir.NormalizeFast();
  3682. rightDir.NormalizeFast();
  3683. idMat3 axis = idAngles(0, yaw, 0).ToMat3();
  3684. idVec3 org = b->owner->origin + offset;
  3685. idVec3 entorg = b->owner->origin;
  3686. float cone_dot = cone_right * axis[ 1 ];
  3687. if ( idMath::Fabs( cone_dot ) > 0.1 ) {
  3688. idVec3 pt, pt1, pt2, pt3, pt4;
  3689. float cone_dist = max_dist / cone_dot;
  3690. pt1 = org + leftDir * min_dist;
  3691. pt2 = org + leftDir * cone_dist;
  3692. pt3 = org + rightDir * cone_dist;
  3693. pt4 = org + rightDir * min_dist;
  3694. qglColor4fv(color.ToFloatPtr());
  3695. qglBegin(GL_LINE_STRIP);
  3696. qglVertex3fv( pt1.ToFloatPtr());
  3697. qglVertex3fv( pt2.ToFloatPtr());
  3698. qglVertex3fv( pt3.ToFloatPtr());
  3699. qglVertex3fv( pt4.ToFloatPtr());
  3700. qglVertex3fv( pt1.ToFloatPtr());
  3701. qglEnd();
  3702. qglColor4fv(colorGreen.ToFloatPtr());
  3703. qglBegin(GL_LINE_STRIP);
  3704. qglVertex3fv( entorg.ToFloatPtr());
  3705. pt = (pt1 + pt4) * 0.5f;
  3706. qglVertex3fv( pt.ToFloatPtr());
  3707. pt = (pt2 + pt3) * 0.5f;
  3708. qglVertex3fv( pt.ToFloatPtr());
  3709. idVec3 tip = pt;
  3710. idVec3 dir = ((pt1 + pt2) * 0.5f) - tip;
  3711. dir.Normalize();
  3712. pt = tip + dir * 15.0f;
  3713. qglVertex3fv( pt.ToFloatPtr());
  3714. qglVertex3fv( tip.ToFloatPtr());
  3715. dir = ((pt4 + pt3) * 0.5f) - tip;
  3716. dir.Normalize();
  3717. pt = tip + dir * 15.0f;
  3718. qglVertex3fv( pt.ToFloatPtr());
  3719. qglEnd();
  3720. }
  3721. }
  3722. /*
  3723. ================
  3724. Brush_Draw
  3725. ================
  3726. */
  3727. void Brush_Draw(brush_t *b, bool bSelected) {
  3728. face_t *face;
  3729. int i, order;
  3730. const idMaterial *prev = NULL;
  3731. idWinding *w;
  3732. bool model = false;
  3733. //
  3734. // (TTimo) NOTE: added by build 173, I check after pPlugEnt so it doesn't
  3735. // interfere ?
  3736. //
  3737. if ( b->hiddenBrush ) {
  3738. return;
  3739. }
  3740. Brush_DrawCurve( b, bSelected, true );
  3741. if (b->pPatch) {
  3742. Patch_DrawCam(b->pPatch, bSelected);
  3743. return;
  3744. }
  3745. int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  3746. if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE)) {
  3747. Brush_DrawFacingAngle(b, b->owner, false);
  3748. }
  3749. if ( b->owner->eclass->fixedsize ) {
  3750. DrawSpeaker( b, bSelected, false );
  3751. if ( g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT) && !(b->modelHandle || b->entityModel) ) {
  3752. DrawLight( b, bSelected );
  3753. return;
  3754. }
  3755. if ( b->owner->eclass->nShowFlags & ECLASS_ENV ) {
  3756. Brush_DrawEnv( b, true, bSelected );
  3757. }
  3758. if ( b->owner->eclass->nShowFlags & ECLASS_COMBATNODE ) {
  3759. Brush_DrawCombatNode( b, true, bSelected );
  3760. }
  3761. }
  3762. if (!(b->owner && (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN))) {
  3763. qglColor4f( 1.0f, 0.0f, 0.0f, 0.8f );
  3764. qglPointSize(4);
  3765. qglBegin(GL_POINTS);
  3766. qglVertex3fv(b->owner->origin.ToFloatPtr());
  3767. qglEnd();
  3768. }
  3769. if ( b->owner->eclass->entityModel ) {
  3770. qglColor3fv( b->owner->eclass->color.ToFloatPtr() );
  3771. Brush_DrawModel( b, true, bSelected );
  3772. return;
  3773. }
  3774. Brush_DrawEmitter( b, bSelected, true );
  3775. if ( b->modelHandle > 0 && !model ) {
  3776. Brush_DrawModelInfo( b, bSelected );
  3777. return;
  3778. }
  3779. // guarantee the texture will be set first
  3780. prev = NULL;
  3781. for (face = b->brush_faces, order = 0; face; face = face->next, order++) {
  3782. w = face->face_winding;
  3783. if (!w) {
  3784. continue; // freed face
  3785. }
  3786. if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) {
  3787. if (strstr(face->texdef.name, "caulk")) {
  3788. continue;
  3789. }
  3790. }
  3791. if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_VISPORTALS) {
  3792. if (strstr(face->texdef.name, "visportal")) {
  3793. continue;
  3794. }
  3795. }
  3796. if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_NODRAW) {
  3797. if (strstr(face->texdef.name, "nodraw")) {
  3798. continue;
  3799. }
  3800. }
  3801. if ( (nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev && !b->forceWireFrame ) {
  3802. // set the texture for this face
  3803. prev = face->d_texture;
  3804. face->d_texture->GetEditorImage()->Bind();
  3805. }
  3806. if (model) {
  3807. qglEnable(GL_BLEND);
  3808. qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  3809. qglColor4f( face->d_color.x, face->d_color.y, face->d_color.z, 0.1f );
  3810. } else {
  3811. qglColor4f( face->d_color.x, face->d_color.y, face->d_color.z, face->d_texture->GetEditorAlpha() );
  3812. }
  3813. qglBegin(GL_POLYGON);
  3814. for (i = 0; i < w->GetNumPoints(); i++) {
  3815. if ( !b->forceWireFrame && ( nDrawMode == cd_texture || nDrawMode == cd_light ) ) {
  3816. qglTexCoord2fv( &(*w)[i][3] );
  3817. }
  3818. qglVertex3fv( (*w)[i].ToFloatPtr() );
  3819. }
  3820. qglEnd();
  3821. if (model) {
  3822. qglDisable(GL_BLEND);
  3823. }
  3824. }
  3825. globalImages->BindNull();
  3826. }
  3827. /*
  3828. ================
  3829. Face_Draw
  3830. ================
  3831. */
  3832. void Face_Draw(face_t *f) {
  3833. int i;
  3834. if (f->face_winding == NULL) {
  3835. return;
  3836. }
  3837. qglBegin(GL_POLYGON);
  3838. for (i = 0; i < f->face_winding->GetNumPoints(); i++) {
  3839. qglVertex3fv( (*f->face_winding)[i].ToFloatPtr() );
  3840. }
  3841. qglEnd();
  3842. }
  3843. idSurface_SweptSpline *SplineToSweptSpline( idCurve<idVec3> *curve ) {
  3844. // expects a vec3 curve and creates a vec4 based swept spline
  3845. // must be either nurbs or catmull
  3846. idCurve_Spline<idVec4> *newCurve = NULL;
  3847. if ( dynamic_cast<idCurve_NURBS<idVec3>*>( curve ) ) {
  3848. newCurve = new idCurve_NURBS<idVec4>;
  3849. } else if ( dynamic_cast<idCurve_CatmullRomSpline<idVec3>*>( curve ) ) {
  3850. newCurve = new idCurve_CatmullRomSpline<idVec4>;
  3851. }
  3852. if ( curve == NULL || newCurve == NULL ) {
  3853. return NULL;
  3854. }
  3855. int c = curve->GetNumValues();
  3856. float len = 0.0f;
  3857. for ( int i = 0; i < c; i++ ) {
  3858. idVec3 v = curve->GetValue( i );
  3859. newCurve->AddValue( curve->GetTime( i ), idVec4( v.x, v.y, v.z, len ) );
  3860. if ( i < c - 1 ) {
  3861. len += curve->GetLengthBetweenKnots( i, i + 1 ) * 0.1f;
  3862. }
  3863. }
  3864. idSurface_SweptSpline *ss = new idSurface_SweptSpline;
  3865. ss->SetSpline( newCurve );
  3866. ss->SetSweptCircle( 10.0f );
  3867. ss->Tessellate( newCurve->GetNumValues() * 6, 6 );
  3868. return ss;
  3869. }
  3870. /*
  3871. ================
  3872. Brush_DrawCurve
  3873. ================
  3874. */
  3875. void Brush_DrawCurve( brush_t *b, bool bSelected, bool cam ) {
  3876. if ( b == NULL || b->owner->curve == NULL ) {
  3877. return;
  3878. }
  3879. int maxage = b->owner->curve->GetNumValues();
  3880. int i, time = 0;
  3881. qglColor3f( 0.0f, 0.0f, 1.0f );
  3882. for ( i = 0; i < maxage; i++) {
  3883. if ( bSelected && g_qeglobals.d_select_mode == sel_editpoint ) {
  3884. idVec3 v = b->owner->curve->GetValue( i );
  3885. if ( cam ) {
  3886. glBox( colorBlue, v, 6.0f );
  3887. if ( PointInMoveList( b->owner->curve->GetValueAddress( i ) ) >= 0 ) {
  3888. glBox(colorBlue, v, 8.0f );
  3889. }
  3890. } else {
  3891. qglPointSize( 4.0f );
  3892. qglBegin( GL_POINTS );
  3893. qglVertex3f( v.x, v.y, v.z );
  3894. qglEnd();
  3895. if ( PointInMoveList( b->owner->curve->GetValueAddress( i ) ) >= 0 ) {
  3896. glBox(colorBlue, v, 4.0f );
  3897. }
  3898. }
  3899. }
  3900. /*
  3901. if ( cam ) {
  3902. idSurface_SweptSpline *ss = SplineToSweptSpline( b->owner->curve );
  3903. if ( ss ) {
  3904. idMaterial *mat = declManager->FindMaterial( "_default" );
  3905. mat->GetEditorImage()->Bind();
  3906. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  3907. qglBegin( GL_TRIANGLES );
  3908. const int *indexes = ss->GetIndexes();
  3909. const idDrawVert *verts = ss->GetVertices();
  3910. for ( j = 0; j < ss->GetNumIndexes(); j += 3 ) {
  3911. for ( k = 0; k < 3; k++ ) {
  3912. int index = indexes[ j + 2 - k ];
  3913. float f = ShadeForNormal( verts[index].normal );
  3914. qglColor3f( f, f, f );
  3915. qglTexCoord2fv( verts[index].st.ToFloatPtr() );
  3916. qglVertex3fv( verts[index].xyz.ToFloatPtr() );
  3917. }
  3918. }
  3919. qglEnd();
  3920. delete ss;
  3921. }
  3922. } else {
  3923. */
  3924. /* qglPointSize( 1.0f );
  3925. qglBegin( GL_POINTS );
  3926. if ( i + 1 < maxage ) {
  3927. int start = b->owner->curve->GetTime( i );
  3928. int end = b->owner->curve->GetTime( i + 1 );
  3929. int inc = (end - start) / POINTS_PER_KNOT;
  3930. for ( int j = 0; j < POINTS_PER_KNOT; j++ ) {
  3931. idVec3 v = b->owner->curve->GetCurrentValue( start );
  3932. qglVertex3f( v.x, v.y, v.z );
  3933. start += inc;
  3934. }
  3935. }*/
  3936. // DHM - _D3XP : Makes it easier to see curve
  3937. qglBegin( GL_LINE_STRIP );
  3938. if ( i + 1 < maxage ) {
  3939. int start = b->owner->curve->GetTime( i );
  3940. int end = b->owner->curve->GetTime( i + 1 );
  3941. int inc = (end - start) / POINTS_PER_KNOT;
  3942. for ( int j = 0; j <= POINTS_PER_KNOT; j++ ) {
  3943. idVec3 v = b->owner->curve->GetCurrentValue( start );
  3944. qglVertex3f( v.x, v.y, v.z );
  3945. start += inc;
  3946. }
  3947. }
  3948. qglEnd();
  3949. /*
  3950. }
  3951. */
  3952. }
  3953. qglPointSize(1);
  3954. }
  3955. /*
  3956. ================
  3957. Brush_DrawXY
  3958. ================
  3959. */
  3960. void Brush_DrawXY(brush_t *b, int nViewType, bool bSelected, bool ignoreViewType) {
  3961. face_t *face;
  3962. int order;
  3963. idWinding *w;
  3964. int i;
  3965. if ( b->hiddenBrush ) {
  3966. return;
  3967. }
  3968. idVec4 colorSave;
  3969. qglGetFloatv(GL_CURRENT_COLOR, colorSave.ToFloatPtr());
  3970. if (!(b->owner && (b->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN))) {
  3971. qglColor4f( 1.0f, 0.0f, 0.0f, 0.8f );
  3972. qglPointSize(4);
  3973. qglBegin(GL_POINTS);
  3974. qglVertex3fv(b->owner->origin.ToFloatPtr());
  3975. qglEnd();
  3976. }
  3977. Brush_DrawCurve( b, bSelected, false );
  3978. qglColor4fv(colorSave.ToFloatPtr());
  3979. if (b->pPatch) {
  3980. Patch_DrawXY(b->pPatch);
  3981. if (!g_bPatchShowBounds) {
  3982. return;
  3983. }
  3984. }
  3985. if (b->owner->eclass->fixedsize) {
  3986. DrawSpeaker(b, bSelected, true);
  3987. if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT) && !(b->modelHandle || b->entityModel)) {
  3988. idVec3 vCorners[4];
  3989. float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
  3990. vCorners[0][0] = b->mins[0];
  3991. vCorners[0][1] = b->mins[1];
  3992. vCorners[0][2] = fMid;
  3993. vCorners[1][0] = b->mins[0];
  3994. vCorners[1][1] = b->maxs[1];
  3995. vCorners[1][2] = fMid;
  3996. vCorners[2][0] = b->maxs[0];
  3997. vCorners[2][1] = b->maxs[1];
  3998. vCorners[2][2] = fMid;
  3999. vCorners[3][0] = b->maxs[0];
  4000. vCorners[3][1] = b->mins[1];
  4001. vCorners[3][2] = fMid;
  4002. idVec3 vTop, vBottom;
  4003. vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
  4004. vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
  4005. vTop[2] = b->maxs[2];
  4006. VectorCopy(vTop, vBottom);
  4007. vBottom[2] = b->mins[2];
  4008. qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  4009. qglBegin(GL_TRIANGLE_FAN);
  4010. qglVertex3fv(vTop.ToFloatPtr());
  4011. qglVertex3fv(vCorners[0].ToFloatPtr());
  4012. qglVertex3fv(vCorners[1].ToFloatPtr());
  4013. qglVertex3fv(vCorners[2].ToFloatPtr());
  4014. qglVertex3fv(vCorners[3].ToFloatPtr());
  4015. qglVertex3fv(vCorners[0].ToFloatPtr());
  4016. qglEnd();
  4017. qglBegin(GL_TRIANGLE_FAN);
  4018. qglVertex3fv(vBottom.ToFloatPtr());
  4019. qglVertex3fv(vCorners[0].ToFloatPtr());
  4020. qglVertex3fv(vCorners[3].ToFloatPtr());
  4021. qglVertex3fv(vCorners[2].ToFloatPtr());
  4022. qglVertex3fv(vCorners[1].ToFloatPtr());
  4023. qglVertex3fv(vCorners[0].ToFloatPtr());
  4024. qglEnd();
  4025. DrawBrushEntityName(b);
  4026. DrawProjectedLight(b, bSelected, false);
  4027. return;
  4028. } else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL) {
  4029. // if (PaintedModel(b, false)) return;
  4030. } else if (b->owner->eclass->nShowFlags & ECLASS_ENV) {
  4031. Brush_DrawEnv( b, false, bSelected );
  4032. } else if (b->owner->eclass->nShowFlags & ECLASS_COMBATNODE) {
  4033. Brush_DrawCombatNode(b, false, bSelected);
  4034. }
  4035. if (b->owner->eclass->entityModel) {
  4036. Brush_DrawModel( b, false, bSelected );
  4037. DrawBrushEntityName(b);
  4038. qglColor4fv(colorSave.ToFloatPtr());
  4039. return;
  4040. }
  4041. }
  4042. qglColor4fv(colorSave.ToFloatPtr());
  4043. if (b->modelHandle > 0) {
  4044. Brush_DrawEmitter( b, bSelected, false );
  4045. Brush_DrawModel(b, false, bSelected);
  4046. qglColor4fv(colorSave.ToFloatPtr());
  4047. return;
  4048. }
  4049. for (face = b->brush_faces, order = 0; face; face = face->next, order++) {
  4050. // only draw polygons facing in a direction we care about
  4051. if (!ignoreViewType) {
  4052. if (nViewType == XY) {
  4053. if (face->plane[2] <= 0) {
  4054. continue;
  4055. }
  4056. } else {
  4057. if (nViewType == XZ) {
  4058. if (face->plane[1] <= 0) {
  4059. continue;
  4060. }
  4061. } else {
  4062. if (face->plane[0] <= 0) {
  4063. continue;
  4064. }
  4065. }
  4066. }
  4067. }
  4068. w = face->face_winding;
  4069. if (!w) {
  4070. continue;
  4071. }
  4072. //
  4073. // if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA)) continue;
  4074. // draw the polygon
  4075. //
  4076. qglBegin(GL_LINE_LOOP);
  4077. for (i = 0; i < w->GetNumPoints(); i++) {
  4078. qglVertex3fv( (*w)[i].ToFloatPtr() );
  4079. }
  4080. qglEnd();
  4081. /*
  4082. for (i = 0; i < 3; i++) {
  4083. glLabeledPoint(idVec4(1, 0, 0, 1), face->planepts[i], 3, va("%i", i));
  4084. }
  4085. */
  4086. }
  4087. DrawBrushEntityName(b);
  4088. }
  4089. /*
  4090. ==================
  4091. PointValueInPointList
  4092. ==================
  4093. */
  4094. static int PointValueInPointList( idVec3 v ) {
  4095. for ( int i = 0; i < g_qeglobals.d_numpoints; i++ ) {
  4096. if ( v == g_qeglobals.d_points[i] ) {
  4097. return i;
  4098. }
  4099. }
  4100. return -1;
  4101. }
  4102. extern bool Sys_KeyDown(int key);
  4103. /*
  4104. ================
  4105. Brush_Move
  4106. ================
  4107. */
  4108. void Brush_Move(brush_t *b, const idVec3 move, bool bSnap, bool updateOrigin) {
  4109. int i;
  4110. face_t *f;
  4111. char text[128];
  4112. for (f = b->brush_faces; f; f = f->next) {
  4113. idVec3 vTemp;
  4114. VectorCopy(move, vTemp);
  4115. if (g_PrefsDlg.m_bTextureLock) {
  4116. Face_MoveTexture(f, vTemp);
  4117. }
  4118. for (i = 0; i < 3; i++) {
  4119. VectorAdd(f->planepts[i], move, f->planepts[i]);
  4120. }
  4121. }
  4122. bool controlDown = Sys_KeyDown(VK_CONTROL);
  4123. Brush_Build(b, bSnap, true, false, !controlDown);
  4124. if (b->pPatch) {
  4125. Patch_Move(b->pPatch, move);
  4126. }
  4127. if ( b->owner->curve ) {
  4128. b->owner->curve->Translate( move );
  4129. Entity_UpdateCurveData( b->owner );
  4130. }
  4131. idVec3 temp;
  4132. // PGM - keep the origin vector up to date on fixed size entities.
  4133. if (b->owner->eclass->fixedsize || EntityHasModel(b->owner) || (updateOrigin && GetVectorForKey(b->owner, "origin", temp))) {
  4134. // if (!b->entityModel) {
  4135. bool adjustOrigin = true;
  4136. if(b->trackLightOrigin) {
  4137. b->owner->lightOrigin += move;
  4138. sprintf(text, "%i %i %i", (int)b->owner->lightOrigin[0], (int)b->owner->lightOrigin[1], (int)b->owner->lightOrigin[2]);
  4139. SetKeyValue(b->owner, "light_origin", text);
  4140. if (QE_SingleBrush(true, true)) {
  4141. adjustOrigin = false;
  4142. }
  4143. }
  4144. if (adjustOrigin && updateOrigin) {
  4145. b->owner->origin += move;
  4146. if (g_moveOnly) {
  4147. sprintf(text, "%g %g %g", b->owner->origin[0], b->owner->origin[1], b->owner->origin[2]);
  4148. } else {
  4149. sprintf(text, "%i %i %i", (int)b->owner->origin[0], (int)b->owner->origin[1], (int)b->owner->origin[2]);
  4150. }
  4151. SetKeyValue(b->owner, "origin", text);
  4152. }
  4153. // rebuild the light dragging points now that the origin has changed
  4154. idVec3 offset;
  4155. offset.Zero();
  4156. if (controlDown) {
  4157. offset.x = -move.x;
  4158. offset.y = -move.y;
  4159. offset.z = -move.z;
  4160. Brush_UpdateLightPoints(b, offset);
  4161. } else {
  4162. offset.Zero();
  4163. Brush_UpdateLightPoints(b, offset);
  4164. }
  4165. //}
  4166. if (b->owner->eclass->nShowFlags & ECLASS_ENV) {
  4167. const idKeyValue *arg = b->owner->epairs.MatchPrefix( "body ", NULL );
  4168. idStr val;
  4169. idVec3 org;
  4170. idAngles ang;
  4171. while ( arg ) {
  4172. sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
  4173. org += move;
  4174. val = org.ToString(8);
  4175. val += " ";
  4176. val += ang.ToString(8);
  4177. b->owner->epairs.Set(arg->GetKey(), val);
  4178. arg = b->owner->epairs.MatchPrefix( "body ", arg );
  4179. }
  4180. }
  4181. }
  4182. }
  4183. /*
  4184. ================
  4185. Select_AddProjectedLight
  4186. ================
  4187. */
  4188. void Select_AddProjectedLight() {
  4189. idVec3 vTemp;
  4190. CString str;
  4191. // if (!QE_SingleBrush ()) return;
  4192. brush_t *b = selected_brushes.next;
  4193. if (b->owner->eclass->nShowFlags & ECLASS_LIGHT) {
  4194. vTemp[0] = vTemp[1] = 0;
  4195. vTemp[2] = -256;
  4196. str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
  4197. SetKeyValue(b->owner, "light_target", str);
  4198. vTemp[2] = 0;
  4199. vTemp[1] = -128;
  4200. str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
  4201. SetKeyValue(b->owner, "light_up", str);
  4202. vTemp[1] = 0;
  4203. vTemp[0] = -128;
  4204. str.Format("%f %f %f", vTemp[0], vTemp[1], vTemp[2]);
  4205. SetKeyValue(b->owner, "light_right", str);
  4206. Brush_Build(b);
  4207. }
  4208. }
  4209. /*
  4210. ================
  4211. Brush_Print
  4212. ================
  4213. */
  4214. void Brush_Print(brush_t *b) {
  4215. int nFace = 0;
  4216. for (face_t * f = b->brush_faces; f; f = f->next) {
  4217. common->Printf("Face %i\n", nFace++);
  4218. common->Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
  4219. common->Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
  4220. common->Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
  4221. }
  4222. }
  4223. /*
  4224. ================
  4225. Brush_MakeSidedCone
  4226. Makes the current brush have the given number of 2d sides and turns it into a cone
  4227. ================
  4228. */
  4229. void Brush_MakeSidedCone(int sides) {
  4230. int i;
  4231. idVec3 mins, maxs;
  4232. brush_t *b;
  4233. texdef_t *texdef;
  4234. face_t *f;
  4235. idVec3 mid;
  4236. float width;
  4237. float sv, cv;
  4238. if (sides < 3) {
  4239. Sys_Status("Bad sides number", 0);
  4240. return;
  4241. }
  4242. if (!QE_SingleBrush()) {
  4243. Sys_Status("Must have a single brush selected", 0);
  4244. return;
  4245. }
  4246. b = selected_brushes.next;
  4247. VectorCopy(b->mins, mins);
  4248. VectorCopy(b->maxs, maxs);
  4249. texdef = &g_qeglobals.d_texturewin.texdef;
  4250. Brush_Free(b);
  4251. // find center of brush
  4252. width = 8;
  4253. for (i = 0; i < 2; i++) {
  4254. mid[i] = (maxs[i] + mins[i]) * 0.5f;
  4255. if (maxs[i] - mins[i] > width) {
  4256. width = maxs[i] - mins[i];
  4257. }
  4258. }
  4259. width *= 0.5f;
  4260. b = Brush_Alloc();
  4261. // create bottom face
  4262. f = Face_Alloc();
  4263. f->texdef = *texdef;
  4264. f->next = b->brush_faces;
  4265. b->brush_faces = f;
  4266. f->planepts[0][0] = mins[0];
  4267. f->planepts[0][1] = mins[1];
  4268. f->planepts[0][2] = mins[2];
  4269. f->planepts[1][0] = maxs[0];
  4270. f->planepts[1][1] = mins[1];
  4271. f->planepts[1][2] = mins[2];
  4272. f->planepts[2][0] = maxs[0];
  4273. f->planepts[2][1] = maxs[1];
  4274. f->planepts[2][2] = mins[2];
  4275. for (i = 0; i < sides; i++) {
  4276. f = Face_Alloc();
  4277. f->texdef = *texdef;
  4278. f->next = b->brush_faces;
  4279. b->brush_faces = f;
  4280. sv = sin(i * idMath::TWO_PI / sides);
  4281. cv = cos(i * idMath::TWO_PI / sides);
  4282. f->planepts[0][0] = floor( mid[0] + width * cv + 0.5f );
  4283. f->planepts[0][1] = floor( mid[1] + width * sv + 0.5f );
  4284. f->planepts[0][2] = mins[2];
  4285. f->planepts[1][0] = mid[0];
  4286. f->planepts[1][1] = mid[1];
  4287. f->planepts[1][2] = maxs[2];
  4288. f->planepts[2][0] = floor( f->planepts[0][0] - width * sv + 0.5f );
  4289. f->planepts[2][1] = floor( f->planepts[0][1] + width * cv + 0.5f );
  4290. f->planepts[2][2] = maxs[2];
  4291. }
  4292. Brush_AddToList(b, &selected_brushes);
  4293. Entity_LinkBrush(world_entity, b);
  4294. Brush_Build(b);
  4295. Sys_UpdateWindows(W_ALL);
  4296. }
  4297. /*
  4298. ================
  4299. Brush_MakeSidedSphere
  4300. Makes the current brushhave the given number of 2d sides and turns it into a sphere
  4301. ================
  4302. */
  4303. void Brush_MakeSidedSphere(int sides) {
  4304. int i, j;
  4305. idVec3 mins, maxs;
  4306. brush_t *b;
  4307. texdef_t *texdef;
  4308. face_t *f;
  4309. idVec3 mid;
  4310. float radius;
  4311. if (sides < 4) {
  4312. Sys_Status("Bad sides number", 0);
  4313. return;
  4314. }
  4315. if (!QE_SingleBrush()) {
  4316. Sys_Status("Must have a single brush selected", 0);
  4317. return;
  4318. }
  4319. b = selected_brushes.next;
  4320. mins = b->mins;
  4321. maxs = b->maxs;
  4322. texdef = &g_qeglobals.d_texturewin.texdef;
  4323. Brush_Free(b);
  4324. // find center of brush
  4325. radius = 8;
  4326. for ( i = 0; i < 3; i++ ) {
  4327. mid[i] = (maxs[i] + mins[i]) * 0.5f;
  4328. if (maxs[i] - mins[i] > radius) {
  4329. radius = maxs[i] - mins[i];
  4330. }
  4331. }
  4332. radius *= 0.5f;
  4333. b = Brush_Alloc();
  4334. for (i = 0; i < sides; i++) {
  4335. for (j = 0; j < sides - 1; j++) {
  4336. f = Face_Alloc();
  4337. f->texdef = *texdef;
  4338. f->next = b->brush_faces;
  4339. b->brush_faces = f;
  4340. f->planepts[0] = idPolar3(radius, idMath::TWO_PI * i / sides, idMath::PI * ((float)(j) / sides - 0.5f) ).ToVec3() + mid;
  4341. f->planepts[1] = idPolar3(radius, idMath::TWO_PI * i / sides, idMath::PI * ((float)(j+1) / sides - 0.5f) ).ToVec3() + mid;
  4342. f->planepts[2] = idPolar3(radius, idMath::TWO_PI * (i+1) / sides, idMath::PI * ((float)(j+1) / sides - 0.5f) ).ToVec3() + mid;
  4343. }
  4344. }
  4345. Brush_AddToList(b, &selected_brushes);
  4346. Entity_LinkBrush(world_entity, b);
  4347. Brush_Build(b);
  4348. Sys_UpdateWindows(W_ALL);
  4349. }
  4350. extern void Face_FitTexture_BrushPrimit(face_t *f, idVec3 mins, idVec3 maxs, float nHeight, float nWidth);
  4351. /*
  4352. ================
  4353. Face_FitTexture
  4354. ================
  4355. */
  4356. void Face_FitTexture(face_t *face, float nHeight, float nWidth) {
  4357. if (g_qeglobals.m_bBrushPrimitMode) {
  4358. idVec3 mins, maxs;
  4359. mins[0] = maxs[0] = 0;
  4360. Face_FitTexture_BrushPrimit(face, mins, maxs, nHeight, nWidth);
  4361. }
  4362. else {
  4363. /*
  4364. * winding_t *w; idBounds bounds; int i; float width, height, temp; float rot_width,
  4365. * rot_height; float cosv,sinv,ang; float min_t, min_s, max_t, max_s; float s,t;
  4366. * idVec3 vecs[2]; idVec3 coords[4]; texdef_t *td; if (nHeight < 1) { nHeight = 1;
  4367. * } if (nWidth < 1) { nWidth = 1; } bounds.Clear(); td = &face->texdef; w =
  4368. * face->face_winding; if (!w) { return; } for (i=0 ; i<w->numpoints ; i++) {
  4369. * bounds.AddPoint( w->p[i] ); } // // get the current angle // ang = td->rotate /
  4370. * 180 * Q_PI; sinv = sin(ang); cosv = cos(ang); // get natural texture axis
  4371. * TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]); min_s = DotProduct(
  4372. * bounds.b[0], vecs[0] ); min_t = DotProduct( bounds.b[0], vecs[1] ); max_s =
  4373. * DotProduct( bounds.b[1], vecs[0] ); max_t = DotProduct( bounds.b[1], vecs[1] );
  4374. * width = max_s - min_s; height = max_t - min_t; coords[0][0] = min_s;
  4375. * coords[0][1] = min_t; coords[1][0] = max_s; coords[1][1] = min_t; coords[2][0]
  4376. * = min_s; coords[2][1] = max_t; coords[3][0] = max_s; coords[3][1] = max_t;
  4377. * min_s = min_t = 999999; max_s = max_t = -999999; for (i=0; i<4; i++) { s = cosv
  4378. * * coords[i][0] - sinv * coords[i][1]; t = sinv * coords[i][0] + cosv *
  4379. * coords[i][1]; if (i&1) { if (s > max_s) { max_s = s; } } else { if (s < min_s)
  4380. * { min_s = s; } if (i<2) { if (t < min_t) { min_t = t; } } else { if (t > max_t)
  4381. * { max_t = t; } } } } rot_width = (max_s - min_s); rot_height = (max_t - min_t);
  4382. * td->scale[0] =
  4383. * -(rot_width/((float)(face->d_texture->GetEditorImage()->uploadWidth*nWidth)));
  4384. * td->scale[1] =
  4385. * -(rot_height/((float)(face->d_texture->GetEditorImage()->uploadHeight*nHeight)));
  4386. * td->shift[0] = min_s/td->scale[0]; temp = (int)(td->shift[0] /
  4387. * (face->d_texture->GetEditorImage()->uploadWidth*nWidth)); temp =
  4388. * (temp+1)*face->d_texture->GetEditorImage()->uploadWidth*nWidth; td->shift[0] =
  4389. * (int)(temp -
  4390. * td->shift[0])%(face->d_texture->GetEditorImage()->uploadWidth*nWidth);
  4391. * td->shift[1] = min_t/td->scale[1]; temp = (int)(td->shift[1] /
  4392. * (face->d_texture->GetEditorImage()->uploadHeight*nHeight)); temp =
  4393. * (temp+1)*(face->d_texture->GetEditorImage()->uploadHeight*nHeight);
  4394. * td->shift[1] = (int)(temp -
  4395. * td->shift[1])%(face->d_texture->GetEditorImage()->uploadHeight*nHeight);
  4396. */
  4397. }
  4398. }
  4399. /*
  4400. ================
  4401. Brush_FitTexture
  4402. ================
  4403. */
  4404. void Brush_FitTexture(brush_t *b, float nHeight, float nWidth) {
  4405. face_t *face;
  4406. for (face = b->brush_faces; face; face = face->next) {
  4407. Face_FitTexture(face, nHeight, nWidth);
  4408. }
  4409. }
  4410. void Brush_GetBounds( brush_t *b, idBounds &bo ) {
  4411. if ( b == NULL ) {
  4412. return;
  4413. }
  4414. bo.Clear();
  4415. bo.AddPoint( b->mins );
  4416. bo.AddPoint( b->maxs );
  4417. if ( b->owner->curve ) {
  4418. int c = b->owner->curve->GetNumValues();
  4419. for ( int i = 0; i < c; i++ ) {
  4420. bo.AddPoint ( b->owner->curve->GetValue( i ) );
  4421. }
  4422. }
  4423. }