hlod.cpp 174 KB

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