Work on collision related implementations

This commit is contained in:
Jack Andersen 2017-06-17 15:58:13 -10:00
parent 47e73f9f80
commit 71a361f54e
32 changed files with 1521 additions and 134 deletions

View File

@ -0,0 +1,16 @@
#include "CAABoxFilter.hpp"
namespace urde
{
void CAABoxFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const
{
FilterBoxFloorCollisions(in, out);
}
void CAABoxFilter::FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out)
{
/* TODO: finish */
}
}

View File

@ -0,0 +1,19 @@
#ifndef __URDE_CAABOXFILTER_HPP__
#define __URDE_CAABOXFILTER_HPP__
#include "ICollisionFilter.hpp"
namespace urde
{
class CAABoxFilter : public ICollisionFilter
{
public:
CAABoxFilter(CActor& actor) : ICollisionFilter(actor) {}
void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const;
static void FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out);
};
}
#endif // __URDE_CAABOXFILTER_HPP__

View File

@ -0,0 +1,11 @@
#include "CBallFilter.hpp"
namespace urde
{
void CBallFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const
{
}
}

View File

@ -0,0 +1,19 @@
#ifndef __URDE_CBALLFILTER_HPP__
#define __URDE_CBALLFILTER_HPP__
#include "ICollisionFilter.hpp"
namespace urde
{
class CPhysicsActor;
class CBallFilter : public ICollisionFilter
{
public:
CBallFilter(CActor& actor) : ICollisionFilter(actor) {}
void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const;
};
}
#endif // __URDE_CBALLFILTER_HPP__

View File

@ -1,4 +1,5 @@
#include "CCollidableAABox.hpp"
#include "CollisionUtil.hpp"
namespace urde
{
@ -68,14 +69,26 @@ bool CCollidableAABox::CollideMovingSphere(const CInternalCollisionStructure &,
namespace Collide
{
bool AABox_AABox(const CInternalCollisionStructure &, CCollisionInfoList &)
bool AABox_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list)
{
return false;
const CCollidableAABox& box0 = static_cast<const CCollidableAABox&>(collision.GetLeft().GetPrim());
const CCollidableAABox& box1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform());
return CollisionUtil::AABoxAABoxIntersection(aabb0, box0.GetMaterial(), aabb1, box1.GetMaterial(), list);
}
bool AABox_AABox_Bool(const CInternalCollisionStructure &)
bool AABox_AABox_Bool(const CInternalCollisionStructure& collision)
{
return false;
const CCollidableAABox& box0 = static_cast<const CCollidableAABox&>(collision.GetLeft().GetPrim());
const CCollidableAABox& box1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform());
return CollisionUtil::AABoxAABoxIntersection(aabb0, aabb1);
}
}

View File

@ -28,6 +28,7 @@ public:
virtual zeus::CAABox CalculateLocalAABox() const;
virtual FourCC GetPrimType() const;
virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const;
const zeus::CAABox& GetAABB() const { return x10_aabox; }
static const CCollisionPrimitive::Type& GetType();
static void SetStaticTableIndex(u32 index);

View File

@ -32,6 +32,11 @@ void CCollidableSphere::SetSphereCenter(const zeus::CVector3f&)
}
zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const
{
return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius);
}
u32 CCollidableSphere::GetTableIndex() const { return sTableIndex; }
zeus::CAABox CCollidableSphere::CalculateAABox(const zeus::CTransform&) const { return {}; }

View File

@ -25,6 +25,7 @@ public:
const zeus::CSphere& GetSphere() const;
void SetSphereCenter(const zeus::CVector3f&);
zeus::CSphere Transform(const zeus::CTransform& xf) const;
virtual u32 GetTableIndex() const;
virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const;

View File

@ -3,9 +3,30 @@
namespace urde
{
CCollisionInfo CCollisionInfo::GetSwapped() const
{
CCollisionInfo ret;
ret.x0_point = x0_point;
ret.xc_ = xc_;
ret.x30_valid = x30_valid;
ret.x31_ = x31_;
ret.x38_materialLeft = x40_materialRight;
ret.x40_materialRight = x38_materialLeft;
ret.x48_normalLeft = x54_normalRight;
ret.x54_normalRight = x48_normalLeft;
return ret;
}
void CCollisionInfo::Swap()
{
x48_normalLeft = -x48_normalLeft;
x54_normalRight = -x54_normalRight;
std::swap(x38_materialLeft, x40_materialRight);
}
zeus::CVector3f CCollisionInfo::GetExtreme() const
{
return (x18_ + (x0_aabox.min + x0_aabox.max) + x24_);
return x0_point + xc_ + x18_ + x24_;
}
}

View File

@ -4,42 +4,54 @@
#include "RetroTypes.hpp"
#include "CMaterialList.hpp"
#include "zeus/CAABox.hpp"
#include "zeus/CMatrix3f.hpp"
namespace urde
{
class CCollisionInfo
{
zeus::CAABox x0_aabox = zeus::CAABox::skNullBox;
zeus::CVector3f x0_point;
zeus::CVector3f xc_;
zeus::CVector3f x18_;
zeus::CVector3f x24_;
bool x30_ = false;
bool x30_valid = false;
bool x31_ = false;
/* u32 x34_; */
CMaterialList x38_;
CMaterialList x40_;
zeus::CVector3f x48_;
zeus::CVector3f x54_;
CMaterialList x38_materialLeft;
CMaterialList x40_materialRight;
zeus::CVector3f x48_normalLeft;
zeus::CVector3f x54_normalRight;
public:
CCollisionInfo() = default;
CCollisionInfo(const zeus::CVector3f& v1, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& v2, const zeus::CVector3f& v3);
CCollisionInfo(const zeus::CVector3f& v1, const CMaterialList& list1, const CMaterialList& list2,
zeus::CVector3f const& v2);
CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight)
: x0_point(point), x30_valid(true), x31_(false), x38_materialLeft(list2), x40_materialRight(list1),
x48_normalLeft(normalLeft), x54_normalRight(normalRight) {}
CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& normal)
: x0_point(point), x30_valid(true), x31_(false), x38_materialLeft(list2), x40_materialRight(list1),
x48_normalLeft(normal), x54_normalRight(-normal) {}
CCollisionInfo(const zeus::CAABox& aabox, const CMaterialList& list1, const CMaterialList& list2,
const zeus::CVector3f& v1, const zeus::CVector3f& v2)
: x0_aabox(aabox)
const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight)
: x0_point(aabox.min),
xc_(aabox.max.x - aabox.min.x, 0.f, 0.f),
x18_(0.f, aabox.max.y - aabox.min.y, 0.f),
x24_(0.f, 0.f, aabox.max.z - aabox.min.z),
x30_valid(true), x31_(true), x38_materialLeft(list2),
x40_materialRight(list1), x48_normalLeft(normalLeft),
x54_normalRight(normalRight)
{}
bool IsValid() const;
void GetMaterialLeft() const;
void GetMaterialRight() const;
CCollisionInfo GetSwapped() const;
bool IsValid() const { return x30_valid; }
const CMaterialList& GetMaterialLeft() const { return x38_materialLeft; }
const CMaterialList& GetMaterialRight() const { return x40_materialRight; }
zeus::CVector3f GetExtreme() const;
void Swap();
void Transform(const zeus::CTransform&);
zeus::CVector3f GetNormalLeft() const;
zeus::CVector3f GetNormalRight() const;
zeus::CVector3f GetNormalLeft() const { return x48_normalLeft; }
zeus::CVector3f GetNormalRight() const { return x54_normalRight; }
zeus::CVector3f GetOrigin() const;
zeus::CVector3f GetPoint() const;
zeus::CVector3f GetPoint() const { return x0_point; }
};
}

View File

@ -2,10 +2,10 @@
#define __URDE_CCOLLISIONINFOLIST_HPP__
#include "RetroTypes.hpp"
#include "CCollisionInfo.hpp"
namespace urde
{
class CCollisionInfo;
class CCollisionInfoList
{
rstl::reserved_vector<CCollisionInfo, 32> x0_list;
@ -15,15 +15,23 @@ public:
void GetAverageLeftNormal() const;
void GetAveragePoint() const;
void GetUnionOfAllLeftMaterials() const;
s32 GetCount() const;
s32 GetCount() const { return x0_list.size(); }
void Swap(s32);
void Add(const CCollisionInfo&, bool);
void Clear();
void End();
void End() const;
void Begin();
void Begin() const;
void Add(const CCollisionInfo& info, bool swap)
{
if (x0_list.size() == 32)
return;
if (!swap)
x0_list.push_back(info);
else
x0_list.push_back(info.GetSwapped());
}
void Clear() { x0_list.clear(); }
rstl::reserved_vector<CCollisionInfo, 32>::iterator end() { return x0_list.end(); }
rstl::reserved_vector<CCollisionInfo, 32>::const_iterator end() const { return x0_list.end(); }
rstl::reserved_vector<CCollisionInfo, 32>::iterator begin() { return x0_list.begin(); }
rstl::reserved_vector<CCollisionInfo, 32>::const_iterator begin() const { return x0_list.begin(); }
};
}

View File

