| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634 |
- /*
- ** Command & Conquer Renegade(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 VectorClass<ProxyRecordClass>, public RefCountClass
- {
- 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 = new 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 = new 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 = new 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 = new char *[Lod[index].ModelCount];
- int *bone_indicies = new 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 = new 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 = new char * [ModelCount];
- BoneIndex = new 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 = new ModelArrayClass[LodCount];
- WWASSERT(Lod);
- Cost = new 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 = new 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 = new HTreeClass(*tree);
- } else {
- HTree = new 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 = new ModelArrayClass[LodCount];
- WWASSERT(Lod);
- Cost = new 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 = new 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 = new ModelArrayClass[1];
- WWASSERT(Lod);
- Cost = new 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 = new 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 = new ModelArrayClass[LodCount];
- WWASSERT(Lod != NULL);
- Cost = new 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 = new 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 new 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
- //
- CachedBoundingSphere.Center = Get_Transform () * sphere.Center;
- 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 = new ModelArrayClass[LodCount];
- for (index = 0; index < LodCount; index ++) {
- temp_lods[index] = Lod[index + 1];
- }
- // Now resize the value and cost arrays
- float *temp_cost = new float[LodCount];
- float *temp_value = new 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 = new 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 = new float[LodCount + 1];
- float *temp_value = new 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++) {
- 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;
- }
- /***********************************************************************************************
- * 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 ;
- }
|