1545 lines
78 KiB
C++
1545 lines
78 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/animcollisionmanager.cpp $*
|
|
* *
|
|
* Original Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Author:: Greg_h $*
|
|
* *
|
|
* $Modtime:: 11/14/01 1:34p $*
|
|
* *
|
|
* $Revision:: 33 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass -- Constructor *
|
|
* AnimCollisionManagerClass::CollideableObjClass::~CollideableObjClass -- Destructor *
|
|
* AnimCollisionManagerClass::CollideableObjClass::operator = -- assignment operator *
|
|
* AnimCollisionManagerClass::CollideableObjClass::Set_Collision_Object -- set collision mes *
|
|
* AnimCollisionManagerClass::CollideableObjClass::Intersect_Scene -- intersection test *
|
|
* AnimCollisionManagerClass::CollideableObjClass::Clear_Collision_Bits -- disables collisio *
|
|
* AnimCollisionManagerClass::CollideableObjClass::Restore_Collision_Bits -- set collision b *
|
|
* AnimCollisionManagerClass::AnimCollisionManagerClass -- Constructor *
|
|
* AnimCollisionManagerClass::~AnimCollisionManagerClass -- Destructor *
|
|
* AnimCollisionManagerClass::Set_Animation_Mode -- set the current anim mode *
|
|
* AnimCollisionManagerClass::Get_Animation_Mode -- Get the current anim mode *
|
|
* AnimCollisionManagerClass::Set_Animation -- Set the current animation *
|
|
* AnimCollisionManagerClass::Peek_Animation -- Get the current animation *
|
|
* AnimCollisionManagerClass::Set_Target_Frame -- Set the target animation frame *
|
|
* AnimCollisionManagerClass::Get_Target_Frame -- Get the target animation frame *
|
|
* AnimCollisionManagerClass::Set_Target_Frame_End -- Set the target frame to the end of the *
|
|
* AnimCollisionManagerClass::Is_At_Target -- returns true if in TARGET mode and done animat *
|
|
* AnimCollisionManagerClass::Set_Loop_Start -- Sets frame0 for an anim loop *
|
|
* AnimCollisionManagerClass::Set_Loop_End -- Sets frame1 for an anim loop *
|
|
* AnimCollisionManagerClass::Get_Loop_Start -- returns frame0 for an anim loop *
|
|
* AnimCollisionManagerClass::Get_Loop_End -- returns frame1 for an anim loop *
|
|
* AnimCollisionManagerClass::Set_Current_Frame -- Set the current frame *
|
|
* AnimCollisionManagerClass::Get_Current_Frame -- Get the current frame *
|
|
* AnimCollisionManagerClass::Set_Collision_Mode -- Set the current collision mode *
|
|
* AnimCollisionManagerClass::Get_Collision_Mode -- Get the current collision mode *
|
|
* AnimCollisionManagerClass::Init -- Init this collision manager *
|
|
* AnimCollisionManagerClass::Update_Cached_Model_Parameters -- find all of the collideable *
|
|
* AnimCollisionManagerClass::Is_Collision_Model -- classify a sub-object as collideable or *
|
|
* AnimCollisionManagerClass::Recursive_Count_Collision_Models -- count the collideable mesh *
|
|
* AnimCollisionManagerClass::Recursive_Collect_Collision_Models -- collect collideable mesh *
|
|
* AnimCollisionManagerClass::Timestep -- Update the state of this object *
|
|
* AnimCollisionManagerClass::Check_Collision -- Check the given collision object *
|
|
* AnimCollisionManagerClass::Is_Intersecting -- intersection test *
|
|
* AnimCollisionManagerClass::Push_Collided_Object -- push an object we collided with *
|
|
* AnimCollisionManagerClass::Save -- save! *
|
|
* AnimCollisionManagerClass::Load -- Load! *
|
|
* AnimCollisionManagerClass::Revert_Animation_State -- revert to previous anim frame *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "animcollisionmanager.h"
|
|
#include "colmathaabox.h"
|
|
#include "pscene.h"
|
|
#include "physinttest.h"
|
|
#include "movephys.h"
|
|
#include "bitstream.h"
|
|
#include "assetmgr.h"
|
|
#include "hanim.h"
|
|
#include "boxrobj.h"
|
|
#include "chunkio.h"
|
|
#include "wwdebug.h"
|
|
#include "wwprofile.h"
|
|
|
|
|
|
/*
|
|
** Set this if you want verbose logging. It will be un-set if debugging is not enabled...
|
|
*/
|
|
#define VERBOSE_LOGGING 0
|
|
|
|
#if VERBOSE_LOGGING
|
|
#define VERBOSE_LOG(x) /*if (strstr(Parent.Peek_Model()->Get_Name(),"HND_ELEV03"))*/ WWDEBUG_SAY(x)
|
|
#else
|
|
#define VERBOSE_LOG(x)
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
** PushRecordClass
|
|
** This object is used to record each object's initial state before an animated collision
|
|
** moves them. At the end of an update, if the animated object has to revert to its initial state,
|
|
** all of the objects in the "PushList" will be reverted to there original states as well.
|
|
*/
|
|
class PushRecordClass : public AutoPoolClass<PushRecordClass,32>
|
|
{
|
|
public:
|
|
|
|
PushRecordClass(PhysClass * obj) : Object(NULL), Next(NULL) { REF_PTR_SET(Object,obj); WWASSERT(obj); Transform = obj->Get_Transform(); }
|
|
~PushRecordClass(void) { REF_PTR_RELEASE(Object); };
|
|
|
|
void Revert(void) { Object->Set_Transform(Transform); }
|
|
|
|
PushRecordClass * Get_Next(void) const { return Next; }
|
|
void Set_Next(PushRecordClass * next) { Next = next; }
|
|
|
|
|
|
static void Add_To_List(PushRecordClass ** head, PhysClass * obj)
|
|
{
|
|
PushRecordClass * new_rec = new PushRecordClass(obj);
|
|
new_rec->Set_Next(*head);
|
|
*head = new_rec;
|
|
}
|
|
|
|
static void Revert_List(PushRecordClass * head)
|
|
{
|
|
while (head) {
|
|
head->Revert();
|
|
head = head->Get_Next();
|
|
}
|
|
}
|
|
|
|
static void Delete_List(PushRecordClass * head)
|
|
{
|
|
while (head) {
|
|
PushRecordClass * next = head->Get_Next();
|
|
delete head;
|
|
head = next;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
PhysClass * Object;
|
|
Matrix3D Transform;
|
|
PushRecordClass * Next;
|
|
|
|
};
|
|
|
|
DEFINE_AUTO_POOL(PushRecordClass,32);
|
|
|
|
|
|
/*
|
|
** Chunk ID's used by AnimCollisionManagerClass
|
|
*/
|
|
enum
|
|
{
|
|
ANIMCOLLISIONMANAGER_CHUNK_VARIABLES = 0525000421,
|
|
|
|
ANIMCOLLISIONMANAGER_VARIABLE_COLLISIONMODE = 0x00,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONMODE,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_TARGETFRAME,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_CURFRAME,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONNAME,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_LOOPSTART,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_LOOPEND,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_PREVFRAME,
|
|
ANIMCOLLISIONMANAGER_VARIABLE_PREVANIMATIONNAME,
|
|
};
|
|
|
|
|
|
/********************************************************************************************
|
|
**
|
|
** AnimCollisionManagerClass::CollideableObjClass Implementation
|
|
**
|
|
********************************************************************************************/
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass(void) :
|
|
CollisionMesh(NULL),
|
|
StartTransform(1),
|
|
EndTransform(1)
|
|
{
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass
|
|
(
|
|
RenderObjClass * collisionmesh
|
|
) :
|
|
CollisionMesh(NULL),
|
|
StartTransform(1),
|
|
EndTransform(1)
|
|
{
|
|
Set_Collision_Object(collisionmesh);
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollideableObjClass::CollideableObjClass
|
|
(
|
|
const CollideableObjClass & that
|
|
) :
|
|
CollisionMesh(NULL),
|
|
StartTransform(1),
|
|
EndTransform(1)
|
|
{
|
|
*this = that;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::~CollideableObjClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollideableObjClass::~CollideableObjClass(void)
|
|
{
|
|
REF_PTR_RELEASE(CollisionMesh);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::operator = -- assignment operator *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollideableObjClass &
|
|
AnimCollisionManagerClass::CollideableObjClass::operator = (const CollideableObjClass & that)
|
|
{
|
|
if (this != &that) {
|
|
REF_PTR_SET(CollisionMesh,that.CollisionMesh);
|
|
StartTransform = that.StartTransform;
|
|
EndTransform = that.EndTransform;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::Set_Collision_Object -- set collision mesh *
|
|
* *
|
|
* Sets the render object being tracked by this CollideableObjClass *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void
|
|
AnimCollisionManagerClass::CollideableObjClass::Set_Collision_Object(RenderObjClass * mesh)
|
|
{
|
|
REF_PTR_SET(CollisionMesh,mesh);
|
|
StartTransform = EndTransform = CollisionMesh->Get_Transform();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::Intersect_Scene -- intersection test *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void
|
|
AnimCollisionManagerClass::CollideableObjClass::Intersect_Scene
|
|
(
|
|
int colgroup,
|
|
NonRefPhysListClass * intersect_list
|
|
)
|
|
{
|
|
if (CollisionMesh == NULL) return;
|
|
PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance();
|
|
|
|
#if VERBOSE_LOGGING
|
|
Vector3 pos = CollisionMesh->Get_Transform().Get_Translation();
|
|
WWDEBUG_SAY(("Checking obj: %s position: %10.2f, %10.2f, %10.2f\r\n",CollisionMesh->Get_Name(),pos.X,pos.Y,pos.Z));
|
|
#endif
|
|
|
|
switch (CollisionMesh->Class_ID()) {
|
|
case RenderObjClass::CLASSID_MESH:
|
|
{
|
|
MeshClass * mesh = (MeshClass *)CollisionMesh;
|
|
PhysMeshIntersectionTestClass test(mesh,colgroup,COLLISION_TYPE_PHYSICAL,intersect_list);
|
|
test.CheckStaticObjs = false;
|
|
scene->Intersection_Test(test);
|
|
VERBOSE_LOG(("Mesh intersection: %d\r\n",!intersect_list->Is_Empty()));
|
|
}
|
|
break;
|
|
|
|
case RenderObjClass::CLASSID_OBBOX:
|
|
{
|
|
OBBoxRenderObjClass * boxrobj = (OBBoxRenderObjClass *)CollisionMesh;
|
|
PhysOBBoxIntersectionTestClass test(boxrobj->Get_Box(),colgroup,COLLISION_TYPE_PHYSICAL,intersect_list);
|
|
test.CheckStaticObjs = false;
|
|
scene->Intersection_Test(test);
|
|
VERBOSE_LOG(("OBBox intersection: %d\r\n",!intersect_list->Is_Empty()));
|
|
}
|
|
break;
|
|
case RenderObjClass::CLASSID_AABOX:
|
|
{
|
|
AABoxRenderObjClass * boxrobj = (AABoxRenderObjClass *)CollisionMesh;
|
|
PhysAABoxIntersectionTestClass test(boxrobj->Get_Box(),colgroup,COLLISION_TYPE_PHYSICAL,intersect_list);
|
|
test.CheckStaticObjs = false;
|
|
scene->Intersection_Test(test);
|
|
VERBOSE_LOG(("AABox intersection: %d\r\n",!intersect_list->Is_Empty()));
|
|
}
|
|
break;
|
|
};
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::Clear_Collision_Bits -- disables collision *
|
|
* *
|
|
* Disables all collision on the render object that this CollideableObjClass is managing *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
int AnimCollisionManagerClass::CollideableObjClass::Clear_Collision_Bits(void)
|
|
{
|
|
int oldbits = CollisionMesh->Get_Collision_Type();
|
|
CollisionMesh->Set_Collision_Type(0);
|
|
return oldbits;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::CollideableObjClass::Restore_Collision_Bits -- set collision bit *
|
|
* *
|
|
* restores the collision bits on the render object that this CollideableObjClass is managing *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::CollideableObjClass::Restore_Collision_Bits(int oldbits)
|
|
{
|
|
CollisionMesh->Set_Collision_Type(oldbits);
|
|
}
|
|
|
|
|
|
/********************************************************************************************
|
|
**
|
|
** AnimCollisionManagerClass Implementation
|
|
**
|
|
********************************************************************************************/
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::AnimCollisionManagerClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::AnimCollisionManagerClass(PhysClass & parent) :
|
|
Parent(parent),
|
|
AnimationMode(ANIMATE_LOOP),
|
|
TargetFrame(0.0f),
|
|
LoopStart(0.0f),
|
|
LoopEnd(0.0f),
|
|
CurAnimation(NULL),
|
|
CurFrame(0.0f),
|
|
PrevAnimation(NULL),
|
|
PrevFrame(0.0f),
|
|
CollisionMode(COLLIDE_NONE),
|
|
PushList(NULL)
|
|
{
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::~AnimCollisionManagerClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::~AnimCollisionManagerClass(void)
|
|
{
|
|
WWASSERT(PushList == NULL);
|
|
REF_PTR_RELEASE(CurAnimation);
|
|
REF_PTR_RELEASE(PrevAnimation);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Animation_Mode -- set the current anim mode *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Animation_Mode(AnimModeType mode)
|
|
{
|
|
AnimationMode = mode;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Animation_Mode -- Get the current anim mode *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::AnimModeType
|
|
AnimCollisionManagerClass::Get_Animation_Mode(void)
|
|
{
|
|
return AnimationMode;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Animation -- Set the current animation *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Animation(const char * anim_name)
|
|
{
|
|
Internal_Set_Animation(anim_name);
|
|
|
|
/*
|
|
** Automatically loop this animation by default
|
|
*/
|
|
LoopStart = 0;
|
|
if (CurAnimation != NULL) {
|
|
LoopEnd = TargetFrame = CurAnimation->Get_Num_Frames() - 1;
|
|
} else {
|
|
LoopEnd = TargetFrame = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Internal_Set_Animation -- Set the current animation pointer *
|
|
* *
|
|
* This function doesn't change the animation mode, target frame, or current frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/13/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Internal_Set_Animation(const char * anim_name)
|
|
{
|
|
HAnimClass * anim = WW3DAssetManager::Get_Instance()->Get_HAnim(anim_name);
|
|
if ( anim == NULL && anim_name != NULL ) {
|
|
WWDEBUG_SAY(( "FAILED TO FIND ANIM IN AnimCollisionManagerClass::Internal_Set_Animation(\"%s\")\n", anim_name ));
|
|
}
|
|
REF_PTR_SET(CurAnimation,anim);
|
|
REF_PTR_RELEASE(anim);
|
|
|
|
if (Parent.Peek_Model() != NULL) {
|
|
Parent.Peek_Model()->Set_Animation(CurAnimation,CurFrame);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Peek_Animation -- Get the current animation *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
HAnimClass * AnimCollisionManagerClass::Peek_Animation(void)
|
|
{
|
|
return CurAnimation;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Target_Frame -- Set the target animation frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Target_Frame(float frame)
|
|
{
|
|
TargetFrame = frame;
|
|
Parent.Enable_Is_State_Dirty(true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Target_Frame_End -- Set the target frame to the end of the c *
|
|
* *
|
|
* Sets the target frame to the end of the current anim *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/13/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Target_Frame_End(void)
|
|
{
|
|
if (CurAnimation != NULL) {
|
|
Set_Target_Frame(CurAnimation->Get_Num_Frames() - 1);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Target_Frame -- Get the target animation frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
float AnimCollisionManagerClass::Get_Target_Frame(void)
|
|
{
|
|
return TargetFrame;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Is_At_Target -- returns true if in TARGET mode and done animatin *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/14/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Is_At_Target(void)
|
|
{
|
|
return ((TargetFrame == CurFrame) && (AnimationMode == ANIMATE_TARGET));
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Loop_Start -- Sets frame0 for an anim loop *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* This setting is only used if you are in AnimationMode==ANIMATE_LOOP *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/29/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Loop_Start(float frame0)
|
|
{
|
|
LoopStart = frame0;
|
|
Parent.Enable_Is_State_Dirty(true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Loop_End -- Sets frame1 for an anim loop *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* This setting is only used if you are in AnimationMode==ANIMATE_LOOP *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/29/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Loop_End(float frame1)
|
|
{
|
|
LoopEnd = frame1;
|
|
Parent.Enable_Is_State_Dirty(true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Loop_Start -- returns frame0 for an anim loop *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/29/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
float AnimCollisionManagerClass::Get_Loop_Start(void)
|
|
{
|
|
return LoopStart;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Loop_End -- returns frame1 for an anim loop *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/29/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
float AnimCollisionManagerClass::Get_Loop_End(void)
|
|
{
|
|
return LoopEnd;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Current_Frame -- Set the current frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Current_Frame(float frame)
|
|
{
|
|
CurFrame = frame;
|
|
Parent.Enable_Is_State_Dirty(true);
|
|
|
|
#if VERBOSE_LOGGING
|
|
WWASSERT(!Is_Intersecting());
|
|
#endif
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Current_Frame -- Get the current frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
float AnimCollisionManagerClass::Get_Current_Frame(void)
|
|
{
|
|
return CurFrame;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Set_Collision_Mode -- Set the current collision mode *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Set_Collision_Mode(CollisionModeType mode)
|
|
{
|
|
CollisionMode = mode;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Get_Collision_Mode -- Get the current collision mode *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
AnimCollisionManagerClass::CollisionModeType AnimCollisionManagerClass::Get_Collision_Mode(void)
|
|
{
|
|
return CollisionMode;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Init -- Init this collision manager *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Init(const AnimCollisionManagerDefClass & def)
|
|
{
|
|
/*
|
|
** Set the collision and animation mode
|
|
*/
|
|
CollisionMode = (CollisionModeType)def.CollisionMode;
|
|
AnimationMode = (AnimModeType)def.AnimationMode;
|
|
|
|
/*
|
|
** Plug in the animation
|
|
*/
|
|
if (Parent.Peek_Model()) {
|
|
Set_Current_Frame(0.0f);
|
|
|
|
/*
|
|
** Get the name of the animation from the definition
|
|
*/
|
|
StringClass anim_name = def.AnimationName;
|
|
|
|
/*
|
|
** If the user didn't specify an animation name, then
|
|
** build an animation name from the model name.
|
|
*/
|
|
if (anim_name.Is_Empty ()) {
|
|
StringClass model_name(Parent.Peek_Model()->Get_Name(),true);
|
|
anim_name = model_name;
|
|
anim_name+=".";
|
|
anim_name+=model_name;
|
|
}
|
|
|
|
Set_Animation(anim_name);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Update_Cached_Model_Parameters -- find all of the collideable me *
|
|
* *
|
|
* This function mainly finds all of the animating collideable meshes. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Update_Cached_Model_Parameters(void)
|
|
{
|
|
/*
|
|
** Build the array of collideable animated meshes
|
|
*/
|
|
int count = Recursive_Count_Collision_Models(Parent.Peek_Model());
|
|
CollisionMeshes.Delete_All();
|
|
CollisionMeshes.Resize(count);
|
|
|
|
Recursive_Collect_Collision_Models(Parent.Peek_Model());
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Is_Collision_Model -- classify a sub-object as collideable or no *
|
|
* *
|
|
* A sub object needs a collision object if it is attached to a bone other than the root *
|
|
* and it is collideable. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Is_Collision_Model(RenderObjClass * subobj)
|
|
{
|
|
/*
|
|
** If this sub-object is collideable and it is not attached to the RootTransform (0)
|
|
** then it is considered an animated collideable mesh.
|
|
*/
|
|
return ( (subobj->Get_Collision_Type() & COLLISION_TYPE_PHYSICAL) &&
|
|
(subobj->Get_Container() != NULL) &&
|
|
(subobj->Get_Container()->Get_Sub_Object_Bone_Index(subobj) != 0) );
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Recursive_Count_Collision_Models -- count the collideable meshes *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
int AnimCollisionManagerClass::Recursive_Count_Collision_Models(RenderObjClass * model)
|
|
{
|
|
int count = 0;
|
|
if (model == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
for (int i=0; i<model->Get_Num_Sub_Objects(); i++) {
|
|
RenderObjClass * subobj = model->Get_Sub_Object(i);
|
|
if (subobj->Get_Num_Sub_Objects() > 0) {
|
|
count += Recursive_Count_Collision_Models(subobj); // recurse
|
|
} else {
|
|
if (Is_Collision_Model(model)) {
|
|
count++;
|
|
}
|
|
}
|
|
subobj->Release_Ref();
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Recursive_Collect_Collision_Models -- collect collideable meshes *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Recursive_Collect_Collision_Models(RenderObjClass * model)
|
|
{
|
|
if (model == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (int i=0; i<model->Get_Num_Sub_Objects(); i++) {
|
|
RenderObjClass * subobj = model->Get_Sub_Object(i);
|
|
if (subobj->Get_Num_Sub_Objects() > 0) {
|
|
Recursive_Collect_Collision_Models(subobj); // recurse
|
|
} else {
|
|
|
|
/*
|
|
** If this sub-object is collideable and it is not attached to the RootTransform (0)
|
|
** then it is a candidate for being a collideable object
|
|
*/
|
|
if (Is_Collision_Model(subobj)) {
|
|
|
|
/*
|
|
** Add this collideable mesh to our array of collision meshes
|
|
*/
|
|
CollideableObjClass colmesh(subobj);
|
|
CollisionMeshes.Add(colmesh);
|
|
}
|
|
}
|
|
subobj->Release_Ref();
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Timestep -- Update the state of this object *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Timestep(float dt)
|
|
{
|
|
WWPROFILE("AnimColMgr::Timestep");
|
|
VERBOSE_LOG(("\r\nTimestep for %s - begin\r\n",Parent.Peek_Model()->Get_Name()));
|
|
bool object_animated = false;
|
|
|
|
/*
|
|
** In the case where we're not going to do anything bail out immediately!
|
|
*/
|
|
if ((CurFrame == PrevFrame) && (CurAnimation == PrevAnimation)) {
|
|
if (AnimationMode == ANIMATE_MANUAL) {
|
|
return false;
|
|
}
|
|
if ((AnimationMode == ANIMATE_TARGET) && (CurFrame == TargetFrame)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Store the collision transform prior to updating the animation
|
|
*/
|
|
if (CollisionMode != COLLIDE_NONE) {
|
|
for (int i=0; i<CollisionMeshes.Count(); i++) {
|
|
CollisionMeshes[i].Cache_Start_Transform();
|
|
}
|
|
}
|
|
|
|
#if VERBOSE_LOGGING
|
|
bool started_intersecting = false;
|
|
if (CollisionMode != COLLIDE_NONE) {
|
|
started_intersecting = Is_Intersecting();
|
|
WWDEBUG_SAY(("Checking started_intersecting: %d\r\n",started_intersecting));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** move animation forward
|
|
*/
|
|
if (CurAnimation != NULL) {
|
|
switch (AnimationMode) {
|
|
|
|
case ANIMATE_LOOP:
|
|
CurFrame += CurAnimation->Get_Frame_Rate() * dt;
|
|
|
|
if (CurFrame >= LoopEnd) {
|
|
CurFrame -= (LoopEnd - LoopStart);
|
|
}
|
|
break;
|
|
|
|
case ANIMATE_TARGET:
|
|
if (CurFrame < TargetFrame) {
|
|
CurFrame += CurAnimation->Get_Frame_Rate() * dt;
|
|
// if we overshoot targetframe, snap to targetframe
|
|
if (CurFrame >= TargetFrame) {
|
|
CurFrame = TargetFrame;
|
|
}
|
|
} else if (CurFrame > TargetFrame) {
|
|
CurFrame -= CurAnimation->Get_Frame_Rate() * dt;
|
|
// if we overshoot targetframe, snap to targetframe
|
|
if (CurFrame <= TargetFrame) {
|
|
CurFrame = TargetFrame;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ANIMATE_MANUAL:
|
|
break;
|
|
|
|
default:
|
|
WWASSERT_PRINT(0,("Invalid Animation Mode!\n"));
|
|
|
|
}
|
|
|
|
VERBOSE_LOG(("Cur-Frame: %f Target-Frame: %f\r\n",CurFrame,TargetFrame));
|
|
Parent.Peek_Model()->Set_Animation(CurAnimation,CurFrame);
|
|
}
|
|
|
|
/*
|
|
** Check for collisions.
|
|
** - cache a copy of the ending transform for each collideable object
|
|
** - revert all collideable objects back to their start transform
|
|
** - for each object:
|
|
** - install its ending transform and check for collision.
|
|
** - if collided, compute the movement vector and push objects.
|
|
** - if unable to push objects out of the way, set the revert flag and exit
|
|
*/
|
|
if ((CurAnimation != PrevAnimation) || (CurFrame != PrevFrame)) {
|
|
|
|
/*
|
|
** Add our riders to our push list
|
|
*/
|
|
object_animated = true;
|
|
bool intersecting = false;
|
|
|
|
if (CollisionMode != COLLIDE_NONE) {
|
|
int ci;
|
|
|
|
/*
|
|
** Save the transform as the "ending transform"
|
|
** and roll back to the starting transform
|
|
*/
|
|
for (ci=0; ci<CollisionMeshes.Count(); ci++) {
|
|
CollisionMeshes[ci].Cache_End_Transform();
|
|
CollisionMeshes[ci].Install_Start_Transform();
|
|
}
|
|
|
|
/*
|
|
** Move this mesh forward to the End Transform
|
|
** and see if it collides with anything
|
|
*/
|
|
for (ci=0; (ci<CollisionMeshes.Count()) && (!intersecting); ci++) {
|
|
CollisionMeshes[ci].Install_End_Transform();
|
|
intersecting |= Check_Collision(CollisionMeshes[ci]);
|
|
}
|
|
|
|
/*
|
|
** If we ended up intersecting, then we have to revert
|
|
*/
|
|
if (intersecting) {
|
|
Revert_Animation_State();
|
|
object_animated = false;
|
|
}
|
|
|
|
#if VERBOSE_LOGGING
|
|
WWDEBUG_SAY(("checking is_now_intersecting\r\n"));
|
|
bool is_now_intersecting = Is_Intersecting();
|
|
if ( (started_intersecting == false) && (is_now_intersecting == true)) {
|
|
WWDEBUG_SAY(("Reverting did not fix intersections!\r\n"));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Release the push records
|
|
*/
|
|
PushRecordClass::Delete_List(PushList);
|
|
PushList = NULL;
|
|
|
|
/*
|
|
** Ratchet our animation state forward for the next frame
|
|
*/
|
|
REF_PTR_RELEASE(PrevAnimation);
|
|
REF_PTR_SET(PrevAnimation,CurAnimation);
|
|
PrevFrame = CurFrame;
|
|
|
|
VERBOSE_LOG(("Timestep - done\r\n"));
|
|
return object_animated;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Revert_Animation_State -- revert to previous anim frame *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
void AnimCollisionManagerClass::Revert_Animation_State(void)
|
|
{
|
|
REF_PTR_SET(CurAnimation,PrevAnimation);
|
|
CurFrame = PrevFrame;
|
|
Parent.Peek_Model()->Set_Animation(CurAnimation,CurFrame);
|
|
|
|
VERBOSE_LOG(("Reverted to frame: %f\r\n",CurFrame));
|
|
|
|
/*
|
|
** Force the transforms of the collideable meshes to update
|
|
*/
|
|
for (int ci=0; ci<CollisionMeshes.Count(); ci++) {
|
|
CollisionMeshes[ci].Cache_End_Transform();
|
|
CollisionMeshes[ci].Install_End_Transform();
|
|
}
|
|
|
|
/*
|
|
** Put everyone that we pushed back into their original state
|
|
*/
|
|
PushRecordClass::Revert_List(PushList);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Check_Collision -- Check the given collision object *
|
|
* *
|
|
* This returns true if the object collided with something and could not move it out of the *
|
|
* way. (You must revert or kill the object in this case) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Check_Collision(CollideableObjClass & collisionobj)
|
|
{
|
|
/*
|
|
** Algorithm:
|
|
** - Determine how each attached object should move due to our motion.
|
|
** - Ask all of our attached objects to apply the same delta.
|
|
** - Ask physics scene to do an intersection test between our mesh and all nearby dynamic objects
|
|
** - If (CollisionMode == STOP) REVERT animation and return
|
|
** - Else For each object intersecting the collision mesh:
|
|
** - If it is one of our attached objects, SQUISH and REVERT
|
|
** - Else
|
|
** - Determine how the collided object should move and try to move it
|
|
** - If still colliding, SQUISH and REVERT
|
|
** - Else OK
|
|
** - If no object caused a revert, ACCEPT new animation state and return.
|
|
** - Else REVERT and return
|
|
*/
|
|
|
|
/*
|
|
** Compute the change in the transform of the collision mesh. Note that this
|
|
** is currently only "supposed" to work with pure translational motion...
|
|
*/
|
|
Matrix3D delta_transform;
|
|
Matrix3D pinv;
|
|
|
|
collisionobj.Get_Start_Transform().Get_Orthogonal_Inverse(pinv);
|
|
Matrix3D::Multiply(collisionobj.Get_End_Transform(),pinv,&delta_transform);
|
|
|
|
/*
|
|
** Make all attached objects move with us (people stick on elevators, etc)
|
|
** Adding a push record for each rider in case it gets moved...
|
|
*/
|
|
int collision_bits = collisionobj.Clear_Collision_Bits();
|
|
|
|
NonRefPhysListIterator rider_iterator(RiderManager.Get_Rider_List());
|
|
VERBOSE_LOG((" rider_list: "));
|
|
while (!rider_iterator.Is_Done()) {
|
|
VERBOSE_LOG(("%s, ",rider_iterator.Peek_Obj()->Peek_Model()->Get_Name()));
|
|
PushRecordClass::Add_To_List(&PushList,rider_iterator.Peek_Obj());
|
|
rider_iterator.Next();
|
|
}
|
|
VERBOSE_LOG(("\r\n"));
|
|
|
|
RiderManager.Move_Riders(delta_transform,collisionobj.Peek_Collision_Object());
|
|
collisionobj.Restore_Collision_Bits(collision_bits);
|
|
|
|
/*
|
|
** Perform intersection detection
|
|
*/
|
|
VERBOSE_LOG(("Check Collision: %s\r\n",collisionobj.Peek_Collision_Object()->Get_Name()));
|
|
NonRefPhysListClass intersection_list;
|
|
collisionobj.Intersect_Scene(Parent.Get_Collision_Group(),&intersection_list);
|
|
|
|
/*
|
|
** If nothing is intersecting us, return.
|
|
*/
|
|
if (intersection_list.Is_Empty()) {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** CollisionMode == COLLIDE_STOP
|
|
** If something is intersecting us and we just revert when that happens, revert and return
|
|
*/
|
|
if (CollisionMode == COLLIDE_STOP) {
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
** CollisionMode == COLLIDE_KILL
|
|
** If something is intersecting us and we are in KILL mode, then we kill them!
|
|
*/
|
|
if (CollisionMode == COLLIDE_KILL) {
|
|
NonRefPhysListIterator it(&intersection_list);
|
|
for (it.First(); !it.Is_Done(); it.Next()) {
|
|
it.Peek_Obj()->Expire();
|
|
}
|
|
}
|
|
|
|
/*
|
|
** CollisionMode == COLLIDE_PUSH
|
|
** Handle collisions by pushing the objects out of our way
|
|
*/
|
|
bool revert = false;
|
|
NonRefPhysListIterator it(&intersection_list);
|
|
for (it.First();!it.Is_Done();it.Next()) {
|
|
PhysClass * obj = it.Peek_Obj();
|
|
|
|
VERBOSE_LOG(("intersecting object: %s\r\n",obj->Peek_Model()->Get_Name()));
|
|
|
|
if (RiderManager.Contains(obj) && (obj->Peek_Carrier_Sub_Object() == collisionobj.Peek_Collision_Object())) {
|
|
|
|
/*
|
|
** If an object that we hit is attached to us already, squish and revert
|
|
*/
|
|
//obj->Notify_Squished(this);
|
|
revert = true;
|
|
#pragma message ("(gth) commenting out rider squishing code for critical review!")
|
|
VERBOSE_LOG(("Squishing a rider!\r\n"));
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Otherwise, try to push the object out of our way.
|
|
*/
|
|
int collision_bits = collisionobj.Clear_Collision_Bits();
|
|
if (Push_Collided_Object(obj,delta_transform) == false) {
|
|
VERBOSE_LOG(("SAPO %s Failed to push a rider\r\n",Parent.Peek_Model()->Get_Name()));
|
|
revert = true;
|
|
}
|
|
collisionobj.Restore_Collision_Bits(collision_bits);
|
|
}
|
|
}
|
|
|
|
return revert;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Is_Intersecting -- intersection test *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Is_Intersecting(void)
|
|
{
|
|
NonRefPhysListClass intersection_list;
|
|
for (int ci=0; ci<CollisionMeshes.Count() && intersection_list.Is_Empty(); ci++) {
|
|
CollisionMeshes[ci].Intersect_Scene(Parent.Get_Collision_Group(),&intersection_list);
|
|
}
|
|
return !intersection_list.Is_Empty();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Push_Collided_Object -- push an object we collided with *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Push_Collided_Object(PhysClass * obj,const Matrix3D & delta_transform)
|
|
{
|
|
bool result = false;
|
|
MoveablePhysClass * move_obj = obj->As_MoveablePhysClass();
|
|
if (move_obj != NULL) {
|
|
|
|
VERBOSE_LOG(("Pushing object: %s, vector: (%f, %f, %f)\r\n",move_obj->Peek_Model()->Get_Name(),
|
|
delta_transform.Get_Translation().X,
|
|
delta_transform.Get_Translation().Y,
|
|
delta_transform.Get_Translation().Z ));
|
|
|
|
PushRecordClass::Add_To_List(&PushList,obj);
|
|
result = move_obj->Push(delta_transform.Get_Translation());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Save -- save! *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Save(ChunkSaveClass &csave)
|
|
{
|
|
csave.Begin_Chunk(ANIMCOLLISIONMANAGER_CHUNK_VARIABLES);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_COLLISIONMODE,CollisionMode);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONMODE,AnimationMode);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_TARGETFRAME,TargetFrame);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_CURFRAME,CurFrame);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_PREVFRAME,PrevFrame);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_LOOPSTART,LoopStart);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGER_VARIABLE_LOOPEND,LoopEnd);
|
|
|
|
if (CurAnimation != NULL) {
|
|
WRITE_MICRO_CHUNK_STRING(csave,ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONNAME,CurAnimation->Get_Name());
|
|
}
|
|
|
|
if (PrevAnimation != NULL) {
|
|
WRITE_MICRO_CHUNK_STRING(csave,ANIMCOLLISIONMANAGER_VARIABLE_PREVANIMATIONNAME,PrevAnimation->Get_Name());
|
|
}
|
|
|
|
csave.End_Chunk();
|
|
return true;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* AnimCollisionManagerClass::Load -- Load! *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 8/9/2000 gth : Created. *
|
|
*=============================================================================================*/
|
|
bool AnimCollisionManagerClass::Load(ChunkLoadClass &cload)
|
|
{
|
|
StringClass anim_name;
|
|
StringClass prev_anim_name;
|
|
|
|
/*
|
|
** Read in the chunks from the file
|
|
*/
|
|
while (cload.Open_Chunk()) {
|
|
|
|
switch(cload.Cur_Chunk_ID())
|
|
{
|
|
case ANIMCOLLISIONMANAGER_CHUNK_VARIABLES:
|
|
|
|
while (cload.Open_Micro_Chunk()) {
|
|
switch(cload.Cur_Micro_Chunk_ID()) {
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_COLLISIONMODE,CollisionMode);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONMODE,AnimationMode);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_TARGETFRAME,TargetFrame);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_CURFRAME,CurFrame);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_PREVFRAME,PrevFrame);
|
|
READ_MICRO_CHUNK_WWSTRING(cload,ANIMCOLLISIONMANAGER_VARIABLE_ANIMATIONNAME,anim_name);
|
|
READ_MICRO_CHUNK_WWSTRING(cload,ANIMCOLLISIONMANAGER_VARIABLE_PREVANIMATIONNAME,prev_anim_name);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_LOOPSTART,LoopStart);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGER_VARIABLE_LOOPEND,LoopEnd);
|
|
}
|
|
cload.Close_Micro_Chunk();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
|
|
break;
|
|
};
|
|
|
|
cload.Close_Chunk();
|
|
}
|
|
|
|
if (!anim_name.Is_Empty()) {
|
|
Internal_Set_Animation(anim_name);
|
|
}
|
|
|
|
if (!prev_anim_name.Is_Empty()) {
|
|
HAnimClass * anim = WW3DAssetManager::Get_Instance()->Get_HAnim(prev_anim_name);
|
|
if ( anim == NULL ) {
|
|
WWDEBUG_SAY(( "FAILED TO FIND PREV ANIM IN AnimCollisionManagerClass::Internal_Set_Animation(\"%s\")\n", prev_anim_name ));
|
|
}
|
|
REF_PTR_SET(PrevAnimation,anim);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/********************************************************************************************
|
|
**
|
|
** AnimCollisionManagerDefClass Implementation
|
|
** Note, AnimCollisionManagerDef is not a full-fleged definition class. It is meant to be
|
|
** embedded inside another real definition. (e.g. StaticAnimPhys)
|
|
**
|
|
********************************************************************************************/
|
|
|
|
enum
|
|
{
|
|
ANIMCOLLISIONMANAGERDEF_CHUNK_VARIABLES = 525000306,
|
|
|
|
ANIMCOLLISIONMANAGERDEF_VARIABLE_COLLISIONMODE = 0x00,
|
|
ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONMODE,
|
|
ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONNAME,
|
|
};
|
|
|
|
AnimCollisionManagerDefClass::AnimCollisionManagerDefClass(void) :
|
|
CollisionMode(AnimCollisionManagerClass::COLLIDE_PUSH),
|
|
AnimationMode(AnimCollisionManagerClass::ANIMATE_LOOP)
|
|
{
|
|
}
|
|
|
|
AnimCollisionManagerDefClass::~AnimCollisionManagerDefClass(void)
|
|
{
|
|
}
|
|
|
|
void AnimCollisionManagerDefClass::Validate_Parameters(void)
|
|
{
|
|
if (CollisionMode < 0) CollisionMode = 0;
|
|
if (CollisionMode > AnimCollisionManagerClass::ANIMATE_MANUAL) CollisionMode = AnimCollisionManagerClass::ANIMATE_MANUAL;
|
|
}
|
|
|
|
bool AnimCollisionManagerDefClass::Save(ChunkSaveClass &csave)
|
|
{
|
|
Validate_Parameters();
|
|
|
|
csave.Begin_Chunk(ANIMCOLLISIONMANAGERDEF_CHUNK_VARIABLES);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGERDEF_VARIABLE_COLLISIONMODE,CollisionMode);
|
|
WRITE_MICRO_CHUNK(csave,ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONMODE,AnimationMode);
|
|
WRITE_MICRO_CHUNK_WWSTRING(csave,ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONNAME,AnimationName);
|
|
csave.End_Chunk();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AnimCollisionManagerDefClass::Load(ChunkLoadClass &cload)
|
|
{
|
|
while (cload.Open_Chunk()) {
|
|
|
|
switch(cload.Cur_Chunk_ID()) {
|
|
|
|
case ANIMCOLLISIONMANAGERDEF_CHUNK_VARIABLES:
|
|
while (cload.Open_Micro_Chunk()) {
|
|
switch(cload.Cur_Micro_Chunk_ID()) {
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGERDEF_VARIABLE_COLLISIONMODE,CollisionMode);
|
|
READ_MICRO_CHUNK(cload,ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONMODE,AnimationMode);
|
|
READ_MICRO_CHUNK_WWSTRING(cload,ANIMCOLLISIONMANAGERDEF_VARIABLE_ANIMATIONNAME,AnimationName);
|
|
}
|
|
cload.Close_Micro_Chunk();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
|
|
break;
|
|
}
|
|
|
|
cload.Close_Chunk();
|
|
}
|
|
return true;
|
|
}
|
|
|