@ -2,18 +2,23 @@
#include "CInternalRayCastStructure.hpp"
#include "CMaterialFilter.hpp"
#include "InternalColliders.hpp"
#include "CCollisionInfoList.hpp"
namespace urde
{
std::unique_ptr<std::vector<CCollisionPrimitive::Type>> CCollisionPrimitive::sCollisionTypeList;
std::unique_ptr<std::vector<ComparisonFunc>> CCollisionPrimitive::sTableOfCollidables;
std::unique_ptr<std::vector<BooleanComparisonFunc>> CCollisionPrimitive::sTableOfBooleanCollidables;
std::unique_ptr<std::vector<MovingComparisonFunc>> CCollisionPrimitive::sTableOfMovingCollidables;
s32 CCollisionPrimitive::sNumTypes = 0;
bool CCollisionPrimitive::sInitComplete = false;
bool CCollisionPrimitive::sTypesAdded = false;
bool CCollisionPrimitive::sTypesAdding = false;
bool CCollisionPrimitive::sCollidersAdded = false;
bool CCollisionPrimitive::sCollidersAdding = false;
std::unique_ptr<std::vector<CCollisionPrimitive::Type>> CCollisionPrimitive::sCollisionTypeList;
std::unique_ptr<std::vector<ComparisonFunc>> CCollisionPrimitive::sTableOfCollidables;
std::unique_ptr<std::vector<BooleanComparisonFunc>> CCollisionPrimitive::sTableOfBooleanCollidables;
std::unique_ptr<std::vector<MovingComparisonFunc>> CCollisionPrimitive::sTableOfMovingCollidables;
ComparisonFunc CCollisionPrimitive::sNullCollider = {};
BooleanComparisonFunc CCollisionPrimitive::sNullBooleanCollider = {};
MovingComparisonFunc CCollisionPrimitive::sNullMovingCollider = {};
CCollisionPrimitive::CCollisionPrimitive(const CMaterialList& list) : x8_material(list) {}
void CCollisionPrimitive::SetMaterial(const CMaterialList& material) { x8_material = material; }
@ -26,6 +31,119 @@ CRayCastResult CCollisionPrimitive::CastRay(const zeus::CVector3f& start, const
return CastRayInternal(CInternalRayCastStructure(start, dir, length, xf, filter));
}
bool CCollisionPrimitive::InternalCollide(const CInternalCollisionStructure& collision,
CCollisionInfoList& list)
{
u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex();
u32 idx1 = collision.GetRight().GetPrim().GetTableIndex();
ComparisonFunc func;
if (idx0 == -1 || idx1 == -1)
{
sNullCollider = nullptr;
func = sNullCollider;
}
else
{
func = (*sTableOfCollidables)[sNumTypes * idx1 + idx0];
}
if (func)
{
if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) ||
!collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial()))
return false;
return func(collision, list);
}
if (idx0 == -1 || idx1 == -1)
{
sNullCollider = nullptr;
func = sNullCollider;
}
else
{
func = (*sTableOfCollidables)[sNumTypes * idx0 + idx1];
}
if (func)
{
if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) ||
!collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial()))
return false;
CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft());
u32 startListCount = list.GetCount();
if (func(swappedCollision, list))
{
for (auto it = list.begin() + startListCount ; it != list.end() ; ++it)
it->Swap();
return true;
}
}
return false;
}
bool CCollisionPrimitive::Collide(CInternalCollisionStructure::CPrimDesc& prim0,
CInternalCollisionStructure::CPrimDesc& prim1,
CCollisionInfoList& list)
{
return InternalCollide({prim0, prim1}, list);
}
bool CCollisionPrimitive::InternalCollideBoolean(const CInternalCollisionStructure& collision)
{
u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex();
u32 idx1 = collision.GetRight().GetPrim().GetTableIndex();
BooleanComparisonFunc func;
if (idx0 == -1 || idx1 == -1)
{
sNullBooleanCollider = nullptr;
func = sNullBooleanCollider;
}
else
{
func = (*sTableOfBooleanCollidables)[sNumTypes * idx1 + idx0];
}
if (func)
{
if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) ||
!collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial()))
return false;
return func(collision);
}
if (idx0 == -1 || idx1 == -1)
{
sNullBooleanCollider = nullptr;
func = sNullBooleanCollider;
}
else
{
func = (*sTableOfBooleanCollidables)[sNumTypes * idx0 + idx1];
}
if (func)
{
if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) ||
!collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial()))
return false;
CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft());
return func(swappedCollision);
}
CCollisionInfoList list;
return InternalCollide(collision, list);
}
bool CCollisionPrimitive::CollideBoolean(CInternalCollisionStructure::CPrimDesc& prim0,
CInternalCollisionStructure::CPrimDesc& prim1)
{
return InternalCollideBoolean({prim0, prim1});
}
void CCollisionPrimitive::InitBeginTypes()
{
sCollisionTypeList.reset(new std::vector<CCollisionPrimitive::Type>());
@ -37,67 +155,154 @@ void CCollisionPrimitive::InitBeginTypes()
void CCollisionPrimitive::InitAddType(const CCollisionPrimitive::Type& tp)
{
tp.GetSetter()(sCollisionTypeList->size());
sCollisionTypeList->reserve(sCollisionTypeList->size() + 1);
sCollisionTypeList->push_back(tp);
}
void CCollisionPrimitive::InitEndTypes() { sTypesAdding = false; }
void CCollisionPrimitive::InitEndTypes()
{
sCollisionTypeList->shrink_to_fit();
sNumTypes = sCollisionTypeList->size();
sTypesAdding = false;
sTypesAdded = true;
}
void CCollisionPrimitive::InitBeginColliders()
{
sTableOfCollidables.reset(new std::vector<ComparisonFunc>());
sTableOfBooleanCollidables.reset(new std::vector<BooleanComparisonFunc>());
sTableOfMovingCollidables.reset(new std::vector<MovingComparisonFunc>());
size_t tableSz = sCollisionTypeList->size() * sCollisionTypeList->size();
sTableOfCollidables->resize(tableSz);
sTableOfBooleanCollidables->resize(tableSz);
sTableOfMovingCollidables->resize(tableSz);
sCollidersAdding = true;
InternalColliders::AddColliders();
}
void CCollisionPrimitive::InitAddBooleanCollider(const CCollisionPrimitive::BooleanComparison& cmp)
{
int idx0 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo()))
{
idx0 = i;
break;
}
}
int idx1 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo()))
{
idx1 = i;
break;
}
}
if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes)
return;
BooleanComparisonFunc& funcOut =
(idx0 == -1 || idx1 == -1) ? sNullBooleanCollider : (*sTableOfBooleanCollidables)[idx1 * sNumTypes + idx0];
funcOut = cmp.GetCollider();
}
void CCollisionPrimitive::InitAddBooleanCollider(const BooleanComparisonFunc& cmp, const char* a, const char* b)
void CCollisionPrimitive::InitAddBooleanCollider(BooleanComparisonFunc cmp, const char* a, const char* b)
{
InitAddBooleanCollider({std::move(cmp), a, b});
InitAddBooleanCollider({cmp, a, b});
}
void CCollisionPrimitive::InitAddMovingCollider(const CCollisionPrimitive::MovingComparison& cmp) {}
void CCollisionPrimitive::InitAddMovingCollider(const MovingComparisonFunc& cmp, const char* a, const char* b)
void CCollisionPrimitive::InitAddMovingCollider(const CCollisionPrimitive::MovingComparison& cmp)
{
InitAddMovingCollider({std::move(cmp), a, b});
int idx0 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo()))
{
idx0 = i;
break;
}
}
int idx1 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo()))
{
idx1 = i;
break;
}
}
if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes)
return;
MovingComparisonFunc& funcOut =
(idx0 == -1 || idx1 == -1) ? sNullMovingCollider : (*sTableOfMovingCollidables)[idx1 * sNumTypes + idx0];
funcOut = cmp.GetCollider();
}
void CCollisionPrimitive::InitAddMovingCollider(MovingComparisonFunc cmp, const char* a, const char* b)
{
InitAddMovingCollider({cmp, a, b});
}
void CCollisionPrimitive::InitAddCollider(const CCollisionPrimitive::Comparison& cmp)
{
int idx0 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo()))
{
idx0 = i;
break;
}
}
int idx1 = -1;
for (int i=0 ; i<sCollisionTypeList->size() ; ++i)
{
if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo()))
{
idx1 = i;
break;
}
}
if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes)
return;
ComparisonFunc& funcOut =
(idx0 == -1 || idx1 == -1) ? sNullCollider : (*sTableOfCollidables)[idx1 * sNumTypes + idx0];
funcOut = cmp.GetCollider();
}
void CCollisionPrimitive::InitAddCollider(const ComparisonFunc& cmp, const char* a, const char* b)
void CCollisionPrimitive::InitAddCollider(ComparisonFunc cmp, const char* a, const char* b)
{
InitAddCollider({std::move(cmp), a, b});
InitAddCollider({cmp, a, b});
}
void CCollisionPrimitive::InitEndColliders()
{
sCollidersAdding = false;
sCollidersAdded = true;
sInitComplete = true;
}
void CCollisionPrimitive::Unitialize()
void CCollisionPrimitive::Uninitialize()
{
sInitComplete = false;
sCollidersAdding = false;
sCollidersAdded = false;
sTypesAdding = false;
sTypesAdded = false;
sNumTypes = 0;
sCollisionTypeList.reset();
sTableOfCollidables.reset();
sTableOfMovingCollidables.reset();
sTableOfBooleanCollidables.reset();
}
CCollisionPrimitive::Type::Type(const std::function<void(u32)>& setter, const char* info)
: x0_setter(setter), x4_info(info)
{
}
const char* CCollisionPrimitive::Type::GetInfo() const { return x4_info; }
std::function<void(u32)> CCollisionPrimitive::Type::GetSetter() const { return x0_setter; }
}

