| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411 |
- /*
- ** 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/>.
- */
- /* $Header: /Commando/Code/ww3d2/rendobj.cpp 21 1/07/03 3:51p Bhayes $ */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando / G 3D Engine *
- * *
- * $Archive:: /Commando/Code/ww3d2/rendobj.cpp $*
- * *
- * Author:: Greg_h *
- * *
- * $Modtime:: 1/07/03 3:06p $*
- * *
- * $Revision:: 21 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * RenderObjClass::RenderObjClass -- constructor *
- * RenderObjClass::RenderObjClass -- copy constructor *
- * RenderObjClass::operator == -- assignment operator *
- * RenderObjClass::Calculate_Texture_Reduction_Factor -- calculate texture reduction factor *
- * RenderObjClass::Set_Texture_Reduction_Factor -- set texture reduction factor. *
- * RenderObjClass::Get_Screen_Size -- get normalized area of object. *
- * RenderObjClass::Get_Scene -- returns the (add_ref'd) scene pointer *
- * RenderObjClass::Set_Container -- sets the container pointer *
- * RenderObjClass::Get_Container -- returns the container pointer *
- * RenderObjClass::Set_Transform -- set the transform for this object *
- * RenderObjClass::Set_Position -- Sets the position of this object *
- * RenderObjClass::Get_Transform -- returns the transform for the object *
- * RenderObjClass::Get_Position -- returns the position of this render object *
- * RenderObjClass::Validate_Transform -- If the transform is dirty, this causes it to be re- *
- * RenderObjClass::Get_Sub_Object -- returns pointer to first sub-obj with given name *
- * RenderObjClass::Add_Sub_Object_To_Bone -- add an object to a named bone *
- * RenderObjClass::Prepare_LOD -- prepare object for predictive and texture LOD processing. *
- * RenderObjClass::Get_Cost -- get object rendering cost for predictive LOD processing. *
- * RenderObjClass::Update_Sub_Object_Bits -- updates our bits according to our sub-objects *
- * RenderObjClass::Update_Sub_Object_Transforms -- re-evaluate the transforms my sub-objects *
- * RenderObjClass::Add -- Generic add for render objects *
- * RenderObjClass::Remove -- Generic Remove for Render Objects *
- * RenderObjClass::Notify_Added -- notifies the object that it is in a scene *
- * RenderObjClass::Notify_Removed -- notifies an object that it has been removed *
- * RenderObjClass::Update_Cached_Bounding_Volumes -- default collision sphere. *
- * RenderObjClass::Get_Obj_Space_Bounding_Sphere -- default collision sphere. *
- * RenderObjClass::Get_Obj_Space_Bounding_Box -- default collision box. *
- * RenderObjClass::Intersect - Returns true if specified intersection object *
- * RenderObjClass::Intersect_Sphere -- tests for intersection with the bounding sphere *
- * RenderObjClass::Intersect_Sphere_Quick -- tests for intersection with the bounding sphere *
- * RenderObjClass::Build_Dependency_List -- Generates a list of files this obj depends on. *
- * RenderObjClass::Build_Texture_List -- Builds a list of texture files this obj depends on. *
- * RenderObjClass::Add_Dependencies_To_List -- Add dependent files to the list. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "rendobj.h"
- #include "assetmgr.h"
- #include "_mono.h"
- #include "bsurface.h"
- #include "pot.h"
- #include "scene.h"
- #include "colmath.h"
- #include "coltest.h"
- #include "inttest.h"
- #include "wwdebug.h"
- #include "matinfo.h"
- #include "htree.h"
- #include "predlod.h"
- #include "camera.h"
- #include "ww3d.h"
- #include "chunkio.h"
- #include "persistfactory.h"
- #include "saveload.h"
- #include "ww3dids.h"
- #include "intersec.h"
- // Definitions of static members:
- const float RenderObjClass::AT_MIN_LOD = FLT_MAX;
- const float RenderObjClass::AT_MAX_LOD = -1.0f;
- // Local inline functions
- StringClass
- Filename_From_Asset_Name (const char *asset_name)
- {
- StringClass filename;
- if (asset_name != NULL) {
-
- //
- // Copy the model name into a new filename buffer
- //
- ::lstrcpy (filename.Get_Buffer (::lstrlen (asset_name) + 5), asset_name);
-
- //
- // Do we need to strip off the model's suffix?
- //
- char *suffix = ::strchr (filename, '.');
- if (suffix != NULL) {
- suffix[0] = 0;
- }
- //
- // Concat the w3d file extension
- //
- filename += ".w3d";
- }
- return filename;
- }
- static inline bool Check_Is_Transform_Identity(const Matrix3D& m)
- {
- const float zero=0.0f;
- const float one=1.0f;
- unsigned d=
- ((unsigned&)m[0][0]^(unsigned&)one) |
- ((unsigned&)m[0][1]^(unsigned&)zero) |
- ((unsigned&)m[0][2]^(unsigned&)zero) |
- ((unsigned&)m[0][3]^(unsigned&)zero) |
- ((unsigned&)m[1][0]^(unsigned&)zero) |
- ((unsigned&)m[1][1]^(unsigned&)one) |
- ((unsigned&)m[1][2]^(unsigned&)zero) |
- ((unsigned&)m[1][3]^(unsigned&)zero) |
- ((unsigned&)m[2][0]^(unsigned&)zero) |
- ((unsigned&)m[2][1]^(unsigned&)zero) |
- ((unsigned&)m[2][2]^(unsigned&)one) |
- ((unsigned&)m[2][3]^(unsigned&)zero);
- return !d;
- }
- /***********************************************************************************************
- * RenderObjClass::RenderObjClass -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/04/1997 GH : Created. *
- *=============================================================================================*/
- RenderObjClass::RenderObjClass(void) :
- Bits(DEFAULT_BITS),
- Transform(1),
- NativeScreenSize(WW3D::Get_Default_Native_Screen_Size()),
- Scene(NULL),
- Container(NULL),
- User_Data(NULL),
- CachedBoundingSphere(Vector3(0,0,0),1.0f),
- CachedBoundingBox(Vector3(0,0,0),Vector3(1,1,1)),
- IsTransformIdentity(false)
- {
- }
- /***********************************************************************************************
- * RenderObjClass::RenderObjClass -- copy constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/5/97 GTH : Created. *
- * 1/28/98 EHC : Created. *
- *=============================================================================================*/
- RenderObjClass::RenderObjClass(const RenderObjClass & src) :
- Bits(src.Bits),
- Transform(src.Transform),
- NativeScreenSize(src.NativeScreenSize),
- Scene(NULL),
- Container(NULL),
- User_Data(NULL),
- CachedBoundingSphere(src.CachedBoundingSphere),
- CachedBoundingBox(src.CachedBoundingBox),
- IsTransformIdentity(src.IsTransformIdentity)
- {
- // Even though we're copying an object which might be in a scene
- // this copy won't be so I'm clearing the scene pointer, same logic
- // follows for things like the Container pointer.
- }
- /***********************************************************************************************
- * RenderObjClass -- assignment operator *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/5/97 GTH : Created. *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- RenderObjClass & RenderObjClass::operator = (const RenderObjClass & that)
- {
- // don't do anything if we're assigning this to this
- if (this != &that) {
- Set_Hidden(that.Is_Hidden());
- Set_Animation_Hidden(that.Is_Animation_Hidden());
- Set_Force_Visible(that.Is_Force_Visible());
- Set_Collision_Type(that.Get_Collision_Type());
- Set_Native_Screen_Size(that.Get_Native_Screen_Size());
- IsTransformIdentity=false;
- }
- return *this;
- }
-
- /***********************************************************************************************
- * RenderObjClass::Calculate_Texture_Reduction_Factor -- calculate texture reduction factor. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 04/08/99 NH : Created. *
- *=============================================================================================*/
- /*
- float RenderObjClass::Calculate_Texture_Reduction_Factor(float norm_screensize)
- {
- // NOTE: The texture reduction factor represents the number of powers of two that the texture
- // must be reduced by in both dimensions. The reason that such an inherently integral quantity
- // is represented as a float is for the texture reduction algorithms to incorporate hysteresis
- // properly.
- float reduction = sqrt(Get_Native_Screen_Size() / norm_screensize);
- reduction = MAX(1.0f, reduction);
- // We want to calculate the log base 2. Since the standard libraries have no log-base-2
- // function, we use the following: log-base-2(x) = log(x)/log(2) where log is the natural
- // logarithm (which does exist in the stadard libraries).
- // We precalculare 1/log(2) as 1.442695f.
- return log(reduction) * 1.442695f;
- }
- */
- /***********************************************************************************************
- * RenderObjClass::Set_Texture_Reduction_Factor -- set texture reduction factor. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 04/08/99 NH : Created. *
- *=============================================================================================*/
- /*
- void RenderObjClass::Set_Texture_Reduction_Factor(float trf)
- {
- WWASSERT(0); // Texture reduction system is broken! Don't call!
- MaterialInfoClass *minfo = Get_Material_Info();
- if (minfo) {
- minfo->Set_Texture_Reduction_Factor(trf);
- minfo->Release_Ref();
- } else {
- int num_obj = Get_Num_Sub_Objects();
- RenderObjClass *sub_obj;
- for (int i = 0; i < num_obj; i++) {
- sub_obj = Get_Sub_Object(i);
- if (sub_obj) {
- sub_obj->Set_Texture_Reduction_Factor(trf);
- sub_obj->Release_Ref();
- }
- }
- }
- }
- */
- /***********************************************************************************************
- * RenderObjClass::Get_Screen_Size -- get normalized area of object. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/12/99 NH : Created. *
- *=============================================================================================*/
- float RenderObjClass::Get_Screen_Size(CameraClass &camera)
- {
- // Currently this works by projecting the bounding sphere to the screen
- // (as if the object was at the center) - in future this may be made more
- // accurate (perhaps by using the object-space bounding-box)
- Vector3 cam = camera.Get_Position();
- ViewportClass viewport = camera.Get_Viewport();
- Vector2 vpr_min, vpr_max;
- camera.Get_View_Plane(vpr_min, vpr_max);
- float width_factor = viewport.Width() / (vpr_max.X - vpr_min.X);
- float height_factor = viewport.Height() / (vpr_max.Y - vpr_min.Y);
- const SphereClass & sphere = Get_Bounding_Sphere();
- float dist = (sphere.Center - cam).Length();
- float radius = 0.0f;
- if (dist) {
- radius = sphere.Radius / dist;
- }
- // Return area in normalized units.
- return WWMATH_PI * radius * radius * width_factor * height_factor;
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Scene -- returns the (add_ref'd) scene pointer *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/4/99 GTH : Created. *
- *=============================================================================================*/
- SceneClass * RenderObjClass::Get_Scene(void)
- {
- if (Scene != NULL) {
- Scene->Add_Ref();
- }
- return Scene;
- }
- /***********************************************************************************************
- * RenderObjClass::Set_Container -- sets the container pointer *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/4/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Set_Container(RenderObjClass * con)
- {
- // Either we arent currently in a container or we are clearing our container, otherwise
- // Houston, there is a problem!
- WWASSERT((con == NULL) || (Container == NULL));
- Container = con;
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Container -- returns the container pointer *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/4/99 GTH : Created. *
- *=============================================================================================*/
- RenderObjClass * RenderObjClass::Get_Container(void) const
- {
- return Container;
- }
- /***********************************************************************************************
- * RenderObjClass::Set_Transform -- set the transform for this object *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Set_Transform(const Matrix3D &m)
- {
- Transform = m;
- IsTransformIdentity=Check_Is_Transform_Identity(m);
- Invalidate_Cached_Bounding_Volumes();
- }
- /***********************************************************************************************
- * RenderObjClass::Set_Position -- Sets the position of this object *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- * 07/14/2001 SKB : Add Check_Is_Transform_Identity *
- *=============================================================================================*/
- void RenderObjClass::Set_Position(const Vector3 &v)
- {
- Transform.Set_Translation(v);
- IsTransformIdentity=Check_Is_Transform_Identity(Transform);
- Invalidate_Cached_Bounding_Volumes();
- }
- /***********************************************************************************************
- * RenderObjClass::Validate_Transform -- If the transform is dirty, this causes it to be re-ca *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 6/15/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Validate_Transform(void) const
- {
- /*
- ** Recurse up the tree to see if any of my parents are saying that their sub-object
- ** transforms are dirty
- */
- RenderObjClass * con = Get_Container();
- bool dirty=false;
- if (con != NULL) {
- dirty = con->Are_Sub_Object_Transforms_Dirty();
- while (con->Get_Container() != NULL) {
- dirty |= con->Are_Sub_Object_Transforms_Dirty();
- con = con->Get_Container();
- }
- /*
- ** If the transforms are dirty, update them
- */
- if (dirty) {
- con->Update_Sub_Object_Transforms();
- }
- }
- if (dirty) IsTransformIdentity=Check_Is_Transform_Identity(Transform);
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Position -- returns the position of this render object *
- * *
- * Similar to Get_Transform but returns only the position. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- Vector3 RenderObjClass::Get_Position(void) const
- {
- Validate_Transform();
- return Transform.Get_Translation();
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Sub_Object -- returns pointer to first sub-obj with given name *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/4/99 GTH : Created. *
- *=============================================================================================*/
- RenderObjClass * RenderObjClass::Get_Sub_Object_By_Name(const char * name) const
- {
- int i;
- // first try the un-altered name
- for (i=0; i<Get_Num_Sub_Objects(); i++) {
- RenderObjClass * robj = Get_Sub_Object(i);
- if (robj) {
- if (stricmp(robj->Get_Name(),name) == 0) {
- return robj;
- } else {
- robj->Release_Ref();
- }
- }
- }
- // check the given name against the "suffix" names of each sub-object
- for (i=0; i<Get_Num_Sub_Objects(); i++) {
- RenderObjClass * robj = Get_Sub_Object(i);
- if (robj) {
- const char * subobjname = strchr(robj->Get_Name(),'.');
- if (subobjname == NULL) {
- subobjname = robj->Get_Name();
- } else {
- // skip past the period.
- subobjname = subobjname+1;
- }
- if (stricmp(subobjname,name) == 0) {
- return robj;
- } else {
- robj->Release_Ref();
- }
- }
- }
- return NULL;
- }
- /***********************************************************************************************
- * RenderObjClass::Add_Sub_Object_To_Bone -- add an object to a named bone *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: If the bone name is unknown then this function will add the the object to the *
- * root transform rather than failing. This is due to the fact that GetBoneIndex *
- * returns the root tranform for unknown bones. *
- * *
- * HISTORY: *
- * 3/4/99 GTH : Created. *
- *=============================================================================================*/
- int RenderObjClass::Add_Sub_Object_To_Bone(RenderObjClass * subobj,const char * bname)
- {
- int bindex = Get_Bone_Index(bname);
- return Add_Sub_Object_To_Bone(subobj,bindex);
- }
- /***********************************************************************************************
- * RenderObjClass::Remove_Sub_Objects_From_Bone -- remove all objects from a named bone *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/4/99 NH : Created. *
- *=============================================================================================*/
- int RenderObjClass::Remove_Sub_Objects_From_Bone(const char * bname)
- {
- int boneidx = Get_Bone_Index(bname);
- int count = Get_Num_Sub_Objects_On_Bone(boneidx);
- int remove_count = 0;
- for (int i = count-1; i >= 0; i--) {
- RenderObjClass *robj = Get_Sub_Object_On_Bone(i, boneidx);
- if ( robj ) {
- remove_count += Remove_Sub_Object(robj);
- robj->Release_Ref();
- }
- }
- return remove_count;
- }
- /***********************************************************************************************
- * RenderObjClass::Prepare_LOD -- prepare object for predictive and texture LOD processing. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * HISTORY: *
- * 3/11/99 NH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Prepare_LOD(CameraClass &camera)
- {
- // Since most RenderObjClass derivatives are not LOD-capable, the default
- // implementation just sets the texture reduction factor and doesn't do any
- // predictive LOD preparation (except for adding the objects' cost to the
- // total static (nonoptimizeable) cost).
- // Find the maximum screen dimension of the object in pixels
- // float norm_area = Get_Screen_Size(camera);
- // Find and set texture reduction factor
- // Jani: Don't set tex reduction, it's broken!
- // Set_Texture_Reduction_Factor(Calculate_Texture_Reduction_Factor(norm_area));
- // Since we are not adding this object to the predictive LOD optimizer,
- // at least add its cost in.
- PredictiveLODOptimizerClass::Add_Cost(Get_Cost());
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Cost -- get object rendering cost for predictive LOD processing. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * HISTORY: *
- * 3/11/99 NH : Created. *
- *=============================================================================================*/
- float RenderObjClass::Get_Cost(void) const
- {
- int polycount = Get_Num_Polys();
- // If polycount is zero set Cost to a small nonzero amount to avoid divisions by zero.
- float cost = (polycount != 0)? polycount : 0.000001f;
- return cost;
- }
- /***********************************************************************************************
- * RenderObjClass::Calculate_Cost_Value_Arrays -- calc arrays for predictive LOD processing. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNING: This member function assumes that the arrays passed are large enough (# LODs for *
- * the cost array and # LODs + 1 for the value array) to contain the desired data. *
- * *
- * NOTE: This member function is usually only called internally inside LOD objects for *
- * initialization purposes, or externally by specialized LOD objects like the G *
- * predictive LOD PIP proxy. *
- * *
- * NOTE: The screen area used is in normalized units. *
- * *
- * HISTORY: *
- * 3/11/99 NH : Created. *
- *=============================================================================================*/
- int RenderObjClass::Calculate_Cost_Value_Arrays(float screen_area, float *values, float *costs) const
- {
- values[0] = AT_MIN_LOD;
- values[1] = AT_MAX_LOD;
- costs[0] = Get_Cost();
- return 0;
- }
- /***********************************************************************************************
- * RenderObjClass::Update_Sub_Object_Bits -- updates our bits according to our sub-objects *
- * *
- * This should be called by any object that contains other objects whenever a sub object is *
- * added or removed. It updates the status of the attribute bits which are supposed to be *
- * the union of all of the sub-objects attributes. (I.e. if one of our sub-objects is *
- * translucent, then we should be marked as translucent). *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Update_Sub_Object_Bits(void)
- {
- // this doesn't do anything for non-composite objects
- if (Get_Num_Sub_Objects() == 0) return;
-
- // go through all of our sub-objects
- int coltype = 0;
- int istrans = 0;
- for (int ni = 0; ni < Get_Num_Sub_Objects(); ni++) {
- RenderObjClass * robj = Get_Sub_Object(ni);
- coltype |= robj->Get_Collision_Type();
- istrans |= robj->Is_Translucent();
- robj->Release_Ref();
- }
-
- Set_Collision_Type(coltype);
- Set_Translucent(istrans);
- // if we are a sub-object, tell our container to do this
- if (Container) {
- Container->Update_Sub_Object_Bits();
- }
- }
- /***********************************************************************************************
- * RenderObjClass::Update_Sub_Object_Transforms -- re-evaluate the transforms my sub-objects *
- * *
- * The default implementation is empty, derived classes which have sub-objects should *
- * implement it to update the transforms of their sub-objects *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Update_Sub_Object_Transforms(void)
- {
- }
-
- /***********************************************************************************************
- * RenderObjClass::Add -- Generic add for render objects *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/04/1997 GH : Created. *
- * 2/25/99 GTH : Moved to the base RenderObjClass *
- *=============================================================================================*/
- void RenderObjClass::Add(SceneClass * scene)
- {
- WWASSERT(scene);
- WWASSERT(Container == NULL);
- Scene = scene;
- Scene->Add_Render_Object(this);
- }
- /***********************************************************************************************
- * RenderObjClass::Remove -- Generic Remove for Render Objects *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/04/1997 GH : Created. *
- * 2/25/99 GTH : moved to the base RenderObjClass *
- *=============================================================================================*/
- void RenderObjClass::Remove(void)
- {
- // All render objects have their scene pointers set. To check if this is a "top level"
- // object, (i.e. directly in the scene) you see if its Container pointer is NULL.
- #if 1
- if (Container == NULL) {
- if (Scene != NULL) {
- Scene->Remove_Render_Object(this);
- return;
- }
- } else {
- Container->Remove_Sub_Object(this);
- return;
- }
- #else
- if (!Scene) return;
- Scene->Remove_Render_Object(this);
- Scene = NULL;
- #endif
- }
- /***********************************************************************************************
- * RenderObjClass::Notify_Added -- notifies the object that it is in a scene *
- * *
- * This function will be called whenever an object is directly or indirectly added to a scene *
- * An example of "indirect" addition would be if you were added as a sub-object to an HModel *
- * that was already in a scene. *
- * *
- * Override this function if you want to register your object for per-frame-updating or *
- * as a VertexProcessor. (See the Register method of SceneClass, ParticleBufferClass, etc) *
- * *
- * Container objects must forward this notification to their sub objects. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * Due to implementation details of some derived scenes, the SceneClass calls this function. *
- * Please dont move the call to this to RenderObjClass::Add *
- * Derived classes should also call the base class to ensure that the scene pointer is set *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Notify_Added(SceneClass * scene)
- {
- Scene = scene;
- }
- /***********************************************************************************************
- * RenderObjClass::Notify_Removed -- notifies an object that it has been removed *
- * *
- * Works similar to the Notify_Added function. You can override and Unregister yourself from *
- * any scene based special processing. Container objects must recurse to their sub objects. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * Derived classes should also call the base class to ensure that the scene pointer is cleared *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Notify_Removed(SceneClass * scene)
- {
- Scene = NULL;
- }
- /***********************************************************************************************
- * RenderObjClass::Update_Cached_Bounding_Volumes -- default collision sphere. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/7/97 GTH : Created. *
- *=============================================================================================*/
- void RenderObjClass::Update_Cached_Bounding_Volumes(void) const
- {
- Get_Obj_Space_Bounding_Box(CachedBoundingBox);
- Get_Obj_Space_Bounding_Sphere(CachedBoundingSphere);
- CachedBoundingSphere.Center = Get_Transform() * CachedBoundingSphere.Center;
- CachedBoundingBox.Transform(Get_Transform());
- Validate_Cached_Bounding_Volumes();
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Obj_Space_Bounding_Sphere -- default collision sphere. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 28/8/97 NH : Created. *
- * 2/25/99 GTH : Moved into RenderObjClass *
- *=============================================================================================*/
- void RenderObjClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
- {
- sphere.Center.Set(0,0,0);
- sphere.Radius = 1.0f;
- }
- /***********************************************************************************************
- * RenderObjClass::Get_Obj_Space_Bounding_Box -- default collision box. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 28/8/97 NH : Created. *
- * 2/25/99 GTH : Moved into RenderObjClass *
- *=============================================================================================*/
- void RenderObjClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
- {
- box.Center.Set(0,0,0);
- box.Extent.Set(0,0,0);
- }
- /***********************************************************************************************
- * RenderObjClass::Intersect - Returns true if specified intersection object *
- * intersects this renderobject *
- * *
- * *
- * *
- * *
- * INPUT: A properly configured Intersection object specifying ray direction & vector *
- * *
- * OUTPUT: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Moved into RenderObjClass *
- *=============================================================================================*/
- bool RenderObjClass::Intersect(IntersectionClass *Intersection, IntersectionResultClass *Final_Result)
- {
- // do the quick sphere test just to make sure it is worth the more expensive intersection test
- if (Intersect_Sphere_Quick(Intersection, Final_Result)) {
- CastResultStruct castresult;
- LineSegClass lineseg;
- Vector3 end = *Intersection->RayLocation + *Intersection->RayDirection * Intersection->MaxDistance;
- lineseg.Set(* Intersection->RayLocation, end);
- RayCollisionTestClass ray(lineseg, &castresult);
- ray.CollisionType = COLLISION_TYPE_ALL;
- if (Cast_Ray(ray)) {
- lineseg.Compute_Point(ray.Result->Fraction,&(Final_Result->Intersection));
- Final_Result->Intersects = true;
- Final_Result->IntersectionType = IntersectionResultClass::GENERIC;
- if (Intersection->IntersectionNormal)
- * Intersection->IntersectionNormal = castresult.Normal;
- Final_Result->IntersectedRenderObject = this;
- Final_Result->ModelMatrix = Transform;
- return true;
- }
- }
- Final_Result->Intersects = false;
- return false;
- }
- /***********************************************************************************************
- * RenderObjClass::Intersect_Sphere -- tests for intersection with the bounding sphere *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- bool RenderObjClass::Intersect_Sphere(IntersectionClass *Intersection, IntersectionResultClass *Final_Result)
- {
- SphereClass sphere = Get_Bounding_Sphere();
- return Intersection->Intersect_Sphere(sphere, Final_Result);
- }
- /***********************************************************************************************
- * RenderObjClass::Intersect_Sphere_Quick -- tests for intersection with the bounding sphere *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/25/99 GTH : Created. *
- *=============================================================================================*/
- bool RenderObjClass::Intersect_Sphere_Quick(IntersectionClass *Intersection, IntersectionResultClass *Final_Result)
- {
- SphereClass sphere = Get_Bounding_Sphere();
- return Intersection->Intersect_Sphere_Quick(sphere, Final_Result);
- }
- /***********************************************************************************************
- * RenderObjClass::Build_Dependency_List -- Generates a list of files this obj depends on. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/18/99 PDS : Created. *
- *=============================================================================================*/
- bool RenderObjClass::Build_Dependency_List (DynamicVectorClass<StringClass> &file_list, bool recursive)
- {
- if (recursive)
- {
- // Loop through all this object's subobj's
- int subobj_count = Get_Num_Sub_Objects ();
- for (int index = 0; index < subobj_count; index ++) {
-
- // Ask this subobj to add all of its file dependencies to the list
- RenderObjClass *psub_obj = Get_Sub_Object (index);
- if (psub_obj != NULL) {
- psub_obj->Build_Dependency_List (file_list);
- psub_obj->Release_Ref ();
- }
- }
- }
- // Now add all of this object's dependencies to the list
- Add_Dependencies_To_List (file_list);
- // Return the true/false result code
- return (file_list.Count () > 0);
- }
-
- /***********************************************************************************************
- * RenderObjClass::Build_Texture_List -- Builds a list of texture files this obj depends on. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/18/99 PDS : Created. *
- *=============================================================================================*/
- bool RenderObjClass::Build_Texture_List
- (
- DynamicVectorClass<StringClass> & texture_file_list,
- bool recursive
- )
- {
- if (recursive) {
- //
- // Loop through all this object's subobj's
- //
- int subobj_count = Get_Num_Sub_Objects ();
- for (int index = 0; index < subobj_count; index ++) {
-
- //
- // Ask this subobj to add all of its texture file dependencies to the list
- //
- RenderObjClass *sub_obj = Get_Sub_Object (index);
- if (sub_obj != NULL) {
- sub_obj->Build_Texture_List (texture_file_list);
- sub_obj->Release_Ref ();
- }
- }
- }
- //
- // Now add all of this object's texture dependencies to the list
- //
- Add_Dependencies_To_List (texture_file_list, true);
- // Return the true/false result code
- return (texture_file_list.Count () > 0);
- }
-
- /***********************************************************************************************
- * RenderObjClass::Add_Dependencies_To_List -- Add dependent files to the list. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/18/99 PDS : Created. *
- *=============================================================================================*/
- void RenderObjClass::Add_Dependencies_To_List
- (
- DynamicVectorClass<StringClass> &file_list,
- bool textures_only
- )
- {
- //
- // Should we add W3D files to the list?
- //
- if (textures_only == false) {
-
- //
- // Main W3D file
- //
- const char *model_name = Get_Name ();
- file_list.Add (::Filename_From_Asset_Name (model_name));
- //
- // External hierarchy file
- //
- const HTreeClass *phtree = Get_HTree ();
- if (phtree != NULL) {
- const char *htree_name = phtree->Get_Name ();
- if (::lstrcmpi (htree_name, model_name) != 0) {
-
- //
- // Add this file to the list
- //
- file_list.Add (::Filename_From_Asset_Name (htree_name));
- }
- }
- //
- // Original W3D file (if an aggregate)
- //
- const char *base_model_name = Get_Base_Model_Name ();
- if (base_model_name != NULL) {
-
- //
- // Add this file to the list
- //
- file_list.Add (::Filename_From_Asset_Name (base_model_name));
- }
- }
- return;
- }
- /****************************************************************************************
- RenderObjClass - Persistant object support.
- NOTE: For now, the render obj PersistFactory is going to cheat by simply storing
- the name of the render object that was saved. At load time, it will ask the
- asset manager for that object again. If the asset manager fails to re-create the
- object,
- ****************************************************************************************/
- class RenderObjPersistFactoryClass : public PersistFactoryClass
- {
- virtual uint32 Chunk_ID(void) const;
- virtual PersistClass * Load(ChunkLoadClass & cload) const;
- virtual void Save(ChunkSaveClass & csave,PersistClass * obj) const;
- enum
- {
- RENDOBJFACTORY_CHUNKID_VARIABLES = 0x00555040,
- RENDOBJFACTORY_CHUNKID_USERLIGHTING,
- RENDOBJFACTORY_VARIABLE_OBJPOINTER = 0x00,
- RENDOBJFACTORY_VARIABLE_NAME,
- RENDOBJFACTORY_VARIABLE_TRANSFORM,
- };
- };
- static RenderObjPersistFactoryClass _RenderObjPersistFactory;
- uint32 RenderObjPersistFactoryClass::Chunk_ID(void) const
- {
- return WW3D_PERSIST_CHUNKID_RENDEROBJ;
- }
- PersistClass * RenderObjPersistFactoryClass::Load(ChunkLoadClass & cload) const
- {
- RenderObjClass * old_obj = NULL;
- RenderObjClass * new_obj = NULL;
- Matrix3D tm(1);
- char name[64];
- while (cload.Open_Chunk()) {
- switch (cload.Cur_Chunk_ID()) {
- case RENDOBJFACTORY_CHUNKID_VARIABLES:
- {
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK(cload,RENDOBJFACTORY_VARIABLE_OBJPOINTER,old_obj);
- READ_MICRO_CHUNK(cload,RENDOBJFACTORY_VARIABLE_TRANSFORM,tm);
- READ_MICRO_CHUNK_STRING(cload,RENDOBJFACTORY_VARIABLE_NAME,name,sizeof(name));
- }
- cload.Close_Micro_Chunk();
- }
-
- // if the object we saved didn't have a name, replace it with null
- if (strlen(name) == 0) {
- static int count = 0;
- if ( ++count < 10 ) {
- WWDEBUG_SAY(("RenderObjPersistFactory attempted to load an un-named render object!\r\n"));
- WWDEBUG_SAY(("Replacing it with a NULL render object!\r\n"));
- }
- strcpy(name,"NULL");
- }
- new_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(name);
-
- if (new_obj == NULL) {
- static int count = 0;
- if ( ++count < 10 ) {
- WWDEBUG_SAY(("RenderObjPersistFactory failed to create object: %s!!\r\n",name));
- WWDEBUG_SAY(("Either the asset for this object is gone or you tried to save a procedural object.\r\n"));
- WWDEBUG_SAY(("Replacing it with a NULL render object!\r\n"));
- }
- strcpy(name,"NULL");
- new_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj(name);
- }
- WWASSERT(new_obj != NULL);
- if (new_obj) {
- new_obj->Set_Transform(tm);
- }
- break;
- }
- case RENDOBJFACTORY_CHUNKID_USERLIGHTING:
- if (new_obj != NULL) {
- new_obj->Load_User_Lighting(cload);
- }
- break;
- default:
- WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",(int)cload.Cur_Chunk_ID(), __FILE__,__LINE__));
- break;
- };
- cload.Close_Chunk();
- }
-
- SaveLoadSystemClass::Register_Pointer(old_obj,new_obj);
- return new_obj;
- }
- void RenderObjPersistFactoryClass::Save(ChunkSaveClass & csave,PersistClass * obj) const
- {
- RenderObjClass * robj = (RenderObjClass *)obj;
- const char * name = robj->Get_Name();
- Matrix3D tm = robj->Get_Transform();
- csave.Begin_Chunk(RENDOBJFACTORY_CHUNKID_VARIABLES);
- WRITE_MICRO_CHUNK(csave,RENDOBJFACTORY_VARIABLE_OBJPOINTER,robj);
- WRITE_MICRO_CHUNK_STRING(csave,RENDOBJFACTORY_VARIABLE_NAME,name);
- WRITE_MICRO_CHUNK(csave,RENDOBJFACTORY_VARIABLE_TRANSFORM,tm);
- csave.End_Chunk();
- if (robj->Has_User_Lighting()) {
- csave.Begin_Chunk(RENDOBJFACTORY_CHUNKID_USERLIGHTING);
- robj->Save_User_Lighting(csave);
- csave.End_Chunk();
- }
- }
- /***********************************************************************
- **
- ** RenderObj save-load.
- **
- ***********************************************************************/
- const PersistFactoryClass & RenderObjClass::Get_Factory (void) const
- {
- return _RenderObjPersistFactory;
- }
- bool RenderObjClass::Save (ChunkSaveClass &csave)
- {
- // This should never hit with the persist factory we're using...
- // Yes this looks like a design flaw but the way we're saving render objects is
- // a "shortcut". We specifically designed this capability into the persistant
- // object system so that we could avoid making all render object's save and
- // load themselves if possible.
- WWASSERT(0);
- return true;
- }
- bool RenderObjClass::Load (ChunkLoadClass &cload)
- {
- WWASSERT(0); // this should never hit with the persist factory we're using.
- return true;
- }
- /***********************************************************************
- **
- ** RenderObj User-Lighting save-load.
- **
- ***********************************************************************/
- enum
- {
- CHUNKID_SUBOBJ_USER_LIGHTING = 0x02191159,
- CHUNKID_SUBOBJ_NAME,
- CHUNKD_SUBOBJ_BONE_INDEX,
- CHUNKID_SUBOBJ_LIGHTING_DATA
- };
- void RenderObjClass::Save_User_Lighting (ChunkSaveClass & csave)
- {
- if (Has_User_Lighting()) {
- for (int bi=0; bi<Get_Num_Bones(); bi++) {
- int bone_obj_count = Get_Num_Sub_Objects_On_Bone(bi);
- for (int ri=0; ri<bone_obj_count; ri++) {
- RenderObjClass * sub_obj = Get_Sub_Object_On_Bone(ri,bi);
- if ( sub_obj &&
- (sub_obj->Class_ID() == RenderObjClass::CLASSID_MESH) &&
- (sub_obj->Has_User_Lighting()))
- {
- csave.Begin_Chunk(CHUNKID_SUBOBJ_USER_LIGHTING);
- Save_Sub_Object_User_Lighting(csave,sub_obj,bi);
- csave.End_Chunk();
- REF_PTR_RELEASE(sub_obj);
- }
- }
- }
- }
- }
- void RenderObjClass::Save_Sub_Object_User_Lighting(ChunkSaveClass & csave,RenderObjClass * sub_obj,int bone_index)
- {
- csave.Begin_Chunk(CHUNKID_SUBOBJ_NAME);
- const char * name = sub_obj->Get_Name();
- csave.Write(name,strlen(name) + 1);
- csave.End_Chunk();
- csave.Begin_Chunk(CHUNKD_SUBOBJ_BONE_INDEX);
- csave.Write(&bone_index,sizeof(int));
- csave.End_Chunk();
- csave.Begin_Chunk(CHUNKID_SUBOBJ_LIGHTING_DATA);
- sub_obj->Save_User_Lighting(csave);
- csave.End_Chunk();
- Set_Has_User_Lighting(true);
- }
- void RenderObjClass::Load_User_Lighting (ChunkLoadClass & cload)
- {
- while (cload.Open_Chunk()) {
-
- switch (cload.Cur_Chunk_ID()) {
- case CHUNKID_SUBOBJ_USER_LIGHTING:
- Load_Sub_Object_User_Lighting(cload);
- break;
- }
- cload.Close_Chunk();
- Set_Has_User_Lighting(true);
- }
- }
- void RenderObjClass::Load_Sub_Object_User_Lighting(ChunkLoadClass & cload)
- {
- const int BUFFER_SIZE = 256;
- char tmp_string[BUFFER_SIZE];
- int bone_index;
- /*
- ** Load the name of the object
- */
- cload.Open_Chunk();
- WWASSERT(cload.Cur_Chunk_ID() == CHUNKID_SUBOBJ_NAME);
- WWASSERT(cload.Cur_Chunk_Length() < BUFFER_SIZE);
- cload.Read(tmp_string,cload.Cur_Chunk_Length());
- tmp_string[BUFFER_SIZE-1] = 0;
- cload.Close_Chunk();
- /*
- ** Load the bone index for the object
- */
- cload.Open_Chunk();
- WWASSERT(cload.Cur_Chunk_ID() == CHUNKD_SUBOBJ_BONE_INDEX);
- cload.Read(&bone_index,sizeof(int));
- cload.Close_Chunk();
- if ((bone_index < 0) || (bone_index >= Get_Num_Bones())) {
- WWDEBUG_SAY(("Invalid Bone Index %d referenced in Object %s.\r\n",bone_index, tmp_string));
- WWASSERT(0);
- return;
- }
- /*
- ** Find the object and tell it to load its lighting data
- */
- cload.Open_Chunk();
- WWASSERT(cload.Cur_Chunk_ID() == CHUNKID_SUBOBJ_LIGHTING_DATA);
-
- RenderObjClass * obj = NULL;
- int bone_obj_count = Get_Num_Sub_Objects_On_Bone(bone_index);
- for (int obj_index=0; (obj_index<bone_obj_count) && (obj == NULL); obj_index++) {
- RenderObjClass * sub_obj = Get_Sub_Object_On_Bone(obj_index,bone_index);
- if (stricmp(sub_obj->Get_Name(), tmp_string) == 0) {
- obj = sub_obj;
- }
- REF_PTR_RELEASE(sub_obj);
- }
- if (obj != NULL) {
- obj->Load_User_Lighting(cload);
- }
- cload.Close_Chunk();
- }
|