2019-10-12 03:19:48 +00:00
|
|
|
#include "Runtime/Collision/CCollisionPrimitive.hpp"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <climits>
|
|
|
|
#include <cstring>
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
#include "Runtime/Collision/CCollisionInfoList.hpp"
|
|
|
|
#include "Runtime/Collision/CInternalRayCastStructure.hpp"
|
|
|
|
#include "Runtime/Collision/CMaterialFilter.hpp"
|
|
|
|
#include "Runtime/Collision/InternalColliders.hpp"
|
2016-04-27 00:26:02 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
namespace urde {
|
2017-01-21 15:46:51 +00:00
|
|
|
s32 CCollisionPrimitive::sNumTypes = 0;
|
2017-06-18 01:58:13 +00:00
|
|
|
bool CCollisionPrimitive::sInitComplete = false;
|
2017-01-04 04:08:30 +00:00
|
|
|
bool CCollisionPrimitive::sTypesAdded = false;
|
2016-06-24 21:30:25 +00:00
|
|
|
bool CCollisionPrimitive::sTypesAdding = false;
|
2017-01-04 04:08:30 +00:00
|
|
|
bool CCollisionPrimitive::sCollidersAdded = false;
|
|
|
|
bool CCollisionPrimitive::sCollidersAdding = false;
|
2017-06-18 01:58:13 +00:00
|
|
|
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 = {};
|
2017-01-04 04:08:30 +00:00
|
|
|
CCollisionPrimitive::CCollisionPrimitive(const CMaterialList& list) : x8_material(list) {}
|
2016-04-27 00:26:02 +00:00
|
|
|
|
2017-01-04 04:08:30 +00:00
|
|
|
void CCollisionPrimitive::SetMaterial(const CMaterialList& material) { x8_material = material; }
|
2016-04-27 00:26:02 +00:00
|
|
|
|
2017-01-04 04:08:30 +00:00
|
|
|
const CMaterialList& CCollisionPrimitive::GetMaterial() const { return x8_material; }
|
2016-04-27 00:26:02 +00:00
|
|
|
|
2017-03-30 22:36:18 +00:00
|
|
|
CRayCastResult CCollisionPrimitive::CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
2018-12-08 05:30:43 +00:00
|
|
|
const CMaterialFilter& filter, const zeus::CTransform& xf) const {
|
|
|
|
return CastRayInternal(CInternalRayCastStructure(start, dir, length, xf, filter));
|
2016-04-27 00:26:02 +00:00
|
|
|
}
|
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
std::vector<CCollisionPrimitive::Type>::const_iterator CCollisionPrimitive::FindCollisionType(const char* name) {
|
|
|
|
return std::find_if(sCollisionTypeList->cbegin(), sCollisionTypeList->cend(),
|
|
|
|
[name](const auto& type) { return std::strcmp(name, type.GetInfo()) == 0; });
|
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
bool CCollisionPrimitive::InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) {
|
|
|
|
u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex();
|
|
|
|
u32 idx1 = collision.GetRight().GetPrim().GetTableIndex();
|
|
|
|
|
|
|
|
ComparisonFunc func;
|
2019-06-12 02:05:17 +00:00
|
|
|
if (idx0 == UINT32_MAX || idx1 == UINT32_MAX) {
|
2018-12-08 05:30:43 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-06-12 02:05:17 +00:00
|
|
|
if (idx0 == UINT32_MAX || idx1 == UINT32_MAX) {
|
2018-12-08 05:30:43 +00:00
|
|
|
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;
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
return false;
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
|
|
|
|
2017-09-17 03:13:03 +00:00
|
|
|
bool CCollisionPrimitive::Collide(const CInternalCollisionStructure::CPrimDesc& prim0,
|
2018-12-08 05:30:43 +00:00
|
|
|
const CInternalCollisionStructure::CPrimDesc& prim1, CCollisionInfoList& list) {
|
|
|
|
return InternalCollide({prim0, prim1}, list);
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
bool CCollisionPrimitive::InternalCollideBoolean(const CInternalCollisionStructure& collision) {
|
|
|
|
u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex();
|
|
|
|
u32 idx1 = collision.GetRight().GetPrim().GetTableIndex();
|
|
|
|
|
|
|
|
BooleanComparisonFunc func;
|
2019-06-12 02:05:17 +00:00
|
|
|
if (idx0 == UINT32_MAX || idx1 == UINT32_MAX) {
|
2018-12-08 05:30:43 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-06-12 02:05:17 +00:00
|
|
|
if (idx0 == UINT32_MAX || idx1 == UINT32_MAX) {
|
2018-12-08 05:30:43 +00:00
|
|
|
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);
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
|
|
|
|
2017-09-17 03:13:03 +00:00
|
|
|
bool CCollisionPrimitive::CollideBoolean(const CInternalCollisionStructure::CPrimDesc& prim0,
|
2018-12-08 05:30:43 +00:00
|
|
|
const CInternalCollisionStructure::CPrimDesc& prim1) {
|
|
|
|
return InternalCollideBoolean({prim0, prim1});
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
|
|
|
|
2017-07-04 05:03:11 +00:00
|
|
|
bool CCollisionPrimitive::InternalCollideMoving(const CInternalCollisionStructure& collision,
|
2018-12-08 05:30:43 +00:00
|
|
|
const zeus::CVector3f& dir, double& dOut, CCollisionInfo& infoOut) {
|
|
|
|
u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex();
|
|
|
|
u32 idx1 = collision.GetRight().GetPrim().GetTableIndex();
|
|
|
|
|
|
|
|
MovingComparisonFunc func;
|
2019-06-12 02:05:17 +00:00
|
|
|
if (idx0 == UINT32_MAX || idx1 == UINT32_MAX) {
|
2018-12-08 05:30:43 +00:00
|
|
|
sNullMovingCollider = nullptr;
|
|
|
|
func = sNullMovingCollider;
|
|
|
|
} else {
|
|
|
|
func = (*sTableOfMovingCollidables)[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, dir, dOut, infoOut);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-07-04 05:03:11 +00:00
|
|
|
}
|
|
|
|
|
2017-09-17 03:13:03 +00:00
|
|
|
bool CCollisionPrimitive::CollideMoving(const CInternalCollisionStructure::CPrimDesc& prim0,
|
2018-12-08 05:30:43 +00:00
|
|
|
const CInternalCollisionStructure::CPrimDesc& prim1, const zeus::CVector3f& dir,
|
|
|
|
double& dOut, CCollisionInfo& infoOut) {
|
|
|
|
return InternalCollideMoving({prim0, prim1}, dir, dOut, infoOut);
|
2017-06-22 17:56:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitBeginTypes() {
|
2019-09-12 03:50:38 +00:00
|
|
|
sCollisionTypeList = std::make_unique<std::vector<Type>>();
|
2018-12-08 05:30:43 +00:00
|
|
|
sCollisionTypeList->reserve(3);
|
|
|
|
sTypesAdding = true;
|
|
|
|
InternalColliders::AddTypes();
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 03:50:38 +00:00
|
|
|
void CCollisionPrimitive::InitAddType(const Type& tp) {
|
2018-12-08 05:30:43 +00:00
|
|
|
tp.GetSetter()(sCollisionTypeList->size());
|
|
|
|
sCollisionTypeList->push_back(tp);
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitEndTypes() {
|
|
|
|
sCollisionTypeList->shrink_to_fit();
|
|
|
|
sNumTypes = sCollisionTypeList->size();
|
|
|
|
sTypesAdding = false;
|
|
|
|
sTypesAdded = true;
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
2017-01-04 04:08:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitBeginColliders() {
|
2019-09-12 03:50:38 +00:00
|
|
|
const size_t tableSz = sCollisionTypeList->size() * sCollisionTypeList->size();
|
|
|
|
sTableOfCollidables = std::make_unique<std::vector<ComparisonFunc>>(tableSz);
|
|
|
|
sTableOfBooleanCollidables = std::make_unique<std::vector<BooleanComparisonFunc>>(tableSz);
|
|
|
|
sTableOfMovingCollidables = std::make_unique<std::vector<MovingComparisonFunc>>(tableSz);
|
2018-12-08 05:30:43 +00:00
|
|
|
sCollidersAdding = true;
|
|
|
|
InternalColliders::AddColliders();
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
void CCollisionPrimitive::InitAddBooleanCollider(const BooleanComparison& cmp) {
|
|
|
|
const auto iter1 = FindCollisionType(cmp.GetType1());
|
|
|
|
const auto iter2 = FindCollisionType(cmp.GetType2());
|
|
|
|
const auto index1 = std::distance(sCollisionTypeList->cbegin(), iter1);
|
|
|
|
const auto index2 = std::distance(sCollisionTypeList->cbegin(), iter2);
|
|
|
|
const bool hasReachedEnd = iter1 == sCollisionTypeList->cend() || iter2 == sCollisionTypeList->cend();
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
if (index1 >= sNumTypes || index2 >= sNumTypes || hasReachedEnd) {
|
2018-12-08 05:30:43 +00:00
|
|
|
return;
|
2019-10-12 03:19:48 +00:00
|
|
|
}
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
BooleanComparisonFunc& funcOut =
|
2019-10-12 03:19:48 +00:00
|
|
|
hasReachedEnd ? sNullBooleanCollider : (*sTableOfBooleanCollidables)[index2 * sNumTypes + index1];
|
2018-12-08 05:30:43 +00:00
|
|
|
funcOut = cmp.GetCollider();
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitAddBooleanCollider(BooleanComparisonFunc cmp, const char* a, const char* b) {
|
|
|
|
InitAddBooleanCollider({cmp, a, b});
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
void CCollisionPrimitive::InitAddMovingCollider(const MovingComparison& cmp) {
|
|
|
|
const auto iter1 = FindCollisionType(cmp.GetType1());
|
|
|
|
const auto iter2 = FindCollisionType(cmp.GetType2());
|
|
|
|
const auto index1 = std::distance(sCollisionTypeList->cbegin(), iter1);
|
|
|
|
const auto index2 = std::distance(sCollisionTypeList->cbegin(), iter2);
|
|
|
|
const bool hasReachedEnd = iter1 == sCollisionTypeList->cend() || iter2 == sCollisionTypeList->cend();
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
if (index1 >= sNumTypes || index2 >= sNumTypes || hasReachedEnd) {
|
2018-12-08 05:30:43 +00:00
|
|
|
return;
|
2019-10-12 03:19:48 +00:00
|
|
|
}
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
MovingComparisonFunc& funcOut =
|
2019-10-12 03:19:48 +00:00
|
|
|
hasReachedEnd ? sNullMovingCollider : (*sTableOfMovingCollidables)[index2 * sNumTypes + index1];
|
2018-12-08 05:30:43 +00:00
|
|
|
funcOut = cmp.GetCollider();
|
2017-06-18 01:58:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitAddMovingCollider(MovingComparisonFunc cmp, const char* a, const char* b) {
|
|
|
|
InitAddMovingCollider({cmp, a, b});
|
2016-06-24 20:09:38 +00:00
|
|
|
}
|
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
void CCollisionPrimitive::InitAddCollider(const Comparison& cmp) {
|
|
|
|
const auto iter1 = FindCollisionType(cmp.GetType1());
|
|
|
|
const auto iter2 = FindCollisionType(cmp.GetType2());
|
|
|
|
const auto index1 = std::distance(sCollisionTypeList->cbegin(), iter1);
|
|
|
|
const auto index2 = std::distance(sCollisionTypeList->cbegin(), iter2);
|
|
|
|
const bool hasReachedEnd = iter1 == sCollisionTypeList->cend() || iter2 == sCollisionTypeList->cend();
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
if (index1 >= sNumTypes || index2 >= sNumTypes || hasReachedEnd) {
|
2018-12-08 05:30:43 +00:00
|
|
|
return;
|
2019-10-12 03:19:48 +00:00
|
|
|
}
|
2017-06-18 01:58:13 +00:00
|
|
|
|
2019-10-12 03:19:48 +00:00
|
|
|
ComparisonFunc& funcOut = hasReachedEnd ? sNullCollider : (*sTableOfCollidables)[index2 * sNumTypes + index1];
|
2018-12-08 05:30:43 +00:00
|
|
|
funcOut = cmp.GetCollider();
|
2017-01-21 15:46:51 +00:00
|
|
|
}
|
2017-01-04 04:08:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitAddCollider(ComparisonFunc cmp, const char* a, const char* b) {
|
|
|
|
InitAddCollider({cmp, a, b});
|
2017-01-04 04:08:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::InitEndColliders() {
|
|
|
|
sCollidersAdding = false;
|
|
|
|
sCollidersAdded = true;
|
|
|
|
sInitComplete = true;
|
2017-01-21 15:46:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CCollisionPrimitive::Uninitialize() {
|
|
|
|
sInitComplete = false;
|
|
|
|
sCollidersAdding = false;
|
|
|
|
sCollidersAdded = false;
|
|
|
|
sTypesAdding = false;
|
|
|
|
sTypesAdded = false;
|
|
|
|
sNumTypes = 0;
|
|
|
|
sCollisionTypeList.reset();
|
|
|
|
sTableOfCollidables.reset();
|
|
|
|
sTableOfMovingCollidables.reset();
|
|
|
|
sTableOfBooleanCollidables.reset();
|
2017-01-21 15:46:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
} // namespace urde
|