View File

@ -9,33 +9,60 @@
namespace urde
{
class CCollisionPrimitive;
class CMaterialFilter;
class CInternalCollisionStructure
{
public:
class CPrimDesc
{
const CCollisionPrimitive& x0_prim;
const CMaterialFilter& x4_filter;
zeus::CTransform x8_xf;
public:
CPrimDesc(const CCollisionPrimitive& prim, const CMaterialFilter& filter,
const zeus::CTransform& xf)
: x0_prim(prim), x4_filter(filter), x8_xf(xf) {}
const CCollisionPrimitive& GetPrim() const { return x0_prim; }
const CMaterialFilter& GetFilter() const { return x4_filter; }
const zeus::CTransform& GetTransform() const { return x8_xf; }
};
private:
CPrimDesc x0_p0;
CPrimDesc x38_p1;
public:
CInternalCollisionStructure(const CPrimDesc& p0, const CPrimDesc& p1)
: x0_p0(p0), x38_p1(p1) {}
const CPrimDesc& GetLeft() const { return x0_p0; }
const CPrimDesc& GetRight() const { return x38_p1; }
};
class COBBTree;
class CInternalCollisionStructure;
class CCollisionInfo;
class CCollisionInfoList;
class CInternalRayCastStructure;
class CMaterialFilter;
using ComparisonFunc = std::function<bool(const CInternalCollisionStructure&, CCollisionInfoList&)>;
using MovingComparisonFunc =
std::function<bool(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&)>;
using BooleanComparisonFunc = std::function<bool(const CInternalCollisionStructure&)>;
typedef bool(*ComparisonFunc)(const CInternalCollisionStructure&, CCollisionInfoList&);
typedef bool(*MovingComparisonFunc)(const CInternalCollisionStructure&, const zeus::CVector3f&,
double&, CCollisionInfo&);
typedef bool(*BooleanComparisonFunc)(const CInternalCollisionStructure&);
typedef void(*PrimitiveSetter)(u32);
class CCollisionPrimitive
{
public:
class Type
{
std::function<void(u32)> x0_setter;
PrimitiveSetter x0_setter;
const char* x4_info;
public:
Type() = default;
Type(const std::function<void(u32)>& setter, const char* info);
Type(PrimitiveSetter setter, const char* info)
: x0_setter(setter), x4_info(info) {}
const char* GetInfo() const;
std::function<void(u32)> GetSetter() const;
const char* GetInfo() const { return x4_info; }
PrimitiveSetter GetSetter() const { return x0_setter; }
};
class Comparison
@ -45,12 +72,12 @@ public:
const char* x8_type2;
public:
Comparison(const ComparisonFunc& collider, const char* type1, const char* type2)
Comparison(ComparisonFunc collider, const char* type1, const char* type2)
: x0_collider(collider), x4_type1(type1), x8_type2(type2)
{
}
const ComparisonFunc& GetCollider() const { return x0_collider; }
ComparisonFunc GetCollider() const { return x0_collider; }
const char* GetType1() const { return x4_type1; }
const char* GetType2() const { return x8_type2; }
};
@ -62,12 +89,12 @@ public:
const char* x8_type2;
public:
MovingComparison(const MovingComparisonFunc& collider, const char* type1, const char* type2)
MovingComparison(MovingComparisonFunc collider, const char* type1, const char* type2)
: x0_collider(collider), x4_type1(type1), x8_type2(type2)
{
}
const MovingComparisonFunc& GetCollider() const { return x0_collider; }
MovingComparisonFunc GetCollider() const { return x0_collider; }
const char* GetType1() const { return x4_type1; }
const char* GetType2() const { return x8_type2; }
};
@ -79,26 +106,33 @@ public:
const char* x8_type2;
public:
BooleanComparison(const BooleanComparisonFunc& collider, const char* type1, const char* type2)
BooleanComparison(BooleanComparisonFunc collider, const char* type1, const char* type2)
: x0_collider(collider), x4_type1(type1), x8_type2(type2)
{
}
const BooleanComparisonFunc& GetCollider() const { return x0_collider; }
BooleanComparisonFunc GetCollider() const { return x0_collider; }
const char* GetType1() const { return x4_type1; }
const char* GetType2() const { return x8_type2; }
};
private:
CMaterialList x8_material;
static std::unique_ptr<std::vector<Type>> sCollisionTypeList;
static std::unique_ptr<std::vector<ComparisonFunc>> sTableOfCollidables;
static std::unique_ptr<std::vector<BooleanComparisonFunc>> sTableOfBooleanCollidables;
static std::unique_ptr<std::vector<MovingComparisonFunc>> sTableOfMovingCollidables;
static s32 sNumTypes;
static bool sInitComplete;
static bool sTypesAdded;
static bool sTypesAdding;
static bool sCollidersAdded;
static bool sCollidersAdding;
static std::unique_ptr<std::vector<Type>> sCollisionTypeList;
static std::unique_ptr<std::vector<ComparisonFunc>> sTableOfCollidables;
static std::unique_ptr<std::vector<BooleanComparisonFunc>> sTableOfBooleanCollidables;
static std::unique_ptr<std::vector<MovingComparisonFunc>> sTableOfMovingCollidables;
static ComparisonFunc sNullCollider;
static BooleanComparisonFunc sNullBooleanCollider;
static MovingComparisonFunc sNullMovingCollider;
static bool InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list);
static bool InternalCollideBoolean(const CInternalCollisionStructure& collision);
public:
CCollisionPrimitive() = default;
@ -114,20 +148,26 @@ public:
CRayCastResult CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
const CMaterialFilter& filter, const zeus::CTransform& xf) const;
static bool Collide(CInternalCollisionStructure::CPrimDesc& prim0,
CInternalCollisionStructure::CPrimDesc& prim1,
CCollisionInfoList& list);
static bool CollideBoolean(CInternalCollisionStructure::CPrimDesc& prim0,
CInternalCollisionStructure::CPrimDesc& prim1);
static void InitBeginTypes();
static void InitAddType(const Type& tp);
static void InitEndTypes();
static void InitBeginColliders();
static void InitAddBooleanCollider(const BooleanComparison& cmp);
static void InitAddBooleanCollider(const BooleanComparisonFunc&, const char*, const char*);
static void InitAddBooleanCollider(BooleanComparisonFunc, const char*, const char*);
static void InitAddMovingCollider(const MovingComparison& cmp);
static void InitAddMovingCollider(const MovingComparisonFunc&, const char*, const char*);
static void InitAddMovingCollider(MovingComparisonFunc, const char*, const char*);
static void InitAddCollider(const Comparison& cmp);
static void InitAddCollider(const ComparisonFunc&, const char*, const char*);
static void InitAddCollider(ComparisonFunc, const char*, const char*);
static void InitEndColliders();
static void Unitialize();
static void Uninitialize();
};
}

View File

