hlod.cpp 173 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/hlod.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 8/29/01 7:29p $*
  29. * *
  30. * $Revision:: 10 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * HLodLoaderClass::Load_W3D -- Loads an HlodDef from a W3D file *
  35. * HLodPrototypeClass::Create -- Creates an HLod from an HLodDef *
  36. * HLodDefClass::HLodDefClass -- Constructor *
  37. * HLodDefClass::HLodDefClass -- Copy Constructor *
  38. * HLodDefClass::~HLodDefClass -- Destructor *
  39. * HLodDefClass::Free -- releases all resources being used *
  40. * HLodDefClass::Initialize -- init this def from an HLod *
  41. * HLodDefClass::Save -- save this HLodDef *
  42. * HLodDefClass::Save_Header -- writes the HLodDef header *
  43. * HLodDefClass::Save_Lod_Array -- Saves the lod array *
  44. * HLodDefClass::Save_Aggregate_Array -- Save the array of aggregate models *
  45. * HLodDefClass::Load_W3D -- Loads this HLodDef from a W3d File *
  46. * HLodDefClass::read_header -- loads the HLodDef header from a W3d file *
  47. * HLodDefClass::read_proxy_array -- load the proxy names *
  48. * HLodDefClass::SubObjectArrayClass::SubObjectArrayClass -- LodArray constructor *
  49. * HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass -- LodArray destructor *
  50. * HLodDefClass::SubObjectArrayClass::Save_W3D -- saves a w3d file for this HLodDef *
  51. * HLodDefClass::SubObjectArrayClass::Load_W3D -- LodArray load function *
  52. * HLodDefClass::SubObjectArrayClass::Reset -- release the contents of this array *
  53. * HLodClass::HLodClass -- Constructor *
  54. * HLodClass::HLodClass -- copy constructor *
  55. * HLodClass::HLodClass -- Constructor *
  56. * HLodClass::HLodClass -- Constructs an HLod from an HLodDef *
  57. * HLodClass::HLodClass -- Constructs an HLod from an HModelDef *
  58. * HLodClass::operator -- assignment operator *
  59. * HLodClass::~HLodClass -- Destructor *
  60. * HLodClass::Free -- releases all resources *
  61. * HLodClass::Clone -- virtual copy constructor *
  62. * HLodClass::Set_Max_Screen_Size -- Set max-screen-size for an LOD *
  63. * HLodClass::Get_Max_Screen_Size -- get max-screen-size for an LOD *
  64. * HLodClass::Get_Lod_Count -- returns number of levels of detail *
  65. * HLodClass::Get_Lod_Model_Count -- number of sub-objs in a given level of detail *
  66. * HLodClass::Peek_Lod_Model -- returns pointer to a model in one of the LODs *
  67. * HLodClass::Get_Lod_Model -- returns a pointer to a model in one of the LODs *
  68. * HLodClass::Get_Lod_Model_Bone -- returns the bone index of a model *
  69. * HLodClass::Get_Additional_Model_Count -- number of additional sub-objs *
  70. * HLodClass::Peek_Additional_Model -- returns pointer to an additional model *
  71. * HLodClass::Get_Additional_Model -- returns pointer to an additional model *
  72. * HLodClass::Get_Additional_Model_Bone -- returns the bone index of an additional model *
  73. * HLodClass::Is_NULL_Lod_Included -- does this HLod have NULL as its lowest LOD *
  74. * HLodClass::Include_NULL_Lod -- Add NULL as the lowest LOD *
  75. * HLodClass::Get_Num_Polys -- returns polycount of the current LOD *
  76. * HLodClass::Render -- render this HLod *
  77. * HLodClass::Special_Render -- Special_Render for HLod *
  78. * HLodClass::Set_Transform -- Sets the transform *
  79. * HLodClass::Set_Position -- Sets the position *
  80. * HLodClass::Notify_Added -- callback notifies subobjs that they were added *
  81. * HLodClass::Notify_Removed -- notifies subobjs that they were removed *
  82. * HLodClass::Get_Num_Sub_Objects -- returns total number of sub-objects *
  83. * HLodClass::Get_Sub_Object -- returns a pointer to specified sub-object *
  84. * HLodClass::Add_Sub_Object -- add a sub-object to this HLod *
  85. * HLodClass::Remove_Sub_Object -- remove a sub-object from this HLod *
  86. * HLodClass::Get_Num_Sub_Objects_On_Bone -- returns the number of objects on the given bone *
  87. * HLodClass::Get_Sub_Object_On_Bone -- returns obj on the given bone *
  88. * HLodClass::Get_Sub_Object_Bone_Index -- returns bone index of given object *
  89. * HLodClass::Add_Sub_Object_To_Bone -- adds a sub-object to a bone *
  90. * HLodClass::Set_Animation -- set animation state to the base-pose *
  91. * HLodClass::Set_Animation -- set animation state to an animation frame *
  92. * HLodClass::Set_Animation -- set animation state to a blend of two animations *
  93. * HLodClass::Set_Animation -- set animation state to a combination of anims *
  94. * HLodClass::Cast_Ray -- cast a ray against this HLod *
  95. * HLodClass::Cast_AABox -- Cast a swept AABox against this HLod *
  96. * HLodClass::Cast_OBBox -- Cast a swept OBBox against this HLod *
  97. * HLodClass::Intersect_AABox -- Intersect an AABox with this HLod *
  98. * HLodClass::Intersect_OBBox -- Intersect an OBBox with this HLod *
  99. * HLodClass::Prepare_LOD -- Prepare for LOD processing *
  100. * HLodClass::Recalculate_Static_LOD_Factors -- compute lod factors *
  101. * HLodClass::Increment_LOD -- move to next lod *
  102. * HLodClass::Decrement_LOD -- move to previous lod *
  103. * HLodClass::Get_Cost -- returns the cost of this LOD *
  104. * HLodClass::Get_Value -- returns the value of this LOD *
  105. * HLodClass::Get_Post_Increment_Value -- returns the post increment value *
  106. * HLodClass::Set_LOD_Level -- set the current lod level *
  107. * HLodClass::Get_LOD_Level -- returns the current LOD level *
  108. * HLodClass::Get_LOD_Count -- returns the number of levels of detail *
  109. * HLodClass::Calculate_Cost_Value_Arrays -- computes the cost-value arrays *
  110. * HLodClass::Get_Current_LOD -- returns a render object which represents the current LOD *
  111. * HLodClass::Set_Texture_Reduction_Factor -- resizeable texture support *
  112. * HLodClass::Scale -- scale this HLod model *
  113. * HLodClass::Get_Num_Snap_Points -- returns the number of snap points in this model *
  114. * HLodClass::Get_Snap_Point -- returns specified snap-point *
  115. * HLodClass::Update_Sub_Object_Transforms -- updates transforms of all sub-objects *
  116. * HLodClass::Update_Obj_Space_Bounding_Volumes -- update object-space bounding volumes *
  117. * HLodClass::add_lod_model -- adds a model to one of the lods *
  118. * HLodClass::Create_Decal -- create a decal on this HLod *
  119. * HLodClass::Delete_Decal -- remove a decal from this HLod *
  120. * HLodClass::Set_HTree -- replace the hierarchy tree *
  121. * HLodClass::Get_Proxy_Count -- Returns the number of proxy objects *
  122. * HLodClass::Get_Proxy -- returns the information for the i'th proxy *
  123. * HLodClass::Set_Hidden -- Propogates the hidden bit to particle emitters. *
  124. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  125. #include "hlod.h"
  126. #include "assetmgr.h"
  127. #include "hmdldef.h"
  128. #include "w3derr.h"
  129. #include "chunkio.h"
  130. #include "predlod.h"
  131. #include "rinfo.h"
  132. #include <string.h>
  133. #include <win.h>
  134. #include "sphere.h"
  135. #include "boxrobj.h"
  136. /*
  137. ** Loader Instance
  138. */
  139. HLodLoaderClass _HLodLoader;
  140. /**
  141. ** ProxyRecordClass
  142. ** This is a structure that contains the data describing a single "proxy" object. These
  143. ** are used for application purposes and simply provide a way for the assets to associate
  144. ** a string with a bone index.
  145. */
  146. class ProxyRecordClass
  147. {
  148. public:
  149. ProxyRecordClass(void) : BoneIndex(0)
  150. {
  151. memset(Name,0,sizeof(Name));
  152. }
  153. bool operator == (const ProxyRecordClass & that) { return false; }
  154. bool operator != (const ProxyRecordClass & that) { return !(*this == that); }
  155. void Init(const W3dHLodSubObjectStruct & w3d_data)
  156. {
  157. BoneIndex = w3d_data.BoneIndex;
  158. strncpy(Name,w3d_data.Name,sizeof(Name));
  159. }
  160. int Get_Bone_Index(void) { return BoneIndex; }
  161. const char * Get_Name(void) { return Name; }
  162. protected:
  163. int BoneIndex;
  164. char Name[2*W3D_NAME_LEN];
  165. };
  166. /**
  167. ** ProxyArrayClass
  168. ** This is a ref-counted list of proxy objects. It is generated whenever an HLODdef contains
  169. ** proxies. Each instantiated HLOD simply add-refs a pointer to the single list.
  170. */
  171. class ProxyArrayClass : public VectorClass<ProxyRecordClass>, public RefCountClass
  172. {
  173. public:
  174. ProxyArrayClass(int size) : VectorClass<ProxyRecordClass>(size)
  175. {
  176. }
  177. };
  178. /*
  179. ** The HLod Loader Implementation
  180. */
  181. /***********************************************************************************************
  182. * HLodLoaderClass::Load_W3D -- Loads an HlodDef from a W3D file *
  183. * *
  184. * INPUT: *
  185. * *
  186. * OUTPUT: *
  187. * *
  188. * WARNINGS: *
  189. * *
  190. * HISTORY: *
  191. * 1/26/00 gth : Created. *
  192. *=============================================================================================*/
  193. PrototypeClass *HLodLoaderClass::Load_W3D( ChunkLoadClass &cload )
  194. {
  195. HLodDefClass * def = new HLodDefClass;
  196. if (def == NULL)
  197. {
  198. return NULL;
  199. }
  200. if (def->Load_W3D(cload) != WW3D_ERROR_OK) {
  201. // load failed, delete the model and return an error
  202. delete def;
  203. return NULL;
  204. } else {
  205. // ok, accept this model!
  206. HLodPrototypeClass *proto = new HLodPrototypeClass(def);
  207. return proto;
  208. }
  209. return NULL;
  210. }
  211. /*
  212. ** HLod Prototype Implementation
  213. */
  214. /***********************************************************************************************
  215. * HLodPrototypeClass::Create -- Creates an HLod from an HLodDef *
  216. * *
  217. * INPUT: *
  218. * *
  219. * OUTPUT: *
  220. * *
  221. * WARNINGS: *
  222. * *
  223. * HISTORY: *
  224. * 1/26/00 gth : Created. *
  225. *=============================================================================================*/
  226. RenderObjClass * HLodPrototypeClass::Create(void)
  227. {
  228. HLodClass * hlod = NEW_REF( HLodClass , ( *Definition ) );
  229. return hlod;
  230. }
  231. /*
  232. ** HLodDef Implementation
  233. */
  234. /***********************************************************************************************
  235. * HLodDefClass::HLodDefClass -- Constructor *
  236. * *
  237. * INPUT: *
  238. * *
  239. * OUTPUT: *
  240. * *
  241. * WARNINGS: *
  242. * *
  243. * HISTORY: *
  244. *=============================================================================================*/
  245. HLodDefClass::HLodDefClass(void) :
  246. Name(NULL),
  247. HierarchyTreeName(NULL),
  248. LodCount(0),
  249. Lod(NULL),
  250. ProxyArray(NULL)
  251. {
  252. }
  253. /***********************************************************************************************
  254. * HLodDefClass::HLodDefClass -- Copy Constructor *
  255. * *
  256. * INPUT: *
  257. * *
  258. * OUTPUT: *
  259. * *
  260. * WARNINGS: *
  261. * *
  262. * HISTORY: *
  263. * 1/26/00 gth : Created. *
  264. *=============================================================================================*/
  265. HLodDefClass::HLodDefClass(HLodClass &src_lod) :
  266. Name(NULL),
  267. HierarchyTreeName(NULL),
  268. LodCount(0),
  269. Lod(NULL),
  270. ProxyArray(NULL)
  271. {
  272. Initialize (src_lod);
  273. return ;
  274. }
  275. /***********************************************************************************************
  276. * HLodDefClass::~HLodDefClass -- Destructor *
  277. * *
  278. * INPUT: *
  279. * *
  280. * OUTPUT: *
  281. * *
  282. * WARNINGS: *
  283. * *
  284. * HISTORY: *
  285. * 1/26/00 gth : Created. *
  286. *=============================================================================================*/
  287. HLodDefClass::~HLodDefClass(void)
  288. {
  289. Free ();
  290. return ;
  291. }
  292. /***********************************************************************************************
  293. * HLodDefClass::Free -- releases all resources being used *
  294. * *
  295. * INPUT: *
  296. * *
  297. * OUTPUT: *
  298. * *
  299. * WARNINGS: *
  300. * *
  301. * HISTORY: *
  302. * 1/26/00 gth : Created. *
  303. *=============================================================================================*/
  304. void HLodDefClass::Free(void)
  305. {
  306. if (Name) {
  307. ::free(Name);
  308. Name = NULL;
  309. }
  310. if (HierarchyTreeName) {
  311. ::free(HierarchyTreeName);
  312. HierarchyTreeName = NULL;
  313. }
  314. if (Lod) {
  315. delete[] Lod;
  316. Lod = NULL;
  317. }
  318. LodCount = 0;
  319. REF_PTR_RELEASE(ProxyArray);
  320. return ;
  321. }
  322. /***********************************************************************************************
  323. * HLodDefClass::Initialize -- init this def from an HLod *
  324. * *
  325. * INPUT: *
  326. * *
  327. * OUTPUT: *
  328. * *
  329. * WARNINGS: *
  330. * *
  331. * HISTORY: *
  332. * 1/26/00 gth : Created. *
  333. *=============================================================================================*/
  334. void HLodDefClass::Initialize(HLodClass &src_lod)
  335. {
  336. // Start with a fresh set of data
  337. Free ();
  338. // Copy the name and hierarcy name from the source object
  339. Name = ::strdup (src_lod.Get_Name ());
  340. const HTreeClass *phtree = src_lod.Get_HTree ();
  341. if (phtree != NULL) {
  342. HierarchyTreeName = ::strdup (phtree->Get_Name ());
  343. }
  344. // Determine the number of LODs in the src object
  345. LodCount = src_lod.Get_LOD_Count ();
  346. WWASSERT (LodCount > 0);
  347. if (LodCount > 0) {
  348. // Allocate an array large enough to hold all the LODs and
  349. // loop through each LOD.
  350. Lod = new SubObjectArrayClass[LodCount];
  351. for (int index = 0; index < LodCount; index ++) {
  352. // Fill in the maximum screen size for this LOD
  353. Lod[index].MaxScreenSize = src_lod.Get_Max_Screen_Size (index);
  354. Lod[index].ModelCount = src_lod.Get_Lod_Model_Count (index);
  355. // Loop through all the models that compose this LOD and generate a
  356. // list of model's and the bones they live on
  357. char **model_names = new char *[Lod[index].ModelCount];
  358. int *bone_indicies = new int[Lod[index].ModelCount];
  359. for (int model_index = 0; model_index < Lod[index].ModelCount; model_index ++) {
  360. // Record information about this model (if possible)
  361. RenderObjClass *prender_obj = src_lod.Peek_Lod_Model (index, model_index);
  362. if (prender_obj != NULL) {
  363. model_names[model_index] = ::strdup (prender_obj->Get_Name ());
  364. bone_indicies[model_index] = src_lod.Get_Lod_Model_Bone (index, model_index);
  365. } else {
  366. model_names[model_index] = NULL;
  367. bone_indicies[model_index] = 0;
  368. }
  369. }
  370. // Pass these arrays of information onto our internal data
  371. Lod[index].ModelName = model_names;
  372. Lod[index].BoneIndex = bone_indicies;
  373. }
  374. }
  375. return;
  376. }
  377. /***********************************************************************************************
  378. * HLodDefClass::Save -- save this HLodDef *
  379. * *
  380. * INPUT: *
  381. * *
  382. * OUTPUT: *
  383. * *
  384. * WARNINGS: *
  385. * *
  386. * HISTORY: *
  387. * 1/26/00 gth : Created. *
  388. *=============================================================================================*/
  389. WW3DErrorType HLodDefClass::Save(ChunkSaveClass & csave)
  390. {
  391. // Assume error
  392. WW3DErrorType ret_val = WW3D_ERROR_SAVE_FAILED;
  393. // Begin a chunk that identifies an aggregate
  394. if (csave.Begin_Chunk (W3D_CHUNK_HLOD) == TRUE) {
  395. // Attempt to save the different sections of the aggregate definition
  396. if ((Save_Header (csave) == WW3D_ERROR_OK) &&
  397. (Save_Lod_Array (csave) == WW3D_ERROR_OK)) {
  398. // Success!
  399. ret_val = WW3D_ERROR_OK;
  400. }
  401. // Close the aggregate chunk
  402. csave.End_Chunk ();
  403. }
  404. // Return the WW3DErrorType return code
  405. return ret_val;
  406. }
  407. /***********************************************************************************************
  408. * HLodDefClass::Save_Header -- writes the HLodDef header *
  409. * *
  410. * INPUT: *
  411. * *
  412. * OUTPUT: *
  413. * *
  414. * WARNINGS: *
  415. * *
  416. * HISTORY: *
  417. * 1/26/00 gth : Created. *
  418. *=============================================================================================*/
  419. WW3DErrorType HLodDefClass::Save_Header(ChunkSaveClass &csave)
  420. {
  421. // Assume error
  422. WW3DErrorType ret_val = WW3D_ERROR_SAVE_FAILED;
  423. // Begin a chunk that identifies the aggregate
  424. if (csave.Begin_Chunk (W3D_CHUNK_HLOD_HEADER) == TRUE) {
  425. // Fill the header structure
  426. W3dHLodHeaderStruct header = { 0 };
  427. header.Version = W3D_CURRENT_HLOD_VERSION;
  428. header.LodCount = LodCount;
  429. // Copy the name to the header
  430. ::lstrcpyn (header.Name, Name, sizeof (header.Name));
  431. header.Name[sizeof (header.Name) - 1] = 0;
  432. // Copy the hierarchy tree name to the header
  433. ::lstrcpyn (header.HierarchyName, HierarchyTreeName, sizeof (header.HierarchyName));
  434. header.HierarchyName[sizeof (header.HierarchyName) - 1] = 0;
  435. // Write the header out to the chunk
  436. if (csave.Write (&header, sizeof (header)) == sizeof (header)) {
  437. // Success!
  438. ret_val = WW3D_ERROR_OK;
  439. }
  440. // End the header chunk
  441. csave.End_Chunk ();
  442. }
  443. // Return the WW3DErrorType return code
  444. return ret_val;
  445. }
  446. /***********************************************************************************************
  447. * HLodDefClass::Save_Lod_Array -- Saves the lod array *
  448. * *
  449. * INPUT: *
  450. * *
  451. * OUTPUT: *
  452. * *
  453. * WARNINGS: *
  454. * *
  455. * HISTORY: *
  456. * 1/26/00 gth : Created. *
  457. *=============================================================================================*/
  458. WW3DErrorType HLodDefClass::Save_Lod_Array(ChunkSaveClass &csave)
  459. {
  460. // Loop through all the LODs and save their model array to the chunk
  461. bool success = true;
  462. for (int lod_index = 0;
  463. (lod_index < LodCount) && success;
  464. lod_index ++) {
  465. success = Lod[lod_index].Save_W3D (csave);
  466. }
  467. // Return the WW3DErrorType return code
  468. return success ? WW3D_ERROR_OK : WW3D_ERROR_SAVE_FAILED;
  469. }
  470. /***********************************************************************************************
  471. * HLodDefClass::Save_Aggregate_Array -- Save the array of aggregate models *
  472. * *
  473. * aggregate models are ones that are attached as "additional" models. *
  474. * *
  475. * *
  476. * INPUT: *
  477. * *
  478. * OUTPUT: *
  479. * *
  480. * WARNINGS: *
  481. * *
  482. * HISTORY: *
  483. * 10/25/2000 gth : Created. *
  484. *=============================================================================================*/
  485. WW3DErrorType HLodDefClass::Save_Aggregate_Array(ChunkSaveClass & csave)
  486. {
  487. if (Aggregates.ModelCount > 0) {
  488. csave.Begin_Chunk(W3D_CHUNK_HLOD_AGGREGATE_ARRAY);
  489. Aggregates.Save_W3D(csave);
  490. csave.End_Chunk();
  491. }
  492. return WW3D_ERROR_OK;
  493. }
  494. /***********************************************************************************************
  495. * HLodDefClass::Load_W3D -- Loads this HLodDef from a W3d File *
  496. * *
  497. * INPUT: *
  498. * *
  499. * OUTPUT: *
  500. * *
  501. * WARNINGS: *
  502. * *
  503. * HISTORY: *
  504. * 1/26/00 gth : Created. *
  505. *=============================================================================================*/
  506. WW3DErrorType HLodDefClass::Load_W3D(ChunkLoadClass & cload)
  507. {
  508. /*
  509. ** First make sure we release any memory in use
  510. */
  511. Free();
  512. if (read_header(cload) == FALSE) {
  513. return WW3D_ERROR_LOAD_FAILED;
  514. }
  515. /*
  516. ** Loop through all the LODs and read the info from its chunk
  517. */
  518. for (int iLOD = 0; iLOD < LodCount; iLOD ++) {
  519. /*
  520. ** Open the next chunk, it should be a LOD struct
  521. */
  522. if (!cload.Open_Chunk()) return WW3D_ERROR_LOAD_FAILED;
  523. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_LOD_ARRAY) {
  524. // ERROR: Expected LOD struct!
  525. return WW3D_ERROR_LOAD_FAILED;
  526. }
  527. Lod[iLOD].Load_W3D(cload);
  528. // Close-out the chunk
  529. cload.Close_Chunk();
  530. }
  531. /*
  532. ** Parse the rest of the chunks
  533. */
  534. while (cload.Open_Chunk()) {
  535. switch(cload.Cur_Chunk_ID())
  536. {
  537. case W3D_CHUNK_HLOD_AGGREGATE_ARRAY:
  538. Aggregates.Load_W3D(cload);
  539. break;
  540. case W3D_CHUNK_HLOD_PROXY_ARRAY:
  541. read_proxy_array(cload);
  542. break;
  543. }
  544. cload.Close_Chunk();
  545. }
  546. return WW3D_ERROR_OK;
  547. }
  548. /***********************************************************************************************
  549. * HLodDefClass::read_header -- loads the HLodDef header from a W3d file *
  550. * *
  551. * INPUT: *
  552. * *
  553. * OUTPUT: *
  554. * *
  555. * WARNINGS: *
  556. * *
  557. * HISTORY: *
  558. * 1/26/00 gth : Created. *
  559. *=============================================================================================*/
  560. bool HLodDefClass::read_header(ChunkLoadClass & cload)
  561. {
  562. /*
  563. ** Open the first chunk, it should be the LOD header
  564. */
  565. if (!cload.Open_Chunk()) return false;
  566. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_HEADER) {
  567. // ERROR: Expected HLOD Header!
  568. return false;
  569. }
  570. W3dHLodHeaderStruct header;
  571. if (cload.Read(&header,sizeof(header)) != sizeof(header)) {
  572. return false;
  573. }
  574. cload.Close_Chunk();
  575. // Copy the name into our internal variable
  576. Name = ::_strdup(header.Name);
  577. HierarchyTreeName = ::strdup(header.HierarchyName);
  578. LodCount = header.LodCount;
  579. Lod = new SubObjectArrayClass[LodCount];
  580. return true;
  581. }
  582. /***********************************************************************************************
  583. * HLodDefClass::read_proxy_array -- load the proxy names *
  584. * *
  585. * This function is coded separately from SubObjectArrayClass::Load because we are going *
  586. * to store the proxies in a shared data structure. Because all of the proxy data is *
  587. * constant, each instanced HLOD can just add-ref a pointer to its proxy array. *
  588. * *
  589. * INPUT: *
  590. * *
  591. * OUTPUT: *
  592. * *
  593. * WARNINGS: *
  594. * *
  595. * HISTORY: *
  596. * 10/27/2000 gth : Created. *
  597. *=============================================================================================*/
  598. bool HLodDefClass::read_proxy_array(ChunkLoadClass & cload)
  599. {
  600. REF_PTR_RELEASE(ProxyArray);
  601. /*
  602. ** Open the first chunk, it should be a Lod Array Header
  603. */
  604. if (!cload.Open_Chunk()) return false;
  605. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) return false;
  606. W3dHLodArrayHeaderStruct header;
  607. if (cload.Read(&header,sizeof(header)) != sizeof(header)) return false;
  608. if (!cload.Close_Chunk()) return false;
  609. ProxyArray = NEW_REF(ProxyArrayClass,(header.ModelCount));
  610. /*
  611. ** Read each sub object definition
  612. */
  613. for (int imodel=0; imodel<ProxyArray->Length(); ++imodel) {
  614. if (!cload.Open_Chunk()) return false;
  615. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT) return false;
  616. W3dHLodSubObjectStruct subobjdef;
  617. if (cload.Read(&subobjdef,sizeof(subobjdef)) != sizeof(subobjdef)) return false;
  618. if (!cload.Close_Chunk()) return false;
  619. (*ProxyArray)[imodel].Init(subobjdef);
  620. }
  621. return true;
  622. }
  623. /***********************************************************************************************
  624. * HLodDefClass::SubObjectArrayClass::SubObjectArrayClass -- LodArray constructor *
  625. * *
  626. * INPUT: *
  627. * *
  628. * OUTPUT: *
  629. * *
  630. * WARNINGS: *
  631. * *
  632. * HISTORY: *
  633. *=============================================================================================*/
  634. HLodDefClass::SubObjectArrayClass::SubObjectArrayClass(void) :
  635. MaxScreenSize(NO_MAX_SCREEN_SIZE),
  636. ModelCount(0),
  637. ModelName(NULL),
  638. BoneIndex(NULL)
  639. {
  640. }
  641. /***********************************************************************************************
  642. * HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass -- LodArray destructor *
  643. * *
  644. * INPUT: *
  645. * *
  646. * OUTPUT: *
  647. * *
  648. * WARNINGS: *
  649. * *
  650. * HISTORY: *
  651. * 1/26/00 gth : Created. *
  652. *=============================================================================================*/
  653. HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass(void)
  654. {
  655. Reset();
  656. }
  657. /***********************************************************************************************
  658. * HLodDefClass::SubObjectArrayClass::Reset -- release the contents of this array *
  659. * *
  660. * INPUT: *
  661. * *
  662. * OUTPUT: *
  663. * *
  664. * WARNINGS: *
  665. * *
  666. * HISTORY: *
  667. * 10/25/2000 gth : Created. *
  668. *=============================================================================================*/
  669. void HLodDefClass::SubObjectArrayClass::Reset(void)
  670. {
  671. MaxScreenSize = NO_MAX_SCREEN_SIZE;
  672. if (ModelName != NULL) {
  673. for (int imodel=0; imodel<ModelCount;imodel++) {
  674. free(ModelName[imodel]);
  675. }
  676. delete[] ModelName;
  677. ModelName = NULL;
  678. }
  679. if (BoneIndex != NULL) {
  680. delete[] BoneIndex;
  681. BoneIndex = NULL;
  682. }
  683. ModelCount = 0;
  684. }
  685. /***********************************************************************************************
  686. * HLodDefClass::SubObjectArrayClass::Load_W3D -- LodArray load function *
  687. * *
  688. * INPUT: *
  689. * *
  690. * OUTPUT: *
  691. * *
  692. * WARNINGS: *
  693. * *
  694. * HISTORY: *
  695. * 1/26/00 gth : Created. *
  696. *=============================================================================================*/
  697. bool HLodDefClass::SubObjectArrayClass::Load_W3D(ChunkLoadClass & cload)
  698. {
  699. /*
  700. ** Open the first chunk, it should be a Lod Array Header
  701. */
  702. if (!cload.Open_Chunk()) return false;
  703. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) return false;
  704. W3dHLodArrayHeaderStruct header;
  705. if (cload.Read(&header,sizeof(header)) != sizeof(header)) return false;
  706. if (!cload.Close_Chunk()) return false;
  707. ModelCount = header.ModelCount;
  708. MaxScreenSize = header.MaxScreenSize;
  709. ModelName = new char * [ModelCount];
  710. BoneIndex = new int [ModelCount];
  711. /*
  712. ** Read each sub object definition
  713. */
  714. for (int imodel=0; imodel<ModelCount; ++imodel) {
  715. if (!cload.Open_Chunk()) return false;
  716. if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT) return false;
  717. W3dHLodSubObjectStruct subobjdef;
  718. if (cload.Read(&subobjdef,sizeof(subobjdef)) != sizeof(subobjdef)) return false;
  719. if (!cload.Close_Chunk()) return false;
  720. ModelName[imodel] = strdup(subobjdef.Name);
  721. BoneIndex[imodel] = subobjdef.BoneIndex;
  722. }
  723. return true;
  724. }
  725. /***********************************************************************************************
  726. * HLodDefClass::SubObjectArrayClass::Save_W3D -- saves a w3d file for this HLodDef *
  727. * *
  728. * INPUT: *
  729. * *
  730. * OUTPUT: *
  731. * *
  732. * WARNINGS: *
  733. * *
  734. * HISTORY: *
  735. * 1/26/00 gth : Created. *
  736. *=============================================================================================*/
  737. bool HLodDefClass::SubObjectArrayClass::Save_W3D(ChunkSaveClass &csave)
  738. {
  739. // Assume error
  740. bool ret_val = false;
  741. // Begin a chunk that identifies the LOD array
  742. if (csave.Begin_Chunk (W3D_CHUNK_HLOD_LOD_ARRAY) == TRUE) {
  743. // Begin a chunk that identifies the LOD header
  744. if (csave.Begin_Chunk (W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) == TRUE) {
  745. W3dHLodArrayHeaderStruct header = { 0 };
  746. header.ModelCount = ModelCount;
  747. header.MaxScreenSize = MaxScreenSize;
  748. // Write the LOD header structure out to the chunk
  749. ret_val = (csave.Write (&header, sizeof (header)) == sizeof (header));
  750. // End the header chunk
  751. csave.End_Chunk ();
  752. }
  753. if (ret_val) {
  754. // Write all of this LOD's models to the file
  755. for (int index = 0;
  756. (index < ModelCount) && ret_val;
  757. index ++) {
  758. // Save this LOD sub-obj to the chunk
  759. ret_val &= (csave.Begin_Chunk (W3D_CHUNK_HLOD_SUB_OBJECT) == TRUE);
  760. if (ret_val) {
  761. W3dHLodSubObjectStruct info = { 0 };
  762. info.BoneIndex = BoneIndex[index];
  763. // Copy this model name into the structure
  764. ::lstrcpyn (info.Name, ModelName[index], sizeof (info.Name));
  765. info.Name[sizeof (info.Name) - 1] = 0;
  766. // Write the LOD sub-obj structure out to the chunk
  767. ret_val &= (csave.Write (&info, sizeof (info)) == sizeof (info));
  768. // End the sub-obj chunk
  769. csave.End_Chunk ();
  770. }
  771. }
  772. }
  773. // End the HLOD-Array chunk
  774. csave.End_Chunk ();
  775. }
  776. // Return the true/false result code
  777. return ret_val;
  778. }
  779. /***********************************************************************************************
  780. * HLodClass::HLodClass -- Constructor *
  781. * *
  782. * INPUT: *
  783. * *
  784. * OUTPUT: *
  785. * *
  786. * WARNINGS: *
  787. * *
  788. * HISTORY: *
  789. *=============================================================================================*/
  790. HLodClass::HLodClass(void) :
  791. Animatable3DObjClass(NULL),
  792. LodCount(0),
  793. CurLod(0),
  794. Lod(NULL),
  795. BoundingBoxIndex(-1),
  796. Cost(NULL),
  797. Value(NULL),
  798. AdditionalModels(),
  799. SnapPoints(NULL),
  800. ProxyArray(NULL),
  801. LODBias(1.0f)
  802. {
  803. }
  804. /***********************************************************************************************
  805. * HLodClass::HLodClass -- copy constructor *
  806. * *
  807. * INPUT: *
  808. * *
  809. * OUTPUT: *
  810. * *
  811. * WARNINGS: *
  812. * *
  813. * HISTORY: *
  814. * 1/26/00 gth : Created. *
  815. *=============================================================================================*/
  816. HLodClass::HLodClass(const HLodClass & src) :
  817. Animatable3DObjClass(src),
  818. LodCount(0),
  819. CurLod(0),
  820. Lod(NULL),
  821. BoundingBoxIndex(-1),
  822. Cost(NULL),
  823. Value(NULL),
  824. AdditionalModels(),
  825. SnapPoints(NULL),
  826. ProxyArray(NULL),
  827. LODBias(1.0f)
  828. {
  829. *this = src;
  830. }
  831. /***********************************************************************************************
  832. * HLodClass::HLodClass -- Constructor *
  833. * *
  834. * Creates an HLodClass from an array of render objects. Each render object is assumed to *
  835. * be an alternate level of detail. *
  836. * *
  837. * INPUT: *
  838. * *
  839. * OUTPUT: *
  840. * *
  841. * WARNINGS: *
  842. * *
  843. * HISTORY: *
  844. * 1/26/00 gth : Created. *
  845. *=============================================================================================*/
  846. HLodClass::HLodClass(const char * name,RenderObjClass ** lods,int count) :
  847. Animatable3DObjClass(NULL),
  848. LodCount(0),
  849. CurLod(0),
  850. Lod(NULL),
  851. BoundingBoxIndex(-1),
  852. Cost(NULL),
  853. Value(NULL),
  854. AdditionalModels(),
  855. SnapPoints(NULL),
  856. ProxyArray(NULL),
  857. LODBias(1.0f)
  858. {
  859. // enforce parameters
  860. WWASSERT(name != NULL);
  861. WWASSERT(lods != NULL);
  862. WWASSERT((count > 0) && (count < 256));
  863. // Set the name
  864. Set_Name(name);
  865. LodCount = count;
  866. WWASSERT(LodCount >= 1);
  867. Lod = new ModelArrayClass[LodCount];
  868. WWASSERT(Lod);
  869. Cost = new float[LodCount];
  870. WWASSERT(Cost);
  871. // Value has LodCount + 1 entries so PostIncrementValue can always use
  872. // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
  873. Value = new float[LodCount + 1];
  874. WWASSERT(Value);
  875. // Create our HTree from the highest LOD if it is an HModel
  876. // Otherwise, create a single node tree
  877. const HTreeClass * tree = lods[count-1]->Get_HTree();
  878. if (tree != NULL) {
  879. HTree = new HTreeClass(*tree);
  880. } else {
  881. HTree = new HTreeClass();
  882. HTree->Init_Default();
  883. }
  884. // Ok, now suck the sub-objects out of each LOD model and place them into this HLOD.
  885. for (int lod_index=0; lod_index < LodCount; lod_index++) {
  886. RenderObjClass * lod_obj = lods[lod_index];
  887. WWASSERT(lod_obj);
  888. if ( (lod_obj->Class_ID() == RenderObjClass::CLASSID_HMODEL) ||
  889. (lod_obj->Class_ID() == RenderObjClass::CLASSID_HLOD) ||
  890. (lod_obj->Get_Num_Sub_Objects() > 1) ) {
  891. // here we insert all sub-objects of this render object into the current LOD array
  892. while (lod_obj->Get_Num_Sub_Objects() > 0) {
  893. RenderObjClass * sub_obj = lod_obj->Get_Sub_Object(0);
  894. int boneindex = lod_obj->Get_Sub_Object_Bone_Index(sub_obj);
  895. lod_obj->Remove_Sub_Object(sub_obj);
  896. add_lod_model(lod_index,sub_obj,boneindex);
  897. sub_obj->Release_Ref();
  898. }
  899. } else {
  900. // just insert the render object as the sole member of the current LOD array. This
  901. // case happens if this level of detail is a simple object such as a mesh or NullRenderObj
  902. add_lod_model(lod_index,lod_obj,0);
  903. }
  904. }
  905. Recalculate_Static_LOD_Factors();
  906. // So that the object is ready for use after construction, we will
  907. // complete its initialization by initializing its cost and value arrays
  908. // according to a screen area of 1 pixel.
  909. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  910. // Ensure lod is no less than minimum allowed
  911. if (CurLod < minlod) Set_LOD_Level(minlod);
  912. // Flag our sub-objects as having dirty transforms
  913. Set_Sub_Object_Transforms_Dirty(true);
  914. // Normal render object processing whenever sub-objects are added or removed:
  915. Update_Sub_Object_Bits();
  916. Update_Obj_Space_Bounding_Volumes();
  917. }
  918. /***********************************************************************************************
  919. * HLodClass::HLodClass -- Constructs an HLod from an HLodDef *
  920. * *
  921. * INPUT: *
  922. * *
  923. * OUTPUT: *
  924. * *
  925. * WARNINGS: *
  926. * *
  927. * HISTORY: *
  928. * 1/26/00 gth : Created. *
  929. *=============================================================================================*/
  930. HLodClass::HLodClass(const HLodDefClass & def) :
  931. Animatable3DObjClass(def.HierarchyTreeName),
  932. LodCount(0),
  933. CurLod(0),
  934. Lod(NULL),
  935. BoundingBoxIndex(-1),
  936. Cost(NULL),
  937. Value(NULL),
  938. AdditionalModels(),
  939. SnapPoints(NULL),
  940. ProxyArray(NULL),
  941. LODBias(1.0f)
  942. {
  943. // Set the name
  944. Set_Name(def.Get_Name());
  945. // Number of LODs comes from the distlod
  946. LodCount = def.LodCount;
  947. WWASSERT(LodCount >= 1);
  948. Lod = new ModelArrayClass[LodCount];
  949. WWASSERT(Lod);
  950. Cost = new float[LodCount];
  951. WWASSERT(Cost);
  952. // Value has LodCount + 1 entries so PostIncrementValue can always use
  953. // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
  954. Value = new float[LodCount + 1];
  955. WWASSERT(Value);
  956. // Add Models to the ModelArrays
  957. for (int ilod=0; ilod < def.LodCount; ilod++) {
  958. Lod[ilod].MaxScreenSize = def.Lod[ilod].MaxScreenSize;
  959. for (int imodel=0; imodel < def.Lod[ilod].ModelCount; imodel++) {
  960. RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.Lod[ilod].ModelName[imodel]);
  961. int boneindex = def.Lod[ilod].BoneIndex[imodel];
  962. if (robj != NULL) {
  963. add_lod_model(ilod,robj,boneindex);
  964. robj->Release_Ref();
  965. }
  966. }
  967. }
  968. Recalculate_Static_LOD_Factors();
  969. // Add aggregates to this model
  970. for (int iagg=0; iagg<def.Aggregates.ModelCount; iagg++) {
  971. RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.Aggregates.ModelName[iagg]);
  972. int boneindex = def.Aggregates.BoneIndex[iagg];
  973. if (robj != NULL) {
  974. Add_Sub_Object_To_Bone(robj,boneindex);
  975. robj->Release_Ref();
  976. }
  977. }
  978. // Add a reference to the proxy array
  979. REF_PTR_SET(ProxyArray,def.ProxyArray);
  980. // So that the object is ready for use after construction, we will
  981. // complete its initialization by initializing its cost and value arrays
  982. // according to a screen area of 1 pixel.
  983. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  984. // Ensure lod is no less than minimum allowed
  985. if (CurLod < minlod) Set_LOD_Level(minlod);
  986. // Flag our sub-objects as having dirty transforms
  987. Set_Sub_Object_Transforms_Dirty(true);
  988. Update_Sub_Object_Bits();
  989. Update_Obj_Space_Bounding_Volumes();
  990. return ;
  991. }
  992. /***********************************************************************************************
  993. * HLodClass::HLodClass -- Constructs an HLod from an HModelDef *
  994. * *
  995. * INPUT: *
  996. * *
  997. * OUTPUT: *
  998. * *
  999. * WARNINGS: *
  1000. * *
  1001. * HISTORY: *
  1002. * 1/26/00 gth : Created. *
  1003. *=============================================================================================*/
  1004. HLodClass::HLodClass(const HModelDefClass & def) :
  1005. Animatable3DObjClass(def.BasePoseName),
  1006. LodCount(0),
  1007. CurLod(0),
  1008. Lod(NULL),
  1009. BoundingBoxIndex(-1),
  1010. Cost(NULL),
  1011. Value(NULL),
  1012. AdditionalModels(),
  1013. SnapPoints(NULL),
  1014. ProxyArray(NULL),
  1015. LODBias(1.0f)
  1016. {
  1017. // Set the name
  1018. Set_Name(def.Get_Name());
  1019. // This is a "simple" HLod, only one LOD
  1020. LodCount = 1;
  1021. Lod = new ModelArrayClass[1];
  1022. WWASSERT(Lod);
  1023. Cost = new float[1];
  1024. WWASSERT(Cost);
  1025. // Value has LodCount + 1 entries so PostIncrementValue can always use
  1026. // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
  1027. Value = new float[2];
  1028. WWASSERT(Value);
  1029. // no lod size clamping
  1030. Lod[0].MaxScreenSize = NO_MAX_SCREEN_SIZE;
  1031. // create the sub-objects
  1032. int imodel;
  1033. for (imodel=0; imodel < def.SubObjectCount; ++imodel) {
  1034. RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.SubObjects[imodel].RenderObjName);
  1035. if (robj) {
  1036. int boneindex = def.SubObjects[imodel].PivotID;
  1037. add_lod_model(0,robj,boneindex);
  1038. robj->Release_Ref();
  1039. }
  1040. }
  1041. Recalculate_Static_LOD_Factors();
  1042. // So that the object is ready for use after construction, we will
  1043. // complete its initialization by initializing its cost and value arrays
  1044. // according to a screen area of 1 pixel.
  1045. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  1046. // Ensure lod is no less than minimum allowed
  1047. if (CurLod < minlod) Set_LOD_Level(minlod);
  1048. // Flag our sub-objects as having dirty transforms
  1049. Set_Sub_Object_Transforms_Dirty(true);
  1050. Update_Sub_Object_Bits();
  1051. Update_Obj_Space_Bounding_Volumes();
  1052. return ;
  1053. }
  1054. /***********************************************************************************************
  1055. * HLodClass::operator -- assignment operator *
  1056. * *
  1057. * INPUT: *
  1058. * *
  1059. * OUTPUT: *
  1060. * *
  1061. * WARNINGS: *
  1062. * *
  1063. * HISTORY: *
  1064. * 1/26/00 gth : Created. *
  1065. *=============================================================================================*/
  1066. HLodClass & HLodClass::operator = (const HLodClass & that)
  1067. {
  1068. int lod,model;
  1069. if (this != &that) {
  1070. Free();
  1071. Animatable3DObjClass::operator = (that);
  1072. BoundingBoxIndex = that.BoundingBoxIndex;
  1073. LodCount = that.LodCount;
  1074. WWASSERT(LodCount >= 1);
  1075. Lod = new ModelArrayClass[LodCount];
  1076. WWASSERT(Lod != NULL);
  1077. Cost = new float[LodCount];
  1078. WWASSERT(Cost);
  1079. // Value has LodCount + 1 entries so PostIncrementValue can always use
  1080. // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
  1081. Value = new float[LodCount + 1];
  1082. WWASSERT(Value);
  1083. for (lod=0; lod<LodCount;lod++) {
  1084. Lod[lod].Resize(that.Lod[lod].Count());
  1085. Lod[lod].MaxScreenSize = that.Lod[lod].MaxScreenSize;
  1086. for (model = 0; model < that.Lod[lod].Count(); model++) {
  1087. ModelNodeClass newnode;
  1088. newnode.Model = that.Lod[lod][model].Model->Clone();
  1089. newnode.BoneIndex = that.Lod[lod][model].BoneIndex;
  1090. newnode.Model->Set_Container(this);
  1091. if (Is_In_Scene()) {
  1092. newnode.Model->Notify_Added(Scene);
  1093. }
  1094. Lod[lod].Add(newnode);
  1095. }
  1096. }
  1097. AdditionalModels.Resize(that.AdditionalModels.Count());
  1098. for (model = 0; model < that.AdditionalModels.Count(); model++) {
  1099. ModelNodeClass newnode;
  1100. newnode.Model = that.AdditionalModels[model].Model->Clone();
  1101. newnode.BoneIndex = that.AdditionalModels[model].BoneIndex;
  1102. newnode.Model->Set_Container(this);
  1103. if (Is_In_Scene()) {
  1104. newnode.Model->Notify_Added(Scene);
  1105. }
  1106. AdditionalModels.Add(newnode);
  1107. }
  1108. LODBias = that.LODBias;
  1109. }
  1110. Recalculate_Static_LOD_Factors();
  1111. // So that the object is ready for use after construction, we will
  1112. // complete its initialization by initializing its cost and value arrays
  1113. // according to a screen area of 1 pixel.
  1114. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  1115. // Ensure lod is no less than minimum allowed
  1116. if (CurLod < minlod) Set_LOD_Level(minlod);
  1117. // Flag our sub-objects as having dirty transforms
  1118. Set_Sub_Object_Transforms_Dirty(true);
  1119. Update_Sub_Object_Bits();
  1120. Update_Obj_Space_Bounding_Volumes();
  1121. return *this;
  1122. }
  1123. /***********************************************************************************************
  1124. * HLodClass::~HLodClass -- Destructor *
  1125. * *
  1126. * INPUT: *
  1127. * *
  1128. * OUTPUT: *
  1129. * *
  1130. * WARNINGS: *
  1131. * *
  1132. * HISTORY: *
  1133. * 1/26/00 gth : Created. *
  1134. *=============================================================================================*/
  1135. HLodClass::~HLodClass(void)
  1136. {
  1137. Free();
  1138. }
  1139. /***********************************************************************************************
  1140. * HLodClass::Free -- releases all resources *
  1141. * *
  1142. * INPUT: *
  1143. * *
  1144. * OUTPUT: *
  1145. * *
  1146. * WARNINGS: *
  1147. * *
  1148. * HISTORY: *
  1149. * 1/26/00 gth : Created. *
  1150. *=============================================================================================*/
  1151. void HLodClass::Free(void)
  1152. {
  1153. int lod,model;
  1154. for (lod = 0; lod < LodCount; lod++) {
  1155. for (model = 0; model < Lod[lod].Count(); model++) {
  1156. RenderObjClass * robj = Lod[lod][model].Model;
  1157. Lod[lod][model].Model = NULL;
  1158. WWASSERT(robj);
  1159. robj->Set_Container(NULL);
  1160. robj->Release_Ref();
  1161. }
  1162. Lod[lod].Delete_All();
  1163. }
  1164. if (Lod != NULL) {
  1165. delete[] Lod;
  1166. Lod = NULL;
  1167. }
  1168. LodCount = 0;
  1169. if (Cost != NULL) {
  1170. delete[] Cost;
  1171. Cost = NULL;
  1172. }
  1173. if (Value != NULL) {
  1174. delete[] Value;
  1175. Value = NULL;
  1176. }
  1177. for (model = 0; model < AdditionalModels.Count(); model++) {
  1178. RenderObjClass * robj = AdditionalModels[model].Model;
  1179. AdditionalModels[model].Model = NULL;
  1180. WWASSERT(robj);
  1181. robj->Set_Container(NULL);
  1182. robj->Release_Ref();
  1183. }
  1184. AdditionalModels.Delete_All();
  1185. REF_PTR_RELEASE(SnapPoints);
  1186. REF_PTR_RELEASE(ProxyArray);
  1187. }
  1188. /***********************************************************************************************
  1189. * HLodClass::Clone -- virtual copy constructor *
  1190. * *
  1191. * INPUT: *
  1192. * *
  1193. * OUTPUT: *
  1194. * *
  1195. * WARNINGS: *
  1196. * *
  1197. * HISTORY: *
  1198. * 1/26/00 gth : Created. *
  1199. *=============================================================================================*/
  1200. RenderObjClass * HLodClass::Clone(void) const
  1201. {
  1202. return new HLodClass(*this);
  1203. }
  1204. /***********************************************************************************************
  1205. * HLodClass::Get_Obj_Space_Bounding_Box -- Return the bounding box mesh if we have one. *
  1206. * *
  1207. * INPUT: *
  1208. * *
  1209. * OUTPUT: *
  1210. * *
  1211. * WARNINGS: *
  1212. * *
  1213. * HISTORY: *
  1214. * 4/13/00 pds : Created. *
  1215. *=============================================================================================*/
  1216. void HLodClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  1217. {
  1218. //
  1219. // Do we have a bounding box mesh?
  1220. //
  1221. int count = Lod[LodCount - 1].Count ();
  1222. if (BoundingBoxIndex >= 0 && BoundingBoxIndex < count) {
  1223. RenderObjClass *mesh = Lod[LodCount - 1][BoundingBoxIndex].Model;
  1224. if (mesh != NULL && mesh->Class_ID () == RenderObjClass::CLASSID_OBBOX) {
  1225. OBBoxRenderObjClass *obbox_mesh = (OBBoxRenderObjClass *)mesh;
  1226. //
  1227. // Determine what the box's transform 'should' be this frame.
  1228. // Note: We do this because some animation types don't update
  1229. // unless they are visible.
  1230. //
  1231. Matrix3D box_tm;
  1232. Simple_Evaluate_Bone (Lod[LodCount - 1][BoundingBoxIndex].BoneIndex, &box_tm);
  1233. //
  1234. // Convert the OBBox from its coordinate system to the coordinate
  1235. // system of the HLOD.
  1236. //
  1237. Matrix3D world_to_hlod_tm;
  1238. Matrix3D box_to_hlod_tm;
  1239. Get_Transform ().Get_Orthogonal_Inverse (world_to_hlod_tm);
  1240. Matrix3D::Multiply(world_to_hlod_tm,box_tm,&box_to_hlod_tm);
  1241. box_to_hlod_tm.Transform_Center_Extent_AABox( obbox_mesh->Get_Local_Center(),
  1242. obbox_mesh->Get_Local_Extent(),
  1243. &box.Center,&box.Extent);
  1244. }
  1245. } else {
  1246. Animatable3DObjClass::Get_Obj_Space_Bounding_Box (box);
  1247. }
  1248. }
  1249. /***********************************************************************************************
  1250. * HLodClass::Get_Obj_Space_Bounding_Sphere -- Use the bounding box mesh to calculate a sphere.*
  1251. * *
  1252. * INPUT: *
  1253. * *
  1254. * OUTPUT: *
  1255. * *
  1256. * WARNINGS: *
  1257. * *
  1258. * HISTORY: *
  1259. * 4/13/00 pds : Created. *
  1260. *=============================================================================================*/
  1261. void HLodClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  1262. {
  1263. AABoxClass box;
  1264. Get_Obj_Space_Bounding_Box(box);
  1265. sphere.Center = box.Center;
  1266. sphere.Radius = box.Extent.Length();
  1267. }
  1268. /***********************************************************************************************
  1269. * HLodClass::Get_Obj_Space_Bounding_Sphere -- Use the bounding box mesh to calculate a sphere.*
  1270. * *
  1271. * INPUT: *
  1272. * *
  1273. * OUTPUT: *
  1274. * *
  1275. * WARNINGS: *
  1276. * *
  1277. * HISTORY: *
  1278. * 4/13/00 pds : Created. *
  1279. *=============================================================================================*/
  1280. const SphereClass &HLodClass::Get_Bounding_Sphere(void) const
  1281. {
  1282. if (BoundingBoxIndex >= 0) {
  1283. //
  1284. // Get the bounding sphere in local coordinates
  1285. //
  1286. SphereClass sphere;
  1287. Get_Obj_Space_Bounding_Sphere (sphere);
  1288. //
  1289. // Transform the sphere into world coords and return the sphere
  1290. //
  1291. CachedBoundingSphere.Center = Get_Transform () * sphere.Center;
  1292. CachedBoundingSphere.Radius = sphere.Radius;
  1293. } else {
  1294. Animatable3DObjClass::Get_Bounding_Sphere ();
  1295. }
  1296. return CachedBoundingSphere;
  1297. }
  1298. /***********************************************************************************************
  1299. * HLodClass::Get_Obj_Space_Bounding_Box -- Return the bounding box mesh if we have one. *
  1300. * *
  1301. * INPUT: *
  1302. * *
  1303. * OUTPUT: *
  1304. * *
  1305. * WARNINGS: *
  1306. * *
  1307. * HISTORY: *
  1308. * 4/13/00 pds : Created. *
  1309. *=============================================================================================*/
  1310. const AABoxClass &HLodClass::Get_Bounding_Box(void) const
  1311. {
  1312. if (BoundingBoxIndex >= 0) {
  1313. //
  1314. // Get the bounding box in local coordinates
  1315. //
  1316. AABoxClass box;
  1317. Get_Obj_Space_Bounding_Box (box);
  1318. //
  1319. // Transform the bounding box to world coordinates
  1320. //
  1321. Get_Transform().Transform_Center_Extent_AABox( box.Center,
  1322. box.Extent,
  1323. &CachedBoundingBox.Center,
  1324. &CachedBoundingBox.Extent );
  1325. } else {
  1326. Animatable3DObjClass::Get_Bounding_Box ();
  1327. }
  1328. return CachedBoundingBox;
  1329. }
  1330. /***********************************************************************************************
  1331. * HLodClass::Set_Max_Screen_Size -- Set max-screen-size for an LOD *
  1332. * *
  1333. * INPUT: *
  1334. * *
  1335. * OUTPUT: *
  1336. * *
  1337. * WARNINGS: *
  1338. * *
  1339. * HISTORY: *
  1340. * 1/26/00 gth : Created. *
  1341. *=============================================================================================*/
  1342. void HLodClass::Set_Max_Screen_Size(int lod_index, float size)
  1343. {
  1344. // Params valid?
  1345. WWASSERT(lod_index >= 0);
  1346. WWASSERT(lod_index < LodCount);
  1347. if ((lod_index >= 0) && (lod_index < LodCount)) {
  1348. // Set the new screen size for this LOD
  1349. Lod[lod_index].MaxScreenSize = size;
  1350. Recalculate_Static_LOD_Factors();
  1351. // So that the object is ready for use after construction, we will
  1352. // complete its initialization by initializing its cost and value arrays
  1353. // according to a screen area of 1 pixel.
  1354. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  1355. // Ensure lod is no less than minimum allowed
  1356. if (CurLod < minlod) Set_LOD_Level(minlod);
  1357. }
  1358. return ;
  1359. }
  1360. /***********************************************************************************************
  1361. * HLodClass::Get_Max_Screen_Size -- get max-screen-size for an LOD *
  1362. * *
  1363. * INPUT: *
  1364. * *
  1365. * OUTPUT: *
  1366. * *
  1367. * WARNINGS: *
  1368. * *
  1369. * HISTORY: *
  1370. * 1/26/00 gth : Created. *
  1371. *=============================================================================================*/
  1372. float HLodClass::Get_Max_Screen_Size(int lod_index) const
  1373. {
  1374. float size = NO_MAX_SCREEN_SIZE;
  1375. // Params valid?
  1376. WWASSERT(lod_index >= 0);
  1377. WWASSERT(lod_index < LodCount);
  1378. if ((lod_index >= 0) && (lod_index < LodCount)) {
  1379. // Get the screen size for this LOD
  1380. size = Lod[lod_index].MaxScreenSize;
  1381. }
  1382. // Return the LOD's screen size to the caller
  1383. return size;
  1384. }
  1385. /***********************************************************************************************
  1386. * HLodClass::Get_Lod_Count -- returns number of levels of detail *
  1387. * *
  1388. * INPUT: *
  1389. * *
  1390. * OUTPUT: *
  1391. * *
  1392. * WARNINGS: *
  1393. * *
  1394. * HISTORY: *
  1395. * 1/26/00 gth : Created. *
  1396. *=============================================================================================*/
  1397. int HLodClass::Get_Lod_Count(void) const
  1398. {
  1399. return LodCount;
  1400. }
  1401. /***********************************************************************************************
  1402. * HLodClass::Set_LOD_Bias -- sets LOD bias *
  1403. * *
  1404. * INPUT: *
  1405. * *
  1406. * OUTPUT: *
  1407. * *
  1408. * WARNINGS: *
  1409. * *
  1410. * HISTORY: *
  1411. * 2/08/00 nh : Created. *
  1412. *=============================================================================================*/
  1413. void HLodClass::Set_LOD_Bias(float bias)
  1414. {
  1415. assert(bias > 0.0f);
  1416. bias = MAX(bias, 0.0f);
  1417. LODBias = bias;
  1418. int additional_count = AdditionalModels.Count();
  1419. for (int i = 0; i < additional_count; i++) {
  1420. AdditionalModels[i].Model->Set_LOD_Bias(bias);
  1421. }
  1422. }
  1423. /***********************************************************************************************
  1424. * HLodClass::Get_Lod_Model_Count -- number of sub-objs in a given level of detail *
  1425. * *
  1426. * INPUT: *
  1427. * *
  1428. * OUTPUT: *
  1429. * *
  1430. * WARNINGS: *
  1431. * *
  1432. * HISTORY: *
  1433. * 1/26/00 gth : Created. *
  1434. *=============================================================================================*/
  1435. int HLodClass::Get_Lod_Model_Count(int lod_index) const
  1436. {
  1437. int count = 0;
  1438. // Params valid?
  1439. WWASSERT(lod_index >= 0);
  1440. WWASSERT(lod_index < LodCount);
  1441. if ((lod_index >= 0) && (lod_index < LodCount)) {
  1442. // Get the number of models in this Lod
  1443. count = Lod[lod_index].Count ();
  1444. }
  1445. // Return the number of models that compose this Lod
  1446. return count;
  1447. }
  1448. /***********************************************************************************************
  1449. * HLodClass::Peek_Lod_Model -- returns pointer to a model in one of the LODs *
  1450. * *
  1451. * INPUT: *
  1452. * *
  1453. * OUTPUT: *
  1454. * *
  1455. * WARNINGS: *
  1456. * *
  1457. * HISTORY: *
  1458. * 1/26/00 gth : Created. *
  1459. *=============================================================================================*/
  1460. RenderObjClass *HLodClass::Peek_Lod_Model(int lod_index, int model_index) const
  1461. {
  1462. RenderObjClass *pmodel = NULL;
  1463. // Params valid?
  1464. WWASSERT(lod_index >= 0);
  1465. WWASSERT(lod_index < LodCount);
  1466. if ((lod_index >= 0) &&
  1467. (lod_index < LodCount) &&
  1468. (model_index < Lod[lod_index].Count ())) {
  1469. // Get a pointer to the requested model
  1470. pmodel = Lod[lod_index][model_index].Model;
  1471. }
  1472. // Return a pointer to the requested model
  1473. return pmodel;
  1474. }
  1475. /***********************************************************************************************
  1476. * HLodClass::Get_Lod_Model -- returns a pointer to a model in one of the LODs *
  1477. * *
  1478. * INPUT: *
  1479. * *
  1480. * OUTPUT: *
  1481. * *
  1482. * WARNINGS: *
  1483. * *
  1484. * HISTORY: *
  1485. * 1/26/00 gth : Created. *
  1486. *=============================================================================================*/
  1487. RenderObjClass *HLodClass::Get_Lod_Model(int lod_index, int model_index) const
  1488. {
  1489. RenderObjClass *pmodel = NULL;
  1490. // Params valid?
  1491. WWASSERT(lod_index >= 0);
  1492. WWASSERT(lod_index < LodCount);
  1493. if ((lod_index >= 0) &&
  1494. (lod_index < LodCount) &&
  1495. (model_index < Lod[lod_index].Count ())) {
  1496. // Get a pointer to the requested model
  1497. pmodel = Lod[lod_index][model_index].Model;
  1498. if (pmodel != NULL) {
  1499. pmodel->Add_Ref ();
  1500. }
  1501. }
  1502. // Return the number of models that compose this Lod
  1503. return pmodel;
  1504. }
  1505. /***********************************************************************************************
  1506. * HLodClass::Get_Lod_Model_Bone -- returns the bone index of a model *
  1507. * *
  1508. * INPUT: *
  1509. * *
  1510. * OUTPUT: *
  1511. * *
  1512. * WARNINGS: *
  1513. * *
  1514. * HISTORY: *
  1515. * 1/26/00 gth : Created. *
  1516. *=============================================================================================*/
  1517. int HLodClass::Get_Lod_Model_Bone(int lod_index, int model_index) const
  1518. {
  1519. int bone_index = 0;
  1520. // Params valid?
  1521. WWASSERT(lod_index >= 0);
  1522. WWASSERT(lod_index < LodCount);
  1523. if ((lod_index >= 0) &&
  1524. (lod_index < LodCount) &&
  1525. (model_index < Lod[lod_index].Count ())) {
  1526. // Get the bone that this model resides on
  1527. bone_index = Lod[lod_index][model_index].BoneIndex;
  1528. }
  1529. // Return the bone that this model resides on
  1530. return bone_index;
  1531. }
  1532. /***********************************************************************************************
  1533. * HLodClass::Get_Additional_Model_Count -- number of additional sub-objs *
  1534. * *
  1535. * INPUT: *
  1536. * *
  1537. * OUTPUT: *
  1538. * *
  1539. * WARNINGS: *
  1540. * *
  1541. * HISTORY: *
  1542. * 8/23/00 NH : Created. *
  1543. *=============================================================================================*/
  1544. int HLodClass::Get_Additional_Model_Count(void) const
  1545. {
  1546. return AdditionalModels.Count();
  1547. }
  1548. /***********************************************************************************************
  1549. * HLodClass::Peek_Additional_Model -- returns pointer to an additional model *
  1550. * *
  1551. * INPUT: *
  1552. * *
  1553. * OUTPUT: *
  1554. * *
  1555. * WARNINGS: *
  1556. * *
  1557. * HISTORY: *
  1558. * 8/23/00 NH : Created. *
  1559. *=============================================================================================*/
  1560. RenderObjClass * HLodClass::Peek_Additional_Model (int model_index) const
  1561. {
  1562. RenderObjClass *pmodel = NULL;
  1563. // Param valid?
  1564. WWASSERT(model_index >= 0);
  1565. WWASSERT(model_index < AdditionalModels.Count());
  1566. if ((model_index >= 0) &&
  1567. (model_index < AdditionalModels.Count())) {
  1568. // Get a pointer to the requested model
  1569. pmodel = AdditionalModels[model_index].Model;
  1570. }
  1571. // Return a pointer to the requested model
  1572. return pmodel;
  1573. }
  1574. /***********************************************************************************************
  1575. * HLodClass::Get_Additional_Model -- returns pointer to an additional model *
  1576. * *
  1577. * INPUT: *
  1578. * *
  1579. * OUTPUT: *
  1580. * *
  1581. * WARNINGS: *
  1582. * *
  1583. * HISTORY: *
  1584. * 8/23/00 NH : Created. *
  1585. *=============================================================================================*/
  1586. RenderObjClass * HLodClass::Get_Additional_Model (int model_index) const
  1587. {
  1588. RenderObjClass *pmodel = NULL;
  1589. // Param valid?
  1590. WWASSERT(model_index >= 0);
  1591. WWASSERT(model_index < AdditionalModels.Count());
  1592. if ((model_index >= 0) &&
  1593. (model_index < AdditionalModels.Count())) {
  1594. // Get a pointer to the requested model
  1595. pmodel = AdditionalModels[model_index].Model;
  1596. if (pmodel != NULL) {
  1597. pmodel->Add_Ref ();
  1598. }
  1599. }
  1600. // Return a pointer to the requested model
  1601. return pmodel;
  1602. }
  1603. /***********************************************************************************************
  1604. * HLodClass::Get_Additional_Model_Bone -- returns the bone index of an additional model *
  1605. * *
  1606. * INPUT: *
  1607. * *
  1608. * OUTPUT: *
  1609. * *
  1610. * WARNINGS: *
  1611. * *
  1612. * HISTORY: *
  1613. * 8/23/00 NH : Created. *
  1614. *=============================================================================================*/
  1615. int HLodClass::Get_Additional_Model_Bone (int model_index) const
  1616. {
  1617. int bone_index = 0;
  1618. // Params valid?
  1619. WWASSERT(model_index >= 0);
  1620. WWASSERT(model_index < AdditionalModels.Count());
  1621. if ((model_index >= 0) &&
  1622. (model_index < AdditionalModels.Count())) {
  1623. // Get the bone that this model resides on
  1624. bone_index = AdditionalModels[model_index].BoneIndex;
  1625. }
  1626. // Return the bone that this model resides on
  1627. return bone_index;
  1628. }
  1629. /***********************************************************************************************
  1630. * HLodClass::Is_NULL_Lod_Included -- does this HLod have NULL as its lowest LOD *
  1631. * *
  1632. * INPUT: *
  1633. * *
  1634. * OUTPUT: *
  1635. * *
  1636. * WARNINGS: *
  1637. * *
  1638. * HISTORY: *
  1639. * 1/26/00 gth : Created. *
  1640. *=============================================================================================*/
  1641. bool HLodClass::Is_NULL_Lod_Included(void) const
  1642. {
  1643. bool included = false;
  1644. // Determine if the lowest-level LOD is the null render object or not...
  1645. if ((LodCount > 0) && (Lod[0][0].Model != NULL)) {
  1646. included = (Lod[0][0].Model->Class_ID () == RenderObjClass::CLASSID_NULL);
  1647. }
  1648. // Return the true/false result code
  1649. return included;
  1650. }
  1651. /***********************************************************************************************
  1652. * HLodClass::Include_NULL_Lod -- Add NULL as the lowest LOD *
  1653. * *
  1654. * INPUT: *
  1655. * *
  1656. * OUTPUT: *
  1657. * *
  1658. * WARNINGS: *
  1659. * *
  1660. * HISTORY: *
  1661. * 1/26/00 gth : Created. *
  1662. *=============================================================================================*/
  1663. void HLodClass::Include_NULL_Lod(bool include)
  1664. {
  1665. if ((include == false) && Is_NULL_Lod_Included ()) {
  1666. // Free the 'NULL' object's stored information
  1667. int index = 0;
  1668. for (int model = 0; model < Lod[index].Count (); model++) {
  1669. RenderObjClass * robj = Lod[index][model].Model;
  1670. Lod[index][model].Model = NULL;
  1671. WWASSERT(robj);
  1672. robj->Set_Container (NULL);
  1673. robj->Release_Ref ();
  1674. }
  1675. // Resize the lod array
  1676. LodCount -= 1;
  1677. Lod[index].Delete_All ();
  1678. ModelArrayClass *temp_lods = new ModelArrayClass[LodCount];
  1679. for (index = 0; index < LodCount; index ++) {
  1680. temp_lods[index] = Lod[index + 1];
  1681. }
  1682. // Now resize the value and cost arrays
  1683. float *temp_cost = new float[LodCount];
  1684. float *temp_value = new float[LodCount + 1];
  1685. ::memcpy (temp_cost, &Cost[1], sizeof (float) * LodCount);
  1686. ::memcpy (temp_value, &Value[1], sizeof (float) * (LodCount + 1));
  1687. delete [] Lod;
  1688. delete [] Value;
  1689. delete [] Cost;
  1690. Lod = temp_lods;
  1691. Value = temp_value;
  1692. Cost = temp_cost;
  1693. CurLod = (CurLod >= LodCount) ? (LodCount - 1) : CurLod;
  1694. } else if (include && (Is_NULL_Lod_Included () == false)) {
  1695. // Tag the NULL render object onto the end
  1696. RenderObjClass *null_object = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("NULL");
  1697. WWASSERT (null_object != NULL);
  1698. if (null_object != NULL) {
  1699. // Resize the lod array
  1700. ModelArrayClass *temp_lods = new ModelArrayClass[LodCount + 1];
  1701. for (int index = 0; index < LodCount; index ++) {
  1702. temp_lods[index + 1] = Lod[index];
  1703. }
  1704. // Now resize the value and cost arrays
  1705. float *temp_cost = new float[LodCount + 1];
  1706. float *temp_value = new float[LodCount + 2];
  1707. ::memcpy (&temp_cost[1], Cost, sizeof (float) * LodCount);
  1708. ::memcpy (&temp_value[1], Value, sizeof (float) * (LodCount + 1));
  1709. delete [] Lod;
  1710. delete [] Value;
  1711. delete [] Cost;
  1712. Lod = temp_lods;
  1713. Value = temp_value;
  1714. Cost = temp_cost;
  1715. LodCount ++;
  1716. // Add this NULL object to the start of the lod list
  1717. add_lod_model (0, null_object, 0);
  1718. null_object->Release_Ref ();
  1719. }
  1720. }
  1721. // recalculate cost/value arrays and ensure the current LOD is still valid.
  1722. int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
  1723. // Ensure lod is no less than minimum allowed
  1724. if (CurLod < minlod) Set_LOD_Level(minlod);
  1725. return ;
  1726. }
  1727. /***********************************************************************************************
  1728. * HLodClass::Get_Proxy_Count -- Returns the number of proxy records *
  1729. * *
  1730. * INPUT: *
  1731. * *
  1732. * OUTPUT: *
  1733. * *
  1734. * WARNINGS: *
  1735. * *
  1736. * HISTORY: *
  1737. * 10/27/2000 gth : Created. *
  1738. *=============================================================================================*/
  1739. int HLodClass::Get_Proxy_Count(void) const
  1740. {
  1741. if (ProxyArray != NULL) {
  1742. return ProxyArray->Length();
  1743. } else {
  1744. return 0;
  1745. }
  1746. }
  1747. /***********************************************************************************************
  1748. * HLodClass::Get_Proxy -- returns the information for the i'th proxy *
  1749. * *
  1750. * INPUT: *
  1751. * *
  1752. * OUTPUT: *
  1753. * *
  1754. * WARNINGS: *
  1755. * *
  1756. * HISTORY: *
  1757. * 10/27/2000 gth : Created. *
  1758. *=============================================================================================*/
  1759. bool HLodClass::Get_Proxy (int index, ProxyClass &proxy) const
  1760. {
  1761. bool retval = false;
  1762. if (ProxyArray != NULL) {
  1763. //
  1764. // Lookup the proxy's transform
  1765. //
  1766. HTree->Base_Update(Get_Transform());
  1767. Matrix3D transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index());
  1768. Set_Hierarchy_Valid(false);
  1769. //
  1770. // Pass the data onto the proxy object
  1771. //
  1772. proxy.Set_Transform(transform);
  1773. proxy.Set_Name((*ProxyArray)[index].Get_Name());
  1774. retval = true;
  1775. } else {
  1776. proxy.Set_Name ("");
  1777. proxy.Set_Transform (Matrix3D (1));
  1778. }
  1779. return retval;
  1780. }
  1781. /***********************************************************************************************
  1782. * HLodClass::Get_Num_Polys -- returns polycount of the current LOD *
  1783. * *
  1784. * INPUT: *
  1785. * *
  1786. * OUTPUT: *
  1787. * *
  1788. * WARNINGS: *
  1789. * *
  1790. * HISTORY: *
  1791. * 1/26/00 gth : Created. *
  1792. *=============================================================================================*/
  1793. int HLodClass::Get_Num_Polys(void) const
  1794. {
  1795. int polycount = 0;
  1796. int i;
  1797. int model_count = Lod[CurLod].Count();
  1798. for (i = 0; i < model_count; i++) {
  1799. if (Lod[CurLod][i].Model->Is_Not_Hidden_At_All()) {
  1800. polycount += Lod[CurLod][i].Model->Get_Num_Polys();
  1801. }
  1802. }
  1803. int additional_count = AdditionalModels.Count();
  1804. for (i = 0; i < additional_count; i++) {
  1805. if (AdditionalModels[i].Model->Is_Not_Hidden_At_All()) {
  1806. polycount += AdditionalModels[i].Model->Get_Num_Polys();
  1807. }
  1808. }
  1809. return polycount;
  1810. }
  1811. /***********************************************************************************************
  1812. * HLodClass::Render -- render this HLod *
  1813. * *
  1814. * INPUT: *
  1815. * *
  1816. * OUTPUT: *
  1817. * *
  1818. * WARNINGS: *
  1819. * *
  1820. * HISTORY: *
  1821. * 1/26/00 gth : Created. *
  1822. *=============================================================================================*/
  1823. void HLodClass::Render(RenderInfoClass & rinfo)
  1824. {
  1825. int i;
  1826. if (Is_Not_Hidden_At_All() == false) {
  1827. return;
  1828. }
  1829. Animatable3DObjClass::Render(rinfo);
  1830. for (i = 0; i < Lod[CurLod].Count(); i++) {
  1831. Lod[CurLod][i].Model->Render(rinfo);
  1832. }
  1833. if (Is_Sub_Objects_Match_LOD_Enabled()) {
  1834. for (i = 0; i < AdditionalModels.Count(); i++) {
  1835. AdditionalModels[i].Model->Set_LOD_Level(Get_LOD_Level());
  1836. AdditionalModels[i].Model->Render(rinfo);
  1837. }
  1838. } else {
  1839. for (i = 0; i < AdditionalModels.Count(); i++) {
  1840. AdditionalModels[i].Model->Render(rinfo);
  1841. }
  1842. }
  1843. }
  1844. /***********************************************************************************************
  1845. * HLodClass::Special_Render -- Special_Render for HLod *
  1846. * *
  1847. * INPUT: *
  1848. * *
  1849. * OUTPUT: *
  1850. * *
  1851. * WARNINGS: *
  1852. * *
  1853. * HISTORY: *
  1854. * 1/26/00 gth : Created. *
  1855. *=============================================================================================*/
  1856. void HLodClass::Special_Render(SpecialRenderInfoClass & rinfo)
  1857. {
  1858. int i;
  1859. if (Is_Not_Hidden_At_All() == false) {
  1860. return;
  1861. }
  1862. Animatable3DObjClass::Special_Render(rinfo);
  1863. int lod_index = CurLod;
  1864. if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_SHADOW) { // (gth) HACK HACK! yikes
  1865. lod_index = LodCount-1;
  1866. }
  1867. for (i = 0; i < Lod[lod_index].Count(); i++) {
  1868. Lod[lod_index][i].Model->Special_Render(rinfo);
  1869. }
  1870. for (i = 0; i < AdditionalModels.Count(); i++) {
  1871. AdditionalModels[i].Model->Special_Render(rinfo);
  1872. }
  1873. }
  1874. /***********************************************************************************************
  1875. * HLodClass::Set_Transform -- Sets the transform *
  1876. * *
  1877. * INPUT: *
  1878. * *
  1879. * OUTPUT: *
  1880. * *
  1881. * WARNINGS: *
  1882. * *
  1883. * HISTORY: *
  1884. * 1/26/00 gth : Created. *
  1885. *=============================================================================================*/
  1886. void HLodClass::Set_Transform(const Matrix3D &m)
  1887. {
  1888. Animatable3DObjClass::Set_Transform(m);
  1889. Set_Sub_Object_Transforms_Dirty(true);
  1890. }
  1891. /***********************************************************************************************
  1892. * HLodClass::Set_Position -- Sets the position *
  1893. * *
  1894. * INPUT: *
  1895. * *
  1896. * OUTPUT: *
  1897. * *
  1898. * WARNINGS: *
  1899. * *
  1900. * HISTORY: *
  1901. * 1/26/00 gth : Created. *
  1902. *=============================================================================================*/
  1903. void HLodClass::Set_Position(const Vector3 &v)
  1904. {
  1905. Animatable3DObjClass::Set_Position(v);
  1906. Set_Sub_Object_Transforms_Dirty(true);
  1907. }
  1908. /***********************************************************************************************
  1909. * HLodClass::Notify_Added -- callback notifies subobjs that they were added *
  1910. * *
  1911. * INPUT: *
  1912. * *
  1913. * OUTPUT: *
  1914. * *
  1915. * WARNINGS: *
  1916. * *
  1917. * HISTORY: *
  1918. * 1/26/00 gth : Created. *
  1919. *=============================================================================================*/
  1920. void HLodClass::Notify_Added(SceneClass * scene)
  1921. {
  1922. RenderObjClass::Notify_Added(scene);
  1923. int i;
  1924. int model_count = Lod[CurLod].Count();
  1925. for (i = 0; i < model_count; i++) {
  1926. Lod[CurLod][i].Model->Notify_Added(scene);
  1927. }
  1928. int additional_count = AdditionalModels.Count();
  1929. for (i = 0; i < additional_count; i++) {
  1930. AdditionalModels[i].Model->Notify_Added(scene);
  1931. }
  1932. }
  1933. /***********************************************************************************************
  1934. * HLodClass::Notify_Removed -- notifies subobjs that they were removed *
  1935. * *
  1936. * INPUT: *
  1937. * *
  1938. * OUTPUT: *
  1939. * *
  1940. * WARNINGS: *
  1941. * *
  1942. * HISTORY: *
  1943. * 1/26/00 gth : Created. *
  1944. *=============================================================================================*/
  1945. void HLodClass::Notify_Removed(SceneClass * scene)
  1946. {
  1947. int i;
  1948. int model_count = Lod[CurLod].Count();
  1949. for (i = 0; i < model_count; i++) {
  1950. Lod[CurLod][i].Model->Notify_Removed(scene);
  1951. }
  1952. int additional_count = AdditionalModels.Count();
  1953. for (i = 0; i < additional_count; i++) {
  1954. AdditionalModels[i].Model->Notify_Removed(scene);
  1955. }
  1956. RenderObjClass::Notify_Removed(scene);
  1957. }
  1958. /***********************************************************************************************
  1959. * HLodClass::Get_Num_Sub_Objects -- returns total number of sub-objects *
  1960. * *
  1961. * INPUT: *
  1962. * *
  1963. * OUTPUT: *
  1964. * *
  1965. * WARNINGS: *
  1966. * *
  1967. * HISTORY: *
  1968. * 1/26/00 gth : Created. *
  1969. *=============================================================================================*/
  1970. int HLodClass::Get_Num_Sub_Objects(void) const
  1971. {
  1972. int count = 0;
  1973. for (int lod=0; lod<LodCount;lod++) {
  1974. count += Lod[lod].Count();
  1975. }
  1976. count += AdditionalModels.Count();
  1977. return count;
  1978. }
  1979. /***********************************************************************************************
  1980. * HLodClass::Get_Sub_Object -- returns a pointer to specified sub-object *
  1981. * *
  1982. * INPUT: *
  1983. * *
  1984. * OUTPUT: *
  1985. * *
  1986. * WARNINGS: *
  1987. * *
  1988. * HISTORY: *
  1989. * 1/26/00 gth : Created. *
  1990. *=============================================================================================*/
  1991. RenderObjClass * HLodClass::Get_Sub_Object(int index) const
  1992. {
  1993. WWASSERT(index >= 0);
  1994. for (int lod=0; lod<LodCount; lod++) {
  1995. if (index < Lod[lod].Count()) {
  1996. Lod[lod][index].Model->Add_Ref();
  1997. return Lod[lod][index].Model;
  1998. }
  1999. index -= Lod[lod].Count();
  2000. }
  2001. WWASSERT(index < AdditionalModels.Count());
  2002. AdditionalModels[index].Model->Add_Ref();
  2003. return AdditionalModels[index].Model;
  2004. }
  2005. /***********************************************************************************************
  2006. * HLodClass::Add_Sub_Object -- add a sub-object to this HLod *
  2007. * *
  2008. * INPUT: *
  2009. * *
  2010. * OUTPUT: *
  2011. * *
  2012. * WARNINGS: *
  2013. * *
  2014. * HISTORY: *
  2015. * 1/26/00 gth : Created. *
  2016. *=============================================================================================*/
  2017. int HLodClass::Add_Sub_Object(RenderObjClass * subobj)
  2018. {
  2019. return Add_Sub_Object_To_Bone(subobj,0);
  2020. }
  2021. /***********************************************************************************************
  2022. * HLodClass::Remove_Sub_Object -- remove a sub-object from this HLod *
  2023. * *
  2024. * INPUT: *
  2025. * *
  2026. * OUTPUT: *
  2027. * *
  2028. * WARNINGS: *
  2029. * *
  2030. * HISTORY: *
  2031. * 1/26/00 gth : Created. *
  2032. *=============================================================================================*/
  2033. int HLodClass::Remove_Sub_Object(RenderObjClass * removeme)
  2034. {
  2035. // no object given?
  2036. if (removeme == NULL) {
  2037. return 0;
  2038. }
  2039. // find the sub-object
  2040. bool found = false;
  2041. bool iscurrent = false;
  2042. for (int lod = 0; (lod < LodCount) && (!found); lod++) {
  2043. for (int model = 0; (model < Lod[lod].Count()) && (!found); model++) {
  2044. if (Lod[lod][model].Model == removeme) {
  2045. // remove the model from the array.
  2046. Lod[lod].Delete(model);
  2047. // record that we found it
  2048. found = true;
  2049. if (lod == CurLod) {
  2050. iscurrent = true;
  2051. }
  2052. }
  2053. }
  2054. }
  2055. for (int model = 0; (model < AdditionalModels.Count()) && (!found); model++) {
  2056. if (AdditionalModels[model].Model == removeme) {
  2057. AdditionalModels.Delete(model);
  2058. found = true;
  2059. iscurrent = true;
  2060. }
  2061. }
  2062. if (found) {
  2063. // clear the object's container pointer
  2064. removeme->Set_Container(NULL);
  2065. // let him know in case he is removed from the scene as a result of this
  2066. // this is the combination of this HLod being in the scene and and this model
  2067. // either being in the current LOD or being in the additional model list...
  2068. if (iscurrent && Is_In_Scene()) {
  2069. removeme->Notify_Removed(Scene);
  2070. }
  2071. // release our reference to this render object
  2072. // object may delete itself here...
  2073. removeme->Release_Ref();
  2074. Update_Sub_Object_Bits();
  2075. Update_Obj_Space_Bounding_Volumes();
  2076. return 1;
  2077. }
  2078. return 0;
  2079. }
  2080. /***********************************************************************************************
  2081. * HLodClass::Get_Num_Sub_Objects_On_Bone -- returns the number of objects on the given bone *
  2082. * *
  2083. * INPUT: *
  2084. * *
  2085. * OUTPUT: *
  2086. * *
  2087. * WARNINGS: *
  2088. * *
  2089. * HISTORY: *
  2090. * 1/26/00 gth : Created. *
  2091. *=============================================================================================*/
  2092. int HLodClass::Get_Num_Sub_Objects_On_Bone(int boneindex) const
  2093. {
  2094. int count = 0;
  2095. for (int lod = 0; lod < LodCount; lod++) {
  2096. for (int model = 0; model < Lod[lod].Count(); model++) {
  2097. if (Lod[lod][model].BoneIndex == boneindex) count++;
  2098. }
  2099. }
  2100. for (int model = 0; model < AdditionalModels.Count(); model++) {
  2101. if (AdditionalModels[model].BoneIndex == boneindex) count++;
  2102. }
  2103. return count;
  2104. }
  2105. /***********************************************************************************************
  2106. * HLodClass::Get_Sub_Object_On_Bone -- returns obj on the given bone *
  2107. * *
  2108. * INPUT: *
  2109. * *
  2110. * OUTPUT: *
  2111. * *
  2112. * WARNINGS: *
  2113. * *
  2114. * HISTORY: *
  2115. * 1/26/00 gth : Created. *
  2116. *=============================================================================================*/
  2117. RenderObjClass * HLodClass::Get_Sub_Object_On_Bone(int index,int boneindex) const
  2118. {
  2119. int count = 0;
  2120. for (int lod = 0; lod < LodCount; lod++) {
  2121. for (int model = 0; model < Lod[lod].Count(); model++) {
  2122. if (Lod[lod][model].BoneIndex == boneindex) {
  2123. if (count == index) {
  2124. Lod[lod][model].Model->Add_Ref();
  2125. return Lod[lod][model].Model;
  2126. }
  2127. count++;
  2128. }
  2129. }
  2130. }
  2131. for (int model = 0; model < AdditionalModels.Count(); model++) {
  2132. if (AdditionalModels[model].BoneIndex == boneindex) {
  2133. if (count == index) {
  2134. AdditionalModels[model].Model->Add_Ref();
  2135. return AdditionalModels[model].Model;
  2136. }
  2137. count++;
  2138. }
  2139. }
  2140. return NULL;
  2141. }
  2142. /***********************************************************************************************
  2143. * HLodClass::Get_Sub_Object_Bone_Index -- returns bone index of given object *
  2144. * *
  2145. * INPUT: *
  2146. * *
  2147. * OUTPUT: *
  2148. * *
  2149. * WARNINGS: *
  2150. * *
  2151. * HISTORY: *
  2152. * 1/26/00 gth : Created. *
  2153. *=============================================================================================*/
  2154. int HLodClass::Get_Sub_Object_Bone_Index(RenderObjClass * subobj) const
  2155. {
  2156. for (int lod = 0; lod < LodCount; lod++) {
  2157. for (int model = 0; model < Lod[lod].Count(); model++) {
  2158. if (Lod[lod][model].Model == subobj) {
  2159. return Lod[lod][model].BoneIndex;
  2160. }
  2161. }
  2162. }
  2163. for (int model = 0; model < AdditionalModels.Count(); model++) {
  2164. if (AdditionalModels[model].Model == subobj) {
  2165. return AdditionalModels[model].BoneIndex;
  2166. }
  2167. }
  2168. return 0;
  2169. }
  2170. /***********************************************************************************************
  2171. * HLodClass::Add_Sub_Object_To_Bone -- adds a sub-object to a bone *
  2172. * *
  2173. * INPUT: *
  2174. * *
  2175. * OUTPUT: *
  2176. * *
  2177. * WARNINGS: *
  2178. * *
  2179. * HISTORY: *
  2180. * 1/26/00 gth : Created. *
  2181. *=============================================================================================*/
  2182. int HLodClass::Add_Sub_Object_To_Bone(RenderObjClass * subobj,int boneindex)
  2183. {
  2184. WWASSERT(subobj);
  2185. if ((boneindex < 0) || (boneindex >= HTree->Num_Pivots())) return 0;
  2186. subobj->Set_LOD_Bias(LODBias);
  2187. ModelNodeClass newnode;
  2188. newnode.Model = subobj;
  2189. newnode.Model->Add_Ref();
  2190. newnode.Model->Set_Container(this);
  2191. newnode.Model->Set_Animation_Hidden(HTree->Get_Visibility (boneindex) == false);
  2192. newnode.BoneIndex = boneindex;
  2193. int result = AdditionalModels.Add(newnode);
  2194. Update_Sub_Object_Bits();
  2195. Update_Obj_Space_Bounding_Volumes();
  2196. Set_Hierarchy_Valid (false);
  2197. Set_Sub_Object_Transforms_Dirty(true);
  2198. if (Is_In_Scene()) {
  2199. subobj->Notify_Added(Scene);
  2200. }
  2201. return result;
  2202. }
  2203. /***********************************************************************************************
  2204. * HLodClass::Set_Animation -- set animation state to the base-pose *
  2205. * *
  2206. * INPUT: *
  2207. * *
  2208. * OUTPUT: *
  2209. * *
  2210. * WARNINGS: *
  2211. * *
  2212. * HISTORY: *
  2213. * 1/26/00 gth : Created. *
  2214. *=============================================================================================*/
  2215. void HLodClass::Set_Animation(void)
  2216. {
  2217. Animatable3DObjClass::Set_Animation();
  2218. Set_Sub_Object_Transforms_Dirty(true);
  2219. }
  2220. /***********************************************************************************************
  2221. * HLodClass::Set_Animation -- set animation state to an animation frame *
  2222. * *
  2223. * INPUT: *
  2224. * *
  2225. * OUTPUT: *
  2226. * *
  2227. * WARNINGS: *
  2228. * *
  2229. * HISTORY: *
  2230. * 1/26/00 gth : Created. *
  2231. *=============================================================================================*/
  2232. void HLodClass::Set_Animation(HAnimClass * motion,float frame,int mode)
  2233. {
  2234. Animatable3DObjClass::Set_Animation(motion,frame,mode);
  2235. Set_Sub_Object_Transforms_Dirty(true);
  2236. }
  2237. /***********************************************************************************************
  2238. * HLodClass::Set_Animation -- set animation state to a blend of two animations *
  2239. * *
  2240. * INPUT: *
  2241. * *
  2242. * OUTPUT: *
  2243. * *
  2244. * WARNINGS: *
  2245. * *
  2246. * HISTORY: *
  2247. * 1/26/00 gth : Created. *
  2248. *=============================================================================================*/
  2249. void HLodClass::Set_Animation
  2250. (
  2251. HAnimClass * motion0,
  2252. float frame0,
  2253. HAnimClass * motion1,
  2254. float frame1,
  2255. float percentage
  2256. )
  2257. {
  2258. Animatable3DObjClass::Set_Animation(motion0,frame0,motion1,frame1,percentage);
  2259. Set_Sub_Object_Transforms_Dirty(true);
  2260. }
  2261. /***********************************************************************************************
  2262. * HLodClass::Set_Animation -- set animation state to a combination of anims *
  2263. * *
  2264. * INPUT: *
  2265. * *
  2266. * OUTPUT: *
  2267. * *
  2268. * WARNINGS: *
  2269. * *
  2270. * HISTORY: *
  2271. * 1/26/00 gth : Created. *
  2272. *=============================================================================================*/
  2273. void HLodClass::Set_Animation(HAnimComboClass * anim_combo)
  2274. {
  2275. Animatable3DObjClass::Set_Animation(anim_combo);
  2276. Set_Sub_Object_Transforms_Dirty(true);
  2277. }
  2278. /***********************************************************************************************
  2279. * HLodClass::Cast_Ray -- cast a ray against this HLod *
  2280. * *
  2281. * INPUT: *
  2282. * *
  2283. * OUTPUT: *
  2284. * *
  2285. * WARNINGS: *
  2286. * *
  2287. * HISTORY: *
  2288. * 1/26/00 gth : Created. *
  2289. *=============================================================================================*/
  2290. bool HLodClass::Cast_Ray(RayCollisionTestClass & raytest)
  2291. {
  2292. if (Are_Sub_Object_Transforms_Dirty ()) {
  2293. Update_Sub_Object_Transforms ();
  2294. }
  2295. bool res = false;
  2296. int i;
  2297. // collide against the top LOD
  2298. int top = LodCount-1;
  2299. for (i = 0; i < Lod[top].Count(); i++) {
  2300. res |= Lod[top][i].Model->Cast_Ray(raytest);
  2301. }
  2302. for (i = 0; i < AdditionalModels.Count(); i++) {
  2303. res |= AdditionalModels[i].Model->Cast_Ray(raytest);
  2304. }
  2305. return res;
  2306. }
  2307. /***********************************************************************************************
  2308. * HLodClass::Cast_AABox -- Cast a swept AABox against this HLod *
  2309. * *
  2310. * INPUT: *
  2311. * *
  2312. * OUTPUT: *
  2313. * *
  2314. * WARNINGS: *
  2315. * *
  2316. * HISTORY: *
  2317. * 1/26/00 gth : Created. *
  2318. *=============================================================================================*/
  2319. bool HLodClass::Cast_AABox(AABoxCollisionTestClass & boxtest)
  2320. {
  2321. if (Are_Sub_Object_Transforms_Dirty ()) {
  2322. Update_Sub_Object_Transforms ();
  2323. }
  2324. bool res = false;
  2325. int i;
  2326. // collide against the top LOD
  2327. int top = LodCount-1;
  2328. for (i = 0; i < Lod[top].Count(); i++) {
  2329. res |= Lod[top][i].Model->Cast_AABox(boxtest);
  2330. }
  2331. for (i = 0; i < AdditionalModels.Count(); i++) {
  2332. res |= AdditionalModels[i].Model->Cast_AABox(boxtest);
  2333. }
  2334. return res;
  2335. }
  2336. /***********************************************************************************************
  2337. * HLodClass::Cast_OBBox -- Cast a swept OBBox against this HLod *
  2338. * *
  2339. * INPUT: *
  2340. * *
  2341. * OUTPUT: *
  2342. * *
  2343. * WARNINGS: *
  2344. * *
  2345. * HISTORY: *
  2346. * 1/26/00 gth : Created. *
  2347. *=============================================================================================*/
  2348. bool HLodClass::Cast_OBBox(OBBoxCollisionTestClass & boxtest)
  2349. {
  2350. if (Are_Sub_Object_Transforms_Dirty ()) {
  2351. Update_Sub_Object_Transforms ();
  2352. }
  2353. bool res = false;
  2354. int i;
  2355. // collide against the top LOD
  2356. int top = LodCount-1;
  2357. for (i = 0; i < Lod[top].Count(); i++) {
  2358. res |= Lod[top][i].Model->Cast_OBBox(boxtest);
  2359. }
  2360. for (i = 0; i < AdditionalModels.Count(); i++) {
  2361. res |= AdditionalModels[i].Model->Cast_OBBox(boxtest);
  2362. }
  2363. return res;
  2364. }
  2365. /***********************************************************************************************
  2366. * HLodClass::Intersect_AABox -- Intersect an AABox with this HLod *
  2367. * *
  2368. * INPUT: *
  2369. * *
  2370. * OUTPUT: *
  2371. * *
  2372. * WARNINGS: *
  2373. * *
  2374. * HISTORY: *
  2375. * 1/26/00 gth : Created. *
  2376. *=============================================================================================*/
  2377. bool HLodClass::Intersect_AABox(AABoxIntersectionTestClass & boxtest)
  2378. {
  2379. if (Are_Sub_Object_Transforms_Dirty ()) {
  2380. Update_Sub_Object_Transforms ();
  2381. }
  2382. bool res = false;
  2383. int i;
  2384. // collide against the top LOD
  2385. int top = LodCount-1;
  2386. for (i = 0; i < Lod[top].Count(); i++) {
  2387. res |= Lod[top][i].Model->Intersect_AABox(boxtest);
  2388. }
  2389. for (i = 0; i < AdditionalModels.Count(); i++) {
  2390. res |= AdditionalModels[i].Model->Intersect_AABox(boxtest);
  2391. }
  2392. return res;
  2393. }
  2394. /***********************************************************************************************
  2395. * HLodClass::Intersect_OBBox -- Intersect an OBBox with this HLod *
  2396. * *
  2397. * INPUT: *
  2398. * *
  2399. * OUTPUT: *
  2400. * *
  2401. * WARNINGS: *
  2402. * *
  2403. * HISTORY: *
  2404. * 1/26/00 gth : Created. *
  2405. *=============================================================================================*/
  2406. bool HLodClass::Intersect_OBBox(OBBoxIntersectionTestClass & boxtest)
  2407. {
  2408. if (Are_Sub_Object_Transforms_Dirty ()) {
  2409. Update_Sub_Object_Transforms ();
  2410. }
  2411. bool res = false;
  2412. int i;
  2413. // collide against the top LOD
  2414. int top = LodCount-1;
  2415. for (i = 0; i < Lod[top].Count(); i++) {
  2416. res |= Lod[top][i].Model->Intersect_OBBox(boxtest);
  2417. }
  2418. for (i = 0; i < AdditionalModels.Count(); i++) {
  2419. res |= AdditionalModels[i].Model->Intersect_OBBox(boxtest);
  2420. }
  2421. return res;
  2422. }
  2423. /***********************************************************************************************
  2424. * HLodClass::Prepare_LOD -- Prepare for LOD processing *
  2425. * *
  2426. * INPUT: *
  2427. * *
  2428. * OUTPUT: *
  2429. * *
  2430. * WARNINGS: *
  2431. * *
  2432. * HISTORY: *
  2433. * 1/26/00 gth : Created. *
  2434. *=============================================================================================*/
  2435. void HLodClass::Prepare_LOD(CameraClass &camera)
  2436. {
  2437. if (Is_Not_Hidden_At_All() == false) {
  2438. return;
  2439. }
  2440. // Find the maximum screen dimension of the object in pixels
  2441. float norm_area = Get_Screen_Size(camera);
  2442. /*
  2443. ** Set texture reduction factor for the (non-additional) subobjects:
  2444. */
  2445. // Texture reduction system broken, don't call!
  2446. // Set_Texture_Reduction_Factor(Calculate_Texture_Reduction_Factor(norm_area));
  2447. // Prepare LOD processing if this object has more than one LOD:
  2448. if (LodCount > 1) {
  2449. /*
  2450. ** Prepare cost and value arrays (and ensure current LOD doesn't violate clamping):
  2451. */
  2452. int minlod = Calculate_Cost_Value_Arrays(norm_area, Value, Cost);
  2453. if (CurLod < minlod) Set_LOD_Level(minlod);
  2454. /*
  2455. ** Add myself to the LOD optimizer:
  2456. */
  2457. PredictiveLODOptimizerClass::Add_Object(this);
  2458. } else {
  2459. // Not added to optimizer, need to add cost
  2460. PredictiveLODOptimizerClass::Add_Cost(Get_Cost());
  2461. }
  2462. /*
  2463. ** Recursively call for the additional objects:
  2464. */
  2465. int additional_count = AdditionalModels.Count();
  2466. for (int i = 0; i < additional_count; i++) {
  2467. if (AdditionalModels[i].Model->Is_Not_Hidden_At_All()) {
  2468. AdditionalModels[i].Model->Prepare_LOD(camera);
  2469. }
  2470. }
  2471. }
  2472. /***********************************************************************************************
  2473. * HLodClass::Recalculate_Static_LOD_Factors -- compute lod factors *
  2474. * *
  2475. * INPUT: *
  2476. * *
  2477. * OUTPUT: *
  2478. * *
  2479. * WARNINGS: *
  2480. * *
  2481. * HISTORY: *
  2482. * 1/26/00 gth : Created. *
  2483. *=============================================================================================*/
  2484. void HLodClass::Recalculate_Static_LOD_Factors(void)
  2485. {
  2486. /*
  2487. ** Calculate NonPixelCost, PixelCostPerArea, BenefitFactor for all LOD
  2488. ** levels.
  2489. ** NOTE: for now we are using vastly simplified Cost and Benefit metrics.
  2490. ** (these will be improved after initial experimentation).
  2491. ** the Cost metric is simply the number of polygons, and the Benefit
  2492. ** Metric is 1 - 0.5 / #polygons^2.
  2493. */
  2494. for (int i = 0; i < LodCount; i++) {
  2495. // Currently there are no pixel-related costs taken into account
  2496. Lod[i].PixelCostPerArea = 0.0f;
  2497. // Sum polycount over all non-hidden models in array
  2498. int model_count = Lod[i].Count();
  2499. int polycount = 0;
  2500. for (int j = 0; j < model_count; j++) {
  2501. if (Lod[i][j].Model->Is_Not_Hidden_At_All()) {
  2502. polycount += Lod[i][j].Model->Get_Num_Polys();
  2503. }
  2504. }
  2505. // If polycount is zero set Cost to a small nonzero amount to avoid divisions by zero.
  2506. Lod[i].NonPixelCost = (polycount != 0)? polycount : 0.000001f;
  2507. // A polycount of zero yields a benefit factor of zero: otherwise apply formula.
  2508. Lod[i].BenefitFactor = (polycount != 0) ? (1 - (0.5f / (polycount * polycount))) : 0.0f;
  2509. }
  2510. }
  2511. /***********************************************************************************************
  2512. * HLodClass::Increment_LOD -- move to next lod *
  2513. * *
  2514. * INPUT: *
  2515. * *
  2516. * OUTPUT: *
  2517. * *
  2518. * WARNINGS: *
  2519. * *
  2520. * HISTORY: *
  2521. * 1/26/00 gth : Created. *
  2522. *=============================================================================================*/
  2523. void HLodClass::Increment_LOD(void)
  2524. {
  2525. if (CurLod >= (LodCount-1)) return;
  2526. if (Is_In_Scene()) {
  2527. int model_count = Lod[CurLod].Count();
  2528. for (int i = 0; i < model_count; i++) {
  2529. Lod[CurLod][i].Model->Notify_Removed(Scene);
  2530. }
  2531. }
  2532. CurLod++;
  2533. if (Is_In_Scene()) {
  2534. int model_count = Lod[CurLod].Count();
  2535. for (int i = 0; i < model_count; i++) {
  2536. Lod[CurLod][i].Model->Notify_Added(Scene);
  2537. }
  2538. }
  2539. }
  2540. /***********************************************************************************************
  2541. * HLodClass::Decrement_LOD -- move to previous lod *
  2542. * *
  2543. * INPUT: *
  2544. * *
  2545. * OUTPUT: *
  2546. * *
  2547. * WARNINGS: *
  2548. * *
  2549. * HISTORY: *
  2550. * 1/26/00 gth : Created. *
  2551. *=============================================================================================*/
  2552. void HLodClass::Decrement_LOD(void)
  2553. {
  2554. if (CurLod < 1) return;
  2555. if (Is_In_Scene()) {
  2556. int model_count = Lod[CurLod].Count();
  2557. for (int i = 0; i < model_count; i++) {
  2558. Lod[CurLod][i].Model->Notify_Removed(Scene);
  2559. }
  2560. }
  2561. CurLod--;
  2562. if (Is_In_Scene()) {
  2563. int model_count = Lod[CurLod].Count();
  2564. for (int i = 0; i < model_count; i++) {
  2565. Lod[CurLod][i].Model->Notify_Added(Scene);
  2566. }
  2567. }
  2568. }
  2569. /***********************************************************************************************
  2570. * HLodClass::Get_Cost -- returns the cost of this LOD *
  2571. * *
  2572. * INPUT: *
  2573. * *
  2574. * OUTPUT: *
  2575. * *
  2576. * WARNINGS: *
  2577. * *
  2578. * HISTORY: *
  2579. * 1/26/00 gth : Created. *
  2580. *=============================================================================================*/
  2581. float HLodClass::Get_Cost(void) const
  2582. {
  2583. return(Cost[CurLod]);
  2584. }
  2585. /***********************************************************************************************
  2586. * HLodClass::Get_Value -- returns the value of this LOD *
  2587. * *
  2588. * INPUT: *
  2589. * *
  2590. * OUTPUT: *
  2591. * *
  2592. * WARNINGS: *
  2593. * *
  2594. * HISTORY: *
  2595. * 1/26/00 gth : Created. *
  2596. *=============================================================================================*/
  2597. float HLodClass::Get_Value(void) const
  2598. {
  2599. return(Value[CurLod]);
  2600. }
  2601. /***********************************************************************************************
  2602. * HLodClass::Get_Post_Increment_Value -- returns the post increment value *
  2603. * *
  2604. * INPUT: *
  2605. * *
  2606. * OUTPUT: *
  2607. * *
  2608. * WARNINGS: *
  2609. * *
  2610. * HISTORY: *
  2611. * 1/26/00 gth : Created. *
  2612. *=============================================================================================*/
  2613. float HLodClass::Get_Post_Increment_Value(void) const
  2614. {
  2615. return(Value[CurLod + 1]);
  2616. }
  2617. /***********************************************************************************************
  2618. * HLodClass::Set_LOD_Level -- set the current lod level *
  2619. * *
  2620. * INPUT: *
  2621. * *
  2622. * OUTPUT: *
  2623. * *
  2624. * WARNINGS: *
  2625. * *
  2626. * HISTORY: *
  2627. * 1/26/00 gth : Created. *
  2628. *=============================================================================================*/
  2629. void HLodClass::Set_LOD_Level(int lod)
  2630. {
  2631. lod = MAX(0, lod);
  2632. lod = MIN(lod, (LodCount - 1));
  2633. if (lod == CurLod) return;
  2634. if (Is_In_Scene()) {
  2635. int model_count = Lod[CurLod].Count();
  2636. for (int i = 0; i < model_count; i++) {
  2637. Lod[CurLod][i].Model->Notify_Removed(Scene);
  2638. }
  2639. }
  2640. CurLod = lod;
  2641. if (Is_In_Scene()) {
  2642. int model_count = Lod[CurLod].Count();
  2643. for (int i = 0; i < model_count; i++) {
  2644. Lod[CurLod][i].Model->Notify_Added(Scene);
  2645. }
  2646. }
  2647. }
  2648. /***********************************************************************************************
  2649. * HLodClass::Get_LOD_Level -- returns the current LOD level *
  2650. * *
  2651. * INPUT: *
  2652. * *
  2653. * OUTPUT: *
  2654. * *
  2655. * WARNINGS: *
  2656. * *
  2657. * HISTORY: *
  2658. * 1/26/00 gth : Created. *
  2659. *=============================================================================================*/
  2660. int HLodClass::Get_LOD_Level(void) const
  2661. {
  2662. return CurLod;
  2663. }
  2664. /***********************************************************************************************
  2665. * HLodClass::Get_LOD_Count -- returns the number of levels of detail *
  2666. * *
  2667. * INPUT: *
  2668. * *
  2669. * OUTPUT: *
  2670. * *
  2671. * WARNINGS: *
  2672. * *
  2673. * HISTORY: *
  2674. * 1/26/00 gth : Created. *
  2675. *=============================================================================================*/
  2676. int HLodClass::Get_LOD_Count(void) const
  2677. {
  2678. return LodCount;
  2679. }
  2680. /***********************************************************************************************
  2681. * HLodClass::Calculate_Cost_Value_Arrays -- computes the cost-value arrays *
  2682. * *
  2683. * INPUT: *
  2684. * *
  2685. * OUTPUT: *
  2686. * *
  2687. * WARNINGS: *
  2688. * *
  2689. * HISTORY: *
  2690. * 1/26/00 gth : Created. *
  2691. *=============================================================================================*/
  2692. int HLodClass::Calculate_Cost_Value_Arrays(float screen_area, float *values, float *costs) const
  2693. {
  2694. int lod = 0;
  2695. // Calculate Cost heuristic for each LOD based on normalized screen area:
  2696. for (lod = 0; lod < LodCount; lod++) {
  2697. costs[lod] = Lod[lod].NonPixelCost + Lod[lod].PixelCostPerArea * screen_area;
  2698. }
  2699. // Calculate Value heuristic. First, all LOD levels for which
  2700. // MaxScreenSize is smaller than screen_area have their Value set to
  2701. // AT_MIN_LOD, as well as the first LOD after that (unless there are no
  2702. // other LODs):
  2703. for (lod = 0; lod < LodCount && Lod[lod].MaxScreenSize < screen_area; lod++) {
  2704. values[lod] = AT_MIN_LOD;
  2705. }
  2706. if (lod >= LodCount) {
  2707. lod = LodCount - 1;
  2708. } else {
  2709. values[lod] = AT_MIN_LOD;
  2710. }
  2711. // Now lod is the lowest allowed - return this value.
  2712. int minlod = lod;
  2713. // Calculate Value heuristic for any remaining LODs based on normalized screen area:
  2714. lod++;
  2715. for (; lod < LodCount; lod++) {
  2716. values[lod] = (Lod[lod].BenefitFactor * screen_area * LODBias) / costs[lod];
  2717. }
  2718. values[LodCount] = AT_MAX_LOD; // Post-inc value will flag max LOD.
  2719. return minlod;
  2720. }
  2721. /***********************************************************************************************
  2722. * HLodClass::Get_Current_LOD -- returns a render object which represents the current LOD *
  2723. * *
  2724. * INPUT: *
  2725. * *
  2726. * OUTPUT: *
  2727. * *
  2728. * WARNINGS: *
  2729. * *
  2730. * HISTORY: *
  2731. * 1/26/00 gth : Created. *
  2732. *=============================================================================================*/
  2733. RenderObjClass * HLodClass::Get_Current_LOD(void)
  2734. {
  2735. int count = Get_Lod_Model_Count(CurLod);
  2736. if(!count)
  2737. return 0;
  2738. return Get_Lod_Model(CurLod, 0);
  2739. }
  2740. /***********************************************************************************************
  2741. * HLodClass::Set_Texture_Reduction_Factor -- resizeable texture support *
  2742. * *
  2743. * INPUT: *
  2744. * *
  2745. * OUTPUT: *
  2746. * *
  2747. * WARNINGS: *
  2748. * *
  2749. * HISTORY: *
  2750. * 1/26/00 gth : Created. *
  2751. *=============================================================================================*/
  2752. /*
  2753. void HLodClass::Set_Texture_Reduction_Factor(float trf)
  2754. {
  2755. WWASSERT(0); // don't call to tex reduction system, it's broken!
  2756. // We don't touch the additional subobjects: they will get Prepare_LOD
  2757. // called on them individually which is where texture reduction will be
  2758. // set also.
  2759. for (int lod = 0; lod < LodCount; lod++) {
  2760. int model_count = Lod[lod].Count();
  2761. for (int model_id = 0; model_id < model_count; model_id++) {
  2762. Lod[lod][model_id].Model->Set_Texture_Reduction_Factor(trf);
  2763. }
  2764. }
  2765. }
  2766. */
  2767. /***********************************************************************************************
  2768. * HLodClass::Scale -- scale this HLod model *
  2769. * *
  2770. * INPUT: *
  2771. * *
  2772. * OUTPUT: *
  2773. * *
  2774. * WARNINGS: *
  2775. * *
  2776. * HISTORY: *
  2777. * 1/26/00 gth : Created. *
  2778. *=============================================================================================*/
  2779. void HLodClass::Scale(float scale)
  2780. {
  2781. if (scale==1.0f) return;
  2782. int lod;
  2783. int model;
  2784. //. Scale all subobjects.
  2785. for (lod = 0; lod < LodCount; lod++) {
  2786. for (model = 0; model < Lod[lod].Count(); model++) {
  2787. Lod[lod][model].Model->Scale(scale);
  2788. }
  2789. }
  2790. for (model = 0; model < AdditionalModels.Count(); model++) {
  2791. AdditionalModels[model].Model->Scale(scale);
  2792. }
  2793. // Scale HTree:
  2794. HTree->Scale(scale);
  2795. // Invalidate hierarchy
  2796. Set_Hierarchy_Valid(false);
  2797. // Now update the object space bounding volumes of this object's container:
  2798. RenderObjClass *container = Get_Container();
  2799. if (container) container->Update_Obj_Space_Bounding_Volumes();
  2800. }
  2801. /***********************************************************************************************
  2802. * HLodClass::Get_Num_Snap_Points -- returns the number of snap points in this model *
  2803. * *
  2804. * INPUT: *
  2805. * *
  2806. * OUTPUT: *
  2807. * *
  2808. * WARNINGS: *
  2809. * *
  2810. * HISTORY: *
  2811. * 1/26/00 gth : Created. *
  2812. *=============================================================================================*/
  2813. int HLodClass::Get_Num_Snap_Points(void)
  2814. {
  2815. if (SnapPoints) {
  2816. return SnapPoints->Count();
  2817. } else {
  2818. return 0;
  2819. }
  2820. }
  2821. /***********************************************************************************************
  2822. * HLodClass::Get_Snap_Point -- returns specified snap-point *
  2823. * *
  2824. * INPUT: *
  2825. * *
  2826. * OUTPUT: *
  2827. * *
  2828. * WARNINGS: *
  2829. * *
  2830. * HISTORY: *
  2831. * 1/26/00 gth : Created. *
  2832. *=============================================================================================*/
  2833. void HLodClass::Get_Snap_Point(int index,Vector3 * set)
  2834. {
  2835. WWASSERT(set != NULL);
  2836. if (SnapPoints) {
  2837. *set = (*SnapPoints)[index];
  2838. } else {
  2839. set->X = set->Y = set->Z = 0;
  2840. }
  2841. }
  2842. /***********************************************************************************************
  2843. * HLodClass::Update_Sub_Object_Transforms -- updates transforms of all sub-objects *
  2844. * *
  2845. * INPUT: *
  2846. * *
  2847. * OUTPUT: *
  2848. * *
  2849. * WARNINGS: *
  2850. * *
  2851. * HISTORY: *
  2852. * 1/26/00 gth : Created. *
  2853. *=============================================================================================*/
  2854. void HLodClass::Update_Sub_Object_Transforms(void)
  2855. {
  2856. /*
  2857. ** Update the animation transforms, recurse up to the
  2858. ** top of the tree...
  2859. */
  2860. Animatable3DObjClass::Update_Sub_Object_Transforms();
  2861. /*
  2862. ** Put the computed transforms into our sub objects.
  2863. */
  2864. int lod,model;
  2865. for (lod = 0; lod < LodCount; lod++) {
  2866. for (model = 0; model < Lod[lod].Count(); model++) {
  2867. RenderObjClass * robj = Lod[lod][model].Model;
  2868. int bone = Lod[lod][model].BoneIndex;
  2869. robj->Set_Transform(HTree->Get_Transform(bone));
  2870. robj->Set_Animation_Hidden(!HTree->Get_Visibility(bone));
  2871. robj->Update_Sub_Object_Transforms();
  2872. }
  2873. }
  2874. for (model = 0; model < AdditionalModels.Count(); model++) {
  2875. RenderObjClass * robj = AdditionalModels[model].Model;
  2876. int bone = AdditionalModels[model].BoneIndex;
  2877. robj->Set_Transform(HTree->Get_Transform(bone));
  2878. robj->Set_Animation_Hidden(!HTree->Get_Visibility(bone));
  2879. robj->Update_Sub_Object_Transforms();
  2880. }
  2881. Set_Sub_Object_Transforms_Dirty(false);
  2882. }
  2883. /***********************************************************************************************
  2884. * HLodClass::Update_Obj_Space_Bounding_Volumes -- update object-space bounding volumes *
  2885. * *
  2886. * INPUT: *
  2887. * *
  2888. * OUTPUT: *
  2889. * *
  2890. * WARNINGS: *
  2891. * *
  2892. * HISTORY: *
  2893. * 1/26/00 gth : Created. *
  2894. *=============================================================================================*/
  2895. void HLodClass::Update_Obj_Space_Bounding_Volumes(void)
  2896. {
  2897. //
  2898. // Do we still have a valid bounding box index?
  2899. //
  2900. ModelArrayClass &high_lod = Lod[LodCount - 1];
  2901. int count = high_lod.Count ();
  2902. if ( BoundingBoxIndex < 0 ||
  2903. BoundingBoxIndex >= count ||
  2904. high_lod[BoundingBoxIndex].Model->Class_ID () != RenderObjClass::CLASSID_OBBOX)
  2905. {
  2906. BoundingBoxIndex = -1;
  2907. }
  2908. //
  2909. // Attempt to find an OBBox mesh inside the heirarchy
  2910. //
  2911. int index = high_lod.Count ();
  2912. while (index -- && BoundingBoxIndex == -1) {
  2913. RenderObjClass *model = high_lod[index].Model;
  2914. //
  2915. // Is this an OBBox mesh?
  2916. //
  2917. if (model->Class_ID () == RenderObjClass::CLASSID_OBBOX)
  2918. {
  2919. const char *name = model->Get_Name ();
  2920. const char *name_seg = ::strchr (name, '.');
  2921. if (name_seg != NULL) {
  2922. name = name_seg + 1;
  2923. }
  2924. //
  2925. // Does the name match the designator we are looking for?
  2926. //
  2927. if (::stricmp (name, "BOUNDINGBOX") == 0) {
  2928. BoundingBoxIndex = index;
  2929. }
  2930. }
  2931. }
  2932. int i;
  2933. RenderObjClass * robj = NULL;
  2934. // if we don't have any sub objects, just set default bounds
  2935. if (Get_Num_Sub_Objects() <= 0) {
  2936. ObjSphere.Init(Vector3(0,0,0),0);
  2937. ObjBox.Center.Set(0,0,0);
  2938. ObjBox.Extent.Set(0,0,0);
  2939. return;
  2940. }
  2941. // loop through all sub-objects, combining their object-space bounding spheres and boxes.
  2942. // Put our HTree in its base pose at the origin.
  2943. SphereClass sphere;
  2944. AABoxClass obj_aabox;
  2945. MinMaxAABoxClass box;
  2946. HTree->Base_Update(Matrix3D(1));
  2947. robj = Get_Sub_Object(0);
  2948. WWASSERT(robj);
  2949. const Matrix3D & bonetm = HTree->Get_Transform(Get_Sub_Object_Bone_Index(robj));
  2950. robj->Get_Obj_Space_Bounding_Sphere(sphere);
  2951. sphere.Transform(bonetm);
  2952. robj->Get_Obj_Space_Bounding_Box(obj_aabox);
  2953. box.Init(obj_aabox);
  2954. box.Transform(bonetm);
  2955. robj->Release_Ref();
  2956. for (i=1; i<Get_Num_Sub_Objects(); i++) {
  2957. robj = Get_Sub_Object(i);
  2958. WWASSERT(robj);
  2959. const Matrix3D & bonetm = HTree->Get_Transform(Get_Sub_Object_Bone_Index(robj));
  2960. SphereClass tmpsphere;
  2961. robj->Get_Obj_Space_Bounding_Sphere(tmpsphere);
  2962. tmpsphere.Transform(bonetm);
  2963. sphere.Add_Sphere(tmpsphere);
  2964. AABoxClass tmpbox;
  2965. robj->Get_Obj_Space_Bounding_Box(tmpbox);
  2966. tmpbox.Transform(bonetm);
  2967. box.Add_Box(tmpbox);
  2968. robj->Release_Ref();
  2969. }
  2970. ObjSphere = sphere;
  2971. ObjBox = box;
  2972. Invalidate_Cached_Bounding_Volumes();
  2973. Set_Hierarchy_Valid(false);
  2974. // Now update the object space bounding volumes of this object's container:
  2975. RenderObjClass *container = Get_Container();
  2976. if (container) container->Update_Obj_Space_Bounding_Volumes();
  2977. }
  2978. /***********************************************************************************************
  2979. * HLodClass::add_lod_model -- adds a model to one of the lods *
  2980. * *
  2981. * INPUT: *
  2982. * *
  2983. * OUTPUT: *
  2984. * *
  2985. * WARNINGS: *
  2986. * *
  2987. * HISTORY: *
  2988. * 1/26/00 gth : Created. *
  2989. *=============================================================================================*/
  2990. void HLodClass::add_lod_model(int lod,RenderObjClass * robj,int boneindex)
  2991. {
  2992. WWASSERT(robj != NULL);
  2993. ModelNodeClass newnode;
  2994. newnode.Model = robj;
  2995. newnode.Model->Add_Ref();
  2996. newnode.BoneIndex = boneindex;
  2997. newnode.Model->Set_Container(this);
  2998. newnode.Model->Set_Transform(HTree->Get_Transform(boneindex));
  2999. if (Is_In_Scene() && lod == CurLod) {
  3000. newnode.Model->Notify_Added(Scene);
  3001. }
  3002. Lod[lod].Add(newnode);
  3003. }
  3004. /***********************************************************************************************
  3005. * HLodClass::Create_Decal -- create a decal on this HLod *
  3006. * *
  3007. * INPUT: *
  3008. * *
  3009. * OUTPUT: *
  3010. * *
  3011. * WARNINGS: *
  3012. * *
  3013. * HISTORY: *
  3014. * 1/26/00 gth : Created. *
  3015. *=============================================================================================*/
  3016. void HLodClass::Create_Decal(DecalGeneratorClass * generator)
  3017. {
  3018. for (int lod=0; lod<LodCount; lod++) {
  3019. for (int model=0; model<Lod[lod].Count(); model++) {
  3020. Lod[lod][model].Model->Create_Decal(generator);
  3021. }
  3022. }
  3023. for (int model=0; model<AdditionalModels.Count(); model++) {
  3024. AdditionalModels[model].Model->Create_Decal(generator);
  3025. }
  3026. }
  3027. /***********************************************************************************************
  3028. * HLodClass::Delete_Decal -- remove a decal from this HLod *
  3029. * *
  3030. * The decal_id is the ID which was assigned to the DecalGeneratorClass when you created *
  3031. * the decal. *
  3032. * *
  3033. * INPUT: *
  3034. * *
  3035. * OUTPUT: *
  3036. * *
  3037. * WARNINGS: *
  3038. * *
  3039. * HISTORY: *
  3040. * 1/26/00 gth : Created. *
  3041. *=============================================================================================*/
  3042. void HLodClass::Delete_Decal(uint32 decal_id)
  3043. {
  3044. for (int lod=0; lod<LodCount; lod++) {
  3045. for (int model=0; model<Lod[lod].Count(); model++) {
  3046. Lod[lod][model].Model->Delete_Decal(decal_id);
  3047. }
  3048. }
  3049. for (int model=0; model<AdditionalModels.Count(); model++) {
  3050. AdditionalModels[model].Model->Delete_Decal(decal_id);
  3051. }
  3052. }
  3053. /***********************************************************************************************
  3054. * HLodClass::Set_HTree -- replace the hierarchy tree *
  3055. * *
  3056. * INPUT: *
  3057. * *
  3058. * OUTPUT: *
  3059. * *
  3060. * WARNINGS: *
  3061. * *
  3062. * HISTORY: *
  3063. * 1/26/00 gth : Created. *
  3064. *=============================================================================================*/
  3065. void HLodClass::Set_HTree(HTreeClass * htree)
  3066. {
  3067. Animatable3DObjClass::Set_HTree(htree);
  3068. }
  3069. /***********************************************************************************************
  3070. * HLodClass::Set_Hidden -- Propogates the hidden bit to particle emitters. *
  3071. * *
  3072. * INPUT: *
  3073. * *
  3074. * OUTPUT: *
  3075. * *
  3076. * WARNINGS: *
  3077. * *
  3078. * HISTORY: *
  3079. * 3/19/01 pds : Created. *
  3080. *=============================================================================================*/
  3081. void HLodClass::Set_Hidden(int onoff)
  3082. {
  3083. //
  3084. // Loop over all attached models
  3085. //
  3086. int additional_count = AdditionalModels.Count();
  3087. for (int index = 0; index < additional_count; index ++) {
  3088. //
  3089. // Is this a particle emitter?
  3090. //
  3091. RenderObjClass *model = AdditionalModels[index].Model;
  3092. if (model->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
  3093. //
  3094. // Pass the hidden bit onto the emitter
  3095. //
  3096. model->Set_Hidden(onoff);
  3097. }
  3098. }
  3099. Animatable3DObjClass::Set_Hidden(onoff);
  3100. return ;
  3101. }