825 lines
No EOL
31 KiB
C++
825 lines
No EOL
31 KiB
C++
/*
|
|
** 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 : WWPhys *
|
|
* *
|
|
* $Archive:: /Commando/Code/wwphys/phys.h $*
|
|
* *
|
|
* Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Modtime:: 3/08/02 5:01p $*
|
|
* *
|
|
* $Revision:: 89 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma once
|
|
#endif
|
|
|
|
#ifndef PHYS_H
|
|
#define PHYS_H
|
|
|
|
#include "always.h"
|
|
#include "refcount.h"
|
|
#include "matrix3d.h"
|
|
#include "physobserver.h"
|
|
#include "cullsys.h"
|
|
#include "rendobj.h"
|
|
#include "widgetuser.h"
|
|
#include "persist.h"
|
|
#include "editable.h"
|
|
#include "definition.h"
|
|
#include "multilist.h"
|
|
#include "phystexproject.h"
|
|
#include "wwstring.h"
|
|
#include "materialeffect.h"
|
|
#include "materialeffectlist.h"
|
|
#include "wwstring.h"
|
|
|
|
#include "umbrasupport.h"
|
|
|
|
|
|
class CullSystemClass;
|
|
class CullLinkClass;
|
|
class MonoClass;
|
|
class AABoxClass;
|
|
class CameraClass;
|
|
class srScene;
|
|
class srGERD;
|
|
class RenderInfoClass;
|
|
class SpecialRenderInfoClass;
|
|
class PhysClass;
|
|
class PhysRayCollisionTestClass;
|
|
class PhysAABoxCollisionTestClass;
|
|
class PhysOBBoxCollisionTestClass;
|
|
class PhysAABoxIntersectionTestClass;
|
|
class PhysOBBoxIntersectionTestClass;
|
|
class PhysMeshIntersectionTestClass;
|
|
class AABTreeNodeClass;
|
|
class CullLinkClass;
|
|
class BitStreamClass;
|
|
class LightEnvironmentClass;
|
|
|
|
class DynamicPhysClass;
|
|
class MoveablePhysClass;
|
|
class Phys3Class;
|
|
class HumanPhysClass;
|
|
class RigidBodyClass;
|
|
class VehiclePhysClass;
|
|
class MotorVehicleClass;
|
|
class WheeledVehicleClass;
|
|
class MotorcycleClass;
|
|
class TrackedVehicleClass;
|
|
class VTOLVehicleClass;
|
|
class StaticPhysClass;
|
|
class StaticAnimPhysClass;
|
|
class RenderObjPhysClass;
|
|
class DecorationPhysClass;
|
|
class TimedDecorationPhysClass;
|
|
class DynamicAnimPhysClass;
|
|
class RenderObjPhysClass;
|
|
class ProjectileClass;
|
|
class LightPhysClass;
|
|
class ElevatorPhysClass;
|
|
class DamageableStaticPhysClass;
|
|
class DoorPhysClass;
|
|
class AccessiblePhysClass;
|
|
|
|
class PhysDefClass;
|
|
|
|
#if (UMBRASUPPORT)
|
|
namespace Umbra { class Object; }
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Macros for rendering debug widgets. In the release build, these will automatically
|
|
** be removed. These macros can be used inside a member function of any physics object
|
|
** or by calling them through a pointer to a physics object e.g. my_phys_obj->DEBUG_RENDER_POINT(...)
|
|
*/
|
|
#ifdef WWDEBUG
|
|
#define DEBUG_RENDER_POINT(v,c) Add_Debug_Point(v,c)
|
|
#define DEBUG_RENDER_VECTOR(p,v,c) Add_Debug_Vector(p,v,c)
|
|
#define DEBUG_RENDER_AABOX(box,c,o) Add_Debug_AABox(box,c,o)
|
|
#define DEBUG_RENDER_OBBOX(box,c,o) Add_Debug_OBBox(box,c,o)
|
|
#define DEBUG_RENDER_AXES(tm,c) Add_Debug_Axes(tm,c)
|
|
#else
|
|
#define DEBUG_RENDER_POINT(v,c)
|
|
#define DEBUG_RENDER_VECTOR(p,v,c)
|
|
#define DEBUG_RENDER_AABOX(box,c,o)
|
|
#define DEBUG_RENDER_OBBOX(box,c,o)
|
|
#define DEBUG_RENDER_AXES(tm,c)
|
|
#endif
|
|
|
|
|
|
|
|
/***************************************************************************************
|
|
|
|
Physics Class Hierarchy (Pre-Apr 98):
|
|
------------------------------------
|
|
|
|
PhysObjClass
|
|
|_______________________________
|
|
| |
|
|
MoveableObjClass TerrainPhysClass
|
|
____________|_______________________________________
|
|
| | |
|
|
Phys4Class Phys6Class Phys3Class
|
|
| |
|
|
CharPhysClass ______________|______________________________________
|
|
| | |
|
|
WheeledPhysClass TrackedPhysClass HoverPhysClass
|
|
|
|
|
|
|
|
|
|
Physics Class Hierarchy (Apr 98):
|
|
---------------------------------
|
|
|
|
|
|
MoveableObjClass RefCountClass CollideableObjClass
|
|
| | |
|
|
|_________________|________________|
|
|
|
|
|
PhysObjClass
|
|
|
|
|
__________________|_________________________________________________________________
|
|
| | | |
|
|
ProjectileClass Phys4Class Phys6Class TerrainPhysClass
|
|
| ___|_________________________________
|
|
| | | |
|
|
CharPhysClass WheeledPhysClass TrackedPhysClass HoverPhysClass
|
|
|
|
|
|
NOTES:
|
|
|
|
- CollideableClass and MoveableClass are organizational only. I could just
|
|
put all of their interfaces directly into PhysObjClass.
|
|
|
|
- TerrainPhysClass's never move and are complex meshes which do polygon-level
|
|
collision detection
|
|
|
|
- Projectiles can never be collided with, they collide with others, they
|
|
|
|
- Physics system should store all "Collideable" objects in a list or
|
|
actually in a spatial data structure for collision checking.
|
|
|
|
- Physics system should also store all "Moveable" objects in another list
|
|
for updating everything's motions (or should that be up to the game engine?)
|
|
|
|
- Bullets are Phys3Class's, nothing can collide with them, they will use
|
|
ray casting for collision, they do not have "size" or "orientation"
|
|
|
|
- TerrainPhys is a big object that doesn't move and has complex geometry.
|
|
|
|
- A lot of things will be Phys4Classes, these are axis-aligned boxes to
|
|
the collision system. They can move in x,y, and z and rotate inside their box
|
|
|
|
|
|
Physics Class Hierarchy (Sept 98):
|
|
----------------------------------
|
|
|
|
PhysClass Hierarchy:
|
|
|
|
Starting from scratch in some respects. Culling and collision detection is the
|
|
main focus of the lowest levels of the Phys class hierarchy. Wrote a new base
|
|
class 'PhysClass' which everything will be derived from. It must be as lightweight
|
|
as possible since now everything rendered in the game scene must be a PhysClass.
|
|
|
|
|
|
PhysClass
|
|
|
|
|
----------|-----------------------------
|
|
| |
|
|
Decoration Motion
|
|
|
|
|
|
|
Projectile Controllable
|
|
|
|
Char Vehicle
|
|
|
|
|
|
|
|
Dec 1, 1998
|
|
|
|
Improving the culling linkage system. Physics object now only contain a pointer
|
|
to an abstract link type which each culling system can hang anything they want
|
|
to on. This is better than the old union inside of the Phys object because some
|
|
of these data structures are going to have pointers to allocated memory and I didn't
|
|
like the idea of having those kinds of things shadowed inside of a union. The base
|
|
CullLinkClass only contains an RTTI function which should rarely need to be called.
|
|
|
|
Adding Occlusion culling...
|
|
|
|
Jan 5, 1999
|
|
|
|
Basic Occlusion culling is working. Adding Load/Save for static scene, re-organizing
|
|
so that the AAB stuff can handle things like lights and zones.
|
|
|
|
Jan 15, 1999
|
|
|
|
Improving list code to automatically track refs. An object added to a "phys list"
|
|
will be automatically Add_Ref'd. Moved the list code into a separate module for
|
|
easier reading (physlist.h, cpp)
|
|
|
|
May 21, 1999
|
|
|
|
Splitting much of the culling system code out into WWMath so that it can be re-used
|
|
by other libraries such as the sound system. Removing "CullableClass" from the
|
|
physics library and re-writing the culling stuf to not rely on phys-objects (only
|
|
an abstract "cullable" object).
|
|
|
|
Sept 1, 1999
|
|
|
|
Making the physics library use the new Persistant-Object save/load code. This means
|
|
that each type of PhysClass is a PersistClass now. Each one needs to implement
|
|
save/load methods and declare a PersistFactoryClass. The physics system will have
|
|
two SaveLoadSubSystems in it. One for saving the data which is completely static
|
|
for a level and another for the dynamic data. Things that are treated as 100% static
|
|
are: visibility data, pathfinding data, and culling datastructures (but not the
|
|
objects in them...)
|
|
|
|
August 29, 2000
|
|
|
|
Adding Export_State,Import_State functions which can be used by the App to do
|
|
network communication of physics object states.
|
|
|
|
|
|
****************************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
** PhysClass
|
|
** This is the base class for all objects in the physics system.
|
|
*/
|
|
class PhysClass : public CullableClass, public PersistClass, public MultiListObjectClass
|
|
{
|
|
public:
|
|
|
|
PhysClass(void);
|
|
// PhysClass(const PhysDefClass & def);
|
|
virtual ~PhysClass(void);
|
|
void Init(const PhysDefClass & def);
|
|
|
|
/*
|
|
** DEBUGGING, re-initialize this object because our definition changed
|
|
*/
|
|
virtual void Definition_Changed(void) { }
|
|
|
|
/*
|
|
** Certain physics objects expire when an internal timer runs out or they are crushed. This function
|
|
** is used to handle informing any observers and putting this object into the destroy list which is
|
|
** processed at the end of each frame
|
|
*/
|
|
bool Expire(void);
|
|
|
|
/*
|
|
** Timestep function - system informs the object to update itself for the specified
|
|
** amount of time.
|
|
*/
|
|
virtual bool Needs_Timestep(void) { return false; }
|
|
virtual void Timestep(float dt) = 0;
|
|
virtual void Post_Timestep_Process(void) { }
|
|
|
|
/*
|
|
** Access to the Position/Orientation state of the object
|
|
*/
|
|
virtual const Matrix3D & Get_Transform(void) const = 0;
|
|
virtual void Set_Transform(const Matrix3D & m) = 0;
|
|
void Get_Position(Vector3 * set_pos) const { Get_Transform().Get_Translation(set_pos); }
|
|
void Set_Position(const Vector3 & pos) { Matrix3D tm = Get_Transform(); tm.Set_Translation(pos); Set_Transform(tm); }
|
|
float Get_Facing(void) const { return Get_Transform().Get_Z_Rotation(); }
|
|
void Set_Facing(float new_facing);
|
|
|
|
/*
|
|
** Collision detection - all collideable objects provide the following collision detection
|
|
** functions so that other objects do not pass through them. These functions should test
|
|
** the given primitive against this object's geometric representation.
|
|
*/
|
|
virtual bool Cast_Ray(PhysRayCollisionTestClass & raytest) { return false; }
|
|
virtual bool Cast_AABox(PhysAABoxCollisionTestClass & boxtest) { return false; }
|
|
virtual bool Cast_OBBox(PhysOBBoxCollisionTestClass & boxtest) { return false; }
|
|
|
|
virtual bool Intersection_Test(PhysAABoxIntersectionTestClass & test) { return false; }
|
|
virtual bool Intersection_Test(PhysOBBoxIntersectionTestClass & test) { return false; }
|
|
virtual bool Intersection_Test(PhysMeshIntersectionTestClass & test) { return false; }
|
|
|
|
/*
|
|
** Inter-Object Geometric Dependency. These functions don't really perform any
|
|
** physics-based motion, only purely kinematic. You can link a moveable physics object
|
|
** (the rider) to another object that it is standing on (the carrier). This will cause
|
|
** the carrier to move the rider whenever it moves (by calling Push).
|
|
**
|
|
** Set_Carrier - when a carrier is being destroyed, it tells all riders as it unlinks them
|
|
** Push - carriers push their riders around, also objects not being carried can be pushed
|
|
** Internal_Link_Rider - an object is being attached to you, move him when you move
|
|
** Internal_Unlink_Rider - stop moving this object when you move.
|
|
*/
|
|
virtual void Link_To_Carrier(PhysClass * carrier,RenderObjClass * carrier_sub_obj = NULL) { }
|
|
virtual RenderObjClass * Peek_Carrier_Sub_Object(void) { return NULL; }
|
|
virtual bool Push(const Vector3 & move) { return false; }
|
|
|
|
virtual bool Internal_Link_Rider(PhysClass * rider) { return false; }
|
|
virtual bool Internal_Unlink_Rider(PhysClass * rider) { return false; }
|
|
|
|
/*
|
|
** Culling, this function updates the culling box used by the object. The default implementation
|
|
** is to copy the bounding box of the current Model.
|
|
*/
|
|
void Update_Cull_Box(void);
|
|
|
|
/*
|
|
** Set the model used by this physics object
|
|
*/
|
|
virtual void Set_Model(RenderObjClass * model);
|
|
void Set_Model_By_Name(const char * model_type_name);
|
|
RenderObjClass * Get_Model(void);
|
|
WWINLINE RenderObjClass * Peek_Model(void) { return Model; }
|
|
|
|
/*
|
|
** Set the name of this physics model instance
|
|
*/
|
|
void Set_Name(const char * name);
|
|
const char * Get_Name(void);
|
|
|
|
/*
|
|
** Instance ID related methods
|
|
*/
|
|
uint32 Get_ID(void) const { return InstanceID; }
|
|
void Set_ID(uint32 id) { InstanceID = id; }
|
|
|
|
/*
|
|
** Vis Object ID. Every phys object can store a vis object id. Static objects will
|
|
** have constant ID's assigned by the vis generation process, dynamic objects will
|
|
** update their id based on their current location.
|
|
*/
|
|
void Set_Vis_Object_ID(int new_id) { VisObjectID = new_id; }
|
|
virtual int Get_Vis_Object_ID(void) { return VisObjectID; }
|
|
|
|
/*
|
|
** This is just a shortcut to rendering the phys object's render object if it has one
|
|
*/
|
|
virtual void Render(RenderInfoClass & rinfo);
|
|
virtual void Vis_Render(SpecialRenderInfoClass & rinfo);
|
|
|
|
/*
|
|
** Lighting system. Each physics object caches its static lighting environment. This cache must be
|
|
** invalidated when the object moves or when static lights near it change state. The simulation code
|
|
** for each physics object will be responsible for invalidating the cache when the object moves. The
|
|
** scene will be responsible for invalidating the caches of objects near lights that change state.
|
|
*/
|
|
void Invalidate_Static_Lighting_Cache(void);
|
|
LightEnvironmentClass * Get_Static_Lighting_Environment(void);
|
|
|
|
/*
|
|
** This is a debugging feature which causes all vis-sector meshes to be rendered
|
|
*/
|
|
virtual void Render_Vis_Meshes(RenderInfoClass & rinfo) { }
|
|
|
|
/*
|
|
** When rendering shadows in BLOB mode, this function defines the bounds of
|
|
** the blob. Derived classes will implement this to return something like
|
|
** their collision box.
|
|
*/
|
|
virtual void Get_Shadow_Blob_Box(AABoxClass * set_obj_space_box);
|
|
|
|
/*
|
|
** This function is used to determine whether an object is projecting a shadow.
|
|
** If the object is projecting a shadow, it shouldn't be considered an occluder
|
|
** for the sun.
|
|
*/
|
|
virtual bool Is_Casting_Shadow(void) { return false; }
|
|
|
|
/*
|
|
** Material Effect Support.
|
|
** As the scene is rendered, the textures being projected onto each object will be
|
|
** linked in through the following interface. Then when this object is rendered,
|
|
** it should push those material passes into the render pipeline. As this is done,
|
|
** the list will be reset. Other user-created material effects can also be
|
|
** linked to the object through this interface.
|
|
*/
|
|
void Add_Effect_To_Me(MaterialEffectClass * effect);
|
|
void Remove_Effect_From_Me(MaterialEffectClass * effect);
|
|
bool Do_Any_Effects_Suppress_Shadows(void);
|
|
|
|
/*
|
|
** Set the Collision Group for this physics object. The collision group is an integer
|
|
** between 0 and 15. Collisions between any two groups can be enabled/disabled through
|
|
** the physics system.
|
|
*/
|
|
void Set_Collision_Group(unsigned char group) { group &= COLLISION_MASK; Flags &= ~COLLISION_MASK; Flags |= group; }
|
|
unsigned char Get_Collision_Group(void) const { return Flags & COLLISION_MASK; }
|
|
|
|
|
|
/*
|
|
** The IGNOREME state is basically used when the object is processing its move. It
|
|
** is a way of temporarily making the collision system ignore an object (so you don't
|
|
** collide with yourself for example)
|
|
*/
|
|
void Inc_Ignore_Counter(void);
|
|
void Dec_Ignore_Counter(void);
|
|
bool Is_Ignore_Me(void) const { return ((Flags & IGNORE_MASK) > 0); }
|
|
|
|
|
|
/*
|
|
** The IMMOVABLE state is used to turn off an object's simulation.
|
|
*/
|
|
void Set_Immovable(bool onoff) { Set_Flag(IMMOVABLE,onoff); }
|
|
bool Is_Immovable(void) const { return Get_Flag(IMMOVABLE); }
|
|
|
|
/*
|
|
** Some objects (like light sources) can be disabled.
|
|
*/
|
|
void Set_Disabled(bool onoff) { Set_Flag(DISABLED,onoff); }
|
|
bool Is_Disabled(void) const { return Get_Flag(DISABLED); }
|
|
|
|
/*
|
|
** The Debug Display flag is used (in debug builds) to enable displaying
|
|
** contact points, impulse vectors, etc.
|
|
*/
|
|
void Enable_Debug_Display(bool onoff) { (onoff ? Flags |= DEBUGDISPLAY : Flags &= ~DEBUGDISPLAY); }
|
|
bool Is_Debug_Display_Enabled(void) const;
|
|
|
|
/*
|
|
** User Control. Enabling this flag makes the physics object ingore all
|
|
** physics and just move according to its controller
|
|
*/
|
|
void Enable_User_Control(bool onoff) { Set_Flag(USERCONTROL,onoff); Set_Flag(ASLEEP,false); }
|
|
bool Is_User_Control_Enabled(void) const { return Get_Flag(USERCONTROL); }
|
|
|
|
/*
|
|
** Shadow casting. If this option is enabled, a shadow volume will be
|
|
** calculated for the object each frame
|
|
*/
|
|
void Enable_Shadow_Generation(bool onoff) { Set_Flag(CASTSHADOW,onoff); }
|
|
bool Is_Shadow_Generation_Enabled(void) const { return Get_Flag(CASTSHADOW); }
|
|
|
|
/*
|
|
** Blob Shadow override. There is a shadow mode where all objects get blob
|
|
** shadows except the "main character". This option indicates that this physics
|
|
** object should cast a proper shadow when the shadow mode is "BLOBS_PLUS"
|
|
*/
|
|
void Enable_Force_Projection_Shadow(bool onoff) { Set_Flag(FORCE_PROJECTION_SHADOW,onoff); }
|
|
bool Is_Force_Projection_Shadow_Enabled(void) const { return Get_Flag(FORCE_PROJECTION_SHADOW); }
|
|
|
|
/*
|
|
** DontSave! This is used for transient objects like glass fragments which
|
|
** we don't want to save. There is also a problem with them saving caused by
|
|
** the fact that thier model is procedurally generated and doesn't save...
|
|
*/
|
|
void Enable_Dont_Save(bool onoff) { Set_Flag(DONT_SAVE,onoff); }
|
|
bool Is_Dont_Save_Enabled(void) const { return Get_Flag(DONT_SAVE); }
|
|
|
|
/*
|
|
** Asleep. This indicates that the phyics object has "settled" into a stable
|
|
** configuration and has stopped simulating. Physics objects internally manage this flag.
|
|
*/
|
|
bool Is_Asleep(void) const { return ((Flags & ASLEEP) == ASLEEP); }
|
|
void Force_Awake(void) { Set_Flag(ASLEEP,false); }
|
|
|
|
/*
|
|
** Static-World-Space-Mesh. This flag indicates that the phys object is a static world
|
|
** space mesh (identity transform) and enables some optimizations in the rendering loop.
|
|
*/
|
|
void Enable_Is_World_Space_Mesh(bool onoff) { Set_Flag(IS_WS_MESH,onoff); }
|
|
bool Is_World_Space_Mesh(void) { return Get_Flag(IS_WS_MESH); }
|
|
|
|
/*
|
|
** Is Pre-Lit. This flag indicates that this object has precomputed light
|
|
** maps and does not need to have the static lights applied to it.
|
|
*/
|
|
void Enable_Is_Pre_Lit(bool onoff) { Set_Flag(IS_PRE_LIT,onoff); }
|
|
bool Is_Pre_Lit(void); // { return Get_Flag(IS_PRE_LIT) | Model->Get_F; }
|
|
|
|
/*
|
|
** Is In-the-sun. This flag indicates whether the object is being illuminated by
|
|
** sunlight.
|
|
*/
|
|
void Enable_Is_In_The_Sun(bool onoff) { Set_Flag(IS_IN_THE_SUN,onoff); }
|
|
bool Is_In_The_Sun(void) { return Get_Flag(IS_IN_THE_SUN); }
|
|
|
|
/*
|
|
** Is_State_Dirty. This flag indicates that the physics code has changed the state of
|
|
** this object. It will be set whenever an object changes but it is only cleared by the
|
|
** external user.
|
|
*/
|
|
void Enable_Is_State_Dirty(bool onoff) { Set_Flag(IS_STATE_DIRTY,onoff); }
|
|
bool Is_State_Dirty(void) { return Get_Flag(IS_STATE_DIRTY); }
|
|
|
|
/*
|
|
** Is Object's Simulation Enabled. This flag can be used to disable the physics simulation
|
|
** on an object-by-object basis. The other simulation methods disable whole classes
|
|
** of objects.
|
|
*/
|
|
void Enable_Objects_Simulation(bool onoff) { Set_Flag(SIMULATION_DISABLED,!onoff); }
|
|
bool Is_Objects_Simulation_Enabled(void) const { return !Get_Flag(SIMULATION_DISABLED); }
|
|
bool Is_Object_Simulating(void) { return Is_Objects_Simulation_Enabled() && !Is_Simulation_Disabled(); }
|
|
|
|
/*
|
|
** If you install a collision observer, it will be notified of any collisions which occur
|
|
** involving this object. One way to do this is to derive your game objects from
|
|
** CollisionObserverClass so that they can be directly installed here. Currently, there
|
|
** can only be one observer for any physics object. You are responsible for removing
|
|
** the observer before this phys object is destroyed: Set_Observer(NULL)
|
|
*/
|
|
void Set_Observer(PhysObserverClass * o) { Observer = o; }
|
|
PhysObserverClass * Get_Observer(void) { return Observer; }
|
|
CollisionReactionType Collision_Occurred(CollisionEventClass & event);
|
|
|
|
/*
|
|
** Definition access. Many physics objects are created from a "definition". The definition
|
|
** object contains constants. If this object has a definition, you can access it here.
|
|
*/
|
|
const PhysDefClass * Get_Definition(void) { return Definition; }
|
|
|
|
/*
|
|
** Physics RTTI.
|
|
*/
|
|
virtual DynamicPhysClass * As_DynamicPhysClass(void) { return NULL; }
|
|
virtual MoveablePhysClass * As_MoveablePhysClass(void) { return NULL; }
|
|
virtual Phys3Class * As_Phys3Class(void) { return NULL; }
|
|
virtual HumanPhysClass * As_HumanPhysClass(void) { return NULL; }
|
|
virtual RigidBodyClass * As_RigidBodyClass(void) { return NULL; }
|
|
virtual VehiclePhysClass * As_VehiclePhysClass(void) { return NULL; }
|
|
virtual MotorVehicleClass * As_MotorVehicleClass(void) { return NULL; }
|
|
virtual WheeledVehicleClass * As_WheeledVehicleClass(void) { return NULL; }
|
|
virtual MotorcycleClass * As_MotorcycleClass(void) { return NULL; }
|
|
virtual TrackedVehicleClass * As_TrackedVehicleClass(void) { return NULL; }
|
|
virtual VTOLVehicleClass * As_VTOLVehicleClass(void) { return NULL; }
|
|
virtual StaticPhysClass * As_StaticPhysClass(void) { return NULL; }
|
|
virtual StaticAnimPhysClass * As_StaticAnimPhysClass(void) { return NULL; }
|
|
virtual ElevatorPhysClass * As_ElevatorPhysClass(void) { return NULL; }
|
|
virtual DamageableStaticPhysClass * As_DamageableStaticPhysClass (void) { return NULL; }
|
|
virtual DoorPhysClass * As_DoorPhysClass(void) { return NULL; }
|
|
virtual DecorationPhysClass * As_DecorationPhysClass(void) { return NULL; }
|
|
virtual TimedDecorationPhysClass * As_TimedDecorationPhysClass(void) { return NULL; }
|
|
virtual DynamicAnimPhysClass *As_DynamicAnimPhysClass(void) { return NULL; }
|
|
virtual LightPhysClass * As_LightPhysClass(void) { return NULL; }
|
|
virtual RenderObjPhysClass * As_RenderObjPhysClass(void) { return NULL; }
|
|
virtual ProjectileClass * As_ProjectileClass(void) { return NULL; }
|
|
virtual AccessiblePhysClass * As_AccessiblePhysClass(void) { return NULL; }
|
|
|
|
/*
|
|
** Persistant object save/load system
|
|
*/
|
|
virtual bool Save (ChunkSaveClass &csave);
|
|
virtual bool Load (ChunkLoadClass &cload);
|
|
|
|
/*
|
|
** Debug rendering of vectors, points, boxes, etc etc. These functions actually add debug
|
|
** widgets to the physics scene. Use the macros defined at the top of this file in order to
|
|
** have these debug calls removed from the release build.
|
|
*/
|
|
#ifdef WWDEBUG
|
|
void Add_Debug_Point(const Vector3 & p,const Vector3 & color);
|
|
void Add_Debug_Vector(const Vector3 & p,const Vector3 & v,const Vector3 & color);
|
|
void Add_Debug_AABox(const AABoxClass & box,const Vector3 & color,float opacity = 0.25f);
|
|
void Add_Debug_OBBox(const OBBoxClass & box,const Vector3 & color,float opacity = 0.25f);
|
|
void Add_Debug_Axes(const Matrix3D & transform,const Vector3 & color);
|
|
#endif
|
|
|
|
/*
|
|
** Simulation and Rendering toggles by type. Derived classes implement these functions to test
|
|
** a static flag which is used to indicate whether rendering or simluation of all instances of
|
|
** that class are disabled or not.
|
|
*/
|
|
virtual bool Is_Simulation_Disabled(void) { return false; }
|
|
virtual bool Is_Rendering_Disabled(void) { return false; }
|
|
|
|
/*
|
|
** Umbra Testing
|
|
*/
|
|
#if (UMBRASUPPORT)
|
|
Umbra::Object * Peek_Umbra_Object(void) { return UmbraObject; }
|
|
#endif
|
|
|
|
unsigned Get_Last_Visible_Frame() const { return LastVisibleFrame; }
|
|
void Set_Last_Visible_Frame(unsigned frame) { LastVisibleFrame=frame; }
|
|
|
|
protected:
|
|
|
|
bool Get_Flag(unsigned int flag) const { return ((Flags & flag) == flag); }
|
|
void Set_Flag(unsigned int flag,bool onoff) { (onoff ? Flags |= flag : Flags &= ~flag); }
|
|
|
|
void Push_Effects(RenderInfoClass & rinfo);
|
|
void Pop_Effects(RenderInfoClass & rinfo);
|
|
|
|
virtual void Update_Sun_Status(void);
|
|
|
|
enum {
|
|
COLLISION_MASK = 0x0000000F, // bits for the collision group
|
|
IMMOVABLE = 0x00000100, // this object is immovable.
|
|
DISABLED = 0x00000200, // Some objects can be disabled (e.g. lights)
|
|
DEBUGDISPLAY = 0x00000400, // Render debugging aids (forces, impacts, etc)
|
|
USERCONTROL = 0x00000800, // Ignore physics, move according to controller directly
|
|
CASTSHADOW = 0x00001000, // Does this object cast a shadow?
|
|
FORCE_PROJECTION_SHADOW = 0x00002000, // When the shadow mode is BLOBS_PLUS, this object still uses a "proper" shadow
|
|
DONT_SAVE = 0x00004000, // Scene should never save this object (used for transient things like glass fragments)
|
|
ASLEEP = 0x00008000, // This object is not moving so its simulation was skipped
|
|
IS_WS_MESH = 0x00010000, // Enable the static-world-space-mesh rendering optimizations.
|
|
IS_PRE_LIT = 0x00020000, // Is this a light-mapped object that doesn't need static lights applied.
|
|
IS_IN_THE_SUN = 0x00040000, // Is this object illuminated by the sun?
|
|
IS_STATE_DIRTY = 0x00080000, // This object's state has changed.
|
|
STATIC_LIGHTING_DIRTY = 0x00100000, // This object's static lighting cache is dirty
|
|
FRICTION_DISABLED = 0x00200000, // Friction is disabled for this object (vehicles disable body-friction when their wheels are in contact)
|
|
SIMULATION_DISABLED = 0x00400000, // Turn on/off simulation for this object
|
|
|
|
IGNORE_SHIFT = 28, // shift count for the 'ignore-me' counter
|
|
IGNORE_MASK = 0xF0000000, // mask for the 'ignore-me' counter
|
|
DEFAULT_FLAGS = 0,
|
|
};
|
|
|
|
/*
|
|
** flags for things like whether this object is currently being considered immovable
|
|
*/
|
|
unsigned int Flags;
|
|
|
|
/*
|
|
** Render model
|
|
*/
|
|
RenderObjClass * Model;
|
|
|
|
/*
|
|
** Optional instance name
|
|
*/
|
|
StringClass Name;
|
|
|
|
/*
|
|
** Optional instance identifier (unique if non-zero)
|
|
*/
|
|
uint32 InstanceID;
|
|
|
|
/*
|
|
** Vis Object ID. Every phys object can store a vis object id. Static objects will
|
|
** have constant ID's assigned by the vis generation process, dynamic objects will
|
|
** update their id based on their current location.
|
|
*/
|
|
uint32 VisObjectID;
|
|
|
|
/*
|
|
** Observer object
|
|
*/
|
|
PhysObserverClass * Observer;
|
|
|
|
/*
|
|
** Definition object, contains constants which are shared between instances
|
|
*/
|
|
const PhysDefClass * Definition;
|
|
|
|
/*
|
|
** List of projected textures that are being applied to this object
|
|
*/
|
|
//TexProjListClass ProjectionsOnMe;
|
|
RefMaterialEffectListClass MaterialEffectsOnMe;
|
|
|
|
/*
|
|
** Static lighting cache.
|
|
*/
|
|
LightEnvironmentClass * StaticLightingCache;
|
|
|
|
/*
|
|
** Frame time at which the sun status was last updated. The sun status is cached and only updated few times per second.
|
|
*/
|
|
unsigned SunStatusLastUpdated;
|
|
|
|
/*
|
|
** The pscene uses this to figure out if the mesh is visible, to do some physics optimizations.
|
|
*/
|
|
unsigned LastVisibleFrame;
|
|
|
|
/*
|
|
** UMBRA Testing
|
|
*/
|
|
#if (UMBRASUPPORT)
|
|
Umbra::Object * UmbraObject;
|
|
#endif
|
|
|
|
private:
|
|
|
|
// Not Implemented:
|
|
PhysClass(const PhysClass & src);
|
|
PhysClass & operator = (const PhysClass & src);
|
|
};
|
|
|
|
|
|
inline void PhysClass::Inc_Ignore_Counter(void)
|
|
{
|
|
int count = (Flags & IGNORE_MASK) >> IGNORE_SHIFT;
|
|
count++;
|
|
WWASSERT(count < 12);
|
|
Flags &= ~IGNORE_MASK;
|
|
Flags |= (count << IGNORE_SHIFT);
|
|
}
|
|
|
|
inline void PhysClass::Dec_Ignore_Counter(void)
|
|
{
|
|
int count = (Flags & IGNORE_MASK) >> IGNORE_SHIFT;
|
|
WWASSERT(count > 0);
|
|
count--;
|
|
Flags &= ~IGNORE_MASK;
|
|
Flags |= (count << IGNORE_SHIFT);
|
|
}
|
|
|
|
|
|
inline CollisionReactionType PhysClass::Collision_Occurred(CollisionEventClass & event)
|
|
{
|
|
if (Observer) {
|
|
return Observer->Collision_Occurred(event);
|
|
} else {
|
|
return COLLISION_REACTION_DEFAULT;
|
|
}
|
|
}
|
|
|
|
inline void PhysClass::Update_Cull_Box(void)
|
|
{
|
|
if (Model) {
|
|
Set_Cull_Box(Model->Get_Bounding_Box());
|
|
}
|
|
}
|
|
|
|
inline void PhysClass::Add_Effect_To_Me(MaterialEffectClass * effect)
|
|
{
|
|
WWASSERT(effect != NULL);
|
|
MaterialEffectsOnMe.Add(effect);
|
|
}
|
|
|
|
inline void PhysClass::Remove_Effect_From_Me(MaterialEffectClass * effect)
|
|
{
|
|
WWASSERT(effect != NULL);
|
|
MaterialEffectsOnMe.Remove(effect);
|
|
}
|
|
|
|
inline bool PhysClass::Is_Pre_Lit(void)
|
|
{
|
|
if (Model) {
|
|
return (Get_Flag(IS_PRE_LIT) | (Model->Has_User_Lighting() != 0));
|
|
} else {
|
|
return Get_Flag(IS_PRE_LIT);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
** PhysDefClass - Initialization structure for a PhysClass
|
|
*/
|
|
class PhysDefClass : public DefinitionClass
|
|
{
|
|
public:
|
|
|
|
PhysDefClass(void);
|
|
|
|
// From PersistClass
|
|
virtual bool Save(ChunkSaveClass &csave);
|
|
virtual bool Load(ChunkLoadClass &cload);
|
|
|
|
// PhysDef type filtering mechanism
|
|
virtual const char * Get_Type_Name(void) { return "PhysDef"; }
|
|
virtual bool Is_Type(const char *);
|
|
|
|
// Validation methods
|
|
virtual bool Is_Valid_Config (StringClass &message);
|
|
|
|
// accessors
|
|
const StringClass & Get_Model_Name() { return ModelName; }
|
|
bool Get_Is_Pre_Lit() { return IsPreLit; }
|
|
|
|
// Editable interface requirements
|
|
DECLARE_EDITABLE(PhysDefClass,DefinitionClass);
|
|
|
|
protected:
|
|
|
|
StringClass ModelName;
|
|
bool IsPreLit;
|
|
|
|
friend class PhysClass;
|
|
};
|
|
|
|
|
|
|
|
#endif |