@ -6,15 +6,24 @@
#include "CStateManager.hpp"
#include "TCastTo.hpp"
#include "World/CWorld.hpp"
#include "CAABoxFilter.hpp"
#include "CBallFilter.hpp"
#include "CMetroidAreaCollider.hpp"
#include "CollisionUtil.hpp"
#include "World/CScriptPlatform.hpp"
#include "CCollidableSphere.hpp"
namespace urde
{
float CollisionImpulseFiniteVsInfinite(float f1, float f2, float f3) { return f1 * ((1.f / f3) * f2); }
float CollisionImpulseFiniteVsFinite(float f1, float f2, float f3, float f4)
static float CollisionImpulseFiniteVsInfinite(float mass, float velNormDot, float restitution)
{
return (-(1.f + f4) * f3) / ((1.f / f1) + (1.f / f2));
return mass * ((1.f / restitution) * velNormDot);
}
static float CollisionImpulseFiniteVsFinite(float mass, float velNormDot, float restitution, float f4)
{
return (-(1.f + f4) * restitution) / ((1.f / mass) + (1.f / velNormDot));
}
void CGameCollision::InitCollision()
@ -47,9 +56,207 @@ void CGameCollision::InitCollision()
CCollisionPrimitive::InitEndColliders();
}
void CGameCollision::Move(CStateManager& mgr, CPhysicsActor& actor, float dt, const rstl::reserved_vector<TUniqueId, 1024>*)
void CGameCollision::MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
{
actor.SetAngularEnabled(true);
actor.AddMotionState(actor.PredictAngularMotion(dt));
if (actor.IsUseStandardCollider())
{
MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList);
}
else
{
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
MoveGroundCollider_New(mgr, actor, dt, colliderList);
else
MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList);
}
actor.SetAngularEnabled(false);
}
void CGameCollision::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
{
CMotionState oldState = actor.GetMotionState();
CMotionState newState = actor.PredictMotion_Internal(dt);
newState.x0_translation.magnitude();
actor.GetMaterialFilter();
zeus::CAABox motionVol = actor.GetMotionVolume(dt);
rstl::reserved_vector<TUniqueId, 1024> augmentedColliderList;
if (colliderList)
augmentedColliderList = *colliderList;
mgr.BuildColliderList(augmentedColliderList, actor, motionVol);
CAreaCollisionCache cache(motionVol);
actor.GetCollisionPrimitive()->GetPrimType();
// TODO: finish
}
void CGameCollision::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
{
// TODO: finish
}
void CGameCollision::MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
{
bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player);
bool r28 = false;
bool r27 = false;
int r26 = 0;
float f31 = dt;
float _4AC4 = dt;
float _4AC8 = dt;
CCollisionInfoList accumList;
CMotionState mState = actor.PredictMotion_Internal(dt);
float transMag = mState.x0_translation.magnitude();
float m1 = 0.0005f / actor.GetCollisionAccuracyModifier();
float m2 = transMag / (5.f * actor.GetCollisionAccuracyModifier());
float mMax = std::max(m1, m2);
float m3 = 0.001f / actor.GetCollisionAccuracyModifier();
zeus::CAABox motionVol = actor.GetMotionVolume(dt);
rstl::reserved_vector<TUniqueId, 1024> useColliderList;
if (colliderList)
useColliderList = *colliderList;
else
mgr.BuildColliderList(useColliderList, actor, zeus::CAABox(motionVol.min - 1.f, motionVol.max + 1.f));
CAreaCollisionCache cache(motionVol);
if (actor.GetCollisionPrimitive()->GetPrimType() != FOURCC('OBTG') &&
!actor.GetMaterialFilter().GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight))
{
BuildAreaCollisionCache(mgr, cache);
zeus::CVector3f pos = actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center();
float halfExtent = 0.5f * GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive());
if (transMag > halfExtent)
{
TUniqueId id = kInvalidUniqueId;
zeus::CVector3f dir = (1.f / transMag) * mState.x0_translation;
CRayCastResult intersectRes = mgr.RayWorldIntersection(id, pos, dir, transMag,
actor.GetMaterialFilter(), useColliderList);
if (intersectRes.IsValid())
{
f31 = dt * (intersectRes.GetT() / transMag);
mState = actor.PredictMotion_Internal(f31);
_4AC8 = halfExtent * (dt / transMag);
mMax = std::min(mMax, halfExtent);
}
}
}
float f27 = f31;
while (true)
{
actor.MoveCollisionPrimitive(mState.x0_translation);
if (DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(),
actor.GetPrimitiveTransform(), actor.GetMaterialFilter(),
useColliderList))
{
r28 = true;
if (mState.x0_translation.magnitude() < mMax)
{
r27 = true;
accumList.Clear();
TUniqueId id = kInvalidUniqueId;
DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(),
actor.GetMaterialFilter(), useColliderList, id, accumList);
TCastToPtr<CPhysicsActor> otherActor = mgr.ObjectById(id);
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
zeus::CVector3f relVel = GetActorRelativeVelocities(actor, otherActor.GetPtr());
CCollisionInfoList filterList0, filterList1;
CollisionUtil::FilterOutBackfaces(relVel, accumList, filterList0);
if (filterList0.GetCount() > 0)
{
filter.Filter(filterList0, filterList1);
if (!filterList1.GetCount() && actor.GetMaterialList().HasMaterial(EMaterialTypes::Player))
{
CMotionState mState = actor.GetLastNonCollidingState();
mState.x1c_velocity *= 0.5f;
mState.x28_angularMomentum *= 0.5f;
actor.SetMotionState(mState);
}
}
MakeCollisionCallbacks(mgr, actor, id, filterList1);
SendScriptMessages(mgr, actor, otherActor.GetPtr(), filterList1);
ResolveCollisions(actor, otherActor.GetPtr(), filterList1);
_4AC4 -= f31;
f27 = std::min(_4AC4, _4AC8);
f31 = f27;
}
else
{
f27 *= 0.5f;
f31 *= 0.5f;
}
}
else
{
actor.AddMotionState(mState);
_4AC4 -= f31;
f31 = f27;
actor.ClearImpulses();
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
}
++r26;
if (_4AC4 > 0.f && ((mState.x0_translation.magnitude() > m3 && r27) || !r27) && r26 <= 1000)
mState = actor.PredictMotion_Internal(f31);
else
break;
}
f27 = _4AC4 / dt;
if (!r28 && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling);
if (isPlayer)
CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(), useColliderList, f27, 2);
actor.ClearForcesAndTorques();
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
}
zeus::CVector3f CGameCollision::GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1)
{
zeus::CVector3f ret = act0.GetVelocity();
if (act1)
{
bool rider = false;
if (TCastToConstPtr<CScriptPlatform> plat = act1)
rider = plat->IsRider(act0.GetUniqueId());
if (!rider)
ret =- act1->GetVelocity();
}
return ret;
}
void CGameCollision::Move(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList)
{
if (!actor.IsMovable())
return;
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider) || actor.WillMove(mgr))
{
if (actor.IsAngularEnabled())
actor.AddMotionState(actor.PredictAngularMotion(dt));
actor.UseCollisionImpulses();
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Solid))
{
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player))
MovePlayer(mgr, actor, dt, colliderList);
else if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider))
MoveGroundCollider(mgr, actor, dt, colliderList);
else
MoveAndCollide(mgr, actor, dt, CAABoxFilter(actor), colliderList);
}
else
{
actor.AddMotionState(actor.PredictMotion_Internal(dt));
actor.ClearForcesAndTorques();
}
mgr.UpdateActorInSortedLists(actor);
}
}
bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v)
@ -213,4 +420,417 @@ bool CGameCollision::RayStaticIntersectionArea(const CGameArea& area, const zeus
zeus::CLine line(pos, dir);
return node.LineTest(line, filter, mag);
}
void CGameCollision::BuildAreaCollisionCache(CStateManager& mgr, CAreaCollisionCache& cache)
{
cache.ClearCache();
for (const CGameArea& area : *mgr.GetWorld())
{
const CAreaOctTree& areaCollision = *area.GetPostConstructed()->x0_collision;
CMetroidAreaCollider::COctreeLeafCache octreeCache(areaCollision);
CMetroidAreaCollider::BuildOctreeLeafCache(areaCollision.GetRootNode(),
cache.GetCacheBounds(), octreeCache);
cache.AddOctreeLeafCache(octreeCache);
}
}
float CGameCollision::GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim)
{
if (prim.GetPrimType() == FOURCC('SPHR'))
{
const CCollidableSphere& sphere = static_cast<const CCollidableSphere&>(prim);
return 2.f * sphere.GetSphere().radius;
}
else if (prim.GetPrimType() == FOURCC('AABX'))
{
const CCollidableAABox& aabx = static_cast<const CCollidableAABox&>(prim);
zeus::CVector3f extent = aabx.GetAABB().max - aabx.GetAABB().min;
float minExtent = std::min(extent.x, extent.y);
minExtent = std::min(minExtent, extent.z);
return minExtent;
}
else if (prim.GetPrimType() == FOURCC('ABSH'))
{
// Combination AABB / Sphere cut from game
}
return 1.f;
}
bool CGameCollision::DetectCollisionBoolean_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>& nearList)
{
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight) &&
DetectStaticCollisionBoolean_Cached(mgr, cache, prim, xf, filter))
return true;
if (DetectDynamicCollisionBoolean(prim, xf, nearList, mgr))
return true;
return false;
}
bool CGameCollision::DetectStaticCollisionBoolean(CStateManager& mgr, const CCollisionPrimitive& prim,
const zeus::CTransform& xf, const CMaterialFilter& filter)
{
if (prim.GetPrimType() == FOURCC('OBTG'))
return false;
if (prim.GetPrimType() == FOURCC('AABX'))
{
zeus::CAABox aabb = prim.CalculateAABox(xf);
for (const CGameArea& area : *mgr.GetWorld())
{
if (CMetroidAreaCollider::AABoxCollisionCheckBoolean(
*area.GetPostConstructed()->x0_collision, aabb, filter))
return true;
}
}
else if (prim.GetPrimType() == FOURCC('SPHR'))
{
const CCollidableSphere& sphere = static_cast<const CCollidableSphere&>(prim);
zeus::CAABox aabb = prim.CalculateAABox(xf);
zeus::CSphere xfSphere = sphere.Transform(xf);
for (const CGameArea& area : *mgr.GetWorld())
{
if (CMetroidAreaCollider::SphereCollisionCheckBoolean(
*area.GetPostConstructed()->x0_collision, aabb, xfSphere, filter))
return true;
}
}
else if (prim.GetPrimType() == FOURCC('ABSH'))
{
// Combination AABB / Sphere cut from game
}
return false;
}
bool CGameCollision::DetectStaticCollisionBoolean_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter)
{
if (prim.GetPrimType() == FOURCC('OBTG'))
return false;
zeus::CAABox aabb = prim.CalculateAABox(xf);
if (!aabb.inside(cache.GetCacheBounds()))
{
zeus::CAABox newAABB(aabb.min - 0.2f, aabb.max + 0.2f);
newAABB.accumulateBounds(cache.GetCacheBounds());
cache.SetCacheBounds(newAABB);
BuildAreaCollisionCache(mgr, cache);
}
if (cache.HasCacheOverflowed())
return DetectStaticCollisionBoolean(mgr, prim, xf, filter);
if (prim.GetPrimType() == FOURCC('AABX'))
{
for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache)
if (CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(leafCache, aabb, filter))
return true;
}
else if (prim.GetPrimType() == FOURCC('SPHR'))
{
const CCollidableSphere& sphere = static_cast<const CCollidableSphere&>(prim);
zeus::CSphere xfSphere = sphere.Transform(xf);
for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache)
if (CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(leafCache, aabb, xfSphere, filter))
return true;
}
else if (prim.GetPrimType() == FOURCC('ABSH'))
{
// Combination AABB / Sphere cut from game
}
return false;
}
bool CGameCollision::DetectDynamicCollisionBoolean(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
CStateManager& mgr)
{
for (TUniqueId id : nearList)
{
if (TCastToPtr<CPhysicsActor> actor = mgr.ObjectById(id))
{
CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf);
CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(),
CMaterialFilter::skPassEverything,
actor->GetPrimitiveTransform());
if (CCollisionPrimitive::CollideBoolean(p0, p1))
return true;
}
}
return false;
}
bool CGameCollision::DetectCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
TUniqueId& idOut, CCollisionInfoList& infoList)
{
bool ret = false;
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::ThirtyEight))
if (DetectStaticCollision_Cached(mgr, cache, prim, xf, filter, infoList))
ret = true;
TUniqueId id = kInvalidUniqueId;
if (DetectDynamicCollision(prim, xf, nearList, id, infoList, mgr))
{
ret = true;
idOut = id;
}
return ret;
}
bool CGameCollision::DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
const zeus::CTransform& xf, const CMaterialFilter& filter,
CCollisionInfoList& list)
{
if (prim.GetPrimType() == FOURCC('OBTG'))
return false;
if (prim.GetPrimType() == FOURCC('AABX'))
{
zeus::CAABox aabb = prim.CalculateAABox(xf);
for (const CGameArea& area : *mgr.GetWorld())
{
if (CMetroidAreaCollider::AABoxCollisionCheck(
*area.GetPostConstructed()->x0_collision, aabb, filter,
prim.GetMaterial(), list))
return true;
}
}
else if (prim.GetPrimType() == FOURCC('SPHR'))
{
const CCollidableSphere& sphere = static_cast<const CCollidableSphere&>(prim);
zeus::CAABox aabb = prim.CalculateAABox(xf);
zeus::CSphere xfSphere = sphere.Transform(xf);
for (const CGameArea& area : *mgr.GetWorld())
{
if (CMetroidAreaCollider::SphereCollisionCheck(
*area.GetPostConstructed()->x0_collision, aabb, xfSphere,
prim.GetMaterial(), filter, list))
return true;
}
}
else if (prim.GetPrimType() == FOURCC('ABSH'))
{
// Combination AABB / Sphere cut from game
}
return false;
}
bool CGameCollision::DetectStaticCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter, CCollisionInfoList& list)
{
if (prim.GetPrimType() == FOURCC('OBTG'))
return false;
zeus::CAABox calcAABB = prim.CalculateAABox(xf);
if (!calcAABB.inside(cache.GetCacheBounds()))
{
zeus::CAABox newAABB(calcAABB.min - 0.2f, calcAABB.max + 0.2f);
newAABB.accumulateBounds(cache.GetCacheBounds());
cache.SetCacheBounds(newAABB);
BuildAreaCollisionCache(mgr, cache);
}
if (cache.HasCacheOverflowed())
return DetectStaticCollision(mgr, prim, xf, filter, list);
if (prim.GetPrimType() == FOURCC('AABX'))
{
for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache)
if (CMetroidAreaCollider::AABoxCollisionCheck_Cached(leafCache, calcAABB, filter,
prim.GetMaterial(), list))
return true;
}
else if (prim.GetPrimType() == FOURCC('SPHR'))
{
const CCollidableSphere& sphere = static_cast<const CCollidableSphere&>(prim);
zeus::CSphere xfSphere = sphere.Transform(xf);
for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache)
if (CMetroidAreaCollider::SphereCollisionCheck_Cached(leafCache, calcAABB, xfSphere,
prim.GetMaterial(), filter, list))
return true;
}
else if (prim.GetPrimType() == FOURCC('ABSH'))
{
// Combination AABB / Sphere cut from game
}
return false;
}
bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr)
{
for (TUniqueId id : nearList)
{
if (TCastToPtr<CPhysicsActor> actor = mgr.ObjectById(id))
{
CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf);
CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(),
CMaterialFilter::skPassEverything,
actor->GetPrimitiveTransform());
if (CCollisionPrimitive::Collide(p0, p1, list))
{
idOut = actor->GetUniqueId();
return true;
}
}
}
return false;
}
void CGameCollision::MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor,
TUniqueId id, const CCollisionInfoList& list)
{
actor.CollidedWith(id, list, mgr);
if (id != kInvalidUniqueId)
{
if (TCastToPtr<CPhysicsActor> actor = mgr.ObjectById(id))
{
CCollisionInfoList swappedList = list;
for (CCollisionInfo& info : swappedList)
info.Swap();
actor->CollidedWith(actor->GetUniqueId(), list, mgr);
}
}
}
void CGameCollision::SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list)
{
bool onFloor = false;
bool platform = false;
bool platform2 = false;
for (const CCollisionInfo& info : list)
{
if (IsFloor(info.GetMaterialLeft(), info.GetNormalLeft()))
{
onFloor = true;
if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Platform))
platform = true;
SendMaterialMessage(mgr, info.GetMaterialLeft(), a0);
}
}
if (onFloor)
{
mgr.SendScriptMsg(&a0, kInvalidUniqueId, EScriptObjectMessage::OnFloor);
if (platform)
{
if (TCastToPtr<CScriptPlatform> plat = a1)
{
mgr.SendScriptMsg(plat.GetPtr(), a0.GetUniqueId(),
EScriptObjectMessage::AddPlatformRider);
}
}
else if (a1)
{
if (TCastToPtr<CScriptPlatform> plat = a0)
{
for (const CCollisionInfo& info : list)
{
if (IsFloor(info.GetMaterialRight(), info.GetNormalRight()))
{
if (info.GetMaterialRight().HasMaterial(EMaterialTypes::Platform))
platform2 = true;
SendMaterialMessage(mgr, info.GetMaterialLeft(), a0);
}
}
if (platform2)
{
mgr.SendScriptMsg(plat.GetPtr(), a1->GetUniqueId(),
EScriptObjectMessage::AddPlatformRider);
}
}
}
}
}
void CGameCollision::ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list)
{
for (const CCollisionInfo& info : list)
{
CCollisionInfo infoCopy = info;
float restitution = GetCoefficientOfRestitution(infoCopy) + a0.GetCoefficientOfRestitutionModifier();
if (a1)
{
CollideWithDynamicBodyNoRot(a0, *a1, infoCopy, restitution, false);
}
else
{
CollideWithStaticBodyNoRot(a0, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(),
infoCopy.GetNormalLeft(), restitution, false);
}
}
}
void CGameCollision::CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1,
const CCollisionInfo& info, float restitution, bool)
{
/* TODO: Finish */
}
void CGameCollision::CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1,
const zeus::CUnitVector3f& normal, float restitution, bool b)
{
zeus::CUnitVector3f useNorm = normal;
if (b && m0.HasMaterial(EMaterialTypes::Player) && !m1.HasMaterial(EMaterialTypes::Floor))
useNorm.z = 0.f;
if (useNorm.canBeNormalized())
{
useNorm.normalize();
float velNormDot = a0.GetVelocity().dot(useNorm);
if (velNormDot < 0.0001f)
{
a0.ApplyImpulseWR(
useNorm * CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution),
zeus::CAxisAngle::sIdentity);
a0.UseCollisionImpulses();
}
else if (velNormDot < 0.001f)
{
a0.ApplyImpulseWR(0.05f * a0.GetMass() * useNorm, zeus::CAxisAngle::sIdentity);
a0.UseCollisionImpulses();
}
}
}
void CGameCollision::CollisionFailsafe(CStateManager& mgr, CAreaCollisionCache& cache,
CPhysicsActor& actor, const CCollisionPrimitive& prim,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float f1, u32 failsafeTicks)
{
actor.MoveCollisionPrimitive(zeus::CVector3f::skZero);
if (f1 > 0.5f)
actor.SetNumTicksPartialUpdate(actor.GetNumTicksPartialUpdate() + 1);
if (actor.GetNumTicksPartialUpdate() > 1 ||
DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(),
actor.GetMaterialFilter(), nearList))
{
actor.SetNumTicksPartialUpdate(0);
actor.SetNumTicksStuck(actor.GetNumTicksStuck() + 1);
if (actor.GetNumTicksStuck() < failsafeTicks)
return;
/* TODO: Finish */
}
else
{
actor.SetLastNonCollidingState(actor.GetMotionState());
actor.SetNumTicksStuck(0);
}
}
}

