| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : WW3D *
- * *
- * $Archive:: /VSS_Sync/ww3d2/hlod.cpp $*
- * *
- * Author:: Greg Hjelstrom *
- * *
- * $Modtime:: 8/29/01 7:29p $*
- * *
- * $Revision:: 10 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * HLodLoaderClass::Load_W3D -- Loads an HlodDef from a W3D file *
- * HLodPrototypeClass::Create -- Creates an HLod from an HLodDef *
- * HLodDefClass::HLodDefClass -- Constructor *
- * HLodDefClass::HLodDefClass -- Copy Constructor *
- * HLodDefClass::~HLodDefClass -- Destructor *
- * HLodDefClass::Free -- releases all resources being used *
- * HLodDefClass::Initialize -- init this def from an HLod *
- * HLodDefClass::Save -- save this HLodDef *
- * HLodDefClass::Save_Header -- writes the HLodDef header *
- * HLodDefClass::Save_Lod_Array -- Saves the lod array *
- * HLodDefClass::Save_Aggregate_Array -- Save the array of aggregate models *
- * HLodDefClass::Load_W3D -- Loads this HLodDef from a W3d File *
- * HLodDefClass::read_header -- loads the HLodDef header from a W3d file *
- * HLodDefClass::read_proxy_array -- load the proxy names *
- * HLodDefClass::SubObjectArrayClass::SubObjectArrayClass -- LodArray constructor *
- * HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass -- LodArray destructor *
- * HLodDefClass::SubObjectArrayClass::Save_W3D -- saves a w3d file for this HLodDef *
- * HLodDefClass::SubObjectArrayClass::Load_W3D -- LodArray load function *
- * HLodDefClass::SubObjectArrayClass::Reset -- release the contents of this array *
- * HLodClass::HLodClass -- Constructor *
- * HLodClass::HLodClass -- copy constructor *
- * HLodClass::HLodClass -- Constructor *
- * HLodClass::HLodClass -- Constructs an HLod from an HLodDef *
- * HLodClass::HLodClass -- Constructs an HLod from an HModelDef *
- * HLodClass::operator -- assignment operator *
- * HLodClass::~HLodClass -- Destructor *
- * HLodClass::Free -- releases all resources *
- * HLodClass::Clone -- virtual copy constructor *
- * HLodClass::Set_Max_Screen_Size -- Set max-screen-size for an LOD *
- * HLodClass::Get_Max_Screen_Size -- get max-screen-size for an LOD *
- * HLodClass::Get_Lod_Count -- returns number of levels of detail *
- * HLodClass::Get_Lod_Model_Count -- number of sub-objs in a given level of detail *
- * HLodClass::Peek_Lod_Model -- returns pointer to a model in one of the LODs *
- * HLodClass::Get_Lod_Model -- returns a pointer to a model in one of the LODs *
- * HLodClass::Get_Lod_Model_Bone -- returns the bone index of a model *
- * HLodClass::Get_Additional_Model_Count -- number of additional sub-objs *
- * HLodClass::Peek_Additional_Model -- returns pointer to an additional model *
- * HLodClass::Get_Additional_Model -- returns pointer to an additional model *
- * HLodClass::Get_Additional_Model_Bone -- returns the bone index of an additional model *
- * HLodClass::Is_NULL_Lod_Included -- does this HLod have NULL as its lowest LOD *
- * HLodClass::Include_NULL_Lod -- Add NULL as the lowest LOD *
- * HLodClass::Get_Num_Polys -- returns polycount of the current LOD *
- * HLodClass::Render -- render this HLod *
- * HLodClass::Special_Render -- Special_Render for HLod *
- * HLodClass::Set_Transform -- Sets the transform *
- * HLodClass::Set_Position -- Sets the position *
- * HLodClass::Notify_Added -- callback notifies subobjs that they were added *
- * HLodClass::Notify_Removed -- notifies subobjs that they were removed *
- * HLodClass::Get_Num_Sub_Objects -- returns total number of sub-objects *
- * HLodClass::Get_Sub_Object -- returns a pointer to specified sub-object *
- * HLodClass::Add_Sub_Object -- add a sub-object to this HLod *
- * HLodClass::Remove_Sub_Object -- remove a sub-object from this HLod *
- * HLodClass::Get_Num_Sub_Objects_On_Bone -- returns the number of objects on the given bone *
- * HLodClass::Get_Sub_Object_On_Bone -- returns obj on the given bone *
- * HLodClass::Get_Sub_Object_Bone_Index -- returns bone index of given object *
- * HLodClass::Add_Sub_Object_To_Bone -- adds a sub-object to a bone *
- * HLodClass::Set_Animation -- set animation state to the base-pose *
- * HLodClass::Set_Animation -- set animation state to an animation frame *
- * HLodClass::Set_Animation -- set animation state to a blend of two animations *
- * HLodClass::Set_Animation -- set animation state to a combination of anims *
- * HLodClass::Cast_Ray -- cast a ray against this HLod *
- * HLodClass::Cast_AABox -- Cast a swept AABox against this HLod *
- * HLodClass::Cast_OBBox -- Cast a swept OBBox against this HLod *
- * HLodClass::Intersect_AABox -- Intersect an AABox with this HLod *
- * HLodClass::Intersect_OBBox -- Intersect an OBBox with this HLod *
- * HLodClass::Prepare_LOD -- Prepare for LOD processing *
- * HLodClass::Recalculate_Static_LOD_Factors -- compute lod factors *
- * HLodClass::Increment_LOD -- move to next lod *
- * HLodClass::Decrement_LOD -- move to previous lod *
- * HLodClass::Get_Cost -- returns the cost of this LOD *
- * HLodClass::Get_Value -- returns the value of this LOD *
- * HLodClass::Get_Post_Increment_Value -- returns the post increment value *
- * HLodClass::Set_LOD_Level -- set the current lod level *
- * HLodClass::Get_LOD_Level -- returns the current LOD level *
- * HLodClass::Get_LOD_Count -- returns the number of levels of detail *
- * HLodClass::Calculate_Cost_Value_Arrays -- computes the cost-value arrays *
- * HLodClass::Get_Current_LOD -- returns a render object which represents the current LOD *
- * HLodClass::Set_Texture_Reduction_Factor -- resizeable texture support *
- * HLodClass::Scale -- scale this HLod model *
- * HLodClass::Get_Num_Snap_Points -- returns the number of snap points in this model *
- * HLodClass::Get_Snap_Point -- returns specified snap-point *
- * HLodClass::Update_Sub_Object_Transforms -- updates transforms of all sub-objects *
- * HLodClass::Update_Obj_Space_Bounding_Volumes -- update object-space bounding volumes *
- * HLodClass::add_lod_model -- adds a model to one of the lods *
- * HLodClass::Create_Decal -- create a decal on this HLod *
- * HLodClass::Delete_Decal -- remove a decal from this HLod *
- * HLodClass::Set_HTree -- replace the hierarchy tree *
- * HLodClass::Get_Proxy_Count -- Returns the number of proxy objects *
- * HLodClass::Get_Proxy -- returns the information for the i'th proxy *
- * HLodClass::Set_Hidden -- Propogates the hidden bit to particle emitters. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "hlod.h"
- #include "assetmgr.h"
- #include "hmdldef.h"
- #include "w3derr.h"
- #include "chunkio.h"
- #include "predlod.h"
- #include "rinfo.h"
- #include <string.h>
- #include <win.h>
- #include "sphere.h"
- #include "boxrobj.h"
- /*
- ** Loader Instance
- */
- HLodLoaderClass _HLodLoader;
- /**
- ** ProxyRecordClass
- ** This is a structure that contains the data describing a single "proxy" object. These
- ** are used for application purposes and simply provide a way for the assets to associate
- ** a string with a bone index.
- */
- class ProxyRecordClass
- {
- public:
- ProxyRecordClass(void) : BoneIndex(0)
- {
- memset(Name,0,sizeof(Name));
- }
- bool operator == (const ProxyRecordClass & that) { return false; }
- bool operator != (const ProxyRecordClass & that) { return !(*this == that); }
- void Init(const W3dHLodSubObjectStruct & w3d_data)
- {
- BoneIndex = w3d_data.BoneIndex;
- strncpy(Name,w3d_data.Name,sizeof(Name));
- }
- int Get_Bone_Index(void) { return BoneIndex; }
- const char * Get_Name(void) { return Name; }
- protected:
- int BoneIndex;
- char Name[2*W3D_NAME_LEN];
- };
- /**
- ** ProxyArrayClass
- ** This is a ref-counted list of proxy objects. It is generated whenever an HLODdef contains
- ** proxies. Each instantiated HLOD simply add-refs a pointer to the single list.
- */
- class ProxyArrayClass : public W3DMPO, public VectorClass<ProxyRecordClass>, public RefCountClass
- {
- W3DMPO_GLUE(ProxyArrayClass)
- public:
- ProxyArrayClass(int size) : VectorClass<ProxyRecordClass>(size)
- {
- }
- };
- /*
- ** The HLod Loader Implementation
- */
- /***********************************************************************************************
- * HLodLoaderClass::Load_W3D -- Loads an HlodDef from a W3D file *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- PrototypeClass *HLodLoaderClass::Load_W3D( ChunkLoadClass &cload )
- {
- HLodDefClass * def = W3DNEW HLodDefClass;
- if (def == NULL)
- {
- return NULL;
- }
- if (def->Load_W3D(cload) != WW3D_ERROR_OK) {
- // load failed, delete the model and return an error
- delete def;
- return NULL;
- } else {
- // ok, accept this model!
- HLodPrototypeClass *proto = W3DNEW HLodPrototypeClass(def);
- return proto;
- }
- return NULL;
- }
- /*
- ** HLod Prototype Implementation
- */
- /***********************************************************************************************
- * HLodPrototypeClass::Create -- Creates an HLod from an HLodDef *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodPrototypeClass::Create(void)
- {
- HLodClass * hlod = NEW_REF( HLodClass , ( *Definition ) );
- return hlod;
- }
- /*
- ** HLodDef Implementation
- */
- /***********************************************************************************************
- * HLodDefClass::HLodDefClass -- Constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- HLodDefClass::HLodDefClass(void) :
- Name(NULL),
- HierarchyTreeName(NULL),
- LodCount(0),
- Lod(NULL),
- ProxyArray(NULL)
- {
- }
- /***********************************************************************************************
- * HLodDefClass::HLodDefClass -- Copy Constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodDefClass::HLodDefClass(HLodClass &src_lod) :
- Name(NULL),
- HierarchyTreeName(NULL),
- LodCount(0),
- Lod(NULL),
- ProxyArray(NULL)
- {
- Initialize (src_lod);
- return ;
- }
- /***********************************************************************************************
- * HLodDefClass::~HLodDefClass -- Destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodDefClass::~HLodDefClass(void)
- {
- Free ();
- return ;
- }
- /***********************************************************************************************
- * HLodDefClass::Free -- releases all resources being used *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodDefClass::Free(void)
- {
- if (Name) {
- ::free(Name);
- Name = NULL;
- }
- if (HierarchyTreeName) {
- ::free(HierarchyTreeName);
- HierarchyTreeName = NULL;
- }
- if (Lod) {
- delete[] Lod;
- Lod = NULL;
- }
- LodCount = 0;
- REF_PTR_RELEASE(ProxyArray);
- return ;
- }
- /***********************************************************************************************
- * HLodDefClass::Initialize -- init this def from an HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodDefClass::Initialize(HLodClass &src_lod)
- {
- // Start with a fresh set of data
- Free ();
- // Copy the name and hierarcy name from the source object
- Name = ::strdup (src_lod.Get_Name ());
- const HTreeClass *phtree = src_lod.Get_HTree ();
- if (phtree != NULL) {
- HierarchyTreeName = ::strdup (phtree->Get_Name ());
- }
- // Determine the number of LODs in the src object
- LodCount = src_lod.Get_LOD_Count ();
- WWASSERT (LodCount > 0);
- if (LodCount > 0) {
-
- // Allocate an array large enough to hold all the LODs and
- // loop through each LOD.
- Lod = W3DNEWARRAY SubObjectArrayClass[LodCount];
- for (int index = 0; index < LodCount; index ++) {
- // Fill in the maximum screen size for this LOD
- Lod[index].MaxScreenSize = src_lod.Get_Max_Screen_Size (index);
- Lod[index].ModelCount = src_lod.Get_Lod_Model_Count (index);
-
- // Loop through all the models that compose this LOD and generate a
- // list of model's and the bones they live on
- char **model_names = W3DNEWARRAY char *[Lod[index].ModelCount];
- int *bone_indicies = W3DNEWARRAY int[Lod[index].ModelCount];
- for (int model_index = 0; model_index < Lod[index].ModelCount; model_index ++) {
-
- // Record information about this model (if possible)
- RenderObjClass *prender_obj = src_lod.Peek_Lod_Model (index, model_index);
- if (prender_obj != NULL) {
- model_names[model_index] = ::strdup (prender_obj->Get_Name ());
- bone_indicies[model_index] = src_lod.Get_Lod_Model_Bone (index, model_index);
- } else {
- model_names[model_index] = NULL;
- bone_indicies[model_index] = 0;
- }
- }
- // Pass these arrays of information onto our internal data
- Lod[index].ModelName = model_names;
- Lod[index].BoneIndex = bone_indicies;
- }
- }
-
- return;
- }
- /***********************************************************************************************
- * HLodDefClass::Save -- save this HLodDef *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- WW3DErrorType HLodDefClass::Save(ChunkSaveClass & csave)
- {
- // Assume error
- WW3DErrorType ret_val = WW3D_ERROR_SAVE_FAILED;
- // Begin a chunk that identifies an aggregate
- if (csave.Begin_Chunk (W3D_CHUNK_HLOD) == TRUE) {
-
- // Attempt to save the different sections of the aggregate definition
- if ((Save_Header (csave) == WW3D_ERROR_OK) &&
- (Save_Lod_Array (csave) == WW3D_ERROR_OK)) {
-
- // Success!
- ret_val = WW3D_ERROR_OK;
- }
- // Close the aggregate chunk
- csave.End_Chunk ();
- }
- // Return the WW3DErrorType return code
- return ret_val;
- }
- /***********************************************************************************************
- * HLodDefClass::Save_Header -- writes the HLodDef header *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- WW3DErrorType HLodDefClass::Save_Header(ChunkSaveClass &csave)
- {
- // Assume error
- WW3DErrorType ret_val = WW3D_ERROR_SAVE_FAILED;
- // Begin a chunk that identifies the aggregate
- if (csave.Begin_Chunk (W3D_CHUNK_HLOD_HEADER) == TRUE) {
-
- // Fill the header structure
- W3dHLodHeaderStruct header = { 0 };
- header.Version = W3D_CURRENT_HLOD_VERSION;
- header.LodCount = LodCount;
-
- // Copy the name to the header
- ::lstrcpyn (header.Name, Name, sizeof (header.Name));
- header.Name[sizeof (header.Name) - 1] = 0;
- // Copy the hierarchy tree name to the header
- ::lstrcpyn (header.HierarchyName, HierarchyTreeName, sizeof (header.HierarchyName));
- header.HierarchyName[sizeof (header.HierarchyName) - 1] = 0;
- // Write the header out to the chunk
- if (csave.Write (&header, sizeof (header)) == sizeof (header)) {
- // Success!
- ret_val = WW3D_ERROR_OK;
- }
- // End the header chunk
- csave.End_Chunk ();
- }
- // Return the WW3DErrorType return code
- return ret_val;
- }
- /***********************************************************************************************
- * HLodDefClass::Save_Lod_Array -- Saves the lod array *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- WW3DErrorType HLodDefClass::Save_Lod_Array(ChunkSaveClass &csave)
- {
- // Loop through all the LODs and save their model array to the chunk
- bool success = true;
- for (int lod_index = 0;
- (lod_index < LodCount) && success;
- lod_index ++) {
- success = Lod[lod_index].Save_W3D (csave);
- }
- // Return the WW3DErrorType return code
- return success ? WW3D_ERROR_OK : WW3D_ERROR_SAVE_FAILED;
- }
- /***********************************************************************************************
- * HLodDefClass::Save_Aggregate_Array -- Save the array of aggregate models *
- * *
- * aggregate models are ones that are attached as "additional" models. *
- * *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/25/2000 gth : Created. *
- *=============================================================================================*/
- WW3DErrorType HLodDefClass::Save_Aggregate_Array(ChunkSaveClass & csave)
- {
- if (Aggregates.ModelCount > 0) {
- csave.Begin_Chunk(W3D_CHUNK_HLOD_AGGREGATE_ARRAY);
- Aggregates.Save_W3D(csave);
- csave.End_Chunk();
- }
- return WW3D_ERROR_OK;
- }
- /***********************************************************************************************
- * HLodDefClass::Load_W3D -- Loads this HLodDef from a W3d File *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- WW3DErrorType HLodDefClass::Load_W3D(ChunkLoadClass & cload)
- {
- /*
- ** First make sure we release any memory in use
- */
- Free();
- if (read_header(cload) == FALSE) {
- return WW3D_ERROR_LOAD_FAILED;
- }
- /*
- ** Loop through all the LODs and read the info from its chunk
- */
- for (int iLOD = 0; iLOD < LodCount; iLOD ++) {
- /*
- ** Open the next chunk, it should be a LOD struct
- */
- if (!cload.Open_Chunk()) return WW3D_ERROR_LOAD_FAILED;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_LOD_ARRAY) {
- // ERROR: Expected LOD struct!
- return WW3D_ERROR_LOAD_FAILED;
- }
- Lod[iLOD].Load_W3D(cload);
- // Close-out the chunk
- cload.Close_Chunk();
- }
- /*
- ** Parse the rest of the chunks
- */
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID())
- {
- case W3D_CHUNK_HLOD_AGGREGATE_ARRAY:
- Aggregates.Load_W3D(cload);
- break;
- case W3D_CHUNK_HLOD_PROXY_ARRAY:
- read_proxy_array(cload);
- break;
- }
- cload.Close_Chunk();
- }
-
- return WW3D_ERROR_OK;
- }
- /***********************************************************************************************
- * HLodDefClass::read_header -- loads the HLodDef header from a W3d file *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodDefClass::read_header(ChunkLoadClass & cload)
- {
- /*
- ** Open the first chunk, it should be the LOD header
- */
- if (!cload.Open_Chunk()) return false;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_HEADER) {
- // ERROR: Expected HLOD Header!
- return false;
- }
- W3dHLodHeaderStruct header;
- if (cload.Read(&header,sizeof(header)) != sizeof(header)) {
- return false;
- }
- cload.Close_Chunk();
- // Copy the name into our internal variable
- Name = ::_strdup(header.Name);
- HierarchyTreeName = ::strdup(header.HierarchyName);
- LodCount = header.LodCount;
- Lod = W3DNEWARRAY SubObjectArrayClass[LodCount];
- return true;
- }
- /***********************************************************************************************
- * HLodDefClass::read_proxy_array -- load the proxy names *
- * *
- * This function is coded separately from SubObjectArrayClass::Load because we are going *
- * to store the proxies in a shared data structure. Because all of the proxy data is *
- * constant, each instanced HLOD can just add-ref a pointer to its proxy array. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/27/2000 gth : Created. *
- *=============================================================================================*/
- bool HLodDefClass::read_proxy_array(ChunkLoadClass & cload)
- {
- REF_PTR_RELEASE(ProxyArray);
- /*
- ** Open the first chunk, it should be a Lod Array Header
- */
- if (!cload.Open_Chunk()) return false;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) return false;
- W3dHLodArrayHeaderStruct header;
- if (cload.Read(&header,sizeof(header)) != sizeof(header)) return false;
-
- if (!cload.Close_Chunk()) return false;
- ProxyArray = NEW_REF(ProxyArrayClass,(header.ModelCount));
- /*
- ** Read each sub object definition
- */
- for (int imodel=0; imodel<ProxyArray->Length(); ++imodel) {
- if (!cload.Open_Chunk()) return false;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT) return false;
- W3dHLodSubObjectStruct subobjdef;
- if (cload.Read(&subobjdef,sizeof(subobjdef)) != sizeof(subobjdef)) return false;
- if (!cload.Close_Chunk()) return false;
- (*ProxyArray)[imodel].Init(subobjdef);
- }
- return true;
- }
- /***********************************************************************************************
- * HLodDefClass::SubObjectArrayClass::SubObjectArrayClass -- LodArray constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- HLodDefClass::SubObjectArrayClass::SubObjectArrayClass(void) :
- MaxScreenSize(NO_MAX_SCREEN_SIZE),
- ModelCount(0),
- ModelName(NULL),
- BoneIndex(NULL)
- {
- }
- /***********************************************************************************************
- * HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass -- LodArray destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodDefClass::SubObjectArrayClass::~SubObjectArrayClass(void)
- {
- Reset();
- }
- /***********************************************************************************************
- * HLodDefClass::SubObjectArrayClass::Reset -- release the contents of this array *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/25/2000 gth : Created. *
- *=============================================================================================*/
- void HLodDefClass::SubObjectArrayClass::Reset(void)
- {
- MaxScreenSize = NO_MAX_SCREEN_SIZE;
-
- if (ModelName != NULL) {
- for (int imodel=0; imodel<ModelCount;imodel++) {
- free(ModelName[imodel]);
- }
- delete[] ModelName;
- ModelName = NULL;
- }
- if (BoneIndex != NULL) {
- delete[] BoneIndex;
- BoneIndex = NULL;
- }
- ModelCount = 0;
- }
- /***********************************************************************************************
- * HLodDefClass::SubObjectArrayClass::Load_W3D -- LodArray load function *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodDefClass::SubObjectArrayClass::Load_W3D(ChunkLoadClass & cload)
- {
- /*
- ** Open the first chunk, it should be a Lod Array Header
- */
- if (!cload.Open_Chunk()) return false;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) return false;
-
- W3dHLodArrayHeaderStruct header;
- if (cload.Read(&header,sizeof(header)) != sizeof(header)) return false;
-
- if (!cload.Close_Chunk()) return false;
- ModelCount = header.ModelCount;
- MaxScreenSize = header.MaxScreenSize;
- ModelName = W3DNEWARRAY char * [ModelCount];
- BoneIndex = W3DNEWARRAY int [ModelCount];
- /*
- ** Read each sub object definition
- */
- for (int imodel=0; imodel<ModelCount; ++imodel) {
- if (!cload.Open_Chunk()) return false;
- if (cload.Cur_Chunk_ID() != W3D_CHUNK_HLOD_SUB_OBJECT) return false;
- W3dHLodSubObjectStruct subobjdef;
- if (cload.Read(&subobjdef,sizeof(subobjdef)) != sizeof(subobjdef)) return false;
- if (!cload.Close_Chunk()) return false;
- ModelName[imodel] = strdup(subobjdef.Name);
- BoneIndex[imodel] = subobjdef.BoneIndex;
- }
- return true;
- }
- /***********************************************************************************************
- * HLodDefClass::SubObjectArrayClass::Save_W3D -- saves a w3d file for this HLodDef *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodDefClass::SubObjectArrayClass::Save_W3D(ChunkSaveClass &csave)
- {
- // Assume error
- bool ret_val = false;
- // Begin a chunk that identifies the LOD array
- if (csave.Begin_Chunk (W3D_CHUNK_HLOD_LOD_ARRAY) == TRUE) {
- // Begin a chunk that identifies the LOD header
- if (csave.Begin_Chunk (W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER) == TRUE) {
- W3dHLodArrayHeaderStruct header = { 0 };
- header.ModelCount = ModelCount;
- header.MaxScreenSize = MaxScreenSize;
-
- // Write the LOD header structure out to the chunk
- ret_val = (csave.Write (&header, sizeof (header)) == sizeof (header));
- // End the header chunk
- csave.End_Chunk ();
- }
- if (ret_val) {
- // Write all of this LOD's models to the file
- for (int index = 0;
- (index < ModelCount) && ret_val;
- index ++) {
-
- // Save this LOD sub-obj to the chunk
- ret_val &= (csave.Begin_Chunk (W3D_CHUNK_HLOD_SUB_OBJECT) == TRUE);
- if (ret_val) {
-
- W3dHLodSubObjectStruct info = { 0 };
- info.BoneIndex = BoneIndex[index];
-
- // Copy this model name into the structure
- ::lstrcpyn (info.Name, ModelName[index], sizeof (info.Name));
- info.Name[sizeof (info.Name) - 1] = 0;
- // Write the LOD sub-obj structure out to the chunk
- ret_val &= (csave.Write (&info, sizeof (info)) == sizeof (info));
- // End the sub-obj chunk
- csave.End_Chunk ();
- }
- }
- }
- // End the HLOD-Array chunk
- csave.End_Chunk ();
- }
- // Return the true/false result code
- return ret_val;
- }
- /***********************************************************************************************
- * HLodClass::HLodClass -- Constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- HLodClass::HLodClass(void) :
- Animatable3DObjClass(NULL),
- LodCount(0),
- CurLod(0),
- Lod(NULL),
- BoundingBoxIndex(-1),
- Cost(NULL),
- Value(NULL),
- AdditionalModels(),
- SnapPoints(NULL),
- ProxyArray(NULL),
- LODBias(1.0f)
- {
- }
- /***********************************************************************************************
- * HLodClass::HLodClass -- copy constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass::HLodClass(const HLodClass & src) :
- Animatable3DObjClass(src),
- LodCount(0),
- CurLod(0),
- Lod(NULL),
- BoundingBoxIndex(-1),
- Cost(NULL),
- Value(NULL),
- AdditionalModels(),
- SnapPoints(NULL),
- ProxyArray(NULL),
- LODBias(1.0f)
- {
- *this = src;
- }
- /***********************************************************************************************
- * HLodClass::HLodClass -- Constructor *
- * *
- * Creates an HLodClass from an array of render objects. Each render object is assumed to *
- * be an alternate level of detail. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass::HLodClass(const char * name,RenderObjClass ** lods,int count) :
- Animatable3DObjClass(NULL),
- LodCount(0),
- CurLod(0),
- Lod(NULL),
- BoundingBoxIndex(-1),
- Cost(NULL),
- Value(NULL),
- AdditionalModels(),
- SnapPoints(NULL),
- ProxyArray(NULL),
- LODBias(1.0f)
- {
- // enforce parameters
- WWASSERT(name != NULL);
- WWASSERT(lods != NULL);
- WWASSERT((count > 0) && (count < 256));
-
- // Set the name
- Set_Name(name);
-
- LodCount = count;
- WWASSERT(LodCount >= 1);
- Lod = W3DNEWARRAY ModelArrayClass[LodCount];
- WWASSERT(Lod);
- Cost = W3DNEWARRAY float[LodCount];
- WWASSERT(Cost);
- // Value has LodCount + 1 entries so PostIncrementValue can always use
- // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
- Value = W3DNEWARRAY float[LodCount + 1];
- WWASSERT(Value);
- // Create our HTree from the highest LOD if it is an HModel
- // Otherwise, create a single node tree
- const HTreeClass * tree = lods[count-1]->Get_HTree();
- if (tree != NULL) {
- HTree = W3DNEW HTreeClass(*tree);
- } else {
- HTree = W3DNEW HTreeClass();
- HTree->Init_Default();
- }
- // Ok, now suck the sub-objects out of each LOD model and place them into this HLOD.
- for (int lod_index=0; lod_index < LodCount; lod_index++) {
- RenderObjClass * lod_obj = lods[lod_index];
- WWASSERT(lod_obj);
- if ( (lod_obj->Class_ID() == RenderObjClass::CLASSID_HMODEL) ||
- (lod_obj->Class_ID() == RenderObjClass::CLASSID_HLOD) ||
- (lod_obj->Get_Num_Sub_Objects() > 1) ) {
-
- // here we insert all sub-objects of this render object into the current LOD array
- while (lod_obj->Get_Num_Sub_Objects() > 0) {
- RenderObjClass * sub_obj = lod_obj->Get_Sub_Object(0);
- int boneindex = lod_obj->Get_Sub_Object_Bone_Index(sub_obj);
- lod_obj->Remove_Sub_Object(sub_obj);
-
- add_lod_model(lod_index,sub_obj,boneindex);
- sub_obj->Release_Ref();
- }
-
- } else {
- // just insert the render object as the sole member of the current LOD array. This
- // case happens if this level of detail is a simple object such as a mesh or NullRenderObj
- add_lod_model(lod_index,lod_obj,0);
- }
- }
- Recalculate_Static_LOD_Factors();
- // So that the object is ready for use after construction, we will
- // complete its initialization by initializing its cost and value arrays
- // according to a screen area of 1 pixel.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- // Flag our sub-objects as having dirty transforms
- Set_Sub_Object_Transforms_Dirty(true);
- // Normal render object processing whenever sub-objects are added or removed:
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- }
- /***********************************************************************************************
- * HLodClass::HLodClass -- Constructs an HLod from an HLodDef *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass::HLodClass(const HLodDefClass & def) :
- Animatable3DObjClass(def.HierarchyTreeName),
- LodCount(0),
- CurLod(0),
- Lod(NULL),
- BoundingBoxIndex(-1),
- Cost(NULL),
- Value(NULL),
- AdditionalModels(),
- SnapPoints(NULL),
- ProxyArray(NULL),
- LODBias(1.0f)
- {
- // Set the name
- Set_Name(def.Get_Name());
-
- // Number of LODs comes from the distlod
- LodCount = def.LodCount;
- WWASSERT(LodCount >= 1);
- Lod = W3DNEWARRAY ModelArrayClass[LodCount];
- WWASSERT(Lod);
- Cost = W3DNEWARRAY float[LodCount];
- WWASSERT(Cost);
- // Value has LodCount + 1 entries so PostIncrementValue can always use
- // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
- Value = W3DNEWARRAY float[LodCount + 1];
- WWASSERT(Value);
- // Add Models to the ModelArrays
- for (int ilod=0; ilod < def.LodCount; ilod++) {
-
- Lod[ilod].MaxScreenSize = def.Lod[ilod].MaxScreenSize;
- for (int imodel=0; imodel < def.Lod[ilod].ModelCount; imodel++) {
- RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.Lod[ilod].ModelName[imodel]);
- int boneindex = def.Lod[ilod].BoneIndex[imodel];
- if (robj != NULL) {
- add_lod_model(ilod,robj,boneindex);
- robj->Release_Ref();
- }
- }
- }
- Recalculate_Static_LOD_Factors();
-
- // Add aggregates to this model
- for (int iagg=0; iagg<def.Aggregates.ModelCount; iagg++) {
- RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.Aggregates.ModelName[iagg]);
- int boneindex = def.Aggregates.BoneIndex[iagg];
- if (robj != NULL) {
- Add_Sub_Object_To_Bone(robj,boneindex);
- robj->Release_Ref();
- }
- }
- // Add a reference to the proxy array
- REF_PTR_SET(ProxyArray,def.ProxyArray);
- // So that the object is ready for use after construction, we will
- // complete its initialization by initializing its cost and value arrays
- // according to a screen area of 1 pixel.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- // Flag our sub-objects as having dirty transforms
- Set_Sub_Object_Transforms_Dirty(true);
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- return ;
- }
- /***********************************************************************************************
- * HLodClass::HLodClass -- Constructs an HLod from an HModelDef *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass::HLodClass(const HModelDefClass & def) :
- Animatable3DObjClass(def.BasePoseName),
- LodCount(0),
- CurLod(0),
- Lod(NULL),
- BoundingBoxIndex(-1),
- Cost(NULL),
- Value(NULL),
- AdditionalModels(),
- SnapPoints(NULL),
- ProxyArray(NULL),
- LODBias(1.0f)
- {
- // Set the name
- Set_Name(def.Get_Name());
-
- // This is a "simple" HLod, only one LOD
- LodCount = 1;
- Lod = W3DNEWARRAY ModelArrayClass[1];
- WWASSERT(Lod);
- Cost = W3DNEWARRAY float[1];
- WWASSERT(Cost);
- // Value has LodCount + 1 entries so PostIncrementValue can always use
- // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
- Value = W3DNEWARRAY float[2];
- WWASSERT(Value);
- // no lod size clamping
- Lod[0].MaxScreenSize = NO_MAX_SCREEN_SIZE;
- // create the sub-objects
- int imodel;
- for (imodel=0; imodel < def.SubObjectCount; ++imodel) {
- RenderObjClass * robj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.SubObjects[imodel].RenderObjName);
- if (robj) {
- int boneindex = def.SubObjects[imodel].PivotID;
- add_lod_model(0,robj,boneindex);
- robj->Release_Ref();
- }
- }
- Recalculate_Static_LOD_Factors();
- // So that the object is ready for use after construction, we will
- // complete its initialization by initializing its cost and value arrays
- // according to a screen area of 1 pixel.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- // Flag our sub-objects as having dirty transforms
- Set_Sub_Object_Transforms_Dirty(true);
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- return ;
- }
- /***********************************************************************************************
- * HLodClass::operator -- assignment operator *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass & HLodClass::operator = (const HLodClass & that)
- {
- int lod,model;
- if (this != &that) {
- Free();
- Animatable3DObjClass::operator = (that);
- BoundingBoxIndex = that.BoundingBoxIndex;
- LodCount = that.LodCount;
- WWASSERT(LodCount >= 1);
- Lod = W3DNEWARRAY ModelArrayClass[LodCount];
- WWASSERT(Lod != NULL);
- Cost = W3DNEWARRAY float[LodCount];
- WWASSERT(Cost);
- // Value has LodCount + 1 entries so PostIncrementValue can always use
- // Value[CurLod + 1] (the last entry wil be AT_MAX_LOD).
- Value = W3DNEWARRAY float[LodCount + 1];
- WWASSERT(Value);
-
- for (lod=0; lod<LodCount;lod++) {
- Lod[lod].Resize(that.Lod[lod].Count());
- Lod[lod].MaxScreenSize = that.Lod[lod].MaxScreenSize;
- for (model = 0; model < that.Lod[lod].Count(); model++) {
-
- ModelNodeClass newnode;
- newnode.Model = that.Lod[lod][model].Model->Clone();
- newnode.BoneIndex = that.Lod[lod][model].BoneIndex;
- newnode.Model->Set_Container(this);
- if (Is_In_Scene()) {
- newnode.Model->Notify_Added(Scene);
- }
- Lod[lod].Add(newnode);
- }
- }
- AdditionalModels.Resize(that.AdditionalModels.Count());
- for (model = 0; model < that.AdditionalModels.Count(); model++) {
- ModelNodeClass newnode;
- newnode.Model = that.AdditionalModels[model].Model->Clone();
- newnode.BoneIndex = that.AdditionalModels[model].BoneIndex;
- newnode.Model->Set_Container(this);
- if (Is_In_Scene()) {
- newnode.Model->Notify_Added(Scene);
- }
- AdditionalModels.Add(newnode);
- }
- LODBias = that.LODBias;
- }
- Recalculate_Static_LOD_Factors();
- // So that the object is ready for use after construction, we will
- // complete its initialization by initializing its cost and value arrays
- // according to a screen area of 1 pixel.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- // Flag our sub-objects as having dirty transforms
- Set_Sub_Object_Transforms_Dirty(true);
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- return *this;
- }
- /***********************************************************************************************
- * HLodClass::~HLodClass -- Destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- HLodClass::~HLodClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * HLodClass::Free -- releases all resources *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Free(void)
- {
- int lod,model;
- for (lod = 0; lod < LodCount; lod++) {
- for (model = 0; model < Lod[lod].Count(); model++) {
- RenderObjClass * robj = Lod[lod][model].Model;
- Lod[lod][model].Model = NULL;
-
- WWASSERT(robj);
- robj->Set_Container(NULL);
- robj->Release_Ref();
-
- }
- Lod[lod].Delete_All();
- }
- if (Lod != NULL) {
- delete[] Lod;
- Lod = NULL;
- }
- LodCount = 0;
- if (Cost != NULL) {
- delete[] Cost;
- Cost = NULL;
- }
- if (Value != NULL) {
- delete[] Value;
- Value = NULL;
- }
- for (model = 0; model < AdditionalModels.Count(); model++) {
- RenderObjClass * robj = AdditionalModels[model].Model;
- AdditionalModels[model].Model = NULL;
- WWASSERT(robj);
- robj->Set_Container(NULL);
- robj->Release_Ref();
- }
- AdditionalModels.Delete_All();
- REF_PTR_RELEASE(SnapPoints);
- REF_PTR_RELEASE(ProxyArray);
- }
- /***********************************************************************************************
- * HLodClass::Clone -- virtual copy constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Clone(void) const
- {
- return W3DNEW HLodClass(*this);
- }
- /***********************************************************************************************
- * HLodClass::Get_Obj_Space_Bounding_Box -- Return the bounding box mesh if we have one. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/13/00 pds : Created. *
- *=============================================================================================*/
- void HLodClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
- {
- //
- // Do we have a bounding box mesh?
- //
- int count = Lod[LodCount - 1].Count ();
- if (BoundingBoxIndex >= 0 && BoundingBoxIndex < count) {
-
- RenderObjClass *mesh = Lod[LodCount - 1][BoundingBoxIndex].Model;
- if (mesh != NULL && mesh->Class_ID () == RenderObjClass::CLASSID_OBBOX) {
-
- OBBoxRenderObjClass *obbox_mesh = (OBBoxRenderObjClass *)mesh;
-
- //
- // Determine what the box's transform 'should' be this frame.
- // Note: We do this because some animation types don't update
- // unless they are visible.
- //
- Matrix3D box_tm;
- Simple_Evaluate_Bone (Lod[LodCount - 1][BoundingBoxIndex].BoneIndex, &box_tm);
- //
- // Convert the OBBox from its coordinate system to the coordinate
- // system of the HLOD.
- //
- Matrix3D world_to_hlod_tm;
- Matrix3D box_to_hlod_tm;
- Get_Transform ().Get_Orthogonal_Inverse (world_to_hlod_tm);
- Matrix3D::Multiply(world_to_hlod_tm,box_tm,&box_to_hlod_tm);
- box_to_hlod_tm.Transform_Center_Extent_AABox( obbox_mesh->Get_Local_Center(),
- obbox_mesh->Get_Local_Extent(),
- &box.Center,&box.Extent);
- }
- } else {
- Animatable3DObjClass::Get_Obj_Space_Bounding_Box (box);
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_Obj_Space_Bounding_Sphere -- Use the bounding box mesh to calculate a sphere.*
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/13/00 pds : Created. *
- *=============================================================================================*/
- void HLodClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
- {
- AABoxClass box;
- Get_Obj_Space_Bounding_Box(box);
- sphere.Center = box.Center;
- sphere.Radius = box.Extent.Length();
- }
- /***********************************************************************************************
- * HLodClass::Get_Obj_Space_Bounding_Sphere -- Use the bounding box mesh to calculate a sphere.*
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/13/00 pds : Created. *
- *=============================================================================================*/
- const SphereClass &HLodClass::Get_Bounding_Sphere(void) const
- {
- if (BoundingBoxIndex >= 0) {
- //
- // Get the bounding sphere in local coordinates
- //
- SphereClass sphere;
- Get_Obj_Space_Bounding_Sphere (sphere);
-
- //
- // Transform the sphere into world coords and return the sphere
- //
- #ifdef ALLOW_TEMPORARIES
- CachedBoundingSphere.Center = Get_Transform () * sphere.Center;
- #else
- Get_Transform().mulVector3(sphere.Center, CachedBoundingSphere.Center);
- #endif
- CachedBoundingSphere.Radius = sphere.Radius;
- } else {
- Animatable3DObjClass::Get_Bounding_Sphere ();
- }
- return CachedBoundingSphere;
- }
- /***********************************************************************************************
- * HLodClass::Get_Obj_Space_Bounding_Box -- Return the bounding box mesh if we have one. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/13/00 pds : Created. *
- *=============================================================================================*/
- const AABoxClass &HLodClass::Get_Bounding_Box(void) const
- {
- if (BoundingBoxIndex >= 0) {
- //
- // Get the bounding box in local coordinates
- //
- AABoxClass box;
- Get_Obj_Space_Bounding_Box (box);
-
- //
- // Transform the bounding box to world coordinates
- //
- Get_Transform().Transform_Center_Extent_AABox( box.Center,
- box.Extent,
- &CachedBoundingBox.Center,
- &CachedBoundingBox.Extent );
- } else {
- Animatable3DObjClass::Get_Bounding_Box ();
- }
- return CachedBoundingBox;
- }
- /***********************************************************************************************
- * HLodClass::Set_Max_Screen_Size -- Set max-screen-size for an LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Max_Screen_Size(int lod_index, float size)
- {
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) && (lod_index < LodCount)) {
- // Set the new screen size for this LOD
- Lod[lod_index].MaxScreenSize = size;
- Recalculate_Static_LOD_Factors();
- // So that the object is ready for use after construction, we will
- // complete its initialization by initializing its cost and value arrays
- // according to a screen area of 1 pixel.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- }
-
- return ;
- }
- /***********************************************************************************************
- * HLodClass::Get_Max_Screen_Size -- get max-screen-size for an LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- float HLodClass::Get_Max_Screen_Size(int lod_index) const
- {
- float size = NO_MAX_SCREEN_SIZE;
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) && (lod_index < LodCount)) {
- // Get the screen size for this LOD
- size = Lod[lod_index].MaxScreenSize;
- }
-
- // Return the LOD's screen size to the caller
- return size;
- }
- /***********************************************************************************************
- * HLodClass::Get_Lod_Count -- returns number of levels of detail *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Lod_Count(void) const
- {
- return LodCount;
- }
- /***********************************************************************************************
- * HLodClass::Set_LOD_Bias -- sets LOD bias *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/08/00 nh : Created. *
- *=============================================================================================*/
- void HLodClass::Set_LOD_Bias(float bias)
- {
- assert(bias > 0.0f);
- bias = MAX(bias, 0.0f);
- LODBias = bias;
- int additional_count = AdditionalModels.Count();
- for (int i = 0; i < additional_count; i++) {
- AdditionalModels[i].Model->Set_LOD_Bias(bias);
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_Lod_Model_Count -- number of sub-objs in a given level of detail *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Lod_Model_Count(int lod_index) const
- {
- int count = 0;
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) && (lod_index < LodCount)) {
- // Get the number of models in this Lod
- count = Lod[lod_index].Count ();
- }
-
- // Return the number of models that compose this Lod
- return count;
- }
- /***********************************************************************************************
- * HLodClass::Peek_Lod_Model -- returns pointer to a model in one of the LODs *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass *HLodClass::Peek_Lod_Model(int lod_index, int model_index) const
- {
- RenderObjClass *pmodel = NULL;
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) &&
- (lod_index < LodCount) &&
- (model_index < Lod[lod_index].Count ())) {
- // Get a pointer to the requested model
- pmodel = Lod[lod_index][model_index].Model;
- }
-
- // Return a pointer to the requested model
- return pmodel;
- }
- /***********************************************************************************************
- * HLodClass::Get_Lod_Model -- returns a pointer to a model in one of the LODs *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass *HLodClass::Get_Lod_Model(int lod_index, int model_index) const
- {
- RenderObjClass *pmodel = NULL;
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) &&
- (lod_index < LodCount) &&
- (model_index < Lod[lod_index].Count ())) {
- // Get a pointer to the requested model
- pmodel = Lod[lod_index][model_index].Model;
- if (pmodel != NULL) {
- pmodel->Add_Ref ();
- }
- }
-
- // Return the number of models that compose this Lod
- return pmodel;
- }
- /***********************************************************************************************
- * HLodClass::Get_Lod_Model_Bone -- returns the bone index of a model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Lod_Model_Bone(int lod_index, int model_index) const
- {
- int bone_index = 0;
- // Params valid?
- WWASSERT(lod_index >= 0);
- WWASSERT(lod_index < LodCount);
- if ((lod_index >= 0) &&
- (lod_index < LodCount) &&
- (model_index < Lod[lod_index].Count ())) {
- // Get the bone that this model resides on
- bone_index = Lod[lod_index][model_index].BoneIndex;
- }
-
- // Return the bone that this model resides on
- return bone_index;
- }
- /***********************************************************************************************
- * HLodClass::Get_Additional_Model_Count -- number of additional sub-objs *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 8/23/00 NH : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Additional_Model_Count(void) const
- {
- return AdditionalModels.Count();
- }
- /***********************************************************************************************
- * HLodClass::Peek_Additional_Model -- returns pointer to an additional model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 8/23/00 NH : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Peek_Additional_Model (int model_index) const
- {
- RenderObjClass *pmodel = NULL;
- // Param valid?
- WWASSERT(model_index >= 0);
- WWASSERT(model_index < AdditionalModels.Count());
- if ((model_index >= 0) &&
- (model_index < AdditionalModels.Count())) {
- // Get a pointer to the requested model
- pmodel = AdditionalModels[model_index].Model;
- }
-
- // Return a pointer to the requested model
- return pmodel;
- }
- /***********************************************************************************************
- * HLodClass::Get_Additional_Model -- returns pointer to an additional model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 8/23/00 NH : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Get_Additional_Model (int model_index) const
- {
- RenderObjClass *pmodel = NULL;
- // Param valid?
- WWASSERT(model_index >= 0);
- WWASSERT(model_index < AdditionalModels.Count());
- if ((model_index >= 0) &&
- (model_index < AdditionalModels.Count())) {
- // Get a pointer to the requested model
- pmodel = AdditionalModels[model_index].Model;
- if (pmodel != NULL) {
- pmodel->Add_Ref ();
- }
- }
-
- // Return a pointer to the requested model
- return pmodel;
- }
- /***********************************************************************************************
- * HLodClass::Get_Additional_Model_Bone -- returns the bone index of an additional model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 8/23/00 NH : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Additional_Model_Bone (int model_index) const
- {
- int bone_index = 0;
- // Params valid?
- WWASSERT(model_index >= 0);
- WWASSERT(model_index < AdditionalModels.Count());
- if ((model_index >= 0) &&
- (model_index < AdditionalModels.Count())) {
- // Get the bone that this model resides on
- bone_index = AdditionalModels[model_index].BoneIndex;
- }
-
- // Return the bone that this model resides on
- return bone_index;
- }
- /***********************************************************************************************
- * HLodClass::Is_NULL_Lod_Included -- does this HLod have NULL as its lowest LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Is_NULL_Lod_Included(void) const
- {
- bool included = false;
- // Determine if the lowest-level LOD is the null render object or not...
- if ((LodCount > 0) && (Lod[0][0].Model != NULL)) {
- included = (Lod[0][0].Model->Class_ID () == RenderObjClass::CLASSID_NULL);
- }
-
- // Return the true/false result code
- return included;
- }
- /***********************************************************************************************
- * HLodClass::Include_NULL_Lod -- Add NULL as the lowest LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Include_NULL_Lod(bool include)
- {
- if ((include == false) && Is_NULL_Lod_Included ()) {
- // Free the 'NULL' object's stored information
- int index = 0;
- for (int model = 0; model < Lod[index].Count (); model++) {
- RenderObjClass * robj = Lod[index][model].Model;
- Lod[index][model].Model = NULL;
-
- WWASSERT(robj);
- robj->Set_Container (NULL);
- robj->Release_Ref ();
- }
- // Resize the lod array
- LodCount -= 1;
- Lod[index].Delete_All ();
- ModelArrayClass *temp_lods = W3DNEWARRAY ModelArrayClass[LodCount];
- for (index = 0; index < LodCount; index ++) {
- temp_lods[index] = Lod[index + 1];
- }
- // Now resize the value and cost arrays
- float *temp_cost = W3DNEWARRAY float[LodCount];
- float *temp_value = W3DNEWARRAY float[LodCount + 1];
- ::memcpy (temp_cost, &Cost[1], sizeof (float) * LodCount);
- ::memcpy (temp_value, &Value[1], sizeof (float) * (LodCount + 1));
- delete [] Lod;
- delete [] Value;
- delete [] Cost;
- Lod = temp_lods;
- Value = temp_value;
- Cost = temp_cost;
- CurLod = (CurLod >= LodCount) ? (LodCount - 1) : CurLod;
-
- } else if (include && (Is_NULL_Lod_Included () == false)) {
- // Tag the NULL render object onto the end
- RenderObjClass *null_object = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("NULL");
- WWASSERT (null_object != NULL);
- if (null_object != NULL) {
- // Resize the lod array
- ModelArrayClass *temp_lods = W3DNEWARRAY ModelArrayClass[LodCount + 1];
- for (int index = 0; index < LodCount; index ++) {
- temp_lods[index + 1] = Lod[index];
- }
- // Now resize the value and cost arrays
- float *temp_cost = W3DNEWARRAY float[LodCount + 1];
- float *temp_value = W3DNEWARRAY float[LodCount + 2];
- ::memcpy (&temp_cost[1], Cost, sizeof (float) * LodCount);
- ::memcpy (&temp_value[1], Value, sizeof (float) * (LodCount + 1));
- delete [] Lod;
- delete [] Value;
- delete [] Cost;
- Lod = temp_lods;
- Value = temp_value;
- Cost = temp_cost;
- LodCount ++;
- // Add this NULL object to the start of the lod list
- add_lod_model (0, null_object, 0);
- null_object->Release_Ref ();
- }
- }
- // recalculate cost/value arrays and ensure the current LOD is still valid.
- int minlod = Calculate_Cost_Value_Arrays(1.0f, Value, Cost);
- // Ensure lod is no less than minimum allowed
- if (CurLod < minlod) Set_LOD_Level(minlod);
- return ;
- }
- /***********************************************************************************************
- * HLodClass::Get_Proxy_Count -- Returns the number of proxy records *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/27/2000 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Proxy_Count(void) const
- {
- if (ProxyArray != NULL) {
- return ProxyArray->Length();
- } else {
- return 0;
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_Proxy -- returns the information for the i'th proxy *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/27/2000 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Get_Proxy (int index, ProxyClass &proxy) const
- {
- bool retval = false;
- if (ProxyArray != NULL) {
-
- //
- // Lookup the proxy's transform
- //
- HTree->Base_Update(Get_Transform());
- Matrix3D transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index());
- Set_Hierarchy_Valid(false);
-
- //
- // Pass the data onto the proxy object
- //
- proxy.Set_Transform(transform);
- proxy.Set_Name((*ProxyArray)[index].Get_Name());
- retval = true;
- } else {
- proxy.Set_Name ("");
- proxy.Set_Transform (Matrix3D (1));
- }
- return retval;
- }
- /***********************************************************************************************
- * HLodClass::Get_Num_Polys -- returns polycount of the current LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Num_Polys(void) const
- {
- int polycount = 0;
- int i;
- int model_count = Lod[CurLod].Count();
- for (i = 0; i < model_count; i++) {
- if (Lod[CurLod][i].Model->Is_Not_Hidden_At_All()) {
- polycount += Lod[CurLod][i].Model->Get_Num_Polys();
- }
- }
- int additional_count = AdditionalModels.Count();
- for (i = 0; i < additional_count; i++) {
- if (AdditionalModels[i].Model->Is_Not_Hidden_At_All()) {
- polycount += AdditionalModels[i].Model->Get_Num_Polys();
- }
- }
- return polycount;
- }
- /***********************************************************************************************
- * HLodClass::Render -- render this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Render(RenderInfoClass & rinfo)
- {
- int i;
- if (Is_Not_Hidden_At_All() == false) {
- return;
- }
- Animatable3DObjClass::Render(rinfo);
- for (i = 0; i < Lod[CurLod].Count(); i++) {
- if (Lod[CurLod][i].Model->Class_ID() != CLASSID_OBBOX) ///We have no use for these - MW
- Lod[CurLod][i].Model->Render(rinfo);
- }
- if (Is_Sub_Objects_Match_LOD_Enabled()) {
- for (i = 0; i < AdditionalModels.Count(); i++) {
- AdditionalModels[i].Model->Set_LOD_Level(Get_LOD_Level());
- AdditionalModels[i].Model->Render(rinfo);
- }
- } else {
- for (i = 0; i < AdditionalModels.Count(); i++) {
- AdditionalModels[i].Model->Render(rinfo);
- }
- }
- }
- /***********************************************************************************************
- * HLodClass::Special_Render -- Special_Render for HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Special_Render(SpecialRenderInfoClass & rinfo)
- {
- int i;
- if (Is_Not_Hidden_At_All() == false) {
- return;
- }
- Animatable3DObjClass::Special_Render(rinfo);
- int lod_index = CurLod;
- if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_SHADOW) { // (gth) HACK HACK! yikes
- lod_index = LodCount-1;
- }
- for (i = 0; i < Lod[lod_index].Count(); i++) {
- Lod[lod_index][i].Model->Special_Render(rinfo);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- AdditionalModels[i].Model->Special_Render(rinfo);
- }
- }
- /***********************************************************************************************
- * HLodClass::Set_Transform -- Sets the transform *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Transform(const Matrix3D &m)
- {
- Animatable3DObjClass::Set_Transform(m);
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Set_Position -- Sets the position *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Position(const Vector3 &v)
- {
- Animatable3DObjClass::Set_Position(v);
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Notify_Added -- callback notifies subobjs that they were added *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Notify_Added(SceneClass * scene)
- {
- RenderObjClass::Notify_Added(scene);
- int i;
- int model_count = Lod[CurLod].Count();
- for (i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Added(scene);
- }
- int additional_count = AdditionalModels.Count();
- for (i = 0; i < additional_count; i++) {
- AdditionalModels[i].Model->Notify_Added(scene);
- }
- }
- /***********************************************************************************************
- * HLodClass::Notify_Removed -- notifies subobjs that they were removed *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Notify_Removed(SceneClass * scene)
- {
- int i;
- int model_count = Lod[CurLod].Count();
- for (i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Removed(scene);
- }
- int additional_count = AdditionalModels.Count();
- for (i = 0; i < additional_count; i++) {
- AdditionalModels[i].Model->Notify_Removed(scene);
- }
- RenderObjClass::Notify_Removed(scene);
- }
- /***********************************************************************************************
- * HLodClass::Get_Num_Sub_Objects -- returns total number of sub-objects *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Num_Sub_Objects(void) const
- {
- int count = 0;
- for (int lod=0; lod<LodCount;lod++) {
- count += Lod[lod].Count();
- }
- count += AdditionalModels.Count();
- return count;
- }
- /***********************************************************************************************
- * HLodClass::Get_Sub_Object -- returns a pointer to specified sub-object *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Get_Sub_Object(int index) const
- {
- WWASSERT(index >= 0);
- for (int lod=0; lod<LodCount; lod++) {
- if (index < Lod[lod].Count()) {
- Lod[lod][index].Model->Add_Ref();
- return Lod[lod][index].Model;
- }
- index -= Lod[lod].Count();
- }
- WWASSERT(index < AdditionalModels.Count());
- AdditionalModels[index].Model->Add_Ref();
- return AdditionalModels[index].Model;
- }
- /***********************************************************************************************
- * HLodClass::Add_Sub_Object -- add a sub-object to this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Add_Sub_Object(RenderObjClass * subobj)
- {
- return Add_Sub_Object_To_Bone(subobj,0);
- }
- /***********************************************************************************************
- * HLodClass::Remove_Sub_Object -- remove a sub-object from this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Remove_Sub_Object(RenderObjClass * removeme)
- {
- // no object given?
- if (removeme == NULL) {
- return 0;
- }
- // find the sub-object
- bool found = false;
- bool iscurrent = false;
- for (int lod = 0; (lod < LodCount) && (!found); lod++) {
- for (int model = 0; (model < Lod[lod].Count()) && (!found); model++) {
- if (Lod[lod][model].Model == removeme) {
- // remove the model from the array.
- Lod[lod].Delete(model);
- // record that we found it
- found = true;
- if (lod == CurLod) {
- iscurrent = true;
- }
- }
- }
- }
- for (int model = 0; (model < AdditionalModels.Count()) && (!found); model++) {
- if (AdditionalModels[model].Model == removeme) {
- AdditionalModels.Delete(model);
- found = true;
- iscurrent = true;
- }
- }
-
- if (found) {
- // clear the object's container pointer
- removeme->Set_Container(NULL);
- // let him know in case he is removed from the scene as a result of this
- // this is the combination of this HLod being in the scene and and this model
- // either being in the current LOD or being in the additional model list...
- if (iscurrent && Is_In_Scene()) {
- removeme->Notify_Removed(Scene);
- }
- // release our reference to this render object
- // object may delete itself here...
- removeme->Release_Ref();
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * HLodClass::Get_Num_Sub_Objects_On_Bone -- returns the number of objects on the given bone *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Num_Sub_Objects_On_Bone(int boneindex) const
- {
- int count = 0;
- for (int lod = 0; lod < LodCount; lod++) {
- for (int model = 0; model < Lod[lod].Count(); model++) {
- if (Lod[lod][model].BoneIndex == boneindex) count++;
- }
- }
- for (int model = 0; model < AdditionalModels.Count(); model++) {
- if (AdditionalModels[model].BoneIndex == boneindex) count++;
- }
- return count;
- }
- /***********************************************************************************************
- * HLodClass::Get_Sub_Object_On_Bone -- returns obj on the given bone *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Get_Sub_Object_On_Bone(int index,int boneindex) const
- {
- int count = 0;
- for (int lod = 0; lod < LodCount; lod++) {
- for (int model = 0; model < Lod[lod].Count(); model++) {
- if (Lod[lod][model].BoneIndex == boneindex) {
- if (count == index) {
- Lod[lod][model].Model->Add_Ref();
- return Lod[lod][model].Model;
- }
- count++;
- }
- }
- }
- for (int model = 0; model < AdditionalModels.Count(); model++) {
- if (AdditionalModels[model].BoneIndex == boneindex) {
- if (count == index) {
- AdditionalModels[model].Model->Add_Ref();
- return AdditionalModels[model].Model;
- }
- count++;
- }
- }
- return NULL;
- }
- /***********************************************************************************************
- * HLodClass::Get_Sub_Object_Bone_Index -- returns bone index of given object *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Sub_Object_Bone_Index(RenderObjClass * subobj) const
- {
- for (int lod = 0; lod < LodCount; lod++) {
- for (int model = 0; model < Lod[lod].Count(); model++) {
- if (Lod[lod][model].Model == subobj) {
- return Lod[lod][model].BoneIndex;
- }
- }
- }
- for (int model = 0; model < AdditionalModels.Count(); model++) {
- if (AdditionalModels[model].Model == subobj) {
- return AdditionalModels[model].BoneIndex;
- }
- }
- return 0;
- }
- //Custom version of above function for cases where we know the lod/model index. -MW
- int HLodClass::Get_Sub_Object_Bone_Index(int LodIndex, int ModelIndex) const
- {
- return Lod[LodIndex][ModelIndex].BoneIndex;
- }
- /***********************************************************************************************
- * HLodClass::Add_Sub_Object_To_Bone -- adds a sub-object to a bone *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Add_Sub_Object_To_Bone(RenderObjClass * subobj,int boneindex)
- {
- WWASSERT(subobj);
- if ((boneindex < 0) || (boneindex >= HTree->Num_Pivots())) return 0;
- subobj->Set_LOD_Bias(LODBias);
-
- ModelNodeClass newnode;
- newnode.Model = subobj;
- newnode.Model->Add_Ref();
- newnode.Model->Set_Container(this);
- newnode.Model->Set_Animation_Hidden(HTree->Get_Visibility (boneindex) == false);
- newnode.BoneIndex = boneindex;
- int result = AdditionalModels.Add(newnode);
- Update_Sub_Object_Bits();
- Update_Obj_Space_Bounding_Volumes();
- Set_Hierarchy_Valid (false);
- Set_Sub_Object_Transforms_Dirty(true);
- if (Is_In_Scene()) {
- subobj->Notify_Added(Scene);
- }
-
- return result;
- }
- /***********************************************************************************************
- * HLodClass::Set_Animation -- set animation state to the base-pose *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Animation(void)
- {
- Animatable3DObjClass::Set_Animation();
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Set_Animation -- set animation state to an animation frame *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Animation(HAnimClass * motion,float frame,int mode)
- {
- Animatable3DObjClass::Set_Animation(motion,frame,mode);
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Set_Animation -- set animation state to a blend of two animations *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Animation
- (
- HAnimClass * motion0,
- float frame0,
- HAnimClass * motion1,
- float frame1,
- float percentage
- )
- {
- Animatable3DObjClass::Set_Animation(motion0,frame0,motion1,frame1,percentage);
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Set_Animation -- set animation state to a combination of anims *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Animation(HAnimComboClass * anim_combo)
- {
- Animatable3DObjClass::Set_Animation(anim_combo);
- Set_Sub_Object_Transforms_Dirty(true);
- }
- /***********************************************************************************************
- * HLodClass::Cast_Ray -- cast a ray against this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Cast_Ray(RayCollisionTestClass & raytest)
- {
- if (Are_Sub_Object_Transforms_Dirty ()) {
- Update_Sub_Object_Transforms ();
- }
- bool res = false;
- int i;
- // collide against the top LOD
- int top = LodCount-1;
- for (i = 0; i < Lod[top].Count(); i++) {
- res |= Lod[top][i].Model->Cast_Ray(raytest);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- res |= AdditionalModels[i].Model->Cast_Ray(raytest);
- }
- return res;
- }
- /***********************************************************************************************
- * HLodClass::Cast_AABox -- Cast a swept AABox against this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Cast_AABox(AABoxCollisionTestClass & boxtest)
- {
- if (Are_Sub_Object_Transforms_Dirty ()) {
- Update_Sub_Object_Transforms ();
- }
- bool res = false;
- int i;
- // collide against the top LOD
- int top = LodCount-1;
- for (i = 0; i < Lod[top].Count(); i++) {
- res |= Lod[top][i].Model->Cast_AABox(boxtest);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- res |= AdditionalModels[i].Model->Cast_AABox(boxtest);
- }
- return res;
- }
- /***********************************************************************************************
- * HLodClass::Cast_OBBox -- Cast a swept OBBox against this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Cast_OBBox(OBBoxCollisionTestClass & boxtest)
- {
- if (Are_Sub_Object_Transforms_Dirty ()) {
- Update_Sub_Object_Transforms ();
- }
-
- bool res = false;
- int i;
- // collide against the top LOD
- int top = LodCount-1;
- for (i = 0; i < Lod[top].Count(); i++) {
- res |= Lod[top][i].Model->Cast_OBBox(boxtest);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- res |= AdditionalModels[i].Model->Cast_OBBox(boxtest);
- }
- return res;
- }
- /***********************************************************************************************
- * HLodClass::Intersect_AABox -- Intersect an AABox with this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Intersect_AABox(AABoxIntersectionTestClass & boxtest)
- {
- if (Are_Sub_Object_Transforms_Dirty ()) {
- Update_Sub_Object_Transforms ();
- }
- bool res = false;
- int i;
- // collide against the top LOD
- int top = LodCount-1;
- for (i = 0; i < Lod[top].Count(); i++) {
- res |= Lod[top][i].Model->Intersect_AABox(boxtest);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- res |= AdditionalModels[i].Model->Intersect_AABox(boxtest);
- }
- return res;
- }
- /***********************************************************************************************
- * HLodClass::Intersect_OBBox -- Intersect an OBBox with this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- bool HLodClass::Intersect_OBBox(OBBoxIntersectionTestClass & boxtest)
- {
- if (Are_Sub_Object_Transforms_Dirty ()) {
- Update_Sub_Object_Transforms ();
- }
- bool res = false;
- int i;
- // collide against the top LOD
- int top = LodCount-1;
- for (i = 0; i < Lod[top].Count(); i++) {
- res |= Lod[top][i].Model->Intersect_OBBox(boxtest);
- }
- for (i = 0; i < AdditionalModels.Count(); i++) {
- res |= AdditionalModels[i].Model->Intersect_OBBox(boxtest);
- }
- return res;
- }
- /***********************************************************************************************
- * HLodClass::Prepare_LOD -- Prepare for LOD processing *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Prepare_LOD(CameraClass &camera)
- {
- if (Is_Not_Hidden_At_All() == false) {
- return;
- }
- // Find the maximum screen dimension of the object in pixels
- float norm_area = Get_Screen_Size(camera);
- /*
- ** Set texture reduction factor for the (non-additional) subobjects:
- */
- // Texture reduction system broken, don't call!
- // Set_Texture_Reduction_Factor(Calculate_Texture_Reduction_Factor(norm_area));
- // Prepare LOD processing if this object has more than one LOD:
- if (LodCount > 1) {
- /*
- ** Prepare cost and value arrays (and ensure current LOD doesn't violate clamping):
- */
- int minlod = Calculate_Cost_Value_Arrays(norm_area, Value, Cost);
- if (CurLod < minlod) Set_LOD_Level(minlod);
- /*
- ** Add myself to the LOD optimizer:
- */
- PredictiveLODOptimizerClass::Add_Object(this);
- } else {
- // Not added to optimizer, need to add cost
- PredictiveLODOptimizerClass::Add_Cost(Get_Cost());
- }
- /*
- ** Recursively call for the additional objects:
- */
- int additional_count = AdditionalModels.Count();
- for (int i = 0; i < additional_count; i++) {
- if (AdditionalModels[i].Model->Is_Not_Hidden_At_All()) {
- AdditionalModels[i].Model->Prepare_LOD(camera);
- }
- }
- }
- /***********************************************************************************************
- * HLodClass::Recalculate_Static_LOD_Factors -- compute lod factors *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Recalculate_Static_LOD_Factors(void)
- {
- /*
- ** Calculate NonPixelCost, PixelCostPerArea, BenefitFactor for all LOD
- ** levels.
- ** NOTE: for now we are using vastly simplified Cost and Benefit metrics.
- ** (these will be improved after initial experimentation).
- ** the Cost metric is simply the number of polygons, and the Benefit
- ** Metric is 1 - 0.5 / #polygons^2.
- */
- for (int i = 0; i < LodCount; i++) {
- // Currently there are no pixel-related costs taken into account
- Lod[i].PixelCostPerArea = 0.0f;
- // Sum polycount over all non-hidden models in array
- int model_count = Lod[i].Count();
- int polycount = 0;
- for (int j = 0; j < model_count; j++) {
- if (Lod[i][j].Model->Is_Not_Hidden_At_All()) {
- polycount += Lod[i][j].Model->Get_Num_Polys();
- }
- }
- // If polycount is zero set Cost to a small nonzero amount to avoid divisions by zero.
- Lod[i].NonPixelCost = (polycount != 0)? polycount : 0.000001f;
- // A polycount of zero yields a benefit factor of zero: otherwise apply formula.
- Lod[i].BenefitFactor = (polycount != 0) ? (1 - (0.5f / (polycount * polycount))) : 0.0f;
- }
- }
- /***********************************************************************************************
- * HLodClass::Increment_LOD -- move to next lod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Increment_LOD(void)
- {
- if (CurLod >= (LodCount-1)) return;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Removed(Scene);
- }
- }
- CurLod++;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Added(Scene);
- }
- }
- }
- /***********************************************************************************************
- * HLodClass::Decrement_LOD -- move to previous lod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Decrement_LOD(void)
- {
- if (CurLod < 1) return;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Removed(Scene);
- }
- }
- CurLod--;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Added(Scene);
- }
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_Cost -- returns the cost of this LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- float HLodClass::Get_Cost(void) const
- {
- return(Cost[CurLod]);
- }
- /***********************************************************************************************
- * HLodClass::Get_Value -- returns the value of this LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- float HLodClass::Get_Value(void) const
- {
- return(Value[CurLod]);
- }
- /***********************************************************************************************
- * HLodClass::Get_Post_Increment_Value -- returns the post increment value *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- float HLodClass::Get_Post_Increment_Value(void) const
- {
- return(Value[CurLod + 1]);
- }
- /***********************************************************************************************
- * HLodClass::Set_LOD_Level -- set the current lod level *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_LOD_Level(int lod)
- {
- lod = MAX(0, lod);
- lod = MIN(lod, (LodCount - 1));
- if (lod == CurLod) return;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Removed(Scene);
- }
- }
- CurLod = lod;
- if (Is_In_Scene()) {
- int model_count = Lod[CurLod].Count();
- for (int i = 0; i < model_count; i++) {
- Lod[CurLod][i].Model->Notify_Added(Scene);
- }
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_LOD_Level -- returns the current LOD level *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_LOD_Level(void) const
- {
- return CurLod;
- }
- /***********************************************************************************************
- * HLodClass::Get_LOD_Count -- returns the number of levels of detail *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_LOD_Count(void) const
- {
- return LodCount;
- }
- /***********************************************************************************************
- * HLodClass::Calculate_Cost_Value_Arrays -- computes the cost-value arrays *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Calculate_Cost_Value_Arrays(float screen_area, float *values, float *costs) const
- {
- int lod = 0;
- // Calculate Cost heuristic for each LOD based on normalized screen area:
- for (lod = 0; lod < LodCount; lod++) {
- costs[lod] = Lod[lod].NonPixelCost + Lod[lod].PixelCostPerArea * screen_area;
- }
- // Calculate Value heuristic. First, all LOD levels for which
- // MaxScreenSize is smaller than screen_area have their Value set to
- // AT_MIN_LOD, as well as the first LOD after that (unless there are no
- // other LODs):
- for (lod = 0; lod < LodCount && Lod[lod].MaxScreenSize < screen_area; lod++) {
- values[lod] = AT_MIN_LOD;
- }
- if (lod >= LodCount) {
- lod = LodCount - 1;
- } else {
- values[lod] = AT_MIN_LOD;
- }
- // Now lod is the lowest allowed - return this value.
- int minlod = lod;
- // Calculate Value heuristic for any remaining LODs based on normalized screen area:
- lod++;
- for (; lod < LodCount; lod++) {
- values[lod] = (Lod[lod].BenefitFactor * screen_area * LODBias) / costs[lod];
- }
- values[LodCount] = AT_MAX_LOD; // Post-inc value will flag max LOD.
- return minlod;
- }
- /***********************************************************************************************
- * HLodClass::Get_Current_LOD -- returns a render object which represents the current LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- RenderObjClass * HLodClass::Get_Current_LOD(void)
- {
- int count = Get_Lod_Model_Count(CurLod);
- if(!count)
- return 0;
- return Get_Lod_Model(CurLod, 0);
- }
- /***********************************************************************************************
- * HLodClass::Set_Texture_Reduction_Factor -- resizeable texture support *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- /*
- void HLodClass::Set_Texture_Reduction_Factor(float trf)
- {
- WWASSERT(0); // don't call to tex reduction system, it's broken!
- // We don't touch the additional subobjects: they will get Prepare_LOD
- // called on them individually which is where texture reduction will be
- // set also.
- for (int lod = 0; lod < LodCount; lod++) {
- int model_count = Lod[lod].Count();
- for (int model_id = 0; model_id < model_count; model_id++) {
- Lod[lod][model_id].Model->Set_Texture_Reduction_Factor(trf);
- }
- }
- }
- */
- /***********************************************************************************************
- * HLodClass::Scale -- scale this HLod model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Scale(float scale)
- {
- if (scale==1.0f) return;
- int lod;
- int model;
- //. Scale all subobjects.
- for (lod = 0; lod < LodCount; lod++) {
- for (model = 0; model < Lod[lod].Count(); model++) {
- Lod[lod][model].Model->Scale(scale);
- }
- }
-
- for (model = 0; model < AdditionalModels.Count(); model++) {
- AdditionalModels[model].Model->Scale(scale);
- }
- // Scale HTree:
- HTree->Scale(scale);
- // Invalidate hierarchy
- Set_Hierarchy_Valid(false);
- // Now update the object space bounding volumes of this object's container:
- RenderObjClass *container = Get_Container();
- if (container) container->Update_Obj_Space_Bounding_Volumes();
- }
- /***********************************************************************************************
- * HLodClass::Get_Num_Snap_Points -- returns the number of snap points in this model *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- int HLodClass::Get_Num_Snap_Points(void)
- {
- if (SnapPoints) {
- return SnapPoints->Count();
- } else {
- return 0;
- }
- }
- /***********************************************************************************************
- * HLodClass::Get_Snap_Point -- returns specified snap-point *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Get_Snap_Point(int index,Vector3 * set)
- {
- WWASSERT(set != NULL);
- if (SnapPoints) {
- *set = (*SnapPoints)[index];
- } else {
- set->X = set->Y = set->Z = 0;
- }
- }
- /***********************************************************************************************
- * HLodClass::Update_Sub_Object_Transforms -- updates transforms of all sub-objects *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Update_Sub_Object_Transforms(void)
- {
- /*
- ** Update the animation transforms, recurse up to the
- ** top of the tree...
- */
- Animatable3DObjClass::Update_Sub_Object_Transforms();
- /*
- ** Put the computed transforms into our sub objects.
- */
- int lod,model;
-
- for (lod = 0; lod < LodCount; lod++) {
- for (model = 0; model < Lod[lod].Count(); model++) {
- RenderObjClass * robj = Lod[lod][model].Model;
- int bone = Lod[lod][model].BoneIndex;
- robj->Set_Transform(HTree->Get_Transform(bone));
- robj->Set_Animation_Hidden(!HTree->Get_Visibility(bone));
- robj->Update_Sub_Object_Transforms();
- }
- }
- for (model = 0; model < AdditionalModels.Count(); model++) {
- RenderObjClass * robj = AdditionalModels[model].Model;
- int bone = AdditionalModels[model].BoneIndex;
- robj->Set_Transform(HTree->Get_Transform(bone));
- robj->Set_Animation_Hidden(!HTree->Get_Visibility(bone));
- robj->Update_Sub_Object_Transforms();
- }
- Set_Sub_Object_Transforms_Dirty(false);
- }
- /***********************************************************************************************
- * HLodClass::Update_Obj_Space_Bounding_Volumes -- update object-space bounding volumes *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Update_Obj_Space_Bounding_Volumes(void)
- {
- //
- // Do we still have a valid bounding box index?
- //
- ModelArrayClass &high_lod = Lod[LodCount - 1];
- int count = high_lod.Count ();
- if ( BoundingBoxIndex < 0 ||
- BoundingBoxIndex >= count ||
- high_lod[BoundingBoxIndex].Model->Class_ID () != RenderObjClass::CLASSID_OBBOX)
- {
- BoundingBoxIndex = -1;
- }
- //
- // Attempt to find an OBBox mesh inside the heirarchy
- //
- int index = high_lod.Count ();
- while (index -- && BoundingBoxIndex == -1) {
- RenderObjClass *model = high_lod[index].Model;
-
- //
- // Is this an OBBox mesh?
- //
- if (model->Class_ID () == RenderObjClass::CLASSID_OBBOX)
- {
- const char *name = model->Get_Name ();
- const char *name_seg = ::strchr (name, '.');
- if (name_seg != NULL) {
- name = name_seg + 1;
- }
- //
- // Does the name match the designator we are looking for?
- //
- if (::stricmp (name, "BOUNDINGBOX") == 0) {
- BoundingBoxIndex = index;
- }
- }
- }
- int i;
- RenderObjClass * robj = NULL;
- // if we don't have any sub objects, just set default bounds
- if (Get_Num_Sub_Objects() <= 0) {
- ObjSphere.Init(Vector3(0,0,0),0);
- ObjBox.Center.Set(0,0,0);
- ObjBox.Extent.Set(0,0,0);
- return;
- }
- // loop through all sub-objects, combining their object-space bounding spheres and boxes.
- // Put our HTree in its base pose at the origin.
- SphereClass sphere;
- AABoxClass obj_aabox;
- MinMaxAABoxClass box;
- HTree->Base_Update(Matrix3D(1));
-
- robj = Get_Sub_Object(0);
- WWASSERT(robj);
-
- const Matrix3D & bonetm = HTree->Get_Transform(Get_Sub_Object_Bone_Index(robj));
- robj->Get_Obj_Space_Bounding_Sphere(sphere);
- sphere.Transform(bonetm);
- robj->Get_Obj_Space_Bounding_Box(obj_aabox);
-
- box.Init(obj_aabox);
- box.Transform(bonetm);
- robj->Release_Ref();
- for (i=1; i<Get_Num_Sub_Objects(); i++) {
- robj = Get_Sub_Object(i);
- WWASSERT(robj);
-
- const Matrix3D & bonetm = HTree->Get_Transform(Get_Sub_Object_Bone_Index(robj));
-
- SphereClass tmpsphere;
- robj->Get_Obj_Space_Bounding_Sphere(tmpsphere);
- tmpsphere.Transform(bonetm);
- sphere.Add_Sphere(tmpsphere);
- AABoxClass tmpbox;
- robj->Get_Obj_Space_Bounding_Box(tmpbox);
- tmpbox.Transform(bonetm);
- box.Add_Box(tmpbox);
- robj->Release_Ref();
- }
- ObjSphere = sphere;
- ObjBox = box;
- Invalidate_Cached_Bounding_Volumes();
- Set_Hierarchy_Valid(false);
- // Now update the object space bounding volumes of this object's container:
- RenderObjClass *container = Get_Container();
- if (container) container->Update_Obj_Space_Bounding_Volumes();
- }
- /***********************************************************************************************
- * HLodClass::add_lod_model -- adds a model to one of the lods *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::add_lod_model(int lod,RenderObjClass * robj,int boneindex)
- {
- WWASSERT(robj != NULL);
- ModelNodeClass newnode;
- newnode.Model = robj;
- newnode.Model->Add_Ref();
- newnode.BoneIndex = boneindex;
- newnode.Model->Set_Container(this);
- newnode.Model->Set_Transform(HTree->Get_Transform(boneindex));
- if (Is_In_Scene() && lod == CurLod) {
- newnode.Model->Notify_Added(Scene);
- }
- Lod[lod].Add(newnode);
- }
- /***********************************************************************************************
- * HLodClass::Create_Decal -- create a decal on this HLod *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Create_Decal(DecalGeneratorClass * generator)
- {
- for (int lod=0; lod<LodCount; lod++) {
- for (int model=0; model<Lod[lod].Count(); model++) {
- Lod[lod][model].Model->Create_Decal(generator);
- }
- }
- for (int model=0; model<AdditionalModels.Count(); model++) {
- AdditionalModels[model].Model->Create_Decal(generator);
- }
- }
- /***********************************************************************************************
- * HLodClass::Delete_Decal -- remove a decal from this HLod *
- * *
- * The decal_id is the ID which was assigned to the DecalGeneratorClass when you created *
- * the decal. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Delete_Decal(uint32 decal_id)
- {
- for (int lod=0; lod<LodCount; lod++) {
- for (int model=0; model<Lod[lod].Count(); model++) {
- Lod[lod][model].Model->Delete_Decal(decal_id);
- }
- }
- for (int model=0; model<AdditionalModels.Count(); model++) {
- AdditionalModels[model].Model->Delete_Decal(decal_id);
- }
- }
- /***********************************************************************************************
- * HLodClass::Set_HTree -- replace the hierarchy tree *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/26/00 gth : Created. *
- *=============================================================================================*/
- void HLodClass::Set_HTree(HTreeClass * htree)
- {
- Animatable3DObjClass::Set_HTree(htree);
- }
- /***********************************************************************************************
- * HLodClass::Set_Hidden -- Propogates the hidden bit to particle emitters. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/19/01 pds : Created. *
- *=============================================================================================*/
- void HLodClass::Set_Hidden(int onoff)
- {
- //
- // Loop over all attached models
- //
- int additional_count = AdditionalModels.Count();
- for (int index = 0; index < additional_count; index ++) {
-
- //
- // Is this a particle emitter?
- //
- RenderObjClass *model = AdditionalModels[index].Model;
- if (model->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
-
- //
- // Pass the hidden bit onto the emitter
- //
- model->Set_Hidden(onoff);
- }
- }
- Animatable3DObjClass::Set_Hidden(onoff);
- return ;
- }
|