PMESH.CPP 112 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462
  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 "DialogInfo.h"
  24. #include "CapDialog.h"
  25. // externs
  26. extern void MemFile_fprintf( CMemFile *pMemFile,const char *pText,... );
  27. extern face_t *Face_Alloc( void );
  28. void _Write3DMatrix( FILE *f,int y,int x,int z,float *m );
  29. void _Write3DMatrix( CMemFile *f,int y,int x,int z,float *m );
  30. extern void SamplePatch( float ctrl[3][3][5],int baseCol,int baseRow,int width,int horzSub,int vertSub,idDrawVert *outVerts,idDrawVert *drawVerts );
  31. patchMesh_t *Patch_GenerateGeneric( int width,int height,int orientation,const idVec3 &mins,const idVec3 &maxs );
  32. patchMesh_t * MakeNewPatch( int width,int height ) {
  33. patchMesh_t *pm = reinterpret_cast< patchMesh_t*>(Mem_ClearedAlloc(sizeof(patchMesh_t)));
  34. pm->horzSubdivisions = DEFAULT_CURVE_SUBDIVISION;
  35. pm->vertSubdivisions = DEFAULT_CURVE_SUBDIVISION;
  36. pm->explicitSubdivisions = false;
  37. pm->width = width;
  38. pm->height = height;
  39. pm->verts = reinterpret_cast< idDrawVert*>(Mem_ClearedAlloc(sizeof(idDrawVert) * width * height));
  40. //pm->ctrl = reinterpret_cast<idDrawVert*>(Mem_ClearedAlloc(sizeof(idDrawVert) * width * height));
  41. //pm->ctrl = &pm->verts;
  42. return pm;
  43. }
  44. void Patch_AdjustSize( patchMesh_t *p,int wadj,int hadj ) {
  45. idDrawVert *newverts = reinterpret_cast< idDrawVert*>(Mem_ClearedAlloc(sizeof(idDrawVert) * (p->width + wadj) * (p->height + hadj)));
  46. int copyWidth = (wadj < 0) ? p->width + wadj : p->width;
  47. int copyHeight = (hadj < 0) ? p->height + hadj : p->height;
  48. int copysize = copyWidth *copyHeight * sizeof(idDrawVert);
  49. for ( int i = 0; i < p->width; i++ ) {
  50. for ( int j = 0; j < p->height; j++ ) {
  51. newverts[j * (p->width + wadj) + i] = p->ctrl(i, j);
  52. }
  53. }
  54. p->width += wadj;
  55. p->height += hadj;
  56. Mem_Free(p->verts);
  57. p->verts = newverts;
  58. }
  59. // algorithm from Journal of graphics tools, 2(1):21-28, 1997
  60. bool RayIntersectsTri( const idVec3 &origin,const idVec3 &direction,const idVec3 &vert0,const idVec3 &vert1,const idVec3 &vert2,float &scale ) {
  61. idVec3 edge1, edge2, tvec, pvec, qvec;
  62. float det, inv_det;
  63. scale = 0;
  64. /* find vectors for two edges sharing vert0 */
  65. edge1 = vert1 - vert0;
  66. edge2 = vert2 - vert0;
  67. /* begin calculating determinant - also used to calculate U parameter */
  68. pvec.Cross(direction, edge2);
  69. /* if determinant is near zero, ray lies in plane of triangle */
  70. det = edge1 * pvec;
  71. if ( det > -VECTOR_EPSILON && det < VECTOR_EPSILON ) {
  72. return false;
  73. }
  74. inv_det = 1.0f / det;
  75. /* calculate distance from vert0 to ray origin */
  76. tvec = origin - vert0;
  77. /* calculate U parameter and test bounds */
  78. float u = (tvec *pvec) * inv_det;
  79. if ( u < 0.0f || u> 1.0f ) {
  80. return false;
  81. }
  82. /* prepare to test V parameter */
  83. qvec.Cross(tvec, edge1);
  84. /* calculate V parameter and test bounds */
  85. float v = (direction *qvec) * inv_det;
  86. if ( v < 0.0f || u + v> 1.0f ) {
  87. return false;
  88. }
  89. scale = tvec.Length();
  90. return true;
  91. }
  92. bool Patch_Intersect( patchMesh_t *pm,idVec3 origin,idVec3 direction,float &scale ) {
  93. int i, j;
  94. //float scale;
  95. idSurface_Patch cp (pm->width * 6, pm->height * 6);
  96. cp.SetSize(pm->width, pm->height);
  97. for ( i = 0; i < pm->width; i++ ) {
  98. for ( j = 0; j < pm->height; j++ ) {
  99. (cp)[j * cp.GetWidth() + i].xyz = pm->ctrl(i, j).xyz;
  100. (cp)[j * cp.GetWidth() + i].st = pm->ctrl(i, j).st;
  101. }
  102. }
  103. if ( pm->explicitSubdivisions ) {
  104. cp.SubdivideExplicit(pm->horzSubdivisions, pm->vertSubdivisions, false);
  105. } else {
  106. cp.Subdivide(DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_LENGTH, false);
  107. }
  108. if ( cp.RayIntersection(origin, direction, scale) ) {
  109. return true;
  110. } else {
  111. return false;
  112. }
  113. /*
  114. int width = cp.GetWidth();
  115. int height = cp.GetHeight();
  116. for ( i = 0 ; i < width - 1; i++ ) {
  117. for ( j = 0 ; j < height - 1; j++ ) {
  118. // v1-v2-v3-v4 makes a quad
  119. int v1, v2, v3, v4;
  120. v1 = j * width + i;
  121. v2 = v1 + 1;
  122. v3 = v1 + width + 1;
  123. v4 = v1 + width;
  124. if (RayIntersectsTri(origin, direction, (cp)[v1].xyz, (cp)[v2].xyz, (cp)[v3].xyz)) {
  125. return true;
  126. }
  127. if (RayIntersectsTri(origin, direction, (cp)[v3].xyz, (cp)[v4].xyz, (cp)[v1].xyz)) {
  128. return true;
  129. }
  130. }
  131. }
  132. return false;
  133. */
  134. }
  135. patchMesh_t * Patch_MakeNew( patchMesh_t *p,int newWidth,int newHeight ) {
  136. patchMesh_t *newPatch = MakeNewPatch(newWidth, newHeight);
  137. newPatch->d_texture = p->d_texture;
  138. newPatch->horzSubdivisions = p->horzSubdivisions;
  139. newPatch->vertSubdivisions = p->vertSubdivisions;
  140. newPatch->explicitSubdivisions = p->explicitSubdivisions;
  141. return newPatch;
  142. }
  143. void Patch_Combine( patchMesh_t *p,patchMesh_t *p2,int sourceCol1,int sourceCol2,int sourceRow1,int sourceRow2,bool invert1,bool invert2 ) {
  144. int i, j, out;
  145. patchMesh_t *newPatch = NULL;
  146. if ( sourceCol1 >= 0 ) {
  147. // adding width
  148. if ( sourceCol2 >= 0 ) {
  149. // from width
  150. newPatch = Patch_MakeNew(p, p->width + p2->width - 1, p->height);
  151. int adj1 = 1;
  152. int adj2 = 1;
  153. int col1 = 0;
  154. int col2 = 1;
  155. if ( sourceCol1 != 0 ) {
  156. adj1 = -1;
  157. col1 = p->width - 1;
  158. }
  159. if ( sourceCol2 != 0 ) {
  160. adj2 = -1;
  161. col2 = p2->width - 2;
  162. }
  163. out = 0;
  164. for ( i = 0; i < p->width; i++, col1 += adj1 ) {
  165. int in = (invert1) ? p->height - 1 : 0;
  166. for ( j = 0; j < p->height; j++ ) {
  167. newPatch->ctrl(out, j) = p->ctrl(col1, in);
  168. in += (invert1) ? -1 : 1;
  169. }
  170. out++;
  171. }
  172. for ( i = 1; i < p2->width; i++, col2 += adj2 ) {
  173. int in = (invert2) ? p2->height - 1 : 0;
  174. for ( j = 0; j < p2->height; j++ ) {
  175. newPatch->ctrl(out, j) = p2->ctrl(col2, in);
  176. in += (invert2) ? -1 : 1;
  177. }
  178. out++;
  179. }
  180. } else {
  181. // from height
  182. newPatch = Patch_MakeNew(p, p->width + p2->height - 1, p->height);
  183. int adj1 = 1;
  184. int adj2 = 1;
  185. int col1 = 0;
  186. int row2 = 1;
  187. if ( sourceCol1 != 0 ) {
  188. adj1 = -1;
  189. col1 = p->width - 1;
  190. }
  191. if ( sourceRow2 != 0 ) {
  192. adj2 = -1;
  193. row2 = p2->height - 2;
  194. }
  195. out = 0;
  196. for ( i = 0; i < p->width; i++, col1 += adj1 ) {
  197. int in = (invert1) ? p->height - 1 : 0;
  198. for ( j = 0; j < p->height; j++ ) {
  199. newPatch->ctrl(out, j) = p->ctrl(col1, in);
  200. in += (invert1) ? -1 : 1;
  201. }
  202. out++;
  203. }
  204. for ( i = 1; i < p2->height; i++, row2 += adj2 ) {
  205. int in = (invert2) ? p2->width - 1 : 0;
  206. for ( j = 0; j < p2->width; j++ ) {
  207. newPatch->ctrl(out, j) = p2->ctrl(in, row2);
  208. in += (invert2) ? -1 : 1;
  209. }
  210. out++;
  211. }
  212. }
  213. } else {
  214. // adding height
  215. if ( sourceRow1 >= 0 ) {
  216. // from height
  217. newPatch = Patch_MakeNew(p, p->width, p->height + p2->height - 1);
  218. int adj1 = 1;
  219. int adj2 = 1;
  220. int row1 = 0;
  221. int row2 = 0;
  222. if ( sourceRow1 != 0 ) {
  223. adj1 = -1;
  224. row1 = p->height - 1;
  225. }
  226. if ( sourceRow2 != 0 ) {
  227. adj2 = -1;
  228. row2 = p2->height - 2;
  229. }
  230. out = 0;
  231. for ( i = 0; i < p->height; i++, row1 += adj1 ) {
  232. int in = (invert1) ? p->width - 1 : 0;
  233. for ( j = 0; j < p->width; j++ ) {
  234. newPatch->ctrl(j, out) = p->ctrl(in, row1);
  235. in += (invert1) ? -1 : 1;
  236. }
  237. out++;
  238. }
  239. for ( i = 1; i < p2->height; i++, row2 += adj2 ) {
  240. int in = (invert2) ? p->width - 1 : 0;
  241. for ( j = 0; j < p2->width; j++ ) {
  242. newPatch->ctrl(j, out) = p2->ctrl(in, row2);
  243. in += (invert1) ? -1 : 1;
  244. }
  245. out++;
  246. }
  247. } else {
  248. // from width
  249. newPatch = Patch_MakeNew(p, p->width, p->height + p2->width - 1);
  250. int adj1 = 1;
  251. int adj2 = 1;
  252. int row1 = 0;
  253. int col2 = 0;
  254. if ( sourceRow1 != 0 ) {
  255. adj1 = -1;
  256. row1 = p->height - 1;
  257. }
  258. if ( sourceCol2 != 0 ) {
  259. adj2 = -1;
  260. col2 = p2->width - 2;
  261. }
  262. out = 0;
  263. for ( i = 0; i < p->height; i++, row1 += adj1 ) {
  264. int in = (invert1) ? p->width - 1 : 0;
  265. for ( j = 0; j < p->width; j++ ) {
  266. newPatch->ctrl(j, out) = p->ctrl(in, row1);
  267. in += (invert1) ? -1 : 1;
  268. }
  269. out++;
  270. }
  271. for ( i = 1; i < p2->width; i++, col2 += adj2 ) {
  272. int in = (invert2) ? p->height - 1 : 0;
  273. for ( j = 0; j < p2->height; j++ ) {
  274. newPatch->ctrl(j, out) = p2->ctrl(col2, in);
  275. in += (invert1) ? -1 : 1;
  276. }
  277. out++;
  278. }
  279. }
  280. }
  281. if ( newPatch ) {
  282. AddBrushForPatch(newPatch, true);
  283. Brush_Free(p->pSymbiot, true);
  284. Brush_Free(p2->pSymbiot, true);
  285. Patch_Naturalize(newPatch, true, true);
  286. }
  287. }
  288. #define WELD_EPSILON 0.001f
  289. void Patch_Weld( patchMesh_t *p,patchMesh_t *p2 ) {
  290. // check against all 4 edges of p2
  291. // could roll this up but left it out for some semblence of clarity
  292. //
  293. if ( p->width == p2->width ) {
  294. int row = 0;
  295. int row2 = 0;
  296. while ( 1 ) {
  297. bool match = true;
  298. // need to see if any of the corners match then run down or up based
  299. // on the match edges
  300. int col1 = 0;
  301. int col2 = 0;
  302. int adj1 = 1;
  303. int adj2 = 1;
  304. if ( p->ctrl(0, row).xyz.Compare(p2->ctrl(0, row2).xyz, WELD_EPSILON) ) {
  305. } else if ( p->ctrl(0, row).xyz.Compare(p2->ctrl(p2->width - 1, row2).xyz, WELD_EPSILON) ) {
  306. col2 = p2->width - 1;
  307. adj2 = -1;
  308. } else if ( p->ctrl(p->width - 1, row).xyz.Compare(p2->ctrl(p2->width - 1, row2).xyz, WELD_EPSILON) ) {
  309. col2 = p2->width - 1;
  310. adj2 = -1;
  311. col1 = p->width - 1;
  312. adj1 = -1;
  313. } else if ( p->ctrl(p->width - 1, row).xyz.Compare(p2->ctrl(0, row2).xyz, WELD_EPSILON) ) {
  314. col1 = p->width - 1;
  315. adj1 = -1;
  316. } else {
  317. adj1 = 0;
  318. }
  319. if ( adj1 ) {
  320. for ( int col = 0; col < p->width; col++, col2 += adj2, col1 += adj1 ) {
  321. if ( !p->ctrl(col1, row).xyz.Compare(p2->ctrl(col2, row2).xyz, WELD_EPSILON) ) {
  322. match = false;
  323. break;
  324. }
  325. }
  326. } else {
  327. match = false;
  328. }
  329. if ( match ) {
  330. // have a match weld these edges
  331. common->Printf("Welding row %i with row %i\n", row, row2);
  332. row = (row == 0) ? p->height - 1 : 0;
  333. Patch_Combine(p, p2, -1, -1, row, row2, (adj1 == -1), (adj2 == -1));
  334. return;
  335. } else if ( row2 == 0 ) {
  336. row2 = p2->height - 1;
  337. } else if ( row == 0 ) {
  338. row = p->height - 1;
  339. row2 = 0;
  340. } else {
  341. break;
  342. }
  343. }
  344. }
  345. if ( p->width == p2->height ) {
  346. int row = 0;
  347. int col2 = 0;
  348. while ( 1 ) {
  349. bool match = true;
  350. int col1 = 0;
  351. int adj1 = 1;
  352. int row2 = 0;
  353. int adj2 = 1;
  354. if ( p->ctrl(0, row).xyz.Compare(p2->ctrl(col2, 0).xyz, WELD_EPSILON) ) {
  355. } else if ( p->ctrl(0, row).xyz.Compare(p2->ctrl(col2, p2->height - 1).xyz, WELD_EPSILON) ) {
  356. row2 = p2->height - 1;
  357. adj2 = -1;
  358. } else if ( p->ctrl(p->width - 1, row).xyz.Compare(p2->ctrl(col2, p2->height - 1).xyz, WELD_EPSILON) ) {
  359. row2 = p2->height - 1;
  360. adj2 = -1;
  361. col1 = p->width - 1;
  362. adj1 = -1;
  363. } else if ( p->ctrl(p->width - 1, row).xyz.Compare(p2->ctrl(col2, 0).xyz, WELD_EPSILON) ) {
  364. col1 = p->width - 1;
  365. adj1 = -1;
  366. } else {
  367. adj1 = 0;
  368. }
  369. if ( adj1 ) {
  370. for ( int col = 0; col < p->width; col++, col1 += adj1, row2 += adj2 ) {
  371. if ( !p->ctrl(col1, row).xyz.Compare(p2->ctrl(col2, row2).xyz, WELD_EPSILON) ) {
  372. match = false;
  373. break;
  374. }
  375. }
  376. } else {
  377. match = false;
  378. }
  379. if ( match ) {
  380. // have a match weld these edges
  381. common->Printf("Welding row %i with col %i\n", row, col2);
  382. row = (row == 0) ? p->height - 1 : 0;
  383. Patch_Combine(p, p2, -1, col2, row, -1, (adj1 == -1), (adj2 == -1));
  384. return;
  385. } else if ( col2 == 0 ) {
  386. col2 = p2->width - 1;
  387. } else if ( row == 0 ) {
  388. row = p->height - 1;
  389. col2 = 0;
  390. } else {
  391. break;
  392. }
  393. }
  394. }
  395. if ( p->height == p2->width ) {
  396. int col = 0;
  397. int row2 = 0;
  398. while ( 1 ) {
  399. bool match = true;
  400. int row1 = 0;
  401. int adj1 = 1;
  402. int col2 = 0;
  403. int adj2 = 1;
  404. if ( p->ctrl(col, 0).xyz.Compare(p2->ctrl(0, row2).xyz, WELD_EPSILON) ) {
  405. } else if ( p->ctrl(col, 0).xyz.Compare(p2->ctrl(p2->width - 1, row2).xyz, WELD_EPSILON) ) {
  406. col2 = p2->width - 1;
  407. adj2 = -1;
  408. } else if ( p->ctrl(col, p->height - 1).xyz.Compare(p2->ctrl(p2->width - 1, row2).xyz, WELD_EPSILON) ) {
  409. col2 = p2->width - 1;
  410. adj2 = -1;
  411. row1 = p2->height - 1;
  412. adj2 = -1;
  413. } else if ( p->ctrl(col, p->height - 1).xyz.Compare(p2->ctrl(0, row2).xyz, WELD_EPSILON) ) {
  414. row1 = p2->height - 1;
  415. adj2 = -1;
  416. } else {
  417. adj1 = 0;
  418. }
  419. if ( adj1 ) {
  420. for ( int row = 0; row < p->height; row++, row1 += adj1, col2 += adj2 ) {
  421. if ( !p->ctrl(col, row1).xyz.Compare(p2->ctrl(col2, row2).xyz, WELD_EPSILON) ) {
  422. match = false;
  423. break;
  424. }
  425. }
  426. } else {
  427. match = false;
  428. }
  429. if ( match ) {
  430. // have a match weld these edges
  431. common->Printf("Welding col %i with row %i\n", col, row2);
  432. col = (col == 0) ? p->width - 1 : 0;
  433. Patch_Combine(p, p2, col, -1, -1, row2, (adj1 == -1), (adj2 == -1));
  434. return;
  435. } else if ( row2 == 0 ) {
  436. row2 = p2->height - 1;
  437. } else if ( col == 0 ) {
  438. col = p->width - 1;
  439. row2 = 0;
  440. } else {
  441. break;
  442. }
  443. }
  444. }
  445. if ( p->height == p2->height ) {
  446. int col = 0;
  447. int col2 = 0;
  448. while ( 1 ) {
  449. bool match = true;
  450. int row1 = 0;
  451. int adj1 = 1;
  452. int row2 = 0;
  453. int adj2 = 1;
  454. if ( p->ctrl(col, 0).xyz.Compare(p2->ctrl(col2, 0).xyz, WELD_EPSILON) ) {
  455. } else if ( p->ctrl(col, 0).xyz.Compare(p2->ctrl(col2, p2->height - 1).xyz, WELD_EPSILON) ) {
  456. row2 = p2->height - 1;
  457. adj2 = -1;
  458. } else if ( p->ctrl(col, p2->height - 1).xyz.Compare(p2->ctrl(col2, p2->height - 1).xyz, WELD_EPSILON) ) {
  459. row2 = p2->height - 1;
  460. adj2 = -1;
  461. row1 = p->height - 1;
  462. adj1 = -1;
  463. } else if ( p->ctrl(col, p2->height - 1).xyz.Compare(p2->ctrl(col2, 0).xyz, WELD_EPSILON) ) {
  464. row1 = p->height - 1;
  465. adj1 = -1;
  466. } else {
  467. adj1 = 0;
  468. }
  469. if ( adj1 ) {
  470. for ( int row = 0; row < p->height; row++, row1 += adj1, row2 += adj2 ) {
  471. if ( !p->ctrl(col, row1).xyz.Compare(p2->ctrl(col2, row2).xyz, WELD_EPSILON) ) {
  472. match = false;
  473. break;
  474. }
  475. }
  476. } else {
  477. match = false;
  478. }
  479. if ( match ) {
  480. // have a match weld these edges
  481. common->Printf("Welding col %i with col %i\n", col, col2);
  482. col = (col == 0) ? p->width - 1 : 0;
  483. Patch_Combine(p, p2, col, col2, -1, -1, (adj1 == -1), (adj2 == -1));
  484. return;
  485. } else if ( col2 == 0 ) {
  486. col2 = p2->width - 1;
  487. } else if ( col == 0 ) {
  488. col = p->width - 1;
  489. col2 = 0;
  490. } else {
  491. break;
  492. }
  493. }
  494. }
  495. Sys_Status("Unable to weld patches, no common sized edges.\n");
  496. }
  497. // used for a save spot
  498. patchMesh_t *patchSave = NULL;
  499. // Tracks the selected patch for point manipulation/update. FIXME: Need to revert back to a generalized
  500. // brush approach
  501. //--int g_nSelectedPatch = -1;
  502. // HACK: for tracking which view generated the click
  503. // as we dont want to deselect a point on a same point
  504. // click if it is from a different view
  505. int g_nPatchClickedView = -1;
  506. bool g_bSameView = false;
  507. // globals
  508. bool g_bPatchShowBounds = false;
  509. bool g_bPatchWireFrame = false;
  510. bool g_bPatchWeld = true;
  511. bool g_bPatchDrillDown = true;
  512. bool g_bPatchInsertMode = false;
  513. bool g_bPatchBendMode = false;
  514. int g_nPatchBendState = -1;
  515. int g_nPatchInsertState = -1;
  516. int g_nBendOriginIndex = 0;
  517. idVec3 g_vBendOrigin;
  518. bool g_bPatchAxisOnRow = true;
  519. int g_nPatchAxisIndex = 0;
  520. bool g_bPatchLowerEdge = true;
  521. // BEND states
  522. enum {
  523. BEND_SELECT_ROTATION = 0,
  524. BEND_SELECT_ORIGIN,
  525. BEND_SELECT_EDGE,
  526. BEND_BENDIT,
  527. BEND_STATE_COUNT
  528. };
  529. const char *g_pBendStateMsg[] = {
  530. "Use TAB to cycle through available bend axis. Press ENTER when the desired one is highlighted.", "Use TAB to cycle through available rotation axis. This will LOCK around that point. You may also use Shift + Middle Click to select an arbitrary point. Press ENTER when the desired one is highlighted", "Use TAB to choose which side to bend. Press ENTER when the desired one is highlighted.", "Use the MOUSE to bend the patch. It uses the same ui rules as Free Rotation. Press ENTER to accept the bend, press ESC to abandon it and exit Bend mode", ""
  531. };
  532. // INSERT states
  533. enum {
  534. INSERT_SELECT_EDGE = 0,
  535. INSERT_STATE_COUNT
  536. };
  537. const char *g_pInsertStateMsg[] = {
  538. "Use TAB to cycle through available rows/columns for insertion/deletion. Press INS to insert at the highlight, DEL to remove the pair"
  539. };
  540. float *g_InversePoints[1024];
  541. const float fFullBright = 1.0f;
  542. const float fLowerLimit = 0.5f;
  543. const float fDec = 0.05f;
  544. void Patch_SetType( patchMesh_t *p,int nType ) {
  545. p->type = (p->type & PATCH_STYLEMASK) | nType;
  546. }
  547. void Patch_SetStyle( patchMesh_t *p,int nStyle ) {
  548. p->type = (p->type & PATCH_TYPEMASK) | nStyle;
  549. }
  550. /*
  551. ==================
  552. Patch_MemorySize
  553. ==================
  554. */
  555. int Patch_MemorySize( patchMesh_t *p ) {
  556. return (sizeof(patchMesh_t) + p->width * p->height * sizeof(idDrawVert));
  557. }
  558. /*
  559. ===============
  560. InterpolateInteriorPoints
  561. ===============
  562. */
  563. void InterpolateInteriorPoints( patchMesh_t *p ) {
  564. int i, j, k;
  565. int next, prev;
  566. for ( i = 0 ; i < p->width ; i += 2 ) {
  567. next = (i == p->width - 1) ? 1 : (i + 1) % p->width;
  568. prev = (i == 0) ? p->width - 2 : i - 1;
  569. for ( j = 0 ; j < p->height ; j++ ) {
  570. for ( k = 0 ; k < 3 ; k++ ) {
  571. p->ctrl(i, j).xyz[k] = (p->ctrl(next, j).xyz[k] + p->ctrl(prev, j).xyz[k]) * 0.5;
  572. }
  573. }
  574. }
  575. }
  576. /*
  577. =================
  578. MakeMeshNormals
  579. =================
  580. */
  581. int neighbors[8][2] = {
  582. {0,1}, {1,1}, {1,0}, {1, -1}, {0, -1}, { - 1, -1}, { - 1,0}, { - 1,1}
  583. };
  584. void Patch_MeshNormals( patchMesh_t *in ) {
  585. int i, j, k, dist;
  586. idVec3 normal;
  587. idVec3 sum;
  588. int count;
  589. idVec3 base;
  590. idVec3 delta;
  591. int x, y;
  592. idDrawVert *dv;
  593. idVec3 around[8], temp;
  594. bool good[8];
  595. bool wrapWidth, wrapHeight;
  596. float len;
  597. wrapWidth = false;
  598. for ( i = 0 ; i < in->height ; i++ ) {
  599. VectorSubtract(in->ctrl(0, i).xyz, in->ctrl(in->width - 1, i).xyz, delta);
  600. len = delta.Length();
  601. if ( len > 1.0f ) {
  602. break;
  603. }
  604. }
  605. if ( i == in->height ) {
  606. wrapWidth = true;
  607. }
  608. wrapHeight = false;
  609. for ( i = 0 ; i < in->width ; i++ ) {
  610. VectorSubtract(in->ctrl(i, 0).xyz, in->ctrl(i, in->height - 1).xyz, delta);
  611. len = delta.Length();
  612. if ( len > 1.0f ) {
  613. break;
  614. }
  615. }
  616. if ( i == in->width ) {
  617. wrapHeight = true;
  618. }
  619. for ( i = 0 ; i < in->width ; i++ ) {
  620. for ( j = 0 ; j < in->height ; j++ ) {
  621. count = 0;
  622. //--dv = reinterpret_cast<idDrawVert*>(in.ctrl[j*in.width+i]);
  623. dv = &in->ctrl(i, j);
  624. VectorCopy(dv->xyz, base);
  625. for ( k = 0 ; k < 8 ; k++ ) {
  626. around[k] = vec3_origin;
  627. good[k] = false;
  628. for ( dist = 1 ; dist <= 3 ; dist++ ) {
  629. x = i + neighbors[k][0] * dist;
  630. y = j + neighbors[k][1] * dist;
  631. if ( wrapWidth ) {
  632. if ( x < 0 ) {
  633. x = in->width - 1 + x;
  634. } else if ( x >= in->width ) {
  635. x = 1 + x - in->width;
  636. }
  637. }
  638. if ( wrapHeight ) {
  639. if ( y < 0 ) {
  640. y = in->height - 1 + y;
  641. } else if ( y >= in->height ) {
  642. y = 1 + y - in->height;
  643. }
  644. }
  645. if ( x < 0 || x >= in->width || y < 0 || y >= in->height ) {
  646. break; // edge of patch
  647. }
  648. //--VectorSubtract( in.ctrl[y*in.width+x]->xyz, base, temp );
  649. VectorSubtract(in->ctrl(x, y).xyz, base, temp);
  650. if ( temp.Normalize() == 0 ) {
  651. continue; // degenerate edge, get more dist
  652. } else {
  653. good[k] = true;
  654. VectorCopy(temp, around[k]);
  655. break; // good edge
  656. }
  657. }
  658. }
  659. sum = vec3_origin;
  660. for ( k = 0 ; k < 8 ; k++ ) {
  661. if ( !good[k] || !good[(k + 1) & 7] ) {
  662. continue; // didn't get two points
  663. }
  664. normal = around[(k + 1) & 7].Cross(around[k]);
  665. if ( normal.Normalize() == 0 ) {
  666. continue;
  667. }
  668. VectorAdd(normal, sum, sum);
  669. count++;
  670. }
  671. if ( count == 0 ) {
  672. //printf("bad normal\n");
  673. count = 1;
  674. //continue;
  675. }
  676. dv->normal = sum;
  677. dv->normal.Normalize();
  678. }
  679. }
  680. }
  681. void Patch_MakeDirty( patchMesh_t *p ) {
  682. assert(p);
  683. p->nListID = -1;
  684. p->nListIDCam = -1;
  685. p->nListSelected = -1;
  686. }
  687. /*
  688. ==================
  689. Patch_CalcBounds
  690. ==================
  691. */
  692. void Patch_CalcBounds( patchMesh_t *p,idVec3 &vMin,idVec3 &vMax ) {
  693. vMin[0] = vMin[1] = vMin[2] = 999999;
  694. vMax[0] = vMax[1] = vMax[2] = -999999;
  695. Patch_MakeDirty(p);
  696. for ( int w = 0; w < p->width; w++ ) {
  697. for ( int h = 0; h < p->height; h++ ) {
  698. for ( int j = 0; j < 3; j++ ) {
  699. float f = p->ctrl(w, h).xyz[j];
  700. if ( f < vMin[j] )
  701. vMin[j] = f;
  702. if ( f > vMax[j] )
  703. vMax[j] = f;
  704. }
  705. }
  706. }
  707. }
  708. /*
  709. ==================
  710. Brush_RebuildBrush
  711. ==================
  712. */
  713. void Brush_RebuildBrush( brush_t *b,idVec3 vMins,idVec3 vMaxs,bool patch ) {
  714. //
  715. // Total hack job
  716. // Rebuilds a brush
  717. int i, j;
  718. face_t *f, *next;
  719. idVec3 pts[4][2];
  720. texdef_t texdef;
  721. // free faces
  722. for ( j = 0; j < 3; j++ ) {
  723. if ( (int) vMins[j] == (int) vMaxs[j] ) {
  724. vMins[j] -= 4;
  725. vMaxs[j] += 4;
  726. }
  727. }
  728. for ( f = b->brush_faces ; f ; f = next ) {
  729. next = f->next;
  730. if ( f ) {
  731. texdef = f->texdef;
  732. }
  733. Face_Free(f);
  734. }
  735. b->brush_faces = NULL;
  736. // left the last face so we can use its texdef
  737. for ( i = 0 ; i < 3 ; i++ ) {
  738. if ( vMaxs[i] < vMins[i] ) {
  739. Error("Brush_RebuildBrush: backwards");
  740. }
  741. }
  742. pts[0][0][0] = vMins[0];
  743. pts[0][0][1] = vMins[1];
  744. pts[1][0][0] = vMins[0];
  745. pts[1][0][1] = vMaxs[1];
  746. pts[2][0][0] = vMaxs[0];
  747. pts[2][0][1] = vMaxs[1];
  748. pts[3][0][0] = vMaxs[0];
  749. pts[3][0][1] = vMins[1];
  750. for ( i = 0 ; i < 4 ; i++ ) {
  751. pts[i][0][2] = vMins[2];
  752. pts[i][1][0] = pts[i][0][0];
  753. pts[i][1][1] = pts[i][0][1];
  754. pts[i][1][2] = vMaxs[2];
  755. }
  756. for ( i = 0 ; i < 4 ; i++ ) {
  757. f = Face_Alloc();
  758. f->texdef = texdef;
  759. f->next = b->brush_faces;
  760. b->brush_faces = f;
  761. j = (i + 1) % 4;
  762. VectorCopy(pts[j][1], f->planepts[0]);
  763. VectorCopy(pts[i][1], f->planepts[1]);
  764. VectorCopy(pts[i][0], f->planepts[2]);
  765. }
  766. f = Face_Alloc();
  767. f->texdef = texdef;
  768. f->next = b->brush_faces;
  769. b->brush_faces = f;
  770. VectorCopy(pts[0][1], f->planepts[0]);
  771. VectorCopy(pts[1][1], f->planepts[1]);
  772. VectorCopy(pts[2][1], f->planepts[2]);
  773. f = Face_Alloc();
  774. f->texdef = texdef;
  775. f->next = b->brush_faces;
  776. b->brush_faces = f;
  777. VectorCopy(pts[2][0], f->planepts[0]);
  778. VectorCopy(pts[1][0], f->planepts[1]);
  779. VectorCopy(pts[0][0], f->planepts[2]);
  780. Brush_Build(b);
  781. }
  782. void WINAPI Patch_Rebuild( patchMesh_t *p ) {
  783. idVec3 vMin, vMax;
  784. Patch_CalcBounds(p, vMin, vMax);
  785. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  786. Patch_MakeDirty(p);
  787. }
  788. /*
  789. ==================
  790. AddBrushForPatch
  791. ==================
  792. adds a patch brush and ties it to this patch id
  793. */
  794. brush_t * AddBrushForPatch( patchMesh_t *pm,bool bLinkToWorld ) {
  795. // find the farthest points in x,y,z
  796. idVec3 vMin, vMax;
  797. Patch_CalcBounds(pm, vMin, vMax);
  798. for ( int j = 0; j < 3; j++ ) {
  799. if ( idMath::Fabs(vMin[j] - vMax[j]) <= VECTOR_EPSILON ) {
  800. vMin[j] -= 4;
  801. vMax[j] += 4;
  802. }
  803. }
  804. texdef_t td;
  805. //td.SetName(pm->d_texture->getName());
  806. brush_t *b = Brush_Create(vMin, vMax, &td);
  807. //brush_t *b = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
  808. // FIXME: this entire type of linkage needs to be fixed
  809. b->pPatch = pm;
  810. pm->pSymbiot = b;
  811. pm->bSelected = false;
  812. pm->bOverlay = false;
  813. pm->nListID = -1;
  814. pm->nListIDCam = -1;
  815. if ( bLinkToWorld ) {
  816. Brush_AddToList(b, &active_brushes);
  817. Entity_LinkBrush(world_entity, b);
  818. Brush_Build(b);
  819. }
  820. return b;
  821. }
  822. void Patch_SetPointIntensities( int n ) {
  823. #if 0
  824. patchMesh_t *p = patchMeshes[n];
  825. for (int i = 0; i < p->width; i++) {
  826. for (int j = 0; j < p->height; j++) {
  827. }
  828. }
  829. #endif
  830. }
  831. // very approximate widths and heights
  832. /*
  833. ==================
  834. Patch_Width
  835. ==================
  836. */
  837. float Patch_Width( patchMesh_t *p ) {
  838. float f = 0;
  839. for ( int j = 0; j < p->height - 1; j++ ) {
  840. float t = 0;
  841. for ( int i = 0; i < p->width - 1; i++ ) {
  842. idVec3 vTemp;
  843. vTemp = p->ctrl(i, j).xyz - p->ctrl(i + 1, j).xyz;
  844. t += vTemp.Length();
  845. }
  846. if ( f < t ) {
  847. f = t;
  848. }
  849. }
  850. return f;
  851. }
  852. /*
  853. ==================
  854. Patch_Height
  855. ==================
  856. */
  857. float Patch_Height( patchMesh_t *p ) {
  858. float f = 0;
  859. for ( int j = 0; j < p->width - 1; j++ ) {
  860. float t = 0;
  861. for ( int i = 0; i < p->height - 1; i++ ) {
  862. idVec3 vTemp;
  863. vTemp = p->ctrl(j, i).xyz - p->ctrl(j, i + 1).xyz;
  864. t += vTemp.Length();
  865. }
  866. if ( f < t ) {
  867. f = t;
  868. }
  869. }
  870. return f;
  871. }
  872. /*
  873. ==================
  874. Patch_WidthDistanceTo
  875. ==================
  876. */
  877. float Patch_WidthDistanceTo( patchMesh_t *p,int j ) {
  878. float f = 0;
  879. for ( int i = 0; i < j ; i++ ) {
  880. idVec3 vTemp;
  881. vTemp = p->ctrl(i, 0).xyz - p->ctrl(i + 1, 0).xyz;
  882. f += vTemp.Length();
  883. }
  884. return f;
  885. }
  886. /*
  887. ==================
  888. Patch_HeightDistanceTo
  889. ==================
  890. */
  891. float Patch_HeightDistanceTo( patchMesh_t *p,int j ) {
  892. float f = 0;
  893. for ( int i = 0; i < j ; i++ ) {
  894. idVec3 vTemp;
  895. vTemp = p->ctrl(0, i).xyz - p->ctrl(0, i + 1).xyz;
  896. f += vTemp.Length();
  897. }
  898. return f;
  899. }
  900. /*
  901. ==================
  902. Patch_Naturalize
  903. ==================
  904. texture = TotalTexture * LengthToThisControlPoint / TotalControlPointLength
  905. dist( this control point to first control point ) / dist ( last control pt to first)
  906. */
  907. void Patch_Naturalize( patchMesh_t *p,bool horz,bool vert,bool alt ) {
  908. int i, j;
  909. int nWidth = p->d_texture->GetEditorImage()->uploadWidth * 0.5;
  910. int nHeight = p->d_texture->GetEditorImage()->uploadHeight * 0.5;
  911. float fPWidth = Patch_Width(p);
  912. float fPHeight = Patch_Height(p);
  913. float xAccum = 0;
  914. for ( i = 0 ; i < ((alt) ? p->height : p->width) ; i++ ) {
  915. float yAccum = 0;
  916. for ( j = 0 ; j < ((alt) ? p->width : p->height) ; j++ ) {
  917. int r = ((alt) ? j : i);
  918. int c = ((alt) ? i : j);
  919. p->ctrl(r, c).st[0] = (fPWidth / nWidth) * xAccum / fPWidth;
  920. p->ctrl(r, c).st[1] = (fPHeight / nHeight) * yAccum / fPHeight;
  921. if ( alt ) {
  922. yAccum = Patch_WidthDistanceTo(p, j + 1);
  923. } else {
  924. yAccum = Patch_HeightDistanceTo(p, j + 1);
  925. }
  926. }
  927. if ( alt ) {
  928. xAccum = Patch_HeightDistanceTo(p, i + 1);
  929. } else {
  930. xAccum = Patch_WidthDistanceTo(p, i + 1);
  931. }
  932. }
  933. Patch_MakeDirty(p);
  934. }
  935. /*
  936. if (bIBevel)
  937. {
  938. VectorCopy(p->ctrl(1,0], p->ctrl(1,1]);
  939. }
  940. if (bIEndcap)
  941. {
  942. VectorCopy(p->ctrl(3,0], p->ctrl(4,1]);
  943. VectorCopy(p->ctrl(2,0], p->ctrl(3,1]);
  944. VectorCopy(p->ctrl(2,0], p->ctrl(2,1]);
  945. VectorCopy(p->ctrl(2,0], p->ctrl(1,1]);
  946. VectorCopy(p->ctrl(1,0], p->ctrl(0,1]);
  947. VectorCopy(p->ctrl(1,0], p->ctrl(0,2]);
  948. VectorCopy(p->ctrl(1,0], p->ctrl(1,2]);
  949. VectorCopy(p->ctrl(2,0], p->ctrl(2,2]);
  950. VectorCopy(p->ctrl(3,0], p->ctrl(3,2]);
  951. VectorCopy(p->ctrl(3,0], p->ctrl(4,2]);
  952. }
  953. */
  954. int Index3By[][2] = {
  955. {0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {1,2}, {0,2}, {0,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}
  956. };
  957. int Index5By[][2] = {
  958. {0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {4,1}, {4,2}, {4,3}, {4,4}, {3,4}, {2,4}, {1,4}, {0,4}, {0,3}, {0,2}, {0,1}
  959. };
  960. int Interior3By[][2] = {
  961. {1,1}
  962. };
  963. int Interior5By[][2] = {
  964. {1,1}, {2,1}, {3,1}, {1,2}, {2,2}, {3,2}, {1,3}, {2,3}, {3,3}
  965. };
  966. int Interior3ByCount = sizeof(Interior3By) / sizeof(int[2]);
  967. int Interior5ByCount = sizeof(Interior5By) / sizeof(int[2]);
  968. face_t * Patch_GetAxisFace( patchMesh_t *p ) {
  969. face_t *f = NULL;
  970. idVec3 vTemp;
  971. brush_t *b = p->pSymbiot;
  972. for ( f = b->brush_faces ; f ; f = f->next ) {
  973. vTemp = (*f->face_winding)[1].ToVec3() - (*f->face_winding)[0].ToVec3();
  974. int nScore = 0;
  975. // default edge faces on caps are 8 high so
  976. // as soon as we hit one that is bigger it should be on the right axis
  977. for ( int j = 0; j < 3; j++ ) {
  978. if ( vTemp[j] > 8 )
  979. nScore++;
  980. }
  981. if ( nScore > 0 ) {
  982. break;
  983. }
  984. }
  985. if ( f == NULL ) {
  986. f = b->brush_faces;
  987. }
  988. return f;
  989. }
  990. int g_nFaceCycle = 0;
  991. face_t * nextFace( patchMesh_t *p ) {
  992. brush_t *b = p->pSymbiot;
  993. face_t *f = NULL;
  994. int n = 0;
  995. for ( f = b->brush_faces ; f && n <= g_nFaceCycle; f = f->next ) {
  996. n++;
  997. }
  998. g_nFaceCycle++;
  999. if ( g_nFaceCycle > 5 ) {
  1000. g_nFaceCycle = 0;
  1001. f = b->brush_faces;
  1002. }
  1003. return f;
  1004. }
  1005. void Patch_CapTexture( patchMesh_t *p,bool bFaceCycle = false,bool alt = false ) {
  1006. Patch_MeshNormals(p);
  1007. face_t *f = (bFaceCycle) ? nextFace(p) : Patch_GetAxisFace(p);
  1008. idVec3 vSave;
  1009. VectorCopy(f->plane, vSave);
  1010. float fRotate = f->texdef.rotate;
  1011. f->texdef.rotate = 0;
  1012. float fScale[2];
  1013. fScale[0] = f->texdef.scale[0];
  1014. fScale[1] = f->texdef.scale[1];
  1015. f->texdef.scale[0] = (float) p->d_texture->GetEditorImage()->uploadWidth / 32.0f;
  1016. f->texdef.scale[1] = (float) p->d_texture->GetEditorImage()->uploadHeight / 32.0f;
  1017. float fShift[2];
  1018. fShift[0] = f->texdef.shift[0];
  1019. fShift[1] = f->texdef.shift[1];
  1020. f->texdef.shift[0] = 0;
  1021. f->texdef.shift[1] = 0;
  1022. for ( int i = 0 ; i < p->width; i++ ) {
  1023. for ( int j = 0 ; j < p->height ; j++ ) {
  1024. if ( !bFaceCycle ) {
  1025. VectorCopy(p->ctrl(i, j).normal, f->plane);
  1026. }
  1027. idVec5 temp;
  1028. temp.x = p->ctrl(i, j).xyz.x;
  1029. temp.y = p->ctrl(i, j).xyz.y;
  1030. temp.z = p->ctrl(i, j).xyz.z;
  1031. EmitTextureCoordinates(temp, f->d_texture, f, true);
  1032. p->ctrl(i, j).st.x = temp.s;
  1033. p->ctrl(i, j).st.y = temp.t;
  1034. }
  1035. }
  1036. VectorCopy(vSave, f->plane);
  1037. f->texdef.rotate = fRotate;
  1038. f->texdef.scale[0] = fScale[0];
  1039. f->texdef.scale[1] = fScale[1];
  1040. f->texdef.shift[0] = fShift[0];
  1041. f->texdef.shift[1] = fShift[1];
  1042. Patch_ScaleTexture(p, 1.0f, -1.0f, false);
  1043. Patch_MakeDirty(p);
  1044. }
  1045. void FillPatch( patchMesh_t *p,idVec3 v ) {
  1046. for ( int i = 0; i < p->width; i++ ) {
  1047. for ( int j = 0; j < p->height; j++ ) {
  1048. VectorCopy(v, p->ctrl(i, j).xyz);
  1049. }
  1050. }
  1051. }
  1052. brush_t * Cap( patchMesh_t *pParent,bool bByColumn,bool bFirst ) {
  1053. brush_t *b;
  1054. patchMesh_t *p;
  1055. idVec3 vMin, vMax;
  1056. int i, j;
  1057. bool bSmall = true;
  1058. // make a generic patch
  1059. if ( pParent->width <= 9 ) {
  1060. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1061. } else {
  1062. b = Patch_GenericMesh(5, 5, 2, false, false, pParent);
  1063. bSmall = false;
  1064. }
  1065. if ( !b ) {
  1066. Sys_Status("Unable to cap. You may need to ungroup the patch.\n");
  1067. return NULL;
  1068. }
  1069. p = b->pPatch;
  1070. p->type |= PATCH_CAP;
  1071. vMin[0] = vMin[1] = vMin[2] = 99999;
  1072. vMax[0] = vMax[1] = vMax[2] = -99999;
  1073. // we seam the column edge, FIXME: this might need to be able to seem either edge
  1074. //
  1075. int nSize = (bByColumn) ? pParent->width : pParent->height;
  1076. int nIndex = (bFirst) ? 0 : (bByColumn) ? pParent->height - 1 : pParent->width - 1;
  1077. FillPatch(p, pParent->ctrl(0, nIndex).xyz);
  1078. for ( i = 0; i < nSize; i++ ) {
  1079. if ( bByColumn ) {
  1080. if ( bSmall ) {
  1081. VectorCopy(pParent->ctrl(i, nIndex).xyz, p->ctrl(Index3By[i][0], Index3By[i][1]).xyz);
  1082. } else {
  1083. VectorCopy(pParent->ctrl(i, nIndex).xyz, p->ctrl(Index5By[i][0], Index5By[i][1]).xyz);
  1084. }
  1085. } else {
  1086. if ( bSmall ) {
  1087. VectorCopy(pParent->ctrl(nIndex, i).xyz, p->ctrl(Index3By[i][0], Index3By[i][1]).xyz);
  1088. } else {
  1089. VectorCopy(pParent->ctrl(nIndex, i).xyz, p->ctrl(Index5By[i][0], Index5By[i][1]).xyz);
  1090. }
  1091. }
  1092. for ( j = 0; j < 3; j++ ) {
  1093. float f = (bSmall) ? p->ctrl(Index3By[i][0], Index3By[i][1]).xyz[j] : p->ctrl(Index5By[i][0], Index5By[i][1]).xyz[j];
  1094. if ( f < vMin[j] )
  1095. vMin[j] = f;
  1096. if ( f > vMax[j] )
  1097. vMax[j] = f;
  1098. }
  1099. }
  1100. idVec3 vTemp;
  1101. for ( j = 0; j < 3; j++ ) {
  1102. vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
  1103. }
  1104. int nCount = (bSmall) ? Interior3ByCount : Interior5ByCount;
  1105. for ( j = 0; j < nCount; j++ ) {
  1106. if ( bSmall ) {
  1107. VectorCopy(vTemp, p->ctrl(Interior3By[j][0], Interior3By[j][1]).xyz);
  1108. } else {
  1109. VectorCopy(vTemp, p->ctrl(Interior5By[j][0], Interior5By[j][1]).xyz);
  1110. }
  1111. }
  1112. if ( bFirst ) {
  1113. idDrawVert vertTemp;
  1114. for ( i = 0; i < p->width; i++ ) {
  1115. for ( j = 0; j < p->height / 2; j++ ) {
  1116. memcpy(&vertTemp, &p->ctrl(i, p->height - 1 - j), sizeof(idDrawVert));
  1117. memcpy(&p->ctrl(i, p->height - 1 - j), &p->ctrl(i, j), sizeof(idDrawVert));
  1118. memcpy(&p->ctrl(i, j), &vertTemp, sizeof(idDrawVert));
  1119. }
  1120. }
  1121. }
  1122. Patch_Rebuild(p);
  1123. Patch_CapTexture(p);
  1124. return p->pSymbiot;
  1125. }
  1126. brush_t * CapSpecial( patchMesh_t *pParent,int nType,bool bFirst ) {
  1127. brush_t *b;
  1128. patchMesh_t *p;
  1129. idVec3 vMin, vMax, vTemp;
  1130. int i, j;
  1131. if ( nType == CCapDialog::IENDCAP ) {
  1132. b = Patch_GenericMesh(5, 3, 2, false, false, pParent);
  1133. } else {
  1134. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1135. }
  1136. if ( !b ) {
  1137. Sys_Status("Unable to cap. Make sure you ungroup before re-capping.");
  1138. return NULL;
  1139. }
  1140. p = b->pPatch;
  1141. p->type |= PATCH_CAP;
  1142. vMin[0] = vMin[1] = vMin[2] = 99999;
  1143. vMax[0] = vMax[1] = vMax[2] = -99999;
  1144. int nSize = pParent->width;
  1145. int nIndex = (bFirst) ? 0 : pParent->height - 1;
  1146. // parent bounds are used for some things
  1147. Patch_CalcBounds(pParent, vMin, vMax);
  1148. for ( j = 0; j < 3; j++ ) {
  1149. vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
  1150. }
  1151. if ( nType == CCapDialog::IBEVEL ) {
  1152. VectorCopy(pParent->ctrl(0, nIndex).xyz, p->ctrl(0, 0).xyz);
  1153. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(0, 2).xyz);
  1154. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(0, 1).xyz);
  1155. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(2, 2).xyz);
  1156. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 0).xyz);
  1157. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 1).xyz);
  1158. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 2).xyz);
  1159. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(2, 0).xyz);
  1160. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(2, 1).xyz);
  1161. } else if ( nType == CCapDialog::BEVEL ) {
  1162. idVec3 p1, p2, p3, p4, temp, dir;
  1163. VectorCopy(pParent->ctrl(0, nIndex).xyz, p3);
  1164. VectorCopy(pParent->ctrl(1, nIndex).xyz, p1);
  1165. VectorCopy(pParent->ctrl(2, nIndex).xyz, p2);
  1166. VectorSubtract(p3, p2, dir);
  1167. dir.Normalize();
  1168. VectorSubtract(p1, p2, temp);
  1169. float dist = DotProduct(temp, dir);
  1170. VectorScale(dir, dist, temp);
  1171. VectorAdd(p2, temp, temp);
  1172. VectorSubtract(temp, p1, temp);
  1173. VectorScale(temp, 2, temp);
  1174. VectorAdd(p1, temp, p4);
  1175. VectorCopy(p4, p->ctrl(0, 0).xyz);
  1176. VectorCopy(p4, p->ctrl(1, 0).xyz);
  1177. VectorCopy(p4, p->ctrl(0, 1).xyz);
  1178. VectorCopy(p4, p->ctrl(1, 1).xyz);
  1179. VectorCopy(p4, p->ctrl(0, 2).xyz);
  1180. VectorCopy(p4, p->ctrl(1, 2).xyz);
  1181. VectorCopy(p3, p->ctrl(2, 0).xyz);
  1182. VectorCopy(p1, p->ctrl(2, 1).xyz);
  1183. VectorCopy(p2, p->ctrl(2, 2).xyz);
  1184. } else if ( nType == CCapDialog::ENDCAP ) {
  1185. VectorAdd(pParent->ctrl(4, nIndex).xyz, pParent->ctrl(0, nIndex).xyz, vTemp);
  1186. VectorScale(vTemp, 0.5, vTemp);
  1187. VectorCopy(pParent->ctrl(0, nIndex).xyz, p->ctrl(0, 0).xyz);
  1188. VectorCopy(vTemp, p->ctrl(1, 0).xyz);
  1189. VectorCopy(pParent->ctrl(4, nIndex).xyz, p->ctrl(2, 0).xyz);
  1190. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(0, 2).xyz);
  1191. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(1, 2).xyz);
  1192. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(2, 2).xyz);
  1193. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(1, 1).xyz);
  1194. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(0, 1).xyz);
  1195. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(2, 1).xyz);
  1196. } else {
  1197. VectorCopy(pParent->ctrl(0, nIndex).xyz, p->ctrl(0, 0).xyz);
  1198. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 0).xyz);
  1199. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(2, 0).xyz);
  1200. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(3, 0).xyz);
  1201. VectorCopy(pParent->ctrl(4, nIndex).xyz, p->ctrl(4, 0).xyz);
  1202. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(0, 1).xyz);
  1203. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 1).xyz);
  1204. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(2, 1).xyz);
  1205. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(3, 1).xyz);
  1206. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(4, 1).xyz);
  1207. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(0, 2).xyz);
  1208. VectorCopy(pParent->ctrl(1, nIndex).xyz, p->ctrl(1, 2).xyz);
  1209. VectorCopy(pParent->ctrl(2, nIndex).xyz, p->ctrl(2, 2).xyz);
  1210. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(3, 2).xyz);
  1211. VectorCopy(pParent->ctrl(3, nIndex).xyz, p->ctrl(4, 2).xyz);
  1212. }
  1213. bool bEndCap = (nType == CCapDialog::ENDCAP || nType == CCapDialog::IENDCAP);
  1214. if ( (!bFirst && !bEndCap) || (bFirst && bEndCap) ) {
  1215. idDrawVert vertTemp;
  1216. for ( i = 0; i < p->width; i++ ) {
  1217. for ( j = 0; j < p->height / 2; j++ ) {
  1218. memcpy(&vertTemp, &p->ctrl(i, p->height - 1 - j), sizeof(idDrawVert));
  1219. memcpy(&p->ctrl(i, p->height - 1 - j), &p->ctrl(i, j), sizeof(idDrawVert));
  1220. memcpy(&p->ctrl(i, j), &vertTemp, sizeof(idDrawVert));
  1221. }
  1222. }
  1223. }
  1224. //--Patch_CalcBounds(p, vMin, vMax);
  1225. //--Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  1226. Patch_Rebuild(p);
  1227. Patch_CapTexture(p);
  1228. return p->pSymbiot;
  1229. }
  1230. void Patch_CapCurrent( bool bInvertedBevel,bool bInvertedEndcap ) {
  1231. patchMesh_t *pParent = NULL;
  1232. brush_t *b[4];
  1233. brush_t *pCap = NULL;
  1234. b[0] = b[1] = b[2] = b[3] = NULL;
  1235. int nIndex = 0;
  1236. if ( !QE_SingleBrush() ) {
  1237. Sys_Status("Cannot cap multiple selection. Please select a single patch.\n");
  1238. return;
  1239. }
  1240. for ( brush_t*pb = selected_brushes.next ; pb != NULL && pb != &selected_brushes ; pb = pb->next ) {
  1241. if ( pb->pPatch ) {
  1242. pParent = pb->pPatch;
  1243. // decide which if any ends we are going to cap
  1244. // if any of these compares hit, it is a closed patch and as such
  1245. // the generic capping will work.. if we do not find a closed edge
  1246. // then we need to ask which kind of cap to add
  1247. if ( pParent->ctrl(0, 0).xyz.Compare(pParent->ctrl(pParent->width - 1, 0).xyz) ) {
  1248. pCap = Cap(pParent, true, false);
  1249. if ( pCap != NULL ) {
  1250. b[nIndex++] = pCap;
  1251. }
  1252. }
  1253. if ( pParent->ctrl(0, pParent->height - 1).xyz.Compare(pParent->ctrl(pParent->width - 1, pParent->height - 1).xyz) ) {
  1254. pCap = Cap(pParent, true, true);
  1255. if ( pCap != NULL ) {
  1256. b[nIndex++] = pCap;
  1257. }
  1258. }
  1259. if ( pParent->ctrl(0, 0).xyz.Compare(pParent->ctrl(0, pParent->height - 1).xyz) ) {
  1260. pCap = Cap(pParent, false, false);
  1261. if ( pCap != NULL ) {
  1262. b[nIndex++] = pCap;
  1263. }
  1264. }
  1265. if ( pParent->ctrl(pParent->width - 1, 0).xyz.Compare(pParent->ctrl(pParent->width - 1, pParent->height - 1).xyz) ) {
  1266. pCap = Cap(pParent, false, true);
  1267. if ( pCap != NULL ) {
  1268. b[nIndex++] = pCap;
  1269. }
  1270. }
  1271. }
  1272. }
  1273. if ( pParent ) {
  1274. // if we did not cap anything with the above tests
  1275. if ( nIndex == 0 ) {
  1276. CCapDialog dlg;
  1277. if ( dlg.DoModal() == IDOK ) {
  1278. b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), false);
  1279. b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), true);
  1280. }
  1281. }
  1282. if ( nIndex > 0 ) {
  1283. while ( nIndex > 0 ) {
  1284. nIndex--;
  1285. if ( b[nIndex] ) {
  1286. Select_Brush(b[nIndex]);
  1287. }
  1288. }
  1289. eclass_t*pecNew = Eclass_ForName("func_static", false);
  1290. if ( pecNew ) {
  1291. entity_t*e = Entity_Create(pecNew);
  1292. SetKeyValue(e, "type", "patchCapped");
  1293. }
  1294. }
  1295. }
  1296. }
  1297. //FIXME: Table drive all this crap
  1298. //
  1299. void GenerateEndCaps( brush_t *brushParent,bool bBevel,bool bEndcap,bool bInverted ) {
  1300. brush_t *b, *b2;
  1301. patchMesh_t *p, *p2, *pParent;
  1302. idVec3 vTemp, vMin, vMax;
  1303. int i, j;
  1304. pParent = brushParent->pPatch;
  1305. Patch_CalcBounds(pParent, vMin, vMax);
  1306. // basically generate two endcaps, place them, and link the three brushes with a func_group
  1307. if ( pParent->width > 9 ) {
  1308. b = Patch_GenericMesh(5, 3, 2, false, false, pParent);
  1309. } else {
  1310. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1311. }
  1312. p = b->pPatch;
  1313. vMin[0] = vMin[1] = vMin[2] = 99999;
  1314. vMax[0] = vMax[1] = vMax[2] = -99999;
  1315. for ( i = 0; i < pParent->width; i++ ) {
  1316. VectorCopy(pParent->ctrl(i, 0).xyz, p->ctrl(Index3By[i][0], Index3By[i][1]).xyz);
  1317. for ( j = 0; j < 3; j++ ) {
  1318. if ( pParent->ctrl(i, 0).xyz[j] < vMin[j] )
  1319. vMin[j] = pParent->ctrl(i, 0).xyz[j];
  1320. if ( pParent->ctrl(i, 0).xyz[j] > vMax[j] )
  1321. vMax[j] = pParent->ctrl(i, 0).xyz[j];
  1322. }
  1323. }
  1324. for ( j = 0; j < 3; j++ ) {
  1325. vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
  1326. }
  1327. for ( i = 0; i < Interior3ByCount; i++ ) {
  1328. VectorCopy(vTemp, p->ctrl(Interior3By[i][0], Interior3By[i][1]).xyz);
  1329. }
  1330. Patch_CalcBounds(p, vMin, vMax);
  1331. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  1332. Select_Brush(p->pSymbiot);
  1333. return;
  1334. bool bCreated = false;
  1335. if ( bInverted ) {
  1336. if ( bBevel ) {
  1337. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1338. p = b->pPatch;
  1339. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(1, 2).xyz);
  1340. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(2, 1).xyz);
  1341. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(0, 1).xyz);
  1342. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(1, 0).xyz);
  1343. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(1, 1).xyz);
  1344. VectorCopy(p->ctrl(2, 0).xyz, p->ctrl(0, 0).xyz);
  1345. b2 = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1346. p2 = b2->pPatch;
  1347. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(1, 2).xyz);
  1348. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(2, 1).xyz);
  1349. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(0, 1).xyz);
  1350. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(1, 0).xyz);
  1351. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(1, 1).xyz);
  1352. VectorCopy(p2->ctrl(2, 0).xyz, p2->ctrl(0, 0).xyz);
  1353. bCreated = true;
  1354. } else if ( bEndcap ) {
  1355. b = Patch_GenericMesh(5, 5, 2, false, false, pParent);
  1356. p = b->pPatch;
  1357. VectorCopy(p->ctrl(4, 4).xyz, p->ctrl(4, 3).xyz);
  1358. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(1, 4).xyz);
  1359. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(2, 4).xyz);
  1360. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(3, 4).xyz);
  1361. VectorCopy(p->ctrl(4, 0).xyz, p->ctrl(4, 1).xyz);
  1362. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(1, 0).xyz);
  1363. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(2, 0).xyz);
  1364. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(3, 0).xyz);
  1365. for ( i = 1; i < 4; i++ ) {
  1366. for ( j = 0; j < 4; j++ ) {
  1367. VectorCopy(p->ctrl(4, i).xyz, p->ctrl(j, i).xyz);
  1368. }
  1369. }
  1370. b2 = Patch_GenericMesh(5, 5, 2, false, false, pParent);
  1371. p2 = b2->pPatch;
  1372. VectorCopy(p2->ctrl(4, 4).xyz, p2->ctrl(4, 3).xyz);
  1373. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(1, 4).xyz);
  1374. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(2, 4).xyz);
  1375. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(3, 4).xyz);
  1376. VectorCopy(p2->ctrl(4, 0).xyz, p2->ctrl(4, 1).xyz);
  1377. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(1, 0).xyz);
  1378. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(2, 0).xyz);
  1379. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(3, 0).xyz);
  1380. for ( i = 1; i < 4; i++ ) {
  1381. for ( j = 0; j < 4; j++ ) {
  1382. VectorCopy(p2->ctrl(4, i).xyz, p2->ctrl(j, i).xyz);
  1383. }
  1384. }
  1385. bCreated = true;
  1386. }
  1387. } else {
  1388. if ( bBevel ) {
  1389. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1390. p = b->pPatch;
  1391. VectorCopy(p->ctrl(2, 0).xyz, p->ctrl(2, 1).xyz);
  1392. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(1, 0).xyz);
  1393. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(2, 0).xyz);
  1394. b2 = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1395. p2 = b2->pPatch;
  1396. VectorCopy(p2->ctrl(2, 0).xyz, p2->ctrl(2, 1).xyz);
  1397. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(1, 0).xyz);
  1398. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(2, 0).xyz);
  1399. bCreated = true;
  1400. } else if ( bEndcap ) {
  1401. b = Patch_GenericMesh(5, 5, 2, false, false, pParent);
  1402. p = b->pPatch;
  1403. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(1, 0).xyz);
  1404. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(2, 0).xyz);
  1405. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(3, 0).xyz);
  1406. VectorCopy(p->ctrl(4, 0).xyz, p->ctrl(4, 1).xyz);
  1407. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(4, 0).xyz);
  1408. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(1, 4).xyz);
  1409. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(2, 4).xyz);
  1410. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(3, 4).xyz);
  1411. VectorCopy(p->ctrl(4, 4).xyz, p->ctrl(4, 3).xyz);
  1412. VectorCopy(p->ctrl(0, 4).xyz, p->ctrl(4, 4).xyz);
  1413. b2 = Patch_GenericMesh(5, 5, 2, false, false, pParent);
  1414. p2 = b2->pPatch;
  1415. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(1, 0).xyz);
  1416. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(2, 0).xyz);
  1417. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(3, 0).xyz);
  1418. VectorCopy(p2->ctrl(4, 0).xyz, p2->ctrl(4, 1).xyz);
  1419. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(4, 0).xyz);
  1420. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(1, 4).xyz);
  1421. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(2, 4).xyz);
  1422. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(3, 4).xyz);
  1423. VectorCopy(p2->ctrl(4, 4).xyz, p2->ctrl(4, 3).xyz);
  1424. VectorCopy(p2->ctrl(0, 4).xyz, p2->ctrl(4, 4).xyz);
  1425. bCreated = true;
  1426. } else {
  1427. b = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1428. p = b->pPatch;
  1429. VectorCopy(p->ctrl(0, 1).xyz, vTemp);
  1430. VectorCopy(p->ctrl(0, 2).xyz, p->ctrl(0, 1).xyz);
  1431. VectorCopy(p->ctrl(1, 2).xyz, p->ctrl(0, 2).xyz);
  1432. VectorCopy(p->ctrl(2, 2).xyz, p->ctrl(1, 2).xyz);
  1433. VectorCopy(p->ctrl(2, 1).xyz, p->ctrl(2, 2).xyz);
  1434. VectorCopy(p->ctrl(2, 0).xyz, p->ctrl(2, 1).xyz);
  1435. VectorCopy(p->ctrl(1, 0).xyz, p->ctrl(2, 0).xyz);
  1436. VectorCopy(p->ctrl(0, 0).xyz, p->ctrl(1, 0).xyz);
  1437. VectorCopy(vTemp, p->ctrl(0, 0).xyz);
  1438. b2 = Patch_GenericMesh(3, 3, 2, false, false, pParent);
  1439. p2 = b2->pPatch;
  1440. VectorCopy(p2->ctrl(0, 1).xyz, vTemp);
  1441. VectorCopy(p2->ctrl(0, 2).xyz, p2->ctrl(0, 1).xyz);
  1442. VectorCopy(p2->ctrl(1, 2).xyz, p2->ctrl(0, 2).xyz);
  1443. VectorCopy(p2->ctrl(2, 2).xyz, p2->ctrl(1, 2).xyz);
  1444. VectorCopy(p2->ctrl(2, 1).xyz, p2->ctrl(2, 2).xyz);
  1445. VectorCopy(p2->ctrl(2, 0).xyz, p2->ctrl(2, 1).xyz);
  1446. VectorCopy(p2->ctrl(1, 0).xyz, p2->ctrl(2, 0).xyz);
  1447. VectorCopy(p2->ctrl(0, 0).xyz, p2->ctrl(1, 0).xyz);
  1448. VectorCopy(vTemp, p2->ctrl(0, 0).xyz);
  1449. bCreated = true;
  1450. }
  1451. }
  1452. if ( bCreated ) {
  1453. idDrawVert vertTemp;
  1454. for ( i = 0; i < p->width; i++ ) {
  1455. for ( j = 0; j < p->height; j++ ) {
  1456. p->ctrl(i, j).xyz[2] = vMin[2];
  1457. p2->ctrl(i, j).xyz[2] = vMax[2];
  1458. }
  1459. for ( j = 0; j < p->height / 2; j++ ) {
  1460. memcpy(&vertTemp, &p->ctrl(i, p->height - 1 - j), sizeof(idDrawVert));
  1461. memcpy(&p->ctrl(i, p->height - 1 - j), &p->ctrl(i, j), sizeof(idDrawVert));
  1462. memcpy(&p->ctrl(i, j), &vertTemp, sizeof(idDrawVert));
  1463. }
  1464. }
  1465. //Select_Delete();
  1466. Patch_CalcBounds(p, vMin, vMax);
  1467. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  1468. Patch_CalcBounds(p2, vMin, vMax);
  1469. Brush_RebuildBrush(p2->pSymbiot, vMin, vMax);
  1470. Select_Brush(p->pSymbiot);
  1471. Select_Brush(p2->pSymbiot);
  1472. } else {
  1473. Select_Delete();
  1474. }
  1475. //Select_Brush(brushParent);
  1476. }
  1477. /*
  1478. ===============
  1479. BrushToPatchMesh
  1480. ===============
  1481. */
  1482. void Patch_BrushToMesh( bool bCone,bool bBevel,bool bEndcap,bool bSquare,int nHeight ) {
  1483. brush_t *b;
  1484. patchMesh_t *p;
  1485. int i, j;
  1486. int width = 9;
  1487. if ( bBevel & !bSquare ) {
  1488. width = 3;
  1489. } else if ( bEndcap & !bSquare ) {
  1490. width = 5;
  1491. }
  1492. if ( !QE_SingleBrush() ) {
  1493. return;
  1494. }
  1495. b = selected_brushes.next;
  1496. p = MakeNewPatch(width, nHeight);
  1497. p->d_texture = b->brush_faces->d_texture;
  1498. p->type = PATCH_CYLINDER;
  1499. if ( bBevel & !bSquare ) {
  1500. p->type = PATCH_BEVEL;
  1501. int nStep = (b->maxs[2] - b->mins[2]) / (p->height - 1);
  1502. int nStart = b->mins[2];
  1503. for ( i = 0; i < p->height; i++ ) {
  1504. p->ctrl(0, i).xyz[0] = b->mins[0];
  1505. p->ctrl(0, i).xyz[1] = b->mins[1];
  1506. p->ctrl(0, i).xyz[2] = nStart;
  1507. p->ctrl(1, i).xyz[0] = b->maxs[0];
  1508. p->ctrl(1, i).xyz[1] = b->mins[1];
  1509. p->ctrl(1, i).xyz[2] = nStart;
  1510. p->ctrl(2, i).xyz[0] = b->maxs[0];
  1511. p->ctrl(2, i).xyz[1] = b->maxs[1];
  1512. p->ctrl(2, i).xyz[2] = nStart;
  1513. nStart += nStep;
  1514. }
  1515. } else if ( bEndcap & !bSquare ) {
  1516. p->type = PATCH_ENDCAP;
  1517. int nStep = (b->maxs[2] - b->mins[2]) / (p->height - 1);
  1518. int nStart = b->mins[2];
  1519. for ( i = 0; i < p->height; i++ ) {
  1520. p->ctrl(0, i).xyz[0] = b->mins[0];
  1521. p->ctrl(0, i).xyz[1] = b->mins[1];
  1522. p->ctrl(0, i).xyz[2] = nStart;
  1523. p->ctrl(1, i).xyz[0] = b->mins[0];
  1524. p->ctrl(1, i).xyz[1] = b->maxs[1];
  1525. p->ctrl(1, i).xyz[2] = nStart;
  1526. p->ctrl(2, i).xyz[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) * 0.5);
  1527. p->ctrl(2, i).xyz[1] = b->maxs[1];
  1528. p->ctrl(2, i).xyz[2] = nStart;
  1529. p->ctrl(3, i).xyz[0] = b->maxs[0];
  1530. p->ctrl(3, i).xyz[1] = b->maxs[1];
  1531. p->ctrl(3, i).xyz[2] = nStart;
  1532. p->ctrl(4, i).xyz[0] = b->maxs[0];
  1533. p->ctrl(4, i).xyz[1] = b->mins[1];
  1534. p->ctrl(4, i).xyz[2] = nStart;
  1535. nStart += nStep;
  1536. }
  1537. } else {
  1538. p->ctrl(1, 0).xyz[0] = b->mins[0];
  1539. p->ctrl(1, 0).xyz[1] = b->mins[1];
  1540. p->ctrl(3, 0).xyz[0] = b->maxs[0];
  1541. p->ctrl(3, 0).xyz[1] = b->mins[1];
  1542. p->ctrl(5, 0).xyz[0] = b->maxs[0];
  1543. p->ctrl(5, 0).xyz[1] = b->maxs[1];
  1544. p->ctrl(7, 0).xyz[0] = b->mins[0];
  1545. p->ctrl(7, 0).xyz[1] = b->maxs[1];
  1546. for ( i = 1 ; i < p->width - 1 ; i += 2 ) {
  1547. p->ctrl(i, 0).xyz[2] = b->mins[2];
  1548. VectorCopy(p->ctrl(i, 0).xyz, p->ctrl(i, 2).xyz);
  1549. p->ctrl(i, 2).xyz[2] = b->maxs[2];
  1550. p->ctrl(i, 1).xyz[0] = (p->ctrl(i, 0).xyz[0] + p->ctrl(i, 2).xyz[0]) * 0.5;
  1551. p->ctrl(i, 1).xyz[1] = (p->ctrl(i, 0).xyz[1] + p->ctrl(i, 2).xyz[1]) * 0.5;
  1552. p->ctrl(i, 1).xyz[2] = (p->ctrl(i, 0).xyz[2] + p->ctrl(i, 2).xyz[2]) * 0.5;
  1553. }
  1554. InterpolateInteriorPoints(p);
  1555. if ( bSquare ) {
  1556. if ( bBevel || bEndcap ) {
  1557. if ( bBevel ) {
  1558. for ( i = 0; i < p->height; i++ ) {
  1559. VectorCopy(p->ctrl(1, i).xyz, p->ctrl(2, i).xyz);
  1560. VectorCopy(p->ctrl(7, i).xyz, p->ctrl(6, i).xyz);
  1561. }
  1562. } else {
  1563. for ( i = 0; i < p->height; i++ ) {
  1564. VectorCopy(p->ctrl(5, i).xyz, p->ctrl(4, i).xyz);
  1565. VectorCopy(p->ctrl(1, i).xyz, p->ctrl(2, i).xyz);
  1566. VectorCopy(p->ctrl(7, i).xyz, p->ctrl(6, i).xyz);
  1567. VectorCopy(p->ctrl(8, i).xyz, p->ctrl(7, i).xyz);
  1568. }
  1569. }
  1570. } else {
  1571. for ( i = 0; i < p->width - 1; i ++ ) {
  1572. for ( j = 0; j < p->height; j++ ) {
  1573. VectorCopy(p->ctrl(i + 1, j).xyz, p->ctrl(i, j).xyz);
  1574. }
  1575. }
  1576. for ( j = 0; j < p->height; j++ ) {
  1577. VectorCopy(p->ctrl(0, j).xyz, p->ctrl(8, j).xyz);
  1578. }
  1579. }
  1580. }
  1581. }
  1582. Patch_Naturalize(p);
  1583. if ( bCone ) {
  1584. p->type = PATCH_CONE;
  1585. float xc = (b->maxs[0] + b->mins[0]) * 0.5;
  1586. float yc = (b->maxs[1] + b->mins[1]) * 0.5;
  1587. for ( i = 0 ; i < p->width ; i ++ ) {
  1588. p->ctrl(i, 2).xyz[0] = xc;
  1589. p->ctrl(i, 2).xyz[1] = yc;
  1590. }
  1591. }
  1592. b = AddBrushForPatch(p);
  1593. Select_Delete();
  1594. Select_Brush(b);
  1595. }
  1596. patchMesh_t * Patch_GenerateGeneric( int width,int height,int orientation,const idVec3 &mins,const idVec3 &maxs ) {
  1597. patchMesh_t *p = MakeNewPatch(width, height);
  1598. p->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
  1599. p->type = PATCH_GENERIC;
  1600. int nFirst = 0;
  1601. int nSecond = 1;
  1602. if ( orientation == 0 ) {
  1603. nFirst = 1;
  1604. nSecond = 2;
  1605. } else if ( orientation == 1 ) {
  1606. nSecond = 2;
  1607. }
  1608. int xStep = mins[nFirst];
  1609. float xAdj = abs((maxs[nFirst] - mins[nFirst]) / (width - 1));
  1610. float yAdj = abs((maxs[nSecond] - mins[nSecond]) / (height - 1));
  1611. for ( int i = 0; i < width; i++ ) {
  1612. int yStep = mins[nSecond];
  1613. for ( int j = 0; j < height; j++ ) {
  1614. p->ctrl(i, j).xyz[nFirst] = xStep;
  1615. p->ctrl(i, j).xyz[nSecond] = yStep;
  1616. p->ctrl(i, j).xyz[orientation] = g_qeglobals.d_new_brush_bottom[orientation];
  1617. yStep += yAdj;
  1618. }
  1619. xStep += xAdj;
  1620. }
  1621. return p;
  1622. }
  1623. /*
  1624. ==================
  1625. Patch_GenericMesh
  1626. ==================
  1627. */
  1628. brush_t * Patch_GenericMesh( int width,int height,int orientation,bool bDeleteSource,bool bOverride,patchMesh_t *parent ) {
  1629. if ( height < 3 || height> 15 || width < 3 || width> 15 ) {
  1630. Sys_Status("Invalid patch width or height.\n");
  1631. return NULL;
  1632. }
  1633. if ( !bOverride && !QE_SingleBrush() ) {
  1634. Sys_Status("Cannot generate a patch from multiple selections.\n");
  1635. return NULL;
  1636. }
  1637. brush_t *b = selected_brushes.next;
  1638. patchMesh_t *p = Patch_GenerateGeneric(width, height, orientation, b->mins, b->maxs);
  1639. if ( parent ) {
  1640. p->explicitSubdivisions = parent->explicitSubdivisions;
  1641. p->horzSubdivisions = parent->horzSubdivisions;
  1642. p->vertSubdivisions = parent->vertSubdivisions;
  1643. }
  1644. Patch_Naturalize(p);
  1645. b = AddBrushForPatch(p);
  1646. if ( bDeleteSource ) {
  1647. Select_Delete();
  1648. Select_Brush(b);
  1649. }
  1650. return b;
  1651. }
  1652. /*
  1653. ==================
  1654. PointInMoveList
  1655. ==================
  1656. */
  1657. int PointInMoveList( idVec3 *pf ) {
  1658. for ( int i = 0; i < g_qeglobals.d_num_move_points; i++ ) {
  1659. if ( pf == g_qeglobals.d_move_points[i] ) {
  1660. return i;
  1661. }
  1662. }
  1663. return -1;
  1664. }
  1665. /*
  1666. ==================
  1667. PointValueInMoveList
  1668. ==================
  1669. */
  1670. static int PointValueInMoveList( idVec3 v ) {
  1671. for ( int i = 0; i < g_qeglobals.d_num_move_points; i++ ) {
  1672. if ( v.Compare(*g_qeglobals.d_move_points[i]) ) {
  1673. return i;
  1674. }
  1675. }
  1676. return -1;
  1677. }
  1678. /*
  1679. ==================
  1680. RemovePointFromMoveList
  1681. ==================
  1682. */
  1683. void RemovePointFromMoveList( idVec3 v ) {
  1684. int n;
  1685. while ( (n = PointValueInMoveList(v)) >= 0 ) {
  1686. for ( int i = n; i < g_qeglobals.d_num_move_points - 1; i++ ) {
  1687. g_qeglobals.d_move_points[i] = g_qeglobals.d_move_points[i + 1];
  1688. }
  1689. g_qeglobals.d_num_move_points--;
  1690. }
  1691. }
  1692. /*
  1693. ==================
  1694. ColumnSelected
  1695. ==================
  1696. */
  1697. bool ColumnSelected( patchMesh_t *p,int nCol ) {
  1698. for ( int i = 0; i < p->height; i++ ) {
  1699. if ( PointInMoveList(&p->ctrl(nCol, i).xyz) == -1 ) {
  1700. return false;
  1701. }
  1702. }
  1703. return true;
  1704. }
  1705. /*
  1706. ==================
  1707. AddPoint
  1708. ==================
  1709. */
  1710. static void AddPoint( patchMesh_t *p,idVec3 *v,bool bWeldOrDrill = true ) {
  1711. int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
  1712. int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
  1713. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = v;
  1714. if ( (g_bPatchWeld || g_bPatchDrillDown) && bWeldOrDrill ) {
  1715. for ( int i = 0 ; i < p->width ; i++ ) {
  1716. for ( int j = 0 ; j < p->height ; j++ ) {
  1717. if ( g_bPatchWeld ) {
  1718. if ( (*v).Compare(p->ctrl(i, j).xyz) && PointInMoveList(&p->ctrl(i, j).xyz) == -1 ) {
  1719. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = &p->ctrl(i, j).xyz;
  1720. continue;
  1721. }
  1722. }
  1723. if ( g_bPatchDrillDown && g_nPatchClickedView != W_CAMERA ) {
  1724. if ( (idMath::Fabs((*v)[nDim1] - p->ctrl(i, j).xyz[nDim1]) <= VECTOR_EPSILON) && (idMath::Fabs((*v)[nDim2] - p->ctrl(i, j).xyz[nDim2]) <= VECTOR_EPSILON) ) {
  1725. if ( PointInMoveList(&p->ctrl(i, j).xyz) == -1 ) {
  1726. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = &p->ctrl(i, j).xyz;
  1727. continue;
  1728. }
  1729. }
  1730. #if 0
  1731. int l = 0;
  1732. for ( int k = 0; k < 2; k++ ) {
  1733. if (idMath::Fabs(v[k] - p->ctrl(i,j).xyz[k]) > VECTOR_EPSILON)
  1734. continue;
  1735. l++;
  1736. }
  1737. if (l >= 2 && PointInMoveList(&p->ctrl(i,j).xyz) == -1) {
  1738. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = p->ctrl(i,j).xyz;
  1739. continue;
  1740. }
  1741. #endif
  1742. }
  1743. }
  1744. }
  1745. }
  1746. #if 0
  1747. if (g_qeglobals.d_num_move_points == 1) {
  1748. // single point selected
  1749. // FIXME: the two loops can probably be reduced to one
  1750. for ( int i = 0 ; i < p->width ; i++ ) {
  1751. for ( int j = 0 ; j < p->height ; j++ ) {
  1752. int n = PointInMoveList(v);
  1753. if (n >= 0) {
  1754. if (((i & 0x01) && (j & 0x01)) == 0) {
  1755. // put any sibling fixed points
  1756. // into the inverse list
  1757. int p1, p2, p3, p4;
  1758. p1 = i + 2;
  1759. p2 = i - 2;
  1760. p3 = j + 2;
  1761. p4 = j - 2;
  1762. if (p1 < p->width) {
  1763. }
  1764. if (p2 >= 0) {
  1765. }
  1766. if (p3 < p->height) {
  1767. }
  1768. if (p4 >= 0) {
  1769. }
  1770. }
  1771. }
  1772. }
  1773. }
  1774. }
  1775. #endif
  1776. }
  1777. /*
  1778. ==================
  1779. SelectRow
  1780. ==================
  1781. */
  1782. void SelectRow( patchMesh_t *p,int nRow,bool bMulti ) {
  1783. if ( !bMulti ) {
  1784. g_qeglobals.d_num_move_points = 0;
  1785. }
  1786. for ( int i = 0; i < p->width; i++ ) {
  1787. AddPoint(p, &p->ctrl(i, nRow).xyz, false);
  1788. }
  1789. //common->Printf("Selected Row %d\n", nRow);
  1790. }
  1791. /*
  1792. ==================
  1793. SelectColumn
  1794. ==================
  1795. */
  1796. void SelectColumn( patchMesh_t *p,int nCol,bool bMulti ) {
  1797. if ( !bMulti ) {
  1798. g_qeglobals.d_num_move_points = 0;
  1799. }
  1800. for ( int i = 0; i < p->height; i++ ) {
  1801. AddPoint(p, &p->ctrl(nCol, i).xyz, false);
  1802. }
  1803. //common->Printf("Selected Col %d\n", nCol);
  1804. }
  1805. /*
  1806. ==================
  1807. AddPatchMovePoint
  1808. ==================
  1809. */
  1810. void AddPatchMovePoint( idVec3 v,bool bMulti,bool bFull ) {
  1811. if ( !g_bSameView && !bMulti && !bFull ) {
  1812. g_bSameView = true;
  1813. return;
  1814. }
  1815. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  1816. if ( pb->pPatch ) {
  1817. patchMesh_t *p = pb->pPatch;
  1818. for ( int i = 0 ; i < p->width ; i++ ) {
  1819. for ( int j = 0 ; j < p->height ; j++ ) {
  1820. if ( v.Compare(p->ctrl(i, j).xyz) ) {
  1821. if ( PointInMoveList(&p->ctrl(i, j).xyz) == -1 ) {
  1822. if ( bFull ) // if we want the full row/col this is on
  1823. {
  1824. SelectColumn(p, i, bMulti);
  1825. } else {
  1826. if ( !bMulti )
  1827. g_qeglobals.d_num_move_points = 0;
  1828. AddPoint(p, &p->ctrl(i, j).xyz);
  1829. //common->Printf("Selected col:row %d:%d\n", i, j);
  1830. }
  1831. //--if (!bMulti)
  1832. return;
  1833. } else {
  1834. if ( bFull ) {
  1835. if ( ColumnSelected(p, i) ) {
  1836. SelectRow(p, j, bMulti);
  1837. } else {
  1838. SelectColumn(p, i, bMulti);
  1839. }
  1840. return;
  1841. }
  1842. if ( g_bSameView ) {
  1843. RemovePointFromMoveList(v);
  1844. return;
  1845. }
  1846. }
  1847. }
  1848. }
  1849. }
  1850. }
  1851. }
  1852. }
  1853. /*
  1854. ==================
  1855. Patch_UpdateSelected
  1856. ==================
  1857. */
  1858. void Patch_UpdateSelected( idVec3 vMove ) {
  1859. int i, j;
  1860. for ( i = 0 ; i < g_qeglobals.d_num_move_points ; i++ ) {
  1861. VectorAdd(*g_qeglobals.d_move_points[i], vMove, *g_qeglobals.d_move_points[i]);
  1862. if ( g_qeglobals.d_num_move_points == 1 ) {
  1863. }
  1864. }
  1865. //--patchMesh_t* p = &patchMeshes[g_nSelectedPatch];
  1866. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  1867. if ( pb->pPatch ) {
  1868. patchMesh_t *p = pb->pPatch;
  1869. g_qeglobals.d_numpoints = 0;
  1870. for ( i = 0 ; i < p->width ; i++ ) {
  1871. for ( j = 0 ; j < p->height ; j++ ) {
  1872. VectorCopy(p->ctrl(i, j).xyz, g_qeglobals.d_points[g_qeglobals.d_numpoints]);
  1873. if ( g_qeglobals.d_numpoints < MAX_POINTS - 1 ) {
  1874. g_qeglobals.d_numpoints++;
  1875. }
  1876. }
  1877. }
  1878. idVec3 vMin, vMax;
  1879. Patch_CalcBounds(p, vMin, vMax);
  1880. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  1881. }
  1882. }
  1883. //Brush_Free(p->pSymbiot);
  1884. //Select_Brush(AddBrushForPatch(g_nSelectedPatch));
  1885. }
  1886. void Patch_AdjustSubdivisions( float hadj,float vadj ) {
  1887. brush_t *pb;
  1888. for ( pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  1889. if ( pb->pPatch ) {
  1890. patchMesh_t *p = pb->pPatch;
  1891. p->horzSubdivisions += hadj;
  1892. p->vertSubdivisions += vadj;
  1893. Patch_MakeDirty(p);
  1894. }
  1895. }
  1896. Sys_UpdateWindows(W_ALL);
  1897. }
  1898. extern float ShadeForNormal( idVec3 normal );
  1899. /*
  1900. =================
  1901. DrawPatchMesh
  1902. =================
  1903. */
  1904. //FIXME: this routine needs to be reorganized.. should be about 1/4 the size and complexity
  1905. void DrawPatchMesh( patchMesh_t *pm,bool bPoints,int *list,bool bShade = false ) {
  1906. int i, j;
  1907. bool bOverlay = pm->bOverlay;
  1908. int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  1909. // patches use two display lists, one for camera one for xy
  1910. if ( *list <= 0 ) {
  1911. if ( *list <= 0 ) {
  1912. *list = qglGenLists(1);
  1913. }
  1914. if ( *list > 0 ) {
  1915. qglNewList(*list, GL_COMPILE_AND_EXECUTE);
  1916. }
  1917. //FIXME: finish consolidating all the patch crap
  1918. idSurface_Patch *cp = new idSurface_Patch(pm->width * 6, pm->height * 6);
  1919. cp->SetSize(pm->width, pm->height);
  1920. for ( i = 0; i < pm->width; i++ ) {
  1921. for ( j = 0; j < pm->height; j++ ) {
  1922. (*cp)[j * cp->GetWidth() + i].xyz = pm->ctrl(i, j).xyz;
  1923. (*cp)[j * cp->GetWidth() + i].st = pm->ctrl(i, j).st;
  1924. }
  1925. }
  1926. if ( pm->explicitSubdivisions ) {
  1927. cp->SubdivideExplicit(pm->horzSubdivisions, pm->vertSubdivisions, true);
  1928. } else {
  1929. cp->Subdivide(DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_LENGTH, true);
  1930. }
  1931. int width = cp->GetWidth();
  1932. int height = cp->GetHeight();
  1933. /*
  1934. for (i = 0; i < width; i++) {
  1935. for (j = 0; j < height; j++) {
  1936. qglBegin(GL_POINTS);
  1937. int index = j * width + i;
  1938. qglVertex3fv((*cp)[index].xyz);
  1939. qglEnd();
  1940. char msg[64];
  1941. sprintf(msg, "(%0.3f, %0.3f, %0.3f)(%0.3f, %0.3f)", (*cp)[index].xyz.x, (*cp)[index].xyz.y, (*cp)[index].xyz.z, (*cp)[index].st.x, (*cp)[index].st.y);
  1942. qglRasterPos3f((*cp)[index].xyz.x + 1, (*cp)[index].xyz.y + 1, (*cp)[index].xyz.z + 1);
  1943. qglCallLists (strlen(msg), GL_UNSIGNED_BYTE, msg);
  1944. }
  1945. }
  1946. */
  1947. #ifdef TEST_SURFACE_CLIPPING
  1948. int n;
  1949. idSurface *surf = cp;
  1950. idSurface *front, *back;
  1951. surf->Split(idPlane(1, 0, 0, 0), 0.1f, &front, &back);
  1952. if ( front && back ) {
  1953. front->TranslateSelf(idVec3(10, 10, 10));
  1954. (*front) += (*back);
  1955. surf = front;
  1956. } else {
  1957. surf = cp;
  1958. }
  1959. // surf->ClipInPlace( idPlane( 1, 0, 0, 0 ), 0.1f, true );
  1960. qglBegin(GL_TRIANGLES);
  1961. for ( i = 0; i < surf->GetNumIndexes(); i += 3 ) {
  1962. n = surf->GetIndexes()[i + 0];
  1963. qglTexCoord2fv((*surf)[n].st.ToFloatPtr());
  1964. qglVertex3fv((*surf)[n].xyz.ToFloatPtr());
  1965. n = surf->GetIndexes()[i + 1];
  1966. qglTexCoord2fv((*surf)[n].st.ToFloatPtr());
  1967. qglVertex3fv((*surf)[n].xyz.ToFloatPtr());
  1968. n = surf->GetIndexes()[i + 2];
  1969. qglTexCoord2fv((*surf)[n].st.ToFloatPtr());
  1970. qglVertex3fv((*surf)[n].xyz.ToFloatPtr());
  1971. }
  1972. qglEnd();
  1973. if ( front ) {
  1974. delete front;
  1975. }
  1976. if ( back ) {
  1977. delete back;
  1978. }
  1979. #else
  1980. for ( i = 0 ; i < width - 1; i++ ) {
  1981. qglBegin(GL_QUAD_STRIP);
  1982. for ( j = 0 ; j < height; j++ ) {
  1983. // v1-v2-v3-v4 makes a quad
  1984. int v1, v2;
  1985. float f;
  1986. v1 = j * width + i;
  1987. v2 = v1 + 1;
  1988. if ( bShade ) {
  1989. f = ShadeForNormal((*cp)[v2].normal);
  1990. qglColor3f(f, f, f);
  1991. }
  1992. qglTexCoord2fv((*cp)[v2].st.ToFloatPtr());
  1993. qglVertex3fv((*cp)[v2].xyz.ToFloatPtr());
  1994. if ( bShade ) {
  1995. f = ShadeForNormal((*cp)[v1].normal);
  1996. qglColor3f(f, f, f);
  1997. }
  1998. qglTexCoord2fv((*cp)[v1].st.ToFloatPtr());
  1999. qglVertex3fv((*cp)[v1].xyz.ToFloatPtr());
  2000. }
  2001. qglEnd();
  2002. }
  2003. #endif
  2004. if ( list == &pm->nListSelected ) {
  2005. globalImages->BindNull();
  2006. qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2007. qglColor3f(1.0f, 1.0f, 1.0f);
  2008. for ( i = 0 ; i < width - 1; i++ ) {
  2009. qglBegin(GL_QUAD_STRIP);
  2010. for ( j = 0 ; j < height; j++ ) {
  2011. int v1, v2;
  2012. v1 = j * width + i;
  2013. v2 = v1 + 1;
  2014. qglVertex3fv((*cp)[v2].xyz.ToFloatPtr());
  2015. qglVertex3fv((*cp)[v1].xyz.ToFloatPtr());
  2016. }
  2017. qglEnd();
  2018. }
  2019. }
  2020. delete cp;
  2021. if ( *list > 0 ) {
  2022. qglEndList();
  2023. }
  2024. } else {
  2025. qglCallList(*list);
  2026. }
  2027. idVec3 *pSelectedPoints[256];
  2028. int nIndex = 0;
  2029. // FIXME: this bend painting code needs to be rolled up significantly as it is a mess right now
  2030. if ( bPoints && (g_qeglobals.d_select_mode == sel_curvepoint || g_qeglobals.d_select_mode == sel_area || g_bPatchBendMode || g_bPatchInsertMode) ) {
  2031. bOverlay = false;
  2032. // bending or inserting
  2033. if ( g_bPatchBendMode || g_bPatchInsertMode ) {
  2034. qglPointSize(6);
  2035. if ( g_bPatchAxisOnRow ) {
  2036. qglColor3f(1, 0, 1);
  2037. qglBegin(GL_POINTS);
  2038. for ( i = 0; i < pm->width; i++ ) {
  2039. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(i, g_nPatchAxisIndex).xyz));
  2040. }
  2041. qglEnd();
  2042. // could do all of this in one loop but it was pretty messy
  2043. if ( g_bPatchInsertMode ) {
  2044. qglColor3f(0, 0, 1);
  2045. qglBegin(GL_POINTS);
  2046. for ( i = 0; i < pm->width; i++ ) {
  2047. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(i, g_nPatchAxisIndex).xyz));
  2048. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(i, g_nPatchAxisIndex + 1).xyz));
  2049. }
  2050. qglEnd();
  2051. } else {
  2052. if ( g_nPatchBendState == BEND_SELECT_EDGE || g_nPatchBendState == BEND_BENDIT || g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  2053. qglColor3f(0, 0, 1);
  2054. qglBegin(GL_POINTS);
  2055. if ( g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  2056. qglVertex3fv(g_vBendOrigin.ToFloatPtr());
  2057. } else {
  2058. for ( i = 0; i < pm->width; i++ ) {
  2059. if ( g_bPatchLowerEdge ) {
  2060. for ( j = 0; j < g_nPatchAxisIndex; j++ ) {
  2061. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(i, j).xyz));
  2062. }
  2063. } else {
  2064. for ( j = pm->height - 1; j > g_nPatchAxisIndex; j-- ) {
  2065. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(i, j).xyz));
  2066. }
  2067. }
  2068. }
  2069. }
  2070. qglEnd();
  2071. }
  2072. }
  2073. } else {
  2074. qglColor3f(1, 0, 1);
  2075. qglBegin(GL_POINTS);
  2076. for ( i = 0; i < pm->height; i++ ) {
  2077. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(g_nPatchAxisIndex, i).xyz));
  2078. }
  2079. qglEnd();
  2080. // could do all of this in one loop but it was pretty messy
  2081. if ( g_bPatchInsertMode ) {
  2082. qglColor3f(0, 0, 1);
  2083. qglBegin(GL_POINTS);
  2084. for ( i = 0; i < pm->height; i++ ) {
  2085. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(g_nPatchAxisIndex, i).xyz));
  2086. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(g_nPatchAxisIndex + 1, i).xyz));
  2087. }
  2088. qglEnd();
  2089. } else {
  2090. if ( g_nPatchBendState == BEND_SELECT_EDGE || g_nPatchBendState == BEND_BENDIT || g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  2091. qglColor3f(0, 0, 1);
  2092. qglBegin(GL_POINTS);
  2093. for ( i = 0; i < pm->height; i++ ) {
  2094. if ( g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  2095. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(g_nBendOriginIndex, i).xyz));
  2096. } else {
  2097. if ( g_bPatchLowerEdge ) {
  2098. for ( j = 0; j < g_nPatchAxisIndex; j++ ) {
  2099. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(j, i).xyz));
  2100. }
  2101. } else {
  2102. for ( j = pm->width - 1; j > g_nPatchAxisIndex; j-- ) {
  2103. qglVertex3fv(reinterpret_cast< float(*)>(&pm->ctrl(j, i).xyz));
  2104. }
  2105. }
  2106. }
  2107. }
  2108. qglEnd();
  2109. }
  2110. }
  2111. }
  2112. } else {
  2113. qglPointSize(6);
  2114. for ( i = 0 ; i < pm->width ; i++ ) {
  2115. for ( j = 0 ; j < pm->height ; j++ ) {
  2116. qglBegin(GL_POINTS);
  2117. // FIXME: need to not do loop lookups inside here
  2118. int n = PointValueInMoveList(pm->ctrl(i, j).xyz);
  2119. if ( n >= 0 ) {
  2120. pSelectedPoints[nIndex++] = &pm->ctrl(i, j).xyz;
  2121. }
  2122. if ( i & 0x01 || j & 0x01 ) {
  2123. qglColor3f(1, 0, 1);
  2124. } else {
  2125. qglColor3f(0, 1, 0);
  2126. }
  2127. qglVertex3fv(pm->ctrl(i, j).xyz.ToFloatPtr());
  2128. qglEnd();
  2129. }
  2130. }
  2131. }
  2132. if ( nIndex > 0 ) {
  2133. qglBegin(GL_POINTS);
  2134. qglColor3f(0, 0, 1);
  2135. while ( nIndex-- > 0 ) {
  2136. qglVertex3fv((*pSelectedPoints[nIndex]).ToFloatPtr());
  2137. }
  2138. qglEnd();
  2139. }
  2140. }
  2141. if ( bOverlay ) {
  2142. qglPointSize(6);
  2143. qglColor3f(0.5, 0.5, 0.5);
  2144. for ( i = 0 ; i < pm->width ; i++ ) {
  2145. qglBegin(GL_POINTS);
  2146. for ( j = 0 ; j < pm->height ; j++ ) {
  2147. if ( i & 0x01 || j & 0x01 ) {
  2148. qglColor3f(0.5, 0, 0.5);
  2149. } else {
  2150. qglColor3f(0, 0.5, 0);
  2151. }
  2152. qglVertex3fv(pm->ctrl(i, j).xyz.ToFloatPtr());
  2153. }
  2154. qglEnd();
  2155. }
  2156. }
  2157. }
  2158. /*
  2159. ==================
  2160. Patch_DrawXY
  2161. ==================
  2162. */
  2163. void Patch_DrawXY( patchMesh_t *pm ) {
  2164. qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2165. if ( pm->bSelected ) {
  2166. qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr());
  2167. //qglDisable (GL_LINE_STIPPLE);
  2168. //qglLineWidth (1);
  2169. } else {
  2170. qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES].ToFloatPtr());
  2171. }
  2172. DrawPatchMesh(pm, pm->bSelected, &pm->nListID);
  2173. qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  2174. if ( pm->bSelected ) {
  2175. //qglLineWidth (2);
  2176. //qglEnable (GL_LINE_STIPPLE);
  2177. }
  2178. }
  2179. /*
  2180. ==================
  2181. Patch_DrawCam
  2182. ==================
  2183. */
  2184. void Patch_DrawCam( patchMesh_t *pm,bool selected ) {
  2185. int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  2186. if ( !selected ) {
  2187. qglColor3f(1, 1, 1);
  2188. }
  2189. if ( g_bPatchWireFrame || nDrawMode == cd_wire ) {
  2190. qglDisable(GL_CULL_FACE);
  2191. qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2192. globalImages->BindNull();
  2193. DrawPatchMesh(pm, pm->bSelected, &pm->nListIDCam, true);
  2194. qglEnable(GL_CULL_FACE);
  2195. } else {
  2196. qglEnable(GL_CULL_FACE);
  2197. qglCullFace(GL_FRONT);
  2198. qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  2199. if ( nDrawMode == cd_texture || nDrawMode == cd_light ) {
  2200. pm->d_texture->GetEditorImage()->Bind();
  2201. }
  2202. if ( !selected && pm->d_texture->GetEditorAlpha() != 1.0f ) {
  2203. qglEnable(GL_BLEND);
  2204. qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2205. }
  2206. DrawPatchMesh(pm, pm->bSelected, &pm->nListIDCam, true);
  2207. if ( !selected && pm->d_texture->GetEditorAlpha() != 1.0f ) {
  2208. qglDisable(GL_BLEND);
  2209. }
  2210. globalImages->BindNull();
  2211. if ( !selected ) {
  2212. qglCullFace(GL_BACK);
  2213. qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2214. qglDisable(GL_BLEND);
  2215. } else {
  2216. qglEnable(GL_BLEND);
  2217. qglColor4f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0], g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1], g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2], 0.25);
  2218. qglDisable(GL_CULL_FACE);
  2219. }
  2220. DrawPatchMesh(pm, pm->bSelected, (selected) ? &pm->nListSelected : &pm->nListIDCam, !selected);
  2221. qglEnable(GL_CULL_FACE);
  2222. }
  2223. #if 0 // this paints normal indicators on the ctrl points
  2224. //--qglDisable (GL_DEPTH_TEST);
  2225. qglColor3f (1,1,1);
  2226. for (int i = 0; i < pm->width; i++) {
  2227. for (int j = 0; j < pm->height; j++) {
  2228. idVec3 temp;
  2229. qglBegin (GL_LINES);
  2230. qglVertex3fv (pm->ctrl(i,j).xyz);
  2231. VectorMA (pm->ctrl(i,j).xyz, 8, pm->ctrl(i,j].normal, temp);
  2232. qglVertex3fv (temp);
  2233. qglEnd ();
  2234. }
  2235. }
  2236. //--qglEnable (GL_DEPTH_TEST);
  2237. #endif
  2238. }
  2239. void ConvexHullForSection( float section[2][4][7] ) {
  2240. }
  2241. void BrushesForSection( float section[2][4][7] ) {
  2242. }
  2243. /*
  2244. ==================
  2245. Patch_Move
  2246. ==================
  2247. */
  2248. void Patch_Move( patchMesh_t *pm,const idVec3 vMove,bool bRebuild ) {
  2249. Patch_MakeDirty(pm);
  2250. for ( int w = 0; w < pm->width; w++ ) {
  2251. for ( int h = 0; h < pm->height; h++ ) {
  2252. VectorAdd(pm->ctrl(w, h).xyz, vMove, pm->ctrl(w, h).xyz);
  2253. }
  2254. }
  2255. if ( bRebuild ) {
  2256. idVec3 vMin, vMax;
  2257. Patch_CalcBounds(pm, vMin, vMax);
  2258. //Brush_RebuildBrush(patchMeshes[n].pSymbiot, vMin, vMax);
  2259. }
  2260. UpdatePatchInspector();
  2261. }
  2262. /*
  2263. ==================
  2264. Patch_ApplyMatrix
  2265. ==================
  2266. */
  2267. void Patch_ApplyMatrix( patchMesh_t *p,const idVec3 vOrigin,const idMat3 matrix,bool bSnap ) {
  2268. idVec3 vTemp;
  2269. for ( int w = 0; w < p->width; w++ ) {
  2270. for ( int h = 0; h < p->height; h++ ) {
  2271. if ( (g_qeglobals.d_select_mode == sel_curvepoint || g_bPatchBendMode) && PointInMoveList(&p->ctrl(w, h).xyz) == -1 ) {
  2272. continue;
  2273. }
  2274. vTemp = p->ctrl(w, h).xyz - vOrigin;
  2275. vTemp *= matrix;
  2276. p->ctrl(w, h).xyz = vTemp + vOrigin;
  2277. }
  2278. }
  2279. idVec3 vMin, vMax;
  2280. Patch_CalcBounds(p, vMin, vMax);
  2281. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  2282. }
  2283. /*
  2284. ==================
  2285. Patch_EditPatch
  2286. ==================
  2287. */
  2288. void Patch_EditPatch() {
  2289. //--patchMesh_t* p = &patchMeshes[n];
  2290. g_qeglobals.d_numpoints = 0;
  2291. g_qeglobals.d_num_move_points = 0;
  2292. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  2293. if ( pb->pPatch ) {
  2294. patchMesh_t *p = pb->pPatch;
  2295. for ( int i = 0 ; i < p->width ; i++ ) {
  2296. for ( int j = 0 ; j < p->height ; j++ ) {
  2297. VectorCopy(p->ctrl(i, j).xyz, g_qeglobals.d_points[g_qeglobals.d_numpoints]);
  2298. if ( g_qeglobals.d_numpoints < MAX_POINTS - 1 ) {
  2299. g_qeglobals.d_numpoints++;
  2300. }
  2301. }
  2302. }
  2303. }
  2304. }
  2305. g_qeglobals.d_select_mode = sel_curvepoint;
  2306. //--g_nSelectedPatch = n;
  2307. }
  2308. /*
  2309. ==================
  2310. Patch_Deselect
  2311. ==================
  2312. */
  2313. //FIXME: need all sorts of asserts throughout a lot of this crap
  2314. void Patch_Deselect() {
  2315. //--g_nSelectedPatch = -1;
  2316. g_qeglobals.d_select_mode = sel_brush;
  2317. for ( brush_t*b = selected_brushes.next ; b != &selected_brushes ; b = b->next ) {
  2318. if ( b->pPatch ) {
  2319. b->pPatch->bSelected = false;
  2320. }
  2321. }
  2322. if ( g_bPatchBendMode ) {
  2323. Patch_BendToggle();
  2324. }
  2325. if ( g_bPatchInsertMode ) {
  2326. Patch_InsDelToggle();
  2327. }
  2328. }
  2329. /*
  2330. ==================
  2331. Patch_Select
  2332. ==================
  2333. */
  2334. void Patch_Select( patchMesh_t *p ) {
  2335. // maintained for point manip.. which i need to fix as this
  2336. // is pf error prone
  2337. //--g_nSelectedPatch = n;
  2338. p->bSelected = true;
  2339. }
  2340. /*
  2341. ==================
  2342. Patch_Deselect
  2343. ==================
  2344. */
  2345. void Patch_Deselect( patchMesh_t *p ) {
  2346. p->bSelected = false;
  2347. }
  2348. /*
  2349. ==================
  2350. Patch_Delete
  2351. ==================
  2352. */
  2353. void Patch_Delete( patchMesh_t *p ) {
  2354. if ( p->pSymbiot ) {
  2355. p->pSymbiot->pPatch = NULL;
  2356. }
  2357. Mem_Free(p->verts);
  2358. if ( p->epairs ) {
  2359. delete p->epairs;
  2360. }
  2361. Mem_Free(p);
  2362. p = NULL;
  2363. UpdatePatchInspector();
  2364. }
  2365. /*
  2366. ==================
  2367. Patch_Scale
  2368. ==================
  2369. */
  2370. void Patch_Scale( patchMesh_t *p,const idVec3 vOrigin,const idVec3 vAmt,bool bRebuild ) {
  2371. for ( int w = 0; w < p->width; w++ ) {
  2372. for ( int h = 0; h < p->height; h++ ) {
  2373. if ( g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(&p->ctrl(w, h).xyz) == -1 )
  2374. continue;
  2375. for ( int i = 0 ; i < 3 ; i++ ) {
  2376. p->ctrl(w, h).xyz[i] -= vOrigin[i];
  2377. p->ctrl(w, h).xyz[i] *= vAmt[i];
  2378. p->ctrl(w, h).xyz[i] += vOrigin[i];
  2379. }
  2380. }
  2381. }
  2382. if ( bRebuild ) {
  2383. idVec3 vMin, vMax;
  2384. Patch_CalcBounds(p, vMin, vMax);
  2385. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  2386. }
  2387. UpdatePatchInspector();
  2388. }
  2389. /*
  2390. ==================
  2391. Patch_Cleanup
  2392. ==================
  2393. */
  2394. void Patch_Cleanup() {
  2395. //--g_nSelectedPatch = -1;
  2396. //numPatchMeshes = 0;
  2397. }
  2398. /*
  2399. ==================
  2400. Patch_SetView
  2401. ==================
  2402. */
  2403. void Patch_SetView( int n ) {
  2404. g_bSameView = (n == g_nPatchClickedView);
  2405. g_nPatchClickedView = n;
  2406. }
  2407. /*
  2408. ==================
  2409. Patch_SetTexture
  2410. ==================
  2411. */
  2412. // FIXME: need array validation throughout
  2413. void Patch_SetTexture( patchMesh_t *p,texdef_t *tex_def ) {
  2414. p->d_texture = Texture_ForName(tex_def->name);
  2415. UpdatePatchInspector();
  2416. }
  2417. /*
  2418. ==================
  2419. Patch_SetTexture
  2420. ==================
  2421. */
  2422. // FIXME: need array validation throughout
  2423. void Patch_SetTextureName( patchMesh_t *p,const char *name ) {
  2424. p->d_texture = Texture_ForName(name);
  2425. UpdatePatchInspector();
  2426. }
  2427. /*
  2428. ==================
  2429. Patch_DragScale
  2430. ==================
  2431. */
  2432. bool Patch_DragScale( patchMesh_t *p,idVec3 vAmt,idVec3 vMove ) {
  2433. idVec3 vMin, vMax, vScale, vTemp, vMid;
  2434. int i;
  2435. Patch_CalcBounds(p, vMin, vMax);
  2436. VectorSubtract(vMax, vMin, vTemp);
  2437. // if we are scaling in the same dimension the patch has no depth
  2438. for ( i = 0; i < 3; i ++ ) {
  2439. if ( vTemp[i] == 0 && vMove[i] != 0 ) {
  2440. //Patch_Move(n, vMove, true);
  2441. return false;
  2442. }
  2443. }
  2444. for ( i = 0 ; i < 3 ; i++ )
  2445. vMid[i] = (vMin[i] + ((vMax[i] - vMin[i]) / 2));
  2446. for ( i = 0; i < 3; i++ ) {
  2447. if ( vAmt[i] != 0 ) {
  2448. vScale[i] = 1.0f + vAmt[i] / vTemp[i];
  2449. } else {
  2450. vScale[i] = 1.0f;
  2451. }
  2452. }
  2453. Patch_Scale(p, vMid, vScale, false);
  2454. VectorSubtract(vMax, vMin, vTemp);
  2455. Patch_CalcBounds(p, vMin, vMax);
  2456. VectorSubtract(vMax, vMin, vMid);
  2457. VectorSubtract(vMid, vTemp, vTemp);
  2458. VectorScale(vTemp, 0.5, vTemp);
  2459. // abs of both should always be equal
  2460. if ( !vMove.Compare(vAmt) ) {
  2461. for ( i = 0; i < 3; i++ ) {
  2462. if ( vMove[i] != vAmt[i] ) {
  2463. vTemp[i] = -(vTemp[i]);
  2464. }
  2465. }
  2466. }
  2467. Patch_Move(p, vTemp);
  2468. return true;
  2469. }
  2470. /*
  2471. ==================
  2472. Patch_InsertColumn
  2473. ==================
  2474. */
  2475. void Patch_InsertColumn( patchMesh_t *p,bool bAdd ) {
  2476. int h, w, i, j;
  2477. idVec3 vTemp;
  2478. if ( p->width + 2 >= MAX_PATCH_WIDTH ) {
  2479. return;
  2480. }
  2481. Patch_AdjustSize(p, 2, 0);
  2482. // re-adjust til after routine
  2483. //p->width -= 2;
  2484. if ( bAdd ) {
  2485. // add column?
  2486. for ( h = 0; h < p->height; h++ ) {
  2487. j = p->width - 3;
  2488. VectorSubtract(p->ctrl(j, h).xyz, p->ctrl(j - 1, h).xyz, vTemp);
  2489. for ( i = 0; i < 3; i++ ) {
  2490. vTemp[i] /= 3;
  2491. }
  2492. memcpy(&p->ctrl(j + 2, h), &p->ctrl(j, h), sizeof(idDrawVert));
  2493. memcpy(&p->ctrl(j, h), &p->ctrl(j - 1, h), sizeof(idDrawVert));
  2494. VectorAdd(p->ctrl(j, h).xyz, vTemp, p->ctrl(j, h).xyz);
  2495. memcpy(&p->ctrl(j + 1, h), &p->ctrl(j, h), sizeof(idDrawVert));
  2496. VectorAdd(p->ctrl(j + 1, h).xyz, vTemp, p->ctrl(j + 1, h).xyz);
  2497. }
  2498. } else {
  2499. for ( h = 0; h < p->height; h++ ) {
  2500. w = p->width - 3;
  2501. while ( w >= 0 ) {
  2502. memcpy(&p->ctrl(w + 2, h), &p->ctrl(w, h), sizeof(idDrawVert));
  2503. w--;
  2504. }
  2505. VectorSubtract(p->ctrl(1, h).xyz, p->ctrl(0, h).xyz, vTemp);
  2506. for ( i = 0; i < 3; i++ ) {
  2507. vTemp[i] /= 3;
  2508. }
  2509. VectorCopy(p->ctrl(0, h).xyz, p->ctrl(1, h).xyz);
  2510. VectorAdd(p->ctrl(1, h).xyz, vTemp, p->ctrl(1, h).xyz);
  2511. VectorCopy(p->ctrl(1, h).xyz, p->ctrl(2, h).xyz);
  2512. VectorAdd(p->ctrl(2, h).xyz, vTemp, p->ctrl(2, h).xyz);
  2513. }
  2514. }
  2515. //p->width += 2;
  2516. UpdatePatchInspector();
  2517. }
  2518. /*
  2519. ==================
  2520. Patch_InsertRow
  2521. ==================
  2522. */
  2523. void Patch_InsertRow( patchMesh_t *p,bool bAdd ) {
  2524. int h, w, i, j;
  2525. idVec3 vTemp;
  2526. if ( p->height + 2 >= MAX_PATCH_HEIGHT ) {
  2527. return;
  2528. }
  2529. Patch_AdjustSize(p, 0, 2);
  2530. if ( bAdd ) {
  2531. // add column?
  2532. for ( w = 0; w < p->width; w++ ) {
  2533. j = p->height - 3;
  2534. VectorSubtract(p->ctrl(w, j).xyz, p->ctrl(w, j - 1).xyz, vTemp);
  2535. for ( i = 0; i < 3; i++ ) {
  2536. vTemp[i] /= 3;
  2537. }
  2538. memcpy(&p->ctrl(w, j + 2), &p->ctrl(w, j), sizeof(idDrawVert));
  2539. memcpy(&p->ctrl(w, j), &p->ctrl(w, j - 1), sizeof(idDrawVert));
  2540. VectorAdd(p->ctrl(w, j).xyz, vTemp, p->ctrl(w, j).xyz);
  2541. memcpy(&p->ctrl(w, j + 1), &p->ctrl(w, j), sizeof(idDrawVert));
  2542. VectorAdd(p->ctrl(w, j + 1).xyz, vTemp, p->ctrl(w, j + 1).xyz);
  2543. }
  2544. } else {
  2545. for ( w = 0; w < p->width; w++ ) {
  2546. h = p->height - 3;
  2547. while ( h >= 0 ) {
  2548. memcpy(&p->ctrl(w, h + 2), &p->ctrl(w, h), sizeof(idDrawVert));
  2549. h--;
  2550. }
  2551. VectorSubtract(p->ctrl(w, 1).xyz, p->ctrl(w, 0).xyz, vTemp);
  2552. for ( i = 0; i < 3; i++ ) {
  2553. vTemp[i] /= 3;
  2554. }
  2555. VectorCopy(p->ctrl(w, 0).xyz, p->ctrl(w, 1).xyz);
  2556. VectorAdd(p->ctrl(w, 1).xyz, vTemp, p->ctrl(w, 1).xyz);
  2557. VectorCopy(p->ctrl(w, 1).xyz, p->ctrl(w, 2).xyz);
  2558. VectorAdd(p->ctrl(w, 2).xyz, vTemp, p->ctrl(w, 2).xyz);
  2559. }
  2560. }
  2561. UpdatePatchInspector();
  2562. }
  2563. /*
  2564. ==================
  2565. Patch_RemoveRow
  2566. ==================
  2567. */
  2568. void Patch_RemoveRow( patchMesh_t *p,bool bFirst ) {
  2569. if ( p->height <= MIN_PATCH_HEIGHT ) {
  2570. return;
  2571. }
  2572. if ( bFirst ) {
  2573. for ( int w = 0; w < p->width; w++ ) {
  2574. for ( int h = 0; h < p->height - 2; h++ ) {
  2575. memcpy(&p->ctrl(w, h), &p->ctrl(w, h + 2), sizeof(idDrawVert));
  2576. }
  2577. }
  2578. }
  2579. Patch_AdjustSize(p, 0, -2);
  2580. UpdatePatchInspector();
  2581. }
  2582. /*
  2583. ==================
  2584. Patch_RemoveColumn
  2585. ==================
  2586. */
  2587. void Patch_RemoveColumn( patchMesh_t *p,bool bFirst ) {
  2588. if ( p->width <= MIN_PATCH_WIDTH ) {
  2589. return;
  2590. }
  2591. if ( bFirst ) {
  2592. for ( int h = 0; h < p->height; h++ ) {
  2593. for ( int w = 0; w < p->width - 2; w++ ) {
  2594. memcpy(&p->ctrl(w, h), &p->ctrl(w + 2, h), sizeof(idDrawVert));
  2595. }
  2596. }
  2597. }
  2598. Patch_AdjustSize(p, -2, 0);
  2599. UpdatePatchInspector();
  2600. }
  2601. void Patch_DisperseRows() {
  2602. idVec3 vTemp, vTemp2;
  2603. int i, w, h;
  2604. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  2605. if ( pb->pPatch ) {
  2606. patchMesh_t *p = pb->pPatch;
  2607. Patch_Rebuild(p);
  2608. for ( w = 0; w < p->width; w++ ) {
  2609. // for each row, we need to evenly disperse p->height number
  2610. // of points across the old bounds
  2611. // calc total distance to interpolate
  2612. VectorSubtract(p->ctrl(w, p->height - 1).xyz, p->ctrl(w, 0).xyz, vTemp);
  2613. //vTemp[0] = vTemp[1] = vTemp[2] = 0;
  2614. //for (h = 0; h < p->height - nRows; h ++)
  2615. //{
  2616. // VectorAdd(vTemp, p->ctrl(w,h], vTemp);
  2617. //}
  2618. // amount per cycle
  2619. for ( i = 0; i < 3; i ++ ) {
  2620. vTemp2[i] = vTemp[i] / (p->height - 1);
  2621. }
  2622. // move along
  2623. for ( h = 0; h < p->height - 1; h++ ) {
  2624. VectorAdd(p->ctrl(w, h).xyz, vTemp2, p->ctrl(w, h + 1).xyz);
  2625. }
  2626. Patch_Naturalize(p);
  2627. }
  2628. }
  2629. }
  2630. UpdatePatchInspector();
  2631. }
  2632. /*
  2633. ==================
  2634. Patch_AdjustColumns
  2635. ==================
  2636. */
  2637. void Patch_DisperseColumns() {
  2638. idVec3 vTemp, vTemp2;
  2639. int i, w, h;
  2640. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  2641. if ( pb->pPatch ) {
  2642. patchMesh_t *p = pb->pPatch;
  2643. Patch_Rebuild(p);
  2644. for ( h = 0; h < p->height; h++ ) {
  2645. // for each column, we need to evenly disperse p->width number
  2646. // of points across the old bounds
  2647. // calc total distance to interpolate
  2648. VectorSubtract(p->ctrl(p->width - 1, h).xyz, p->ctrl(0, h).xyz, vTemp);
  2649. // amount per cycle
  2650. for ( i = 0; i < 3; i ++ ) {
  2651. vTemp2[i] = vTemp[i] / (p->width - 1);
  2652. }
  2653. // move along
  2654. for ( w = 0; w < p->width - 1; w++ ) {
  2655. VectorAdd(p->ctrl(w, h).xyz, vTemp2, p->ctrl(w + 1, h).xyz);
  2656. }
  2657. }
  2658. Patch_Naturalize(p);
  2659. }
  2660. }
  2661. UpdatePatchInspector();
  2662. }
  2663. /*
  2664. ==================
  2665. Patch_AdjustSelected
  2666. ==================
  2667. */
  2668. void Patch_AdjustSelected( bool bInsert,bool bColumn,bool bFlag ) {
  2669. bool bUpdate = false;
  2670. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  2671. if ( pb->pPatch ) {
  2672. if ( bInsert ) {
  2673. if ( bColumn ) {
  2674. Patch_InsertColumn(pb->pPatch, bFlag);
  2675. } else {
  2676. Patch_InsertRow(pb->pPatch, bFlag);
  2677. }
  2678. } else {
  2679. if ( bColumn ) {
  2680. Patch_RemoveColumn(pb->pPatch, bFlag);
  2681. } else {
  2682. Patch_RemoveRow(pb->pPatch, bFlag);
  2683. }
  2684. }
  2685. bUpdate = true;
  2686. idVec3 vMin, vMax;
  2687. patchMesh_t *p = pb->pPatch;
  2688. Patch_CalcBounds(p, vMin, vMax);
  2689. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  2690. }
  2691. }
  2692. if ( bUpdate ) {
  2693. Sys_UpdateWindows(W_ALL);
  2694. }
  2695. }
  2696. void Parse1DMatrix( int x,float *p ) {
  2697. GetToken(true); // (
  2698. for ( int i = 0; i < x; i++ ) {
  2699. GetToken(false);
  2700. p[i] = atof(token);
  2701. }
  2702. GetToken(true); // )
  2703. }
  2704. void Parse2DMatrix( int y,int x,float *p ) {
  2705. GetToken(true); // (
  2706. for ( int i = 0; i < y; i++ ) {
  2707. Parse1DMatrix(x, p + i * x);
  2708. }
  2709. GetToken(true); // )
  2710. }
  2711. void Parse3DMatrix( int z,int y,int x,float *p ) {
  2712. GetToken(true); // (
  2713. for ( int i = 0; i < z; i++ ) {
  2714. Parse2DMatrix(y, x, p + i * (x * MAX_PATCH_HEIGHT));
  2715. }
  2716. GetToken(true); // )
  2717. }
  2718. // parses a patch
  2719. brush_t * Patch_Parse( bool bOld ) {
  2720. const idMaterial *tex = declManager->FindMaterial(NULL);
  2721. GetToken(true);
  2722. if ( strcmp(token, "{") ) {
  2723. return NULL;
  2724. }
  2725. patchMesh_t *pm = NULL;
  2726. if ( g_qeglobals.bSurfacePropertiesPlugin ) {
  2727. assert(true);
  2728. //GETPLUGINTEXDEF(pm)->ParsePatchTexdef();
  2729. } else {
  2730. // texture def
  2731. GetToken(true);
  2732. // band-aid
  2733. if ( strcmp(token, "(") ) {
  2734. if ( g_qeglobals.mapVersion < 2.0f ) {
  2735. tex = Texture_ForName(va("textures/%s", token));
  2736. } else {
  2737. tex = Texture_ForName(token);
  2738. }
  2739. GetToken(true);
  2740. } else {
  2741. common->Printf("Warning: Patch read with no texture, using notexture... \n");
  2742. }
  2743. if ( strcmp(token, "(") ) {
  2744. return NULL;
  2745. }
  2746. // width, height, flags (currently only negative)
  2747. GetToken(false);
  2748. int width = atoi(token);
  2749. GetToken(false);
  2750. int height = atoi(token);
  2751. pm = MakeNewPatch(width, height);
  2752. pm->d_texture = tex;
  2753. if ( !bOld ) {
  2754. GetToken(false);
  2755. pm->horzSubdivisions = atoi(token);
  2756. GetToken(false);
  2757. pm->vertSubdivisions = atoi(token);
  2758. pm->explicitSubdivisions = true;
  2759. }
  2760. GetToken(false);
  2761. pm->contents = atoi(token);
  2762. GetToken(false);
  2763. pm->flags = atoi(token);
  2764. GetToken(false);
  2765. pm->value = atoi(token);
  2766. //if (!bOld)
  2767. //{
  2768. // GetToken(false);
  2769. // pm->type = atoi(token);
  2770. //}
  2771. GetToken(false);
  2772. if ( strcmp(token, ")") )
  2773. return NULL;
  2774. }
  2775. float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
  2776. Parse3DMatrix(pm->width, pm->height, 5, reinterpret_cast< float*>(&ctrl));
  2777. int w, h;
  2778. for ( w = 0; w < pm->width; w++ ) {
  2779. for ( h = 0; h < pm->height; h++ ) {
  2780. pm->ctrl(w, h).xyz[0] = ctrl[w][h][0];
  2781. pm->ctrl(w, h).xyz[1] = ctrl[w][h][1];
  2782. pm->ctrl(w, h).xyz[2] = ctrl[w][h][2];
  2783. pm->ctrl(w, h).st[0] = ctrl[w][h][3];
  2784. pm->ctrl(w, h).st[1] = ctrl[w][h][4];
  2785. }
  2786. }
  2787. GetToken(true);
  2788. if ( g_qeglobals.m_bBrushPrimitMode ) {
  2789. // we are in brush primit mode, but maybe it's a classic patch that needs converting, test "}"
  2790. if ( strcmp(token, "}") && strcmp(token, "(") ) {
  2791. ParseEpair(pm->epairs);
  2792. GetToken(true);
  2793. }
  2794. }
  2795. if ( strcmp(token, "}") ) {
  2796. return NULL;
  2797. }
  2798. brush_t *b = AddBrushForPatch(pm, false);
  2799. return b;
  2800. }
  2801. /*
  2802. ==================
  2803. Patch_Write
  2804. ==================
  2805. */
  2806. void Patch_Write( patchMesh_t *p,CMemFile *file ) {
  2807. if ( g_qeglobals.bSurfacePropertiesPlugin ) {
  2808. common->Printf("WARNING: Patch_Write to a CMemFile and Surface Properties plugin not done\n");
  2809. }
  2810. if ( p->explicitSubdivisions ) {
  2811. MemFile_fprintf(file, " {\n patchDef3\n {\n");
  2812. MemFile_fprintf(file, " \"%s\"\n", p->d_texture->GetName());
  2813. MemFile_fprintf(file, " ( %i %i %i %i %i %i %i ) \n", p->width, p->height, p->horzSubdivisions, p->vertSubdivisions, p->contents, p->flags, p->value);
  2814. } else {
  2815. MemFile_fprintf(file, " {\n patchDef2\n {\n");
  2816. MemFile_fprintf(file, " \"%s\"\n", p->d_texture->GetName());
  2817. MemFile_fprintf(file, " ( %i %i %i %i %i ) \n", p->width, p->height, p->contents, p->flags, p->value);
  2818. }
  2819. float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
  2820. int w, h;
  2821. for ( w = 0; w < p->width; w++ ) {
  2822. for ( h = 0; h < p->height; h++ ) {
  2823. ctrl[w][h][0] = p->ctrl(w, h).xyz[0];
  2824. ctrl[w][h][1] = p->ctrl(w, h).xyz[1];
  2825. ctrl[w][h][2] = p->ctrl(w, h).xyz[2];
  2826. ctrl[w][h][3] = p->ctrl(w, h).st[0];
  2827. ctrl[w][h][4] = p->ctrl(w, h).st[1];
  2828. }
  2829. }
  2830. _Write3DMatrix(file, p->width, p->height, 5, reinterpret_cast< float*>(&ctrl));
  2831. if ( g_qeglobals.m_bBrushPrimitMode ) {
  2832. if ( p->epairs ) {
  2833. int count = p->epairs->GetNumKeyVals();
  2834. for ( int i = 0; i < count; i++ ) {
  2835. MemFile_fprintf(file, "\"%s\" \"%s\"\n", p->epairs->GetKeyVal(i)->GetKey().c_str(), p->epairs->GetKeyVal(i)->GetValue().c_str());
  2836. }
  2837. }
  2838. }
  2839. MemFile_fprintf(file, " }\n }\n");
  2840. }
  2841. void Patch_Write( patchMesh_t *p,FILE *file ) {
  2842. if ( p->explicitSubdivisions ) {
  2843. fprintf(file, " {\n patchDef3\n {\n");
  2844. fprintf(file, " \"%s\"\n", p->d_texture->GetName());
  2845. fprintf(file, " ( %i %i %i %i %i %i %i ) \n", p->width, p->height, p->horzSubdivisions, p->vertSubdivisions, p->contents, p->flags, p->value);
  2846. } else {
  2847. fprintf(file, " {\n patchDef2\n {\n");
  2848. fprintf(file, " \"%s\"\n", p->d_texture->GetName());
  2849. fprintf(file, " ( %i %i %i %i %i ) \n", p->width, p->height, p->contents, p->flags, p->value);
  2850. }
  2851. float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
  2852. int w, h;
  2853. for ( w = 0; w < p->width; w++ ) {
  2854. for ( h = 0; h < p->height; h++ ) {
  2855. ctrl[w][h][0] = p->ctrl(w, h).xyz[0];
  2856. ctrl[w][h][1] = p->ctrl(w, h).xyz[1];
  2857. ctrl[w][h][2] = p->ctrl(w, h).xyz[2];
  2858. ctrl[w][h][3] = p->ctrl(w, h).st[0];
  2859. ctrl[w][h][4] = p->ctrl(w, h).st[1];
  2860. }
  2861. }
  2862. _Write3DMatrix(file, p->width, p->height, 5, reinterpret_cast< float*>(&ctrl));
  2863. if ( g_qeglobals.m_bBrushPrimitMode ) {
  2864. if ( p->epairs ) {
  2865. int count = p->epairs->GetNumKeyVals();
  2866. for ( int i = 0; i < count; i++ ) {
  2867. fprintf(file, "\"%s\" \"%s\"\n", p->epairs->GetKeyVal(i)->GetKey().c_str(), p->epairs->GetKeyVal(i)->GetValue().c_str());
  2868. }
  2869. }
  2870. }
  2871. fprintf(file, " }\n }\n");
  2872. }
  2873. /*
  2874. ==================
  2875. Patch_RotateTexture
  2876. ==================
  2877. */
  2878. void Patch_RotateTexture( patchMesh_t *p,float fAngle ) {
  2879. idVec3 vMin, vMax;
  2880. Patch_CalcBounds(p, vMin, vMax);
  2881. Patch_MakeDirty(p);
  2882. for ( int w = 0; w < p->width; w++ ) {
  2883. for ( int h = 0; h < p->height; h++ ) {
  2884. if ( g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(&p->ctrl(w, h).xyz) == -1 ) {
  2885. continue;
  2886. }
  2887. float x = p->ctrl(w, h).st[0];
  2888. float y = p->ctrl(w, h).st[1];
  2889. p->ctrl(w, h).st[0] = x * cos(DEG2RAD(fAngle)) - y * sin(DEG2RAD(fAngle));
  2890. p->ctrl(w, h).st[1] = y * cos(DEG2RAD(fAngle)) + x * sin(DEG2RAD(fAngle));
  2891. }
  2892. }
  2893. }
  2894. /*
  2895. ==================
  2896. Patch_ScaleTexture
  2897. ==================
  2898. */
  2899. void Patch_ScaleTexture( patchMesh_t *p,float fx,float fy,bool absolute ) {
  2900. if ( fx == 0 ) {
  2901. fx = 1.0f;
  2902. }
  2903. if ( fy == 0 ) {
  2904. fy = 1.0f;
  2905. }
  2906. if ( absolute ) {
  2907. Patch_ResetTexturing(1, 1);
  2908. }
  2909. for ( int w = 0; w < p->width; w++ ) {
  2910. for ( int h = 0; h < p->height; h++ ) {
  2911. if ( g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(&p->ctrl(w, h).xyz) == -1 ) {
  2912. continue;
  2913. }
  2914. p->ctrl(w, h).st[0] *= fx;
  2915. p->ctrl(w, h).st[1] *= fy;
  2916. }
  2917. }
  2918. Patch_MakeDirty(p);
  2919. }
  2920. /*
  2921. ==================
  2922. Patch_ShiftTexture
  2923. ==================
  2924. */
  2925. void Patch_ShiftTexture( patchMesh_t *p,float fx,float fy,bool autoAdjust ) {
  2926. //if (fx)
  2927. // fx = (fx > 0) ? 0.1 : -0.1;
  2928. //if (fy)
  2929. // fy = (fy > 0) ? 0.1 : -0.1;
  2930. if ( autoAdjust ) {
  2931. fx /= p->d_texture->GetEditorImage()->uploadWidth;
  2932. fy /= p->d_texture->GetEditorImage()->uploadHeight;
  2933. }
  2934. for ( int w = 0; w < p->width; w++ ) {
  2935. for ( int h = 0; h < p->height; h++ ) {
  2936. if ( g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(&p->ctrl(w, h).xyz) == -1 )
  2937. continue;
  2938. p->ctrl(w, h).st[0] += fx;
  2939. p->ctrl(w, h).st[1] += fy;
  2940. }
  2941. }
  2942. Patch_MakeDirty(p);
  2943. }
  2944. void patchInvert( patchMesh_t *p ) {
  2945. idDrawVert vertTemp;
  2946. Patch_MakeDirty(p);
  2947. for ( int i = 0 ; i < p->width ; i++ ) {
  2948. for ( int j = 0; j < p->height / 2; j++ ) {
  2949. memcpy(&vertTemp, &p->ctrl(i, p->height - 1 - j), sizeof(idDrawVert));
  2950. memcpy(&p->ctrl(i, p->height - 1 - j), &p->ctrl(i, j), sizeof(idDrawVert));
  2951. memcpy(&p->ctrl(i, j), &vertTemp, sizeof(idDrawVert));
  2952. }
  2953. }
  2954. }
  2955. /*
  2956. ==================
  2957. Patch_ToggleInverted
  2958. ==================
  2959. */
  2960. void Patch_ToggleInverted() {
  2961. bool bUpdate = false;
  2962. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  2963. if ( pb->pPatch ) {
  2964. bUpdate = true;
  2965. patchInvert(pb->pPatch);
  2966. }
  2967. }
  2968. if ( bUpdate ) {
  2969. Sys_UpdateWindows(W_ALL);
  2970. }
  2971. UpdatePatchInspector();
  2972. }
  2973. void Patch_FlipTexture( patchMesh_t *p,bool y ) {
  2974. idVec2 temp;
  2975. Patch_MakeDirty(p);
  2976. if ( y ) {
  2977. for ( int i = 0 ; i < p->height ; i++ ) {
  2978. for ( int j = 0; j < p->width / 2; j++ ) {
  2979. temp = p->ctrl(p->width - 1 - j, i).st;
  2980. p->ctrl(p->width - 1 - j, i).st = p->ctrl(j, i).st;
  2981. p->ctrl(j, i).st = temp;
  2982. }
  2983. }
  2984. } else {
  2985. for ( int i = 0 ; i < p->width ; i++ ) {
  2986. for ( int j = 0; j < p->height / 2; j++ ) {
  2987. temp = p->ctrl(i, p->height - 1 - j).st;
  2988. p->ctrl(i, p->height - 1 - j).st = p->ctrl(i, j).st;
  2989. p->ctrl(i, j).st = temp;
  2990. }
  2991. }
  2992. }
  2993. }
  2994. /*
  2995. ==================
  2996. Patch_ToggleInverted
  2997. ==================
  2998. */
  2999. void Patch_InvertTexture( bool bY ) {
  3000. bool bUpdate = false;
  3001. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3002. if ( pb->pPatch ) {
  3003. bUpdate = true;
  3004. Patch_FlipTexture(pb->pPatch, bY);
  3005. }
  3006. }
  3007. if ( bUpdate ) {
  3008. Sys_UpdateWindows(W_ALL);
  3009. }
  3010. UpdatePatchInspector();
  3011. }
  3012. /*
  3013. ==================
  3014. Patch_Save
  3015. ==================
  3016. Saves patch ctrl info (originally to deal with a
  3017. cancel in the surface dialog
  3018. */
  3019. void Patch_Save( patchMesh_t *p ) {
  3020. if ( patchSave ) {
  3021. Mem_Free(patchSave->verts);
  3022. Mem_Free(patchSave);
  3023. }
  3024. patchSave = MakeNewPatch(p->width, p->height);
  3025. memcpy(patchSave->verts, p->verts, sizeof(p->verts[0]) * p->width * p->height);
  3026. }
  3027. /*
  3028. ==================
  3029. Patch_Restore
  3030. ==================
  3031. */
  3032. void Patch_Restore( patchMesh_t *p ) {
  3033. if ( patchSave ) {
  3034. p->width = patchSave->width;
  3035. p->height = patchSave->height;
  3036. memcpy(p->verts, patchSave->verts, sizeof(p->verts[0]) * p->width * p->height);
  3037. Mem_Free(patchSave->verts);
  3038. Mem_Free(patchSave);
  3039. patchSave = NULL;
  3040. }
  3041. }
  3042. void Patch_FitTexture( patchMesh_t *p,float fx,float fy ) {
  3043. Patch_MakeDirty(p);
  3044. for ( int i = 0 ; i < p->width ; i++ ) {
  3045. for ( int j = 0 ; j < p->height ; j++ ) {
  3046. p->ctrl(i, j).st[0] = fx * (float) i / (p->width - 1);
  3047. p->ctrl(i, j).st[1] = fy * (float) j / (p->height - 1);
  3048. }
  3049. }
  3050. }
  3051. void Patch_ResetTexturing( float fx,float fy ) {
  3052. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3053. if ( pb->pPatch ) {
  3054. patchMesh_t *p = pb->pPatch;
  3055. Patch_MakeDirty(p);
  3056. for ( int i = 0 ; i < p->width ; i++ ) {
  3057. for ( int j = 0 ; j < p->height ; j++ ) {
  3058. p->ctrl(i, j).st[0] = fx * (float) i / (p->width - 1);
  3059. p->ctrl(i, j).st[1] = fy * (float) j / (p->height - 1);
  3060. }
  3061. }
  3062. }
  3063. }
  3064. }
  3065. void Patch_FitTexturing() {
  3066. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3067. if ( pb->pPatch ) {
  3068. patchMesh_t *p = pb->pPatch;
  3069. Patch_MakeDirty(p);
  3070. for ( int i = 0 ; i < p->width ; i++ ) {
  3071. for ( int j = 0 ; j < p->height ; j++ ) {
  3072. p->ctrl(i, j).st[0] = 1 * (float) i / (p->width - 1);
  3073. p->ctrl(i, j).st[1] = 1 * (float) j / (p->height - 1);
  3074. }
  3075. }
  3076. }
  3077. }
  3078. }
  3079. void Patch_SetTextureInfo( texdef_t *pt ) {
  3080. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3081. if ( pb->pPatch ) {
  3082. if ( pt->rotate )
  3083. Patch_RotateTexture(pb->pPatch, pt->rotate);
  3084. if ( pt->shift[0] || pt->shift[1] )
  3085. Patch_ShiftTexture(pb->pPatch, pt->shift[0], pt->shift[1], false);
  3086. if ( pt->scale[0] || pt->scale[1] )
  3087. Patch_ScaleTexture(pb->pPatch, pt->scale[0], pt->scale[1], false);
  3088. patchMesh_t *p = pb->pPatch;
  3089. p->value = pt->value;
  3090. }
  3091. }
  3092. }
  3093. bool WINAPI OnlyPatchesSelected() {
  3094. if ( g_ptrSelectedFaces.GetSize() > 0 || selected_brushes.next == &selected_brushes ) {
  3095. return false;
  3096. }
  3097. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3098. if ( !pb->pPatch ) {
  3099. return false;
  3100. }
  3101. }
  3102. return true;
  3103. }
  3104. bool WINAPI AnyPatchesSelected() {
  3105. if ( g_ptrSelectedFaces.GetSize() > 0 || selected_brushes.next == &selected_brushes ) {
  3106. return false;
  3107. }
  3108. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3109. if ( pb->pPatch ) {
  3110. return true;
  3111. }
  3112. }
  3113. return false;
  3114. }
  3115. patchMesh_t * SinglePatchSelected() {
  3116. if ( selected_brushes.next->pPatch ) {
  3117. return selected_brushes.next->pPatch;
  3118. }
  3119. return NULL;
  3120. }
  3121. void Patch_BendToggle() {
  3122. if ( g_bPatchBendMode ) {
  3123. g_bPatchBendMode = false;
  3124. HideInfoDialog();
  3125. g_pParentWnd->UpdatePatchToolbarButtons() ;
  3126. return;
  3127. }
  3128. brush_t *b = selected_brushes.next;
  3129. if ( !QE_SingleBrush() || !b->pPatch ) {
  3130. Sys_Status("Must bend a single patch");
  3131. return;
  3132. }
  3133. Patch_Save(b->pPatch);
  3134. g_bPatchBendMode = true;
  3135. g_nPatchBendState = BEND_SELECT_ROTATION;
  3136. g_bPatchAxisOnRow = true;
  3137. g_nPatchAxisIndex = 1;
  3138. ShowInfoDialog(g_pBendStateMsg[BEND_SELECT_ROTATION]);
  3139. }
  3140. void Patch_BendHandleTAB() {
  3141. if ( !g_bPatchBendMode ) {
  3142. return;
  3143. }
  3144. brush_t *b = selected_brushes.next;
  3145. if ( !QE_SingleBrush() || !b->pPatch ) {
  3146. Patch_BendToggle();
  3147. Sys_Status("No patch to bend!");
  3148. return;
  3149. }
  3150. patchMesh_t *p = b->pPatch;
  3151. bool bShift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
  3152. if ( g_nPatchBendState == BEND_SELECT_ROTATION ) {
  3153. // only able to deal with odd numbered rows/cols
  3154. g_nPatchAxisIndex += (bShift) ? -2 : 2;
  3155. if ( g_bPatchAxisOnRow ) {
  3156. if ( (bShift) ? g_nPatchAxisIndex <= 0 : g_nPatchAxisIndex >= p->height ) {
  3157. g_bPatchAxisOnRow = false;
  3158. g_nPatchAxisIndex = (bShift) ? p->width - 1 : 1;
  3159. }
  3160. } else {
  3161. if ( (bShift) ? g_nPatchAxisIndex <= 0 : g_nPatchAxisIndex >= p->width ) {
  3162. g_bPatchAxisOnRow = true;
  3163. g_nPatchAxisIndex = (bShift) ? p->height - 1 : 1;
  3164. }
  3165. }
  3166. } else if ( g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  3167. g_nBendOriginIndex += (bShift) ? -1 : 1;
  3168. if ( g_bPatchAxisOnRow ) {
  3169. if ( bShift ) {
  3170. if ( g_nBendOriginIndex < 0 )
  3171. g_nBendOriginIndex = p->width - 1;
  3172. } else {
  3173. if ( g_nBendOriginIndex > p->width - 1 )
  3174. g_nBendOriginIndex = 0;
  3175. }
  3176. VectorCopy(p->ctrl(g_nBendOriginIndex, g_nPatchAxisIndex).xyz, g_vBendOrigin);
  3177. } else {
  3178. if ( bShift ) {
  3179. if ( g_nBendOriginIndex < 0 )
  3180. g_nBendOriginIndex = p->height - 1;
  3181. } else {
  3182. if ( g_nBendOriginIndex > p->height - 1 )
  3183. g_nBendOriginIndex = 0;
  3184. }
  3185. VectorCopy(p->ctrl(g_nPatchAxisIndex, g_nBendOriginIndex).xyz, g_vBendOrigin);
  3186. }
  3187. } else if ( g_nPatchBendState == BEND_SELECT_EDGE ) {
  3188. g_bPatchLowerEdge ^= 1;
  3189. }
  3190. Sys_UpdateWindows(W_ALL);
  3191. }
  3192. void Patch_BendHandleENTER() {
  3193. if ( !g_bPatchBendMode ) {
  3194. return;
  3195. }
  3196. if ( g_nPatchBendState < BEND_BENDIT ) {
  3197. g_nPatchBendState++;
  3198. ShowInfoDialog(g_pBendStateMsg[g_nPatchBendState]);
  3199. if ( g_nPatchBendState == BEND_SELECT_ORIGIN ) {
  3200. g_vBendOrigin[0] = g_vBendOrigin[1] = g_vBendOrigin[2] = 0;
  3201. g_nBendOriginIndex = 0;
  3202. Patch_BendHandleTAB();
  3203. } else if ( g_nPatchBendState == BEND_SELECT_EDGE ) {
  3204. g_bPatchLowerEdge = true;
  3205. } else if ( g_nPatchBendState == BEND_BENDIT ) {
  3206. // basically we go into rotation mode, set the axis to the center of the
  3207. }
  3208. } else {
  3209. // done
  3210. Patch_BendToggle();
  3211. }
  3212. Sys_UpdateWindows(W_ALL);
  3213. }
  3214. void Patch_BendHandleESC() {
  3215. if ( !g_bPatchBendMode ) {
  3216. return;
  3217. }
  3218. Patch_BendToggle();
  3219. brush_t *b = selected_brushes.next;
  3220. if ( QE_SingleBrush() && b->pPatch ) {
  3221. Patch_Restore(b->pPatch);
  3222. }
  3223. Sys_UpdateWindows(W_ALL);
  3224. }
  3225. void Patch_SetBendRotateOrigin( patchMesh_t *p ) {
  3226. int nType = g_pParentWnd->ActiveXY()->GetViewType();
  3227. int nDim3 = (nType == XY) ? 2 : (nType == YZ) ? 0 : 1;
  3228. g_vBendOrigin[nDim3] = 0;
  3229. VectorCopy(g_vBendOrigin, g_pParentWnd->ActiveXY()->RotateOrigin());
  3230. return;
  3231. }
  3232. // also sets the rotational origin
  3233. void Patch_SelectBendAxis() {
  3234. brush_t *b = selected_brushes.next;
  3235. if ( !QE_SingleBrush() || !b->pPatch ) {
  3236. // should not ever happen
  3237. Patch_BendToggle();
  3238. return;
  3239. }
  3240. patchMesh_t *p = b->pPatch;
  3241. if ( g_bPatchAxisOnRow ) {
  3242. SelectRow(p, g_nPatchAxisIndex, false);
  3243. } else {
  3244. SelectColumn(p, g_nPatchAxisIndex, false);
  3245. }
  3246. Patch_SetBendRotateOrigin(p);
  3247. }
  3248. void Patch_SelectBendNormal() {
  3249. brush_t *b = selected_brushes.next;
  3250. if ( !QE_SingleBrush() || !b->pPatch ) {
  3251. // should not ever happen
  3252. Patch_BendToggle();
  3253. return;
  3254. }
  3255. patchMesh_t *p = b->pPatch;
  3256. g_qeglobals.d_num_move_points = 0;
  3257. if ( g_bPatchAxisOnRow ) {
  3258. if ( g_bPatchLowerEdge ) {
  3259. for ( int j = 0; j < g_nPatchAxisIndex; j++ )
  3260. SelectRow(p, j, true);
  3261. } else {
  3262. for ( int j = p->height - 1; j > g_nPatchAxisIndex; j-- )
  3263. SelectRow(p, j, true);
  3264. }
  3265. } else {
  3266. if ( g_bPatchLowerEdge ) {
  3267. for ( int j = 0; j < g_nPatchAxisIndex; j++ )
  3268. SelectColumn(p, j, true);
  3269. } else {
  3270. for ( int j = p->width - 1; j > g_nPatchAxisIndex; j-- )
  3271. SelectColumn(p, j, true);
  3272. }
  3273. }
  3274. Patch_SetBendRotateOrigin(p);
  3275. }
  3276. void Patch_InsDelToggle() {
  3277. if ( g_bPatchInsertMode ) {
  3278. g_bPatchInsertMode = false;
  3279. HideInfoDialog();
  3280. g_pParentWnd->UpdatePatchToolbarButtons() ;
  3281. return;
  3282. }
  3283. brush_t *b = selected_brushes.next;
  3284. if ( !QE_SingleBrush() || !b->pPatch ) {
  3285. Sys_Status("Must work with a single patch");
  3286. return;
  3287. }
  3288. Patch_Save(b->pPatch);
  3289. g_bPatchInsertMode = true;
  3290. g_nPatchInsertState = INSERT_SELECT_EDGE;
  3291. g_bPatchAxisOnRow = true;
  3292. g_nPatchAxisIndex = 0;
  3293. ShowInfoDialog(g_pInsertStateMsg[INSERT_SELECT_EDGE]);
  3294. }
  3295. void Patch_InsDelESC() {
  3296. if ( !g_bPatchInsertMode ) {
  3297. return;
  3298. }
  3299. Patch_InsDelToggle();
  3300. Sys_UpdateWindows(W_ALL);
  3301. }
  3302. void Patch_InsDelHandleENTER() {
  3303. }
  3304. void Patch_InsDelHandleTAB() {
  3305. if ( !g_bPatchInsertMode ) {
  3306. Patch_InsDelToggle();
  3307. return;
  3308. }
  3309. brush_t *b = selected_brushes.next;
  3310. if ( !QE_SingleBrush() || !b->pPatch ) {
  3311. Patch_BendToggle();
  3312. common->Printf("No patch to bend!");
  3313. return;
  3314. }
  3315. patchMesh_t *p = b->pPatch;
  3316. // only able to deal with odd numbered rows/cols
  3317. g_nPatchAxisIndex += 2;
  3318. if ( g_bPatchAxisOnRow ) {
  3319. if ( g_nPatchAxisIndex >= p->height - 1 ) {
  3320. g_bPatchAxisOnRow = false;
  3321. g_nPatchAxisIndex = 0;
  3322. }
  3323. } else {
  3324. if ( g_nPatchAxisIndex >= p->width - 1 ) {
  3325. g_bPatchAxisOnRow = true;
  3326. g_nPatchAxisIndex = 0;
  3327. }
  3328. }
  3329. Sys_UpdateWindows(W_ALL);
  3330. }
  3331. void _Write1DMatrix( FILE *f,int x,float *m ) {
  3332. int i;
  3333. fprintf(f, "( ");
  3334. for ( i = 0 ; i < x ; i++ ) {
  3335. if ( m[i] == (int) m[i] ) {
  3336. fprintf(f, "%i ", (int) m[i]);
  3337. } else {
  3338. fprintf(f, "%f ", m[i]);
  3339. }
  3340. }
  3341. fprintf(f, ")");
  3342. }
  3343. void _Write2DMatrix( FILE *f,int y,int x,float *m ) {
  3344. int i;
  3345. fprintf(f, "( ");
  3346. for ( i = 0 ; i < y ; i++ ) {
  3347. _Write1DMatrix(f, x, m + i * x);
  3348. fprintf(f, " ");
  3349. }
  3350. fprintf(f, ")\n");
  3351. }
  3352. void _Write3DMatrix( FILE *f,int z,int y,int x,float *m ) {
  3353. int i;
  3354. fprintf(f, "(\n");
  3355. for ( i = 0 ; i < z ; i++ ) {
  3356. _Write2DMatrix(f, y, x, m + i * (x * MAX_PATCH_HEIGHT));
  3357. }
  3358. fprintf(f, ")\n");
  3359. }
  3360. void _Write1DMatrix( CMemFile *f,int x,float *m ) {
  3361. int i;
  3362. MemFile_fprintf(f, "( ");
  3363. for ( i = 0 ; i < x ; i++ ) {
  3364. if ( m[i] == (int) m[i] ) {
  3365. MemFile_fprintf(f, "%i ", (int) m[i]);
  3366. } else {
  3367. MemFile_fprintf(f, "%f ", m[i]);
  3368. }
  3369. }
  3370. MemFile_fprintf(f, ")");
  3371. }
  3372. void _Write2DMatrix( CMemFile *f,int y,int x,float *m ) {
  3373. int i;
  3374. MemFile_fprintf(f, "( ");
  3375. for ( i = 0 ; i < y ; i++ ) {
  3376. _Write1DMatrix(f, x, m + i * x);
  3377. MemFile_fprintf(f, " ");
  3378. }
  3379. MemFile_fprintf(f, ")\n");
  3380. }
  3381. void _Write3DMatrix( CMemFile *f,int z,int y,int x,float *m ) {
  3382. int i;
  3383. MemFile_fprintf(f, "(\n");
  3384. for ( i = 0 ; i < z ; i++ ) {
  3385. _Write2DMatrix(f, y, x, m + i * (x * MAX_PATCH_HEIGHT));
  3386. }
  3387. MemFile_fprintf(f, ")\n");
  3388. }
  3389. void Patch_NaturalizeSelected( bool bCap,bool bCycleCap,bool alt ) {
  3390. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3391. if ( pb->pPatch ) {
  3392. if ( bCap ) {
  3393. Patch_CapTexture(pb->pPatch, bCycleCap, alt);
  3394. } else {
  3395. Patch_Naturalize(pb->pPatch, true, true, alt);
  3396. }
  3397. }
  3398. }
  3399. }
  3400. void Patch_SubdivideSelected( bool subdivide,int horz,int vert ) {
  3401. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3402. if ( pb->pPatch ) {
  3403. pb->pPatch->explicitSubdivisions = subdivide;
  3404. if ( horz <= 0 ) {
  3405. horz = 1;
  3406. }
  3407. if ( vert <= 0 ) {
  3408. vert = 1;
  3409. }
  3410. pb->pPatch->horzSubdivisions = horz;
  3411. pb->pPatch->vertSubdivisions = vert;
  3412. Patch_MakeDirty(pb->pPatch);
  3413. }
  3414. }
  3415. }
  3416. bool within( idVec3 vTest,idVec3 vTL,idVec3 vBR ) {
  3417. int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
  3418. int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
  3419. if ( (vTest[nDim1] > vTL[nDim1] && vTest[nDim1] < vBR[nDim1]) || (vTest[nDim1] < vTL[nDim1] && vTest[nDim1] > vBR[nDim1]) ) {
  3420. if ( (vTest[nDim2] > vTL[nDim2] && vTest[nDim2] < vBR[nDim2]) || (vTest[nDim2] < vTL[nDim2] && vTest[nDim2] > vBR[nDim2]) ) {
  3421. return true;
  3422. }
  3423. }
  3424. return false;
  3425. }
  3426. void Patch_SelectAreaPoints() {
  3427. //jhefty - make patch selection additive ALWAYS
  3428. //g_qeglobals.d_num_move_points = 0;
  3429. g_nPatchClickedView = -1;
  3430. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3431. if ( pb->pPatch ) {
  3432. patchMesh_t *p = pb->pPatch;
  3433. for ( int i = 0; i < p->width; i++ ) {
  3434. for ( int j = 0; j < p->height; j++ ) {
  3435. if ( within(p->ctrl(i, j).xyz, g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR) ) {
  3436. g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = &p->ctrl(i, j).xyz;
  3437. }
  3438. }
  3439. }
  3440. }
  3441. }
  3442. }
  3443. const char * Patch_GetTextureName() {
  3444. brush_t *b = selected_brushes.next;
  3445. if ( b->pPatch ) {
  3446. patchMesh_t *p = b->pPatch;
  3447. if ( p->d_texture->GetName() )
  3448. return p->d_texture->GetName();
  3449. }
  3450. return "";
  3451. }
  3452. patchMesh_t * Patch_Duplicate( patchMesh_t *pFrom ) {
  3453. patchMesh_t *p = MakeNewPatch(pFrom->width, pFrom->height);
  3454. p->contents = pFrom->contents;
  3455. p->value = pFrom->value;
  3456. p->horzSubdivisions = pFrom->horzSubdivisions;
  3457. p->vertSubdivisions = pFrom->vertSubdivisions;
  3458. p->explicitSubdivisions = pFrom->explicitSubdivisions;
  3459. p->d_texture = pFrom->d_texture;
  3460. p->bSelected = false;
  3461. p->bOverlay = false;
  3462. p->nListID = -1;
  3463. memcpy(p->verts, pFrom->verts, p->width * p->height * sizeof(idDrawVert));
  3464. AddBrushForPatch(p);
  3465. return p;
  3466. }
  3467. void Patch_Thicken( int nAmount,bool bSeam ) {
  3468. int i, j, h, w;
  3469. brush_t *b;
  3470. patchMesh_t *pSeam;
  3471. idVec3 vMin, vMax;
  3472. CPtrArray brushes;
  3473. nAmount = -nAmount;
  3474. if ( !QE_SingleBrush() ) {
  3475. Sys_Status("Cannot thicken multiple patches. Please select a single patch.\n");
  3476. return;
  3477. }
  3478. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3479. if ( !pb->pPatch ) {
  3480. return;
  3481. }
  3482. patchMesh_t *p = pb->pPatch;
  3483. Patch_MeshNormals(p);
  3484. patchMesh_t *pNew = Patch_Duplicate(p);
  3485. for ( i = 0; i < p->width; i++ ) {
  3486. for ( j = 0; j < p->height; j++ ) {
  3487. VectorMA(p->ctrl(i, j).xyz, nAmount, p->ctrl(i, j).normal, pNew->ctrl(i, j).xyz);
  3488. }
  3489. }
  3490. Patch_Rebuild(pNew);
  3491. pNew->type |= PATCH_THICK;
  3492. brushes.Add(pNew->pSymbiot);
  3493. if ( bSeam ) {
  3494. // FIXME: this should detect if any edges of the patch are closed and act appropriately
  3495. //
  3496. if ( !(p->type & PATCH_CYLINDER) ) {
  3497. b = Patch_GenericMesh(3, p->height, 2, false, true, p);
  3498. pSeam = b->pPatch;
  3499. pSeam->type |= PATCH_SEAM;
  3500. for ( i = 0; i < p->height; i++ ) {
  3501. VectorCopy(p->ctrl(0, i).xyz, pSeam->ctrl(0, i).xyz);
  3502. VectorCopy(pNew->ctrl(0, i).xyz, pSeam->ctrl(2, i).xyz);
  3503. VectorAdd(pSeam->ctrl(0, i).xyz, pSeam->ctrl(2, i).xyz, pSeam->ctrl(1, i).xyz);
  3504. VectorScale(pSeam->ctrl(1, i).xyz, 0.5, pSeam->ctrl(1, i).xyz);
  3505. }
  3506. Patch_CalcBounds(pSeam, vMin, vMax);
  3507. Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
  3508. //--Patch_CapTexture(pSeam);
  3509. Patch_Naturalize(pSeam);
  3510. patchInvert(pSeam);
  3511. brushes.Add(b);
  3512. w = p->width - 1;
  3513. b = Patch_GenericMesh(3, p->height, 2, false, true, p);
  3514. pSeam = b->pPatch;
  3515. pSeam->type |= PATCH_SEAM;
  3516. for ( i = 0; i < p->height; i++ ) {
  3517. VectorCopy(p->ctrl(w, i).xyz, pSeam->ctrl(0, i).xyz);
  3518. VectorCopy(pNew->ctrl(w, i).xyz, pSeam->ctrl(2, i).xyz);
  3519. VectorAdd(pSeam->ctrl(0, i).xyz, pSeam->ctrl(2, i).xyz, pSeam->ctrl(1, i).xyz);
  3520. VectorScale(pSeam->ctrl(1, i).xyz, 0.5, pSeam->ctrl(1, i).xyz);
  3521. }
  3522. Patch_CalcBounds(pSeam, vMin, vMax);
  3523. Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
  3524. //--Patch_CapTexture(pSeam);
  3525. Patch_Naturalize(pSeam);
  3526. brushes.Add(b);
  3527. }
  3528. //--{
  3529. // otherwise we will add one per end
  3530. b = Patch_GenericMesh(p->width, 3, 2, false, true, p);
  3531. pSeam = b->pPatch;
  3532. pSeam->type |= PATCH_SEAM;
  3533. for ( i = 0; i < p->width; i++ ) {
  3534. VectorCopy(p->ctrl(i, 0).xyz, pSeam->ctrl(i, 0).xyz);
  3535. VectorCopy(pNew->ctrl(i, 0).xyz, pSeam->ctrl(i, 2).xyz);
  3536. VectorAdd(pSeam->ctrl(i, 0).xyz, pSeam->ctrl(i, 2).xyz, pSeam->ctrl(i, 1).xyz);
  3537. VectorScale(pSeam->ctrl(i, 1).xyz, 0.5, pSeam->ctrl(i, 1).xyz);
  3538. }
  3539. Patch_CalcBounds(pSeam, vMin, vMax);
  3540. Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
  3541. //--Patch_CapTexture(pSeam);
  3542. Patch_Naturalize(pSeam);
  3543. patchInvert(pSeam);
  3544. brushes.Add(b);
  3545. h = p->height - 1;
  3546. b = Patch_GenericMesh(p->width, 3, 2, false, true, p);
  3547. pSeam = b->pPatch;
  3548. pSeam->type |= PATCH_SEAM;
  3549. for ( i = 0; i < p->width; i++ ) {
  3550. VectorCopy(p->ctrl(i, h).xyz, pSeam->ctrl(i, 0).xyz);
  3551. VectorCopy(pNew->ctrl(i, h).xyz, pSeam->ctrl(i, 2).xyz);
  3552. VectorAdd(pSeam->ctrl(i, 0).xyz, pSeam->ctrl(i, 2).xyz, pSeam->ctrl(i, 1).xyz);
  3553. VectorScale(pSeam->ctrl(i, 1).xyz, 0.5, pSeam->ctrl(i, 1).xyz);
  3554. }
  3555. Patch_CalcBounds(pSeam, vMin, vMax);
  3556. Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
  3557. //--Patch_CapTexture(pSeam);
  3558. Patch_Naturalize(pSeam);
  3559. brushes.Add(b);
  3560. //--}
  3561. }
  3562. patchInvert(pNew);
  3563. }
  3564. for ( i = 0; i < brushes.GetSize(); i++ ) {
  3565. Select_Brush(reinterpret_cast< brush_t*>(brushes.GetAt(i)));
  3566. }
  3567. if ( brushes.GetSize() > 0 ) {
  3568. eclass_t*pecNew = Eclass_ForName("func_static", false);
  3569. if ( pecNew ) {
  3570. entity_t*e = Entity_Create(pecNew);
  3571. SetKeyValue(e, "type", "patchThick");
  3572. }
  3573. }
  3574. UpdatePatchInspector();
  3575. }
  3576. /*
  3577. lets get another list together as far as necessities..
  3578. *snapping stuff to the grid (i will only snap movements by the mouse to the grid.. snapping the rotational bend stuff will fubar everything)
  3579. capping bevels/endcaps
  3580. hot keys
  3581. texture fix for caps
  3582. clear clipboard
  3583. *region fix
  3584. *surface dialog
  3585. */
  3586. void Patch_SetOverlays() {
  3587. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3588. if ( pb->pPatch ) {
  3589. pb->pPatch->bOverlay = true;
  3590. }
  3591. }
  3592. }
  3593. void Patch_ClearOverlays() {
  3594. brush_t *pb;
  3595. for ( pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3596. if ( pb->pPatch ) {
  3597. pb->pPatch->bOverlay = false;
  3598. }
  3599. }
  3600. for ( pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next ) {
  3601. if ( pb->pPatch ) {
  3602. pb->pPatch->bOverlay = false;
  3603. }
  3604. }
  3605. }
  3606. // freezes selected vertices
  3607. void Patch_Freeze() {
  3608. brush_t *pb;
  3609. for ( pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3610. if ( pb->pPatch ) {
  3611. pb->pPatch->bOverlay = false;
  3612. }
  3613. }
  3614. for ( pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next ) {
  3615. if ( pb->pPatch ) {
  3616. pb->pPatch->bOverlay = false;
  3617. }
  3618. }
  3619. }
  3620. void Patch_UnFreeze( bool bAll ) {
  3621. }
  3622. void Patch_Transpose() {
  3623. int i, j, w;
  3624. idDrawVert dv;
  3625. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3626. if ( pb->pPatch ) {
  3627. patchMesh_t *p = pb->pPatch;
  3628. if ( p->width > p->height ) {
  3629. for ( i = 0 ; i < p->height ; i++ ) {
  3630. for ( j = i + 1 ; j < p->width ; j++ ) {
  3631. if ( j < p->height ) {
  3632. // swap the value
  3633. memcpy(&dv, &p->ctrl(j, i), sizeof(idDrawVert));
  3634. memcpy(&p->ctrl(j, i), &p->ctrl(i, j), sizeof(idDrawVert));
  3635. memcpy(&p->ctrl(i, j), &dv, sizeof(idDrawVert));
  3636. } else {
  3637. // just copy
  3638. memcpy(&p->ctrl(j, i), &p->ctrl(i, j), sizeof(idDrawVert));
  3639. }
  3640. }
  3641. }
  3642. } else {
  3643. for ( i = 0 ; i < p->width ; i++ ) {
  3644. for ( j = i + 1 ; j < p->height ; j++ ) {
  3645. if ( j < p->width ) {
  3646. // swap the value
  3647. memcpy(&dv, &p->ctrl(i, j), sizeof(idDrawVert));
  3648. memcpy(&p->ctrl(i, j), &p->ctrl(j, i), sizeof(idDrawVert));
  3649. memcpy(&p->ctrl(j, i), &dv, sizeof(idDrawVert));
  3650. } else {
  3651. // just copy
  3652. memcpy(&p->ctrl(i, j), &p->ctrl(j, i), sizeof(idDrawVert));
  3653. }
  3654. }
  3655. }
  3656. }
  3657. w = p->width;
  3658. p->width = p->height;
  3659. p->height = w;
  3660. patchInvert(p);
  3661. Patch_Rebuild(p);
  3662. }
  3663. }
  3664. }
  3665. void Select_SnapToGrid() {
  3666. int i, j, k;
  3667. for ( brush_t*pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next ) {
  3668. if ( pb->pPatch ) {
  3669. patchMesh_t *p = pb->pPatch;
  3670. for ( i = 0; i < p->width; i++ ) {
  3671. for ( j = 0; j < p->height; j++ ) {
  3672. for ( k = 0; k < 3; k++ ) {
  3673. p->ctrl(i, j).xyz[k] = floor(p->ctrl(i, j).xyz[k] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  3674. }
  3675. }
  3676. }
  3677. idVec3 vMin, vMax;
  3678. Patch_CalcBounds(p, vMin, vMax);
  3679. Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
  3680. } else {
  3681. Brush_SnapToGrid(pb);
  3682. }
  3683. }
  3684. }
  3685. void Patch_FindReplaceTexture( brush_t *pb,const char *pFind,const char *pReplace,bool bForce ) {
  3686. if ( pb->pPatch ) {
  3687. patchMesh_t *p = pb->pPatch;
  3688. if ( bForce || idStr::Icmp(p->d_texture->GetName(), pFind) == 0 ) {
  3689. p->d_texture = Texture_ForName(pReplace);
  3690. //strcpy(p->d_texture->name, pReplace);
  3691. }
  3692. }
  3693. }
  3694. void Patch_ReplaceQTexture( brush_t *pb,idMaterial *pOld,idMaterial *pNew ) {
  3695. if ( pb->pPatch ) {
  3696. patchMesh_t *p = pb->pPatch;
  3697. if ( p->d_texture == pOld ) {
  3698. p->d_texture = pNew;
  3699. }
  3700. }
  3701. }
  3702. void Patch_Clone( patchMesh_t *p,brush_t *pNewOwner ) {
  3703. }
  3704. void Patch_FromTriangle( idVec5 vx,idVec5 vy,idVec5 vz ) {
  3705. patchMesh_t *p = MakeNewPatch(3, 3);
  3706. p->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
  3707. p->type = PATCH_TRIANGLE;
  3708. // 0 0 goes to x
  3709. // 0 1 goes to x
  3710. // 0 2 goes to x
  3711. // 1 0 goes to mid of x and z
  3712. // 1 1 goes to mid of x y and z
  3713. // 1 2 goes to mid of x and y
  3714. // 2 0 goes to z
  3715. // 2 1 goes to mid of y and z
  3716. // 2 2 goes to y
  3717. idVec5 vMidXZ;
  3718. idVec5 vMidXY;
  3719. idVec5 vMidYZ;
  3720. vMidXZ.Lerp(vx, vz, 0.5);
  3721. vMidXY.Lerp(vx, vy, 0.5);
  3722. vMidYZ.Lerp(vy, vz, 0.5);
  3723. p->ctrl(0, 0).xyz = vx.ToVec3();
  3724. p->ctrl(0, 1).xyz = vx.ToVec3();
  3725. p->ctrl(0, 2).xyz = vx.ToVec3();
  3726. p->ctrl(0, 0).st[0] = vx[3];
  3727. p->ctrl(0, 0).st[1] = vx[4];
  3728. p->ctrl(0, 1).st[0] = vx[3];
  3729. p->ctrl(0, 1).st[1] = vx[4];
  3730. p->ctrl(0, 2).st[0] = vx[3];
  3731. p->ctrl(0, 2).st[1] = vx[4];
  3732. p->ctrl(1, 0).xyz = vMidXY.ToVec3();
  3733. p->ctrl(1, 1).xyz = vx.ToVec3();
  3734. p->ctrl(1, 2).xyz = vMidXZ.ToVec3();
  3735. p->ctrl(1, 0).st[0] = vMidXY[3];
  3736. p->ctrl(1, 0).st[1] = vMidXY[4];
  3737. p->ctrl(1, 1).st[0] = vx[3];
  3738. p->ctrl(1, 1).st[1] = vx[4];
  3739. p->ctrl(1, 2).st[0] = vMidXZ[3];
  3740. p->ctrl(1, 2).st[1] = vMidXZ[4];
  3741. p->ctrl(2, 0).xyz = vy.ToVec3();
  3742. p->ctrl(2, 1).xyz = vMidYZ.ToVec3();
  3743. p->ctrl(2, 2).xyz = vz.ToVec3();
  3744. p->ctrl(2, 0).st[0] = vy[3];
  3745. p->ctrl(2, 0).st[1] = vy[4];
  3746. p->ctrl(2, 1).st[0] = vMidYZ[3];
  3747. p->ctrl(2, 1).st[1] = vMidYZ[4];
  3748. p->ctrl(2, 2).st[0] = vz[3];
  3749. p->ctrl(2, 2).st[1] = vz[4];
  3750. //Patch_Naturalize(p);
  3751. brush_t *b = AddBrushForPatch(p);
  3752. }
  3753. /*
  3754. ==============
  3755. Patch_SetEpair
  3756. sets an epair for the given patch
  3757. ==============
  3758. */
  3759. void Patch_SetEpair( patchMesh_t *p,const char *pKey,const char *pValue ) {
  3760. if ( g_qeglobals.m_bBrushPrimitMode ) {
  3761. if ( p->epairs == NULL ) {
  3762. p->epairs = new idDict;
  3763. }
  3764. p->epairs->Set(pKey, pValue);
  3765. }
  3766. }
  3767. /*
  3768. =================
  3769. Patch_GetKeyValue
  3770. =================
  3771. */
  3772. const char * Patch_GetKeyValue( patchMesh_t *p,const char *pKey ) {
  3773. if ( g_qeglobals.m_bBrushPrimitMode ) {
  3774. if ( p->epairs ) {
  3775. return p->epairs->GetString(pKey);
  3776. }
  3777. }
  3778. return "";
  3779. }
  3780. //Real nitpicky, but could you make CTRL-S save the current map with the current name? (ie: File/Save)
  3781. /*
  3782. Feature addition.
  3783. When reading in textures, please check for the presence of a file called "textures.link" or something, which contains one line such as;
  3784. g:\quake3\baseq3\textures\common
  3785. So that, when I'm reading in, lets say, my \eerie directory, it goes through and adds my textures to the palette, along with everything in common.
  3786. Don't forget to add "Finer texture alignment" to the list. I'd like to be able to move in 0.1 increments using the Shift-Arrow Keys.
  3787. No. Sometimes textures are drawn the wrong way on patches. We'd like the ability to flip a texture. Like the way X/Y scale -1 used to worked.
  3788. 1) Easier way of deleting rows, columns
  3789. 2) Fine tuning of textures on patches (X/Y shifts other than with the surface dialog)
  3790. 2) Patch matrix transposition
  3791. 1) Actually, bump texture flipping on patches to the top of the list of things to do.
  3792. 2) When you select a patch, and hit S, it should read in the selected patch texture. Should not work if you multiselect patches and hit S
  3793. 3) Brandon has a wierd anomoly. He fine-tunes a patch with caps. It looks fine when the patch is selected, but as soon as he escapes out, it reverts to it's pre-tuned state. When he selects the patch again, it looks tuned
  3794. *1) Flipping textures on patches
  3795. *2) When you select a patch, and hit S, it should read in the selected patch texture. Should not work if you multiselect patches and hit S
  3796. 3) Easier way of deleting rows columns
  3797. *4) Thick Curves
  3798. 5) Patch matrix transposition
  3799. 6) Inverted cylinder capping
  3800. *7) bugs
  3801. *8) curve speed
  3802. Have a new feature request. "Compute Bounding Box" for mapobjects (md3 files). This would be used for misc_mapobject (essentially, drop in 3DS Max models into our maps)
  3803. Ok, Feature Request. Load and draw MD3's in the Camera view with proper bounding boxes. This should be off misc_model
  3804. Feature Addition: View/Hide Hint Brushes -- This should be a specific case.
  3805. */