View File

@ -5,14 +5,12 @@
#include "rstl.hpp"
#include "RetroTypes.hpp"
#include "CRayCastResult.hpp"
#include "CMetroidAreaCollider.hpp"
#include "CCollisionPrimitive.hpp"
namespace urde
{
class CInternalCollisionStructure
{
};
class CActor;
class CCollisionInfo;
class CCollisionInfoList;
@ -21,10 +19,21 @@ class CStateManager;
class CPhysicsActor;
class CMaterialFilter;
class CGameArea;
class ICollisionFilter;
class CGameCollision
{
static void MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static void MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static void MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static zeus::CVector3f GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1);
public:
static float GetCoefficientOfRestitution(const CCollisionInfo&) { return 0.f; }
static bool NullMovingCollider(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&)
{
return false;
@ -32,11 +41,12 @@ public:
static bool NullBooleanCollider(const CInternalCollisionStructure&) { return false; }
static bool NullCollisionCollider(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; }
static void InitCollision();
static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt, const rstl::reserved_vector<TUniqueId, 1024>*);
static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt,
const rstl::reserved_vector<TUniqueId, 1024>* colliderList);
static bool CanBlock(const CMaterialList&, const zeus::CVector3f&);
static bool IsFloor(const CMaterialList&, const zeus::CVector3f&);
void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&);
static void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&);
static CRayCastResult RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos,
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter);
static bool RayStaticIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& start,
@ -55,6 +65,46 @@ public:
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
static bool RayStaticIntersectionArea(const CGameArea& area, const zeus::CVector3f& pos,
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter);
static void BuildAreaCollisionCache(CStateManager& mgr, CAreaCollisionCache& cache);
static float GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim);
static bool DetectCollisionBoolean_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
static bool DetectStaticCollisionBoolean(CStateManager& mgr, const CCollisionPrimitive& prim,
const zeus::CTransform& xf, const CMaterialFilter& filter);
static bool DetectStaticCollisionBoolean_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter);
static bool DetectDynamicCollisionBoolean(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
CStateManager& mgr);
static bool DetectCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
TUniqueId& idOut, CCollisionInfoList& infoList);
static bool DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
const zeus::CTransform& xf, const CMaterialFilter& filter,
CCollisionInfoList& list);
static bool DetectStaticCollision_Cached(CStateManager& mgr, CAreaCollisionCache& cache,
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const CMaterialFilter& filter, CCollisionInfoList& list);
static bool DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
TUniqueId& idOut, CCollisionInfoList& list, CStateManager& mgr);
static void MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id,
const CCollisionInfoList& list);
static void SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list);
static void ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list);
static void CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1, const CCollisionInfo& info,
float restitution, bool);
static void CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1,
const zeus::CUnitVector3f& normal, float restitution, bool);
static void CollisionFailsafe(CStateManager& mgr, CAreaCollisionCache& cache,
CPhysicsActor& actor, const CCollisionPrimitive& prim,
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float, u32 failsafeTicks);
};
}

View File

@ -22,6 +22,9 @@ set(COLLISION_SOURCES
CRayCastResult.hpp CRayCastResult.cpp
CCollisionActor.hpp CCollisionActor.cpp
CCollisionActorManager.hpp CCollisionActorManager.cpp
CJointCollisionDescription.hpp CJointCollisionDescription.cpp)
CJointCollisionDescription.hpp CJointCollisionDescription.cpp
CAABoxFilter.hpp CAABoxFilter.cpp
CBallFilter.hpp CBallFilter.cpp
ICollisionFilter.hpp)
runtime_add_list(Collision COLLISION_SOURCES)

View File

@ -0,0 +1,121 @@
#include "CMetroidAreaCollider.hpp"
namespace urde
{
CMetroidAreaCollider::COctreeLeafCache::COctreeLeafCache(const CAreaOctTree& octTree)
: x0_octTree(octTree)
{
x908_24_overflow = false;
}
void CMetroidAreaCollider::COctreeLeafCache::AddLeaf(const CAreaOctTree::Node& node)
{
if (x4_nodeCache.size() == 64)
{
x908_24_overflow = true;
return;
}
x4_nodeCache.push_back(node);
}
void CMetroidAreaCollider::BuildOctreeLeafCache(const CAreaOctTree::Node& node, const zeus::CAABox& aabb,
CMetroidAreaCollider::COctreeLeafCache& cache)
{
for (int i=0 ; i<8 ; ++i)
{
u16 flags = (node.GetChildFlags() >> (i * 2)) & 0x3;
if (flags)
{
CAreaOctTree::Node ch = node.GetChild(i);
if (aabb.intersects(ch.GetBoundingBox()))
{
if (flags == 0x2)
cache.AddLeaf(ch);
else
BuildOctreeLeafCache(ch, aabb, cache);
}
}
}
}
bool CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter)
{
return false;
}
bool CMetroidAreaCollider::AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter)
{
return false;
}
bool CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter)
{
return false;
}
bool CMetroidAreaCollider::SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter)
{
return false;
}
bool CMetroidAreaCollider::AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList,
CCollisionInfoList& list)
{
return false;
}
bool CMetroidAreaCollider::AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList,
CCollisionInfoList& list)
{
return false;
}
bool CMetroidAreaCollider::SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list)
{
return false;
}
bool CMetroidAreaCollider::SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list)
{
return false;
}
void CAreaCollisionCache::ClearCache()
{
x18_leafCaches.clear();
x1b40_24_leafOverflow = false;
x1b40_25_cacheOverflow = false;
}
void CAreaCollisionCache::AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache)
{
if (!leafCache.GetNumLeaves())
return;
if (leafCache.HasCacheOverflowed())
x1b40_24_leafOverflow = true;
if (x18_leafCaches.size() < 3)
{
x18_leafCaches.push_back(leafCache);
}
else
{
x1b40_24_leafOverflow = true;
x1b40_25_cacheOverflow = true;
}
}
}

View File

@ -1,13 +1,78 @@
#ifndef __URDE_CMETROIDAREACOLLIDER_HPP__
#define __URDE_CMETROIDAREACOLLIDER_HPP__
#include "RetroTypes.hpp"
#include "zeus/CAABox.hpp"
#include "CAreaOctTree.hpp"
namespace urde
{
class CCollisionInfoList;
class CMaterialList;
class CMetroidAreaCollider
{
public:
CMetroidAreaCollider();
class COctreeLeafCache
{
const CAreaOctTree& x0_octTree;
rstl::reserved_vector<CAreaOctTree::Node, 64> x4_nodeCache;
bool x908_24_overflow : 1;
public:
COctreeLeafCache(const CAreaOctTree& octTree);
void AddLeaf(const CAreaOctTree::Node& node);
u32 GetNumLeaves() const { return x4_nodeCache.size(); }
bool HasCacheOverflowed() const { return x908_24_overflow; }
};
static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb,
CMetroidAreaCollider::COctreeLeafCache& cache);
static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter);
static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter);
static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter);
static bool SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter);
static bool AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList,
CCollisionInfoList& list);
static bool AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList,
CCollisionInfoList& list);
static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list);
static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list);
};
class CAreaCollisionCache
{
zeus::CAABox x0_aabb;
rstl::reserved_vector<CMetroidAreaCollider::COctreeLeafCache, 3> x18_leafCaches;
union
{
struct
{
bool x1b40_24_leafOverflow : 1;
bool x1b40_25_cacheOverflow : 1;
};
u32 _dummy = 0;
};
public:
CAreaCollisionCache(const zeus::CAABox& aabb) : x0_aabb(aabb) {}
void ClearCache();
const zeus::CAABox& GetCacheBounds() const { return x0_aabb; }
void SetCacheBounds(const zeus::CAABox& aabb) { x0_aabb = aabb; }
void AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache);
u32 GetNumCaches() const { return x18_leafCaches.size(); }
const CMetroidAreaCollider::COctreeLeafCache& GetOctreeLeafCache(int idx) { return x18_leafCaches[idx]; }
bool HasCacheOverflowed() const { return x1b40_24_leafOverflow; }
rstl::reserved_vector<CMetroidAreaCollider::COctreeLeafCache, 3>::iterator begin() { return x18_leafCaches.begin(); }
rstl::reserved_vector<CMetroidAreaCollider::COctreeLeafCache, 3>::iterator end() { return x18_leafCaches.end(); }
};
}

View File

@ -1,8 +1,12 @@
#include "CollisionUtil.hpp"
#include "CCollisionInfo.hpp"
#include "CCollisionInfoList.hpp"
namespace urde
{
namespace CollisionUtil
{
bool LineIntersectsOBBox(const zeus::COBBox& obb, const zeus::CMRay& ray, float& d)
{
const zeus::CVector3f transXf = obb.transform.toMatrix4f().vec[0].toVec3f();
@ -42,5 +46,56 @@ bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& p
return false;
}
void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out)
{
if (vec.canBeNormalized())
{
zeus::CVector3f norm = vec.normalized();
for (const CCollisionInfo& info : in)
{
if (info.GetNormalLeft().dot(norm) < 0.001f)
out.Add(info, false);
}
}
else
{
out = in;
}
}
static const zeus::CVector3f AABBNormalTable[] =
{
{-1.f, 0.f, 0.f},
{1.f, 0.f, 0.f},
{0.f, -1.f, 0.f},
{0.f, 1.f, 0.f},
{0.f, 0.f, -1.f},
{0.f, 0.f, 1.f}
};
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0,
const zeus::CAABox& aabb1, const CMaterialList& list1,
CCollisionInfoList& infoList)
{
zeus::CAABox boolAABB = aabb0.booleanIntersection(aabb1);
if (boolAABB.invalid())
return false;
/* TODO: Finish */
if (!infoList.GetCount())
{
infoList.Add(CCollisionInfo(boolAABB, list0, list1, AABBNormalTable[4], -AABBNormalTable[4]), false);
infoList.Add(CCollisionInfo(boolAABB, list0, list1, AABBNormalTable[5], -AABBNormalTable[5]), false);
}
return true;
}
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1)
{
return aabb0.intersects(aabb1);
}
}
}

View File

@ -3,15 +3,23 @@
#include "GCNTypes.hpp"
#include "zeus/zeus.hpp"
#include "CMaterialList.hpp"
namespace urde
{
class CCollisionInfoList;
namespace CollisionUtil
{
bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&);
u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, const zeus::CVector3f&, float&);
u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, double&);
bool RaySphereIntersection(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, float, float&, zeus::CVector3f&);
bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
float mag, float& T, zeus::CVector3f& point);
void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out);
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0,
const zeus::CAABox& aabb1, const CMaterialList& list1,
CCollisionInfoList& infoList);
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1);
}
}
#endif // __URDE_COLLISIONUTIL_HPP__

View File

@ -0,0 +1,21 @@
#ifndef __URDE_ICOLLISIONFILTER_HPP__
#define __URDE_ICOLLISIONFILTER_HPP__
#include "CCollisionInfoList.hpp"
namespace urde
{
class CActor;
class ICollisionFilter
{
CActor& x4_actor;
protected:
ICollisionFilter(CActor& actor) : x4_actor(actor) {}
public:
virtual void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const = 0;
};
}
#endif // __URDE_ICOLLISIONFILTER_HPP__

View File

@ -11,10 +11,11 @@ namespace urde
class CGrappleArm
{
CModelData x0_modelData;
zeus::CTransform x220_;
public:
CGrappleArm(const zeus::CVector3f& vec);
void AsyncLoadSuit(CStateManager& mgr);
void SetX220(const zeus::CTransform& xf) { x220_ = xf; }
};
}

View File

@ -219,6 +219,8 @@ public:
u32 GetSelectedBeam() const { return x310_selectedBeam; }
u32 GetPendingSelectedBeam() const { return x314_pendingSelectedBeam; }
const CGunMorph& GetGunMorph() const { return x678_morph; }
void SetX3e8(const zeus::CTransform& xf) { x3e8_ = xf; }
CGrappleArm& GetGrappleArm() { return *x740_grappleArm; }
};
}

View File

@ -496,4 +496,12 @@ const CScannableObjectInfo* CActor::GetScannableObjectInfo() const
return info.GetObj();
}
void CActor::SetCalculateLighting(bool c)
{
if (!x90_actorLights)
x90_actorLights = std::make_unique<CActorLights>(8, zeus::CVector3f::skZero,
4, 4, false, false, false, 0.1f);
xe4_31_lightsDirty = c;
}
}

View File

@ -170,6 +170,7 @@ public:
const CScannableObjectInfo* GetScannableObjectInfo() const;
const CHealthInfo* GetHealthInfo() const { return const_cast<CActor*>(this)->HealthInfo(); }
bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; }
void SetCalculateLighting(bool c);
};
}

View File

@ -12,12 +12,11 @@ CPhysicsActor::CPhysicsActor(TUniqueId uid, bool active, const std::string& name
, xec_massRecip(moverData.x30_mass <= 0.f ? 1.f : 1.f / moverData.x30_mass)
, x150_momentum(moverData.x18_momentum)
, x1c0_collisionPrimitive(box, matList)
, x1f4_translation(xf.origin)
, x200_orientation(xf.buildMatrix3f())
, x1f4_lastNonCollidingState(xf.origin, xf.buildMatrix3f())
, x23c_stepUpHeight(stepUp)
, x240_stepDownHeight(stepDown)
{
xf8_24_ = true;
xf8_24_movable = true;
SetMass(moverData.x30_mass);
MoveCollisionPrimitive(zeus::CVector3f::skZero);
SetVelocityOR(moverData.x0_velocity);
@ -37,7 +36,7 @@ zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) co
return GetBoundingBox().center() + trans;
}
void CPhysicsActor::CollidedWith(const TUniqueId&, const CCollisionInfoList&, CStateManager&) {}
void CPhysicsActor::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&) {}
const CCollisionPrimitive* CPhysicsActor::GetCollisionPrimitive() const { return &x1c0_collisionPrimitive; }
@ -52,9 +51,9 @@ float CPhysicsActor::GetStepDownHeight() const { return x240_stepDownHeight; }
float CPhysicsActor::GetWeight() const { return 24.525002f * xe8_mass; }
void CPhysicsActor::sub_8011A4C(float f) { x238_ = f; }
void CPhysicsActor::sub_8011A4C(float f) { x238_maximumCollisionVelocity = f; }
float CPhysicsActor::sub_8011A4B8() const { return x238_; }
float CPhysicsActor::sub_8011A4B8() const { return x238_maximumCollisionVelocity; }
void CPhysicsActor::SetPrimitiveOffset(const zeus::CVector2f& offset) { x1e8_primitiveOffset = offset; }
@ -144,11 +143,6 @@ void CPhysicsActor::SetInertiaTensorScalar(float tensor)
xf4_inertiaTensorRecip = 1.0f / tensor;
}
void CPhysicsActor::SetCoefficientOfRestitutionModifier(float mod)
{
x244_restitutionCoefModifier = mod;
}
void CPhysicsActor::SetMass(float mass)
{
xe8_mass = mass;
@ -302,7 +296,7 @@ CPhysicsState CPhysicsActor::GetPhysicsState() const
CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const
{
if (xf8_25_)
if (xf8_25_angularEnabled)
return PredictMotion(dt);
CMotionState msl = PredictLinearMotion(dt);

View File

@ -29,8 +29,10 @@ struct CMotionState
CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation, const zeus::CVector3f& velocity,
const zeus::CAxisAngle& angle)
: x0_translation(origin), xc_orientation(orientation), x1c_velocity(velocity), x28_angularMomentum(angle)
{
}
{}
CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation)
: x0_translation(origin), xc_orientation(orientation)
{}
};
class CPhysicsState
@ -84,12 +86,12 @@ protected:
union {
struct
{
bool xf8_24_ : 1;
bool xf8_25_ : 1;
bool xf8_24_movable : 1;
bool xf8_25_angularEnabled : 1;
};
u8 _dummy = 0;
};
bool xf9_ = false;
bool xf9_standardCollider = false;
zeus::CVector3f xfc_constantForce;
zeus::CAxisAngle x108_angularMomentum;
zeus::CMatrix3f x114_;
@ -105,18 +107,15 @@ protected:
zeus::CAABox x1a4_baseBoundingBox;
CCollidableAABox x1c0_collisionPrimitive;
zeus::CVector3f x1e8_primitiveOffset;
zeus::CVector3f x1f4_translation;
zeus::CNUQuaternion x200_orientation;
zeus::CAxisAngle x210_;
zeus::CAxisAngle x21c_;
CMotionState x1f4_lastNonCollidingState;
bool x234_ = false;
float x238_ = 1000000.0f;
float x238_maximumCollisionVelocity = 1000000.0f;
float x23c_stepUpHeight;
float x240_stepDownHeight;
float x244_restitutionCoefModifier = 0.f;
float x248_collisionAccuracyModifier = 1.f;
u32 x24c_;
u32 x250_;
u32 x24c_numTicksStuck;
u32 x250_numTicksPartialUpdate;
public:
CPhysicsActor(TUniqueId, bool, const std::string&, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
@ -127,7 +126,7 @@ public:
zeus::CVector3f GetAimPosition(const CStateManager&, float val) const;
virtual const CCollisionPrimitive* GetCollisionPrimitive() const;
virtual zeus::CTransform GetPrimitiveTransform() const;
virtual void CollidedWith(const TUniqueId&, const CCollisionInfoList&, CStateManager&);
virtual void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&);
virtual float GetStepUpHeight() const;
virtual float GetStepDownHeight() const;
virtual float GetWeight() const;
@ -145,15 +144,19 @@ public:
const zeus::CAABox& GetBaseBoundingBox() const;
void AddMotionState(const CMotionState& mst);
CMotionState GetMotionState() const;
const CMotionState& GetLastNonCollidingState() const { return x1f4_lastNonCollidingState; }
void SetLastNonCollidingState(const CMotionState& mst) { x1f4_lastNonCollidingState = mst; }
void SetMotionState(const CMotionState& mst);
float GetMaximumCollisionVelocity() const { return x238_maximumCollisionVelocity; }
void SetMaximumCollisionVelocity(float v) { x238_maximumCollisionVelocity = v; }
void SetInertiaTensorScalar(float tensor);
void SetCoefficientOfRestitutionModifier(float);
void SetMass(float mass);
void SetAngularVelocityOR(const zeus::CAxisAngle& angVel);
zeus::CAxisAngle GetAngularVelocityOR() const;
void SetAngularVelocityWR(const zeus::CAxisAngle& angVel);
void SetVelocityWR(const zeus::CVector3f& vel);
void SetVelocityOR(const zeus::CVector3f& vel);
const zeus::CVector3f& GetVelocity() const { return x138_velocity; }
zeus::CVector3f GetTotalForcesWR() const;
void RotateInOneFrameOR(const zeus::CQuaternion& q, float d);
void MoveInOneFrameOR(const zeus::CVector3f& trans, float d);
@ -170,6 +173,19 @@ public:
bool WillMove(const CStateManager&);
void SetPhysicsState(const CPhysicsState& state);
CPhysicsState GetPhysicsState() const;
bool IsMovable() const { return xf8_24_movable; }
void SetMovable(bool m) { xf8_24_movable = m; }
bool IsAngularEnabled() const { return xf8_25_angularEnabled; }
void SetAngularEnabled(bool e) { xf8_25_angularEnabled = e; }
float GetCollisionAccuracyModifier() const { return x248_collisionAccuracyModifier; }
void SetCollisionAccuracyModifier(float m) { x248_collisionAccuracyModifier = m; }
float GetCoefficientOfRestitutionModifier() const { return x244_restitutionCoefModifier; }
void SetCoefficientOfRestitutionModifier(float m) { x244_restitutionCoefModifier = m; }
bool IsUseStandardCollider() const { return xf9_standardCollider; }
u32 GetNumTicksPartialUpdate() const { return x250_numTicksPartialUpdate; }
void SetNumTicksPartialUpdate(u32 t) { x250_numTicksPartialUpdate = t; }
u32 GetNumTicksStuck() const { return x24c_numTicksStuck; }
void SetNumTicksStuck(u32 t) { x24c_numTicksStuck = t; }
CMotionState PredictMotion_Internal(float) const;
CMotionState PredictMotion(float dt) const;

View File

@ -24,7 +24,7 @@ static CModelData MakePlayerAnimRes(ResId resId, const zeus::CVector3f& scale)
return {CAnimRes(resId, 0, scale, 0, true), 1};
}
CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, unsigned int resId,
CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, ResId resId,
const zeus::CVector3f& playerScale, float mass, float stepUp, float stepDown, float f4,
const CMaterialList& ml)
: CPhysicsActor(uid, true, "CPlayer", CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), xf,
@ -34,7 +34,6 @@ CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox&
x490_gun.reset(new CPlayerGun(uid));
x49c_gunNotFiringTimeout = g_tweakPlayerGun->GetGunNotFiringTime();
x4a0_inputFilter.reset(new CInputFilter());
x768_morphball.reset(new CMorphBall(*this, f4));
x76c_cameraBob.reset(new CPlayerCameraBob(CPlayerCameraBob::ECameraBobType::One,
zeus::CVector2f{CPlayerCameraBob::kCameraBobExtentX,
CPlayerCameraBob::kCameraBobExtentY},
@ -43,8 +42,43 @@ CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox&
x9c4_27_ = true;
x9c4_28_ = true;
x9c5_31_ = true;
ResId beamId = g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_);
ResId beamId = g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam);
x7f0_ballTransitionBeamModel = std::make_unique<CModelData>(CStaticRes(beamId, playerScale));
x730_.reserve(3);
x768_morphball.reset(new CMorphBall(*this, f4));
SetInertiaTensorScalar(xe8_mass);
x1f4_lastNonCollidingState = GetMotionState();
x490_gun->SetX3e8(x34_transform);
x490_gun->GetGrappleArm().SetX220(x34_transform);
InitializeBallTransition();
zeus::CAABox ballTransAABB = x64_modelData->GetBounds();
x2f0_ballTransHeight = ballTransAABB.max.z - ballTransAABB.min.z;
SetCalculateLighting(true);
x90_actorLights->SetCastShadows(true);
x50c_.z = 0.f;
if (x50c_.canBeNormalized())
x50c_.normalize();
x2b4_.push_back(20.f);
x2b4_.push_back(80.f);
x2b4_.push_back(80.f);
x2b4_.push_back(270.f);
SetMaximumCollisionVelocity(25.f);
x354_onScreenOrbitObjects.reserve(64);
x344_nearbyOrbitObjects.reserve(64);
x364_offScreenOrbitObjects.reserve(64);
x64_modelData->SetScale(playerScale);
x7f0_ballTransitionBeamModel->SetScale(playerScale);
LoadAnimationTokens();
}
void CPlayer::InitializeBallTransition()
{
if (x64_modelData && x64_modelData->HasAnimData())
x64_modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false);
}
bool CPlayer::IsTransparent() const { return x588_alpha < 1.f; }
@ -246,7 +280,7 @@ void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CState
{
switch (msg)
{
case EScriptObjectMessage::OnGround:
case EScriptObjectMessage::OnFloor:
if (x258_movementState != EPlayerMovementState::OnGround &&
x2f8_morphTransState != EPlayerMorphBallState::Morphed &&
x300_fallingTime > 0.3f)
@ -834,7 +868,7 @@ const CCollisionPrimitive* CPlayer::GetCollisionPrimitive() const { return CPhys
zeus::CTransform CPlayer::GetPrimitiveTransform() const { return {}; }
bool CPlayer::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr) { return false; }
void CPlayer::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr) {}
float CPlayer::GetActualFirstPersonMaxVelocity() const { return 0.f; }

View File

@ -178,11 +178,11 @@ private:
float x2a8_ = 1000.f;
EPlayerMovementSurface x2ac_movementSurface = EPlayerMovementSurface::Normal;
u32 x2b0_ = 2;
u32 x2b4_ = 0;
rstl::reserved_vector<float, 6> x2b4_;
u32 x2d0_ = 3;
float x2d4_ = 0.f;
zeus::CAABox x2d8_;
float x2f0_ = 0.f;
float x2f0_ballTransHeight = 0.f;
EPlayerCameraState x2f4_cameraState = EPlayerCameraState::Zero;
EPlayerMorphBallState x2f8_morphTransState = EPlayerMorphBallState::Unmorphed;
u32 x2fc_ = 0;
@ -247,7 +247,14 @@ private:
u32 x4a4_ = 0;
float x4f8_ = 0.f;
float x4fc_ = 0.f;
float x53c_ = 0.f;
zeus::CVector3f x500_ = x34_transform.basis[1];
zeus::CVector3f x50c_ = x34_transform.basis[1];
zeus::CVector3f x518_ = x34_transform.basis[1];
zeus::CVector3f x524_ = x34_transform.basis[1];
zeus::CVector3f x530_ = x34_transform.basis[1];
zeus::CVector3f x53c_ = x34_transform.basis[1];
zeus::CVector3f x548_ = x34_transform.basis[1];
float x554_ = x34_transform.basis[1].x;
bool x558_ = false;
float x55c_ = 0.f;
float x560_ = 0.f;
@ -287,7 +294,7 @@ private:
CVisorSteam x7a0_visorSteam = CVisorSteam(0.f, 0.f, 0.f, -1);
ResId x7cc_ = -1;
CAnimRes x7d0_animRes;
CPlayerState::EBeamId x7ec_ = CPlayerState::EBeamId::Power;
CPlayerState::EBeamId x7ec_beam = CPlayerState::EBeamId::Power;
std::unique_ptr<CModelData> x7f0_ballTransitionBeamModel;
zeus::CTransform x7f4_;
float x824_ = 0.f;
@ -365,9 +372,10 @@ private:
void ProcessFrozenInput(float dt, CStateManager& mgr);
bool CheckSubmerged() const;
void UpdateSubmerged(CStateManager& mgr);
void InitializeBallTransition();
public:
CPlayer(TUniqueId, const zeus::CTransform&, const zeus::CAABox&, unsigned int w1, const zeus::CVector3f&, float, float,
CPlayer(TUniqueId, const zeus::CTransform&, const zeus::CAABox&, ResId w1, const zeus::CVector3f&, float, float,
float, float, const CMaterialList&);
bool IsTransparent() const;
@ -493,7 +501,7 @@ public:
zeus::CTransform CreateTransformFromMovementDirection() const;
const CCollisionPrimitive* GetCollisionPrimitive() const;
zeus::CTransform GetPrimitiveTransform() const;
bool CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr);
void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr);
float GetActualFirstPersonMaxVelocity() const;
void SetMoveState(EPlayerMovementState, CStateManager& mgr);
float JumpInput(const CFinalInput& input, CStateManager& mgr);

View File

@ -45,4 +45,12 @@ rstl::optional_object<zeus::CAABox> CScriptPlatform::GetTouchBounds() const
return {CPhysicsActor::GetBoundingBox()};
}
bool CScriptPlatform::IsRider(TUniqueId id) const
{
for (const SRiders& rider : x318_riders)
if (rider.x0_uid == id)
return true;
return false;
}
}

View File

@ -65,6 +65,7 @@ public:
void Accept(IVisitor& visitor);
rstl::optional_object<zeus::CAABox> GetTouchBounds() const;
bool IsRider(TUniqueId id) const;
};
}

View File

@ -200,7 +200,7 @@ enum class EScriptObjectMessage
Play = 20,
Alert = 21,
InternalMessage00 = 22,
OnGround = 23,
OnFloor = 23,
InternalMessage02 = 24,
InternalMessage03 = 25,
Falling = 26,