mirror of https://github.com/AxioDL/metaforce.git
Initial collision testing and CStateManager work
This commit is contained in:
parent
a0549cd82b
commit
2530163a8c
|
@ -1,24 +0,0 @@
|
|||
#include "CFluidPlaneManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CFluidPlaneManager::CFluidProfile CFluidPlaneManager::sProfile = {};
|
||||
|
||||
void CFluidPlaneManager::CFluidProfile::Clear()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::StartFrame(bool b)
|
||||
{
|
||||
x121_ = b;
|
||||
sProfile.Clear();
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::Update(float dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -73,7 +73,6 @@ add_library(RuntimeCommon
|
|||
CIOWin.hpp
|
||||
CIOWinManager.hpp CIOWinManager.cpp
|
||||
CStateManager.hpp CStateManager.cpp
|
||||
CFluidPlaneManager.hpp CFluidPlaneManager.cpp
|
||||
CGameState.hpp CGameState.cpp
|
||||
CScanDisplay.hpp CScanDisplay.cpp
|
||||
CRelayTracker.hpp CRelayTracker.cpp
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "World/CGameLight.hpp"
|
||||
#include "CSortedLists.hpp"
|
||||
#include "Weapon/CWeaponMgr.hpp"
|
||||
#include "CFluidPlaneManager.hpp"
|
||||
#include "World/CFluidPlaneManager.hpp"
|
||||
#include "World/CEnvFxManager.hpp"
|
||||
#include "World/CActorModelParticles.hpp"
|
||||
#include "World/CTeamAiTypes.hpp"
|
||||
|
@ -45,6 +45,7 @@
|
|||
#include "Collision/CCollidableSphere.hpp"
|
||||
#include "zeus/CMRay.hpp"
|
||||
#include "Collision/CollisionUtil.hpp"
|
||||
#include "World/CScriptWater.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -642,20 +643,20 @@ void CStateManager::DrawWorld() const
|
|||
x850_world->TouchSky();
|
||||
|
||||
int areaCount = 0;
|
||||
CGameArea* areaArr[10];
|
||||
for (CGameArea* area = x850_world->GetChainHead(EChain::Alive);
|
||||
area != CWorld::AliveAreasEnd() && areaCount != 10;
|
||||
area = area->x130_next)
|
||||
const CGameArea* areaArr[10];
|
||||
for (const CGameArea& area : *x850_world)
|
||||
{
|
||||
if (areaCount == 10)
|
||||
break;
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
|
||||
if (area->IsPostConstructed())
|
||||
occState = area->GetOcclusionState();
|
||||
if (area.IsPostConstructed())
|
||||
occState = area.GetOcclusionState();
|
||||
if (occState == CGameArea::EOcclusionState::Occluded)
|
||||
areaArr[areaCount++] = area;
|
||||
areaArr[areaCount++] = &area;
|
||||
}
|
||||
|
||||
std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount,
|
||||
[visAreaId](CGameArea* a, CGameArea* b) -> bool
|
||||
[visAreaId](const CGameArea* a, const CGameArea* b) -> bool
|
||||
{
|
||||
if (a->x4_selfIdx == b->x4_selfIdx)
|
||||
return false;
|
||||
|
@ -669,11 +670,11 @@ void CStateManager::DrawWorld() const
|
|||
|
||||
int pvsCount = 0;
|
||||
CPVSVisSet pvsArr[10];
|
||||
for (CGameArea** area = areaArr;
|
||||
for (const CGameArea** area = areaArr;
|
||||
area != areaArr + areaCount;
|
||||
++area)
|
||||
{
|
||||
CGameArea* areaPtr = *area;
|
||||
const CGameArea* areaPtr = *area;
|
||||
CPVSVisSet& pvsSet = pvsArr[pvsCount++];
|
||||
pvsSet.Reset(EPVSVisSetState::OutOfBounds);
|
||||
GetVisSetForArea(areaPtr->x4_selfIdx, visAreaId, pvsSet);
|
||||
|
@ -701,7 +702,7 @@ void CStateManager::DrawWorld() const
|
|||
|
||||
for (int i=areaCount-1 ; i>=0 ; --i)
|
||||
{
|
||||
CGameArea& area = *areaArr[i];
|
||||
const CGameArea& area = *areaArr[i];
|
||||
SetupFogForArea(area);
|
||||
g_Renderer->EnablePVS(&pvsArr[i], area.x4_selfIdx);
|
||||
g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
|
||||
|
@ -726,7 +727,7 @@ void CStateManager::DrawWorld() const
|
|||
CActor* thermalActorArr[1024];
|
||||
for (int i=0 ; i<areaCount ; ++i)
|
||||
{
|
||||
CGameArea& area = *areaArr[i];
|
||||
const CGameArea& area = *areaArr[i];
|
||||
CPVSVisSet& pvs = pvsArr[i];
|
||||
bool isVisArea = area.x4_selfIdx == visAreaId;
|
||||
SetupFogForArea(area);
|
||||
|
@ -807,7 +808,7 @@ void CStateManager::DrawWorld() const
|
|||
|
||||
for (int i=areaCount-1 ; i>=0 ; --i)
|
||||
{
|
||||
CGameArea& area = *areaArr[i];
|
||||
const CGameArea& area = *areaArr[i];
|
||||
CPVSVisSet& pvs = pvsArr[i];
|
||||
|
||||
g_Renderer->EnablePVS(&pvs, area.x4_selfIdx);
|
||||
|
@ -819,7 +820,7 @@ void CStateManager::DrawWorld() const
|
|||
|
||||
for (int i=0 ; i<areaCount ; ++i)
|
||||
{
|
||||
CGameArea& area = *areaArr[i];
|
||||
const CGameArea& area = *areaArr[i];
|
||||
CPVSVisSet& pvs = pvsArr[i];
|
||||
|
||||
for (int j=0 ; j<thermalActorCount ; ++j)
|
||||
|
@ -939,16 +940,14 @@ void CStateManager::PreRender()
|
|||
proj.setPersp(zeus::SProjPersp{zeus::degToRad(cam->GetFov()),
|
||||
cam->GetAspectRatio(), cam->GetNearClipDistance(), cam->GetFarClipDistance()});
|
||||
frustum.updatePlanes(x870_cameraManager->GetCurrentCameraTransform(*this), proj);
|
||||
for (CGameArea* area = x850_world->GetChainHead(EChain::Alive);
|
||||
area != CWorld::AliveAreasEnd();
|
||||
area = area->x130_next)
|
||||
for (const CGameArea& area : *x850_world)
|
||||
{
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
|
||||
if (area->IsPostConstructed())
|
||||
occState = area->GetOcclusionState();
|
||||
if (area.IsPostConstructed())
|
||||
occState = area.GetOcclusionState();
|
||||
if (occState == CGameArea::EOcclusionState::Occluded)
|
||||
{
|
||||
for (CEntity* ent : *area->GetPostConstructed()->x10c0_areaObjs)
|
||||
for (CEntity* ent : *area.GetPostConstructed()->x10c0_areaObjs)
|
||||
{
|
||||
if (TCastToPtr<CActor> act = ent)
|
||||
{
|
||||
|
@ -1385,7 +1384,7 @@ void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, c
|
|||
else if (ent->GetUniqueId() != damager)
|
||||
{
|
||||
TestBombHittingWater(actor, pos, static_cast<CActor&>(*ent));
|
||||
if (TestRadiusDamage(pos, static_cast<CActor&>(*ent), nearList))
|
||||
if (TestRayDamage(pos, static_cast<CActor&>(*ent), nearList))
|
||||
ApplyRadiusDamage(actor, pos, static_cast<CActor&>(*ent), info);
|
||||
}
|
||||
|
||||
|
@ -1412,7 +1411,7 @@ void CStateManager::ProcessRadiusDamage(const CActor& a1, CActor& a2, TUniqueId
|
|||
continue;
|
||||
|
||||
TestBombHittingWater(a1, a1.GetTranslation(), static_cast<CActor&>(*ent));
|
||||
if (TestRadiusDamage(a1.GetTranslation(), static_cast<CActor&>(*ent), nearList))
|
||||
if (TestRayDamage(a1.GetTranslation(), static_cast<CActor&>(*ent), nearList))
|
||||
ApplyRadiusDamage(a1, a1.GetTranslation(), static_cast<CActor&>(*ent), info);
|
||||
}
|
||||
}
|
||||
|
@ -1467,7 +1466,7 @@ void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& p
|
|||
}
|
||||
}
|
||||
|
||||
bool CStateManager::TestRadiusDamage(const zeus::CVector3f& pos, const CActor& damagee,
|
||||
bool CStateManager::TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList)
|
||||
{
|
||||
const CHealthInfo* hInfo = const_cast<CActor&>(damagee).HealthInfo();
|
||||
|
@ -1486,18 +1485,18 @@ bool CStateManager::TestRadiusDamage(const zeus::CVector3f& pos, const CActor& d
|
|||
return false;
|
||||
|
||||
zeus::CVector3f center = bounds->center();
|
||||
zeus::CVector3f delta = center - pos;
|
||||
zeus::CVector3f dir = center - pos;
|
||||
|
||||
if (!delta.canBeNormalized())
|
||||
if (!dir.canBeNormalized())
|
||||
return true;
|
||||
float origMag = delta.magnitude();
|
||||
delta = delta * (1.f / origMag);
|
||||
float origMag = dir.magnitude();
|
||||
dir = dir * (1.f / origMag);
|
||||
|
||||
if (TestRadiusDamage(pos, center, nearList, filter, damagee))
|
||||
if (RayCollideWorld(pos, center, nearList, filter, damagee))
|
||||
return true;
|
||||
|
||||
zeus::CMRay ray(pos, delta, origMag);
|
||||
if (!TestRadiusDamage(ray, filter))
|
||||
zeus::CMRay ray(pos, dir, origMag);
|
||||
if (!MultiRayCollideWorld(ray, filter))
|
||||
return false;
|
||||
|
||||
float depth;
|
||||
|
@ -1505,27 +1504,43 @@ bool CStateManager::TestRadiusDamage(const zeus::CVector3f& pos, const CActor& d
|
|||
if (count == 0 || count == 1)
|
||||
return true;
|
||||
|
||||
return TestRadiusDamage(pos, delta, filter, nearList, damagee, depth * origMag);
|
||||
return RayCollideDynamic(pos, dir, filter, nearList, &damagee, depth * origMag);
|
||||
}
|
||||
|
||||
bool CStateManager::TestRadiusDamage(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool CStateManager::RayCollideWorld(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CMaterialFilter& filter, const CActor& damagee)
|
||||
{
|
||||
return false;
|
||||
return RayCollideWorldInternal(pos, damageeCenter, filter, nearList, &damagee);
|
||||
}
|
||||
|
||||
bool CStateManager::TestRadiusDamage(const zeus::CMRay& ray, const CMaterialFilter& filter)
|
||||
bool CStateManager::RayCollideWorldInternal(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor* damagee)
|
||||
{
|
||||
zeus::CVector3f vecToDamagee = damageeCenter - pos;
|
||||
if (!vecToDamagee.canBeNormalized())
|
||||
return true;
|
||||
|
||||
float mag = vecToDamagee.magnitude();
|
||||
zeus::CVector3f dir = vecToDamagee * (1.f / mag);
|
||||
if (!RayCollideStatic(pos, dir, mag, filter))
|
||||
return false;
|
||||
return RayCollideDynamic(pos, dir, filter, nearList, damagee, mag);
|
||||
}
|
||||
|
||||
bool CStateManager::MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter)
|
||||
{
|
||||
zeus::CVector3f crossed =
|
||||
{
|
||||
-ray.end.z * ray.end.z - ray.end.y * ray.end.x,
|
||||
ray.end.x * ray.end.x - ray.end.z * ray.end.y,
|
||||
ray.end.y * ray.end.y - ray.end.x * -ray.end.z
|
||||
-ray.dir.z * ray.dir.z - ray.dir.y * ray.dir.x,
|
||||
ray.dir.x * ray.dir.x - ray.dir.z * ray.dir.y,
|
||||
ray.dir.y * ray.dir.y - ray.dir.x * -ray.dir.z
|
||||
};
|
||||
|
||||
crossed.normalize();
|
||||
zeus::CVector3f crossed2 = ray.end.cross(crossed) * 0.35355338f;
|
||||
zeus::CVector3f crossed2 = ray.dir.cross(crossed) * 0.35355338f;
|
||||
zeus::CVector3f negCrossed2 = -crossed2;
|
||||
zeus::CVector3f rms = crossed * 0.35355338f;
|
||||
zeus::CVector3f negRms = -rms;
|
||||
|
@ -1534,41 +1549,103 @@ bool CStateManager::TestRadiusDamage(const zeus::CMRay& ray, const CMaterialFilt
|
|||
{
|
||||
zeus::CVector3f& useCrossed = (i & 2) ? negCrossed2 : crossed2;
|
||||
zeus::CVector3f& useRms = (i & 1) ? rms : negRms;
|
||||
if (TestRayDamage(ray.start + useCrossed + useRms, ray.end, ray.d, filter))
|
||||
if (RayCollideStatic(ray.start + useCrossed + useRms, ray.dir, ray.length, filter))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CStateManager::TestRayDamage(const zeus::CVector3f& start, const zeus::CVector3f& end, float d,
|
||||
bool CStateManager::RayCollideStatic(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter)
|
||||
{
|
||||
if (d <= 0.f)
|
||||
d = 100000.f;
|
||||
zeus::CLineSeg seg(start, end);
|
||||
for (CGameArea* area = x850_world->GetChainHead(EChain::Alive) ;
|
||||
area != CWorld::GetAliveAreasEnd() ; area = area->GetNext())
|
||||
if (length <= 0.f)
|
||||
length = 100000.f;
|
||||
zeus::CLine line(start, dir);
|
||||
for (const CGameArea& area : *x850_world)
|
||||
{
|
||||
CAreaOctTree& collision = *area->GetPostConstructed()->x0_collision;
|
||||
const CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision;
|
||||
CAreaOctTree::Node root = collision.GetRootNode();
|
||||
if (!root.LineTest(seg, filter, d))
|
||||
if (!root.LineTest(line, filter, length))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStateManager::TestRadiusDamage(const zeus::CVector3f& pos, const zeus::CVector3f& normToDamagee,
|
||||
const CMaterialFilter& filter, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor& damagee, float mag)
|
||||
bool CStateManager::RayCollideDynamic(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor* damagee, float length)
|
||||
{
|
||||
if (length <= 0.f)
|
||||
length = 100000.f;
|
||||
|
||||
for (TUniqueId id : nearList)
|
||||
{
|
||||
CEntity* ent = ObjectById(id);
|
||||
if (TCastToPtr<CPhysicsActor> physActor = ent)
|
||||
{
|
||||
if (damagee && physActor->GetUniqueId() == damagee->GetUniqueId())
|
||||
continue;
|
||||
zeus::CTransform xf = physActor->GetPrimitiveTransform();
|
||||
const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive();
|
||||
CRayCastResult res = prim->CastRay(pos, dir, length, filter, xf);
|
||||
if (!res.IsInvalid())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee)
|
||||
{
|
||||
|
||||
if (TCastToPtr<CWeapon> wpn = const_cast<CActor&>(damager))
|
||||
{
|
||||
if ((wpn->GetAttribField() & (CWeapon::EProjectileAttrib::Bombs |
|
||||
CWeapon::EProjectileAttrib::PowerBombs)) != CWeapon::EProjectileAttrib::None)
|
||||
{
|
||||
bool powerBomb = (wpn->GetAttribField() & CWeapon::EProjectileAttrib::Bombs) !=
|
||||
CWeapon::EProjectileAttrib::None;
|
||||
if (TCastToPtr<CScriptWater> water = damagee)
|
||||
{
|
||||
zeus::CAABox bounds = water->GetTriggerBoundsWR();
|
||||
zeus::CVector3f hitPos(pos.x, pos.y, bounds.max.z);
|
||||
float bombRad = powerBomb ? 4.f : 2.f;
|
||||
float delta = -(pos.dot(zeus::CVector3f::skUp) - bounds.max.z);
|
||||
if (delta <= bombRad && delta > 0.f)
|
||||
{
|
||||
// Below surface
|
||||
float rippleFactor = 1.f - delta / bombRad;
|
||||
if (x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f)
|
||||
{
|
||||
float bombMag = powerBomb ? 1.f : 0.75f;
|
||||
float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * rippleFactor * 0.25f);
|
||||
water->GetFluidPlane().Ripple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
}
|
||||
if (!powerBomb)
|
||||
x87c_fluidPlaneManager->CreateSplash(damager.GetUniqueId(), *this, *water, hitPos, rippleFactor, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Above surface
|
||||
float bombMag = powerBomb ? 2.f : 1.f;
|
||||
if (delta <= -bombMag || delta >= 0.f)
|
||||
return;
|
||||
CRayCastResult res = RayStaticIntersection(pos, zeus::CVector3f::skDown, -delta,
|
||||
CMaterialFilter::skPassEverything);
|
||||
if (res.IsInvalid() &&
|
||||
x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f)
|
||||
{
|
||||
// Not blocked by static geometry
|
||||
float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * -delta / bombMag * 0.25f);
|
||||
water->GetFluidPlane().Ripple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CStateManager::ApplyLocalDamage(const zeus::CVector3f& vec1, const zeus::CVector3f& vec2, CActor& actor, float dt,
|
||||
|
@ -2313,17 +2390,17 @@ void CStateManager::AddObject(CEntity* ent)
|
|||
AddObject(*ent);
|
||||
}
|
||||
|
||||
bool CStateManager::RayStaticIntersection(const zeus::CVector3f&, const zeus::CVector3f&, float,
|
||||
const CMaterialFilter&) const
|
||||
CRayCastResult CStateManager::RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter) const
|
||||
{
|
||||
return false;
|
||||
return CGameCollision::RayStaticIntersection(*this, pos, dir, length, filter);
|
||||
}
|
||||
|
||||
bool CStateManager::RayWorldIntersection(TUniqueId, const zeus::CVector3f&, const zeus::CVector3f&, float,
|
||||
const CMaterialFilter&,
|
||||
CRayCastResult CStateManager::RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float length, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& list) const
|
||||
{
|
||||
return false;
|
||||
return CGameCollision::RayWorldIntersection(*this, idOut, pos, dir, length, filter, list);
|
||||
}
|
||||
|
||||
void CStateManager::UpdateObjectInLists(CEntity&) {}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "World/ScriptLoader.hpp"
|
||||
#include "Input/CFinalInput.hpp"
|
||||
#include "CSortedLists.hpp"
|
||||
#include "CFluidPlaneManager.hpp"
|
||||
#include "World/CFluidPlaneManager.hpp"
|
||||
#include "World/CEnvFxManager.hpp"
|
||||
#include "World/CActorModelParticles.hpp"
|
||||
#include "Input/CRumbleManager.hpp"
|
||||
|
@ -319,17 +319,21 @@ public:
|
|||
const CDamageInfo& info, const CMaterialFilter&);
|
||||
void ApplyRadiusDamage(const CActor&, const zeus::CVector3f&, CActor&,
|
||||
const CDamageInfo& info);
|
||||
bool TestRadiusDamage(const zeus::CVector3f& pos, const CActor& damagee,
|
||||
bool TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
bool TestRadiusDamage(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
bool RayCollideWorld(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CMaterialFilter& filter, const CActor& damagee);
|
||||
bool TestRadiusDamage(const zeus::CMRay& ray, const CMaterialFilter& filter);
|
||||
bool TestRayDamage(const zeus::CVector3f& start, const zeus::CVector3f& end, float d,
|
||||
bool RayCollideWorldInternal(const zeus::CVector3f& pos, const zeus::CVector3f& damageeCenter,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor* damagee);
|
||||
bool MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter);
|
||||
bool RayCollideStatic(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter);
|
||||
bool TestRadiusDamage(const zeus::CVector3f& pos, const zeus::CVector3f& normToDamagee,
|
||||
bool RayCollideDynamic(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
const CMaterialFilter& filter, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const CActor& damagee, float mag);
|
||||
const CActor* damagee, float length);
|
||||
void TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee);
|
||||
bool ApplyLocalDamage(const zeus::CVector3f&, const zeus::CVector3f&, CActor&, float,
|
||||
const CWeaponMode&);
|
||||
|
@ -380,10 +384,10 @@ public:
|
|||
std::experimental::optional<zeus::CAABox> CalculateObjectBounds(const CActor&);
|
||||
void AddObject(CEntity&);
|
||||
void AddObject(CEntity*);
|
||||
bool RayStaticIntersection(const zeus::CVector3f&, const zeus::CVector3f&, float,
|
||||
const CMaterialFilter&) const;
|
||||
bool RayWorldIntersection(TUniqueId, const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
float, const CMaterialFilter&,
|
||||
CRayCastResult RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter) const;
|
||||
CRayCastResult RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float length, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& list) const;
|
||||
void UpdateObjectInLists(CEntity&);
|
||||
TUniqueId AllocateUniqueId();
|
||||
|
|
|
@ -1,40 +1,484 @@
|
|||
#include "CAreaOctTree.hpp"
|
||||
#include "CMaterialFilter.hpp"
|
||||
#include "zeus/CVector2i.hpp"
|
||||
#include <array>
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
bool CAreaOctTree::Node::LineTestInternal(const zeus::CLineSeg&, const CMaterialFilter&,
|
||||
float, float, float, const zeus::CVector3f&) const
|
||||
static bool _close_enough(float f1, float f2, float epsilon)
|
||||
{
|
||||
return false;
|
||||
return std::fabs(f1 - f2) <= epsilon;
|
||||
}
|
||||
|
||||
bool CAreaOctTree::Node::LineTestExInternal(const zeus::CLineSeg&, const CMaterialFilter&,
|
||||
SRayResult&, float, float, float, const zeus::CVector3f&) const
|
||||
static bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CLine& line, float& lT, float& hT)
|
||||
{
|
||||
const float* aabbMin = &aabb.min.x;
|
||||
const float* aabbMax = &aabb.max.x;
|
||||
const float* lorigin = &line.origin.x;
|
||||
const float* ldir = &line.dir.x;
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (_close_enough(*ldir, 0.f, 0.000099999997f))
|
||||
if (*lorigin < *aabbMin || *lorigin > *aabbMax)
|
||||
return false;
|
||||
|
||||
if (*ldir < 0.f)
|
||||
{
|
||||
if (*aabbMax - *lorigin < lT * *ldir)
|
||||
lT = *aabbMax - *lorigin * 1.f / *ldir;
|
||||
if (*aabbMin - *lorigin > hT * *ldir)
|
||||
hT = *aabbMin - *lorigin * 1.f / *ldir;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*aabbMin - *lorigin > lT * *ldir)
|
||||
lT = *aabbMin - *lorigin * 1.f / *ldir;
|
||||
if (*aabbMax - *lorigin < hT * *ldir)
|
||||
hT = *aabbMax - *lorigin * 1.f / *ldir;
|
||||
}
|
||||
|
||||
++aabbMin;
|
||||
++aabbMax;
|
||||
++lorigin;
|
||||
++ldir;
|
||||
}
|
||||
|
||||
return lT <= hT;
|
||||
}
|
||||
|
||||
bool CAreaOctTree::Node::LineTest(const zeus::CLineSeg&, const CMaterialFilter&, float) const
|
||||
static const int SomeIndexA[] =
|
||||
{
|
||||
1, 2, 4
|
||||
};
|
||||
|
||||
static const int SomeIndexB[] =
|
||||
{
|
||||
1, 2, 0
|
||||
};
|
||||
|
||||
static const int SomeIndexC[8][8] =
|
||||
{
|
||||
{0, 1, 2, 4, 5, 6, 8, 0xA},
|
||||
{0, 1, 2, 3, 5, 6, 8, 0xA},
|
||||
{0, 1, 2, 4, 5, 6, 9, 0xB},
|
||||
{0, 1, 2, 3, 5, 6, 9, 0xC},
|
||||
{0, 1, 2, 4, 5, 7, 8, 0xD},
|
||||
{0, 1, 2, 3, 5, 7, 8, 0xE},
|
||||
{0, 1, 2, 4, 5, 7, 9, 0xF},
|
||||
{0, 1, 2, 3, 5, 7, 9, 0xF}
|
||||
};
|
||||
|
||||
static const std::pair<int, std::array<int, 3>> SubdivIndex[16] =
|
||||
{
|
||||
{0, {0, 0, 0}},
|
||||
{1, {0, 0, 0}},
|
||||
{1, {1, 0, 0}},
|
||||
{2, {0, 1, 0}},
|
||||
{2, {1, 0, 0}},
|
||||
{1, {2, 0, 0}},
|
||||
{2, {0, 2, 0}},
|
||||
{2, {2, 0, 0}},
|
||||
{2, {2, 1, 0}},
|
||||
{2, {1, 2, 0}},
|
||||
{3, {0, 2, 1}},
|
||||
{3, {1, 0, 2}},
|
||||
{3, {0, 1, 2}},
|
||||
{3, {2, 1, 0}},
|
||||
{3, {2, 0, 1}},
|
||||
{3, {1, 2, 0}}
|
||||
};
|
||||
|
||||
bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMaterialFilter& filter,
|
||||
float lT, float hT, float maxT, const zeus::CVector3f& vec) const
|
||||
{
|
||||
float lowT = (1.f - FLT_EPSILON * 100.f) * lT;
|
||||
float highT = (1.f + FLT_EPSILON * 100.f) * hT;
|
||||
if (maxT != 0.f)
|
||||
{
|
||||
if (lowT < 0.f)
|
||||
lowT = 0.f;
|
||||
if (highT > maxT)
|
||||
highT = maxT;
|
||||
if (lowT > highT)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x20_nodeType == ETreeType::Leaf)
|
||||
{
|
||||
TriListReference triList = GetTriangleArray();
|
||||
for (u16 i=0 ; i<triList.GetSize() ; ++i)
|
||||
{
|
||||
CCollisionSurface triangle = x1c_owner.GetMasterListTriangle(triList.GetAt(i));
|
||||
|
||||
// https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm
|
||||
// Find vectors for two edges sharing V0
|
||||
zeus::CVector3f e0 = triangle.GetVert(1) - triangle.GetVert(0);
|
||||
zeus::CVector3f e1 = triangle.GetVert(2) - triangle.GetVert(0);
|
||||
|
||||
// Begin calculating determinant - also used to calculate u parameter
|
||||
zeus::CVector3f P = line.dir.cross(e1);
|
||||
float det = P.dot(e0);
|
||||
|
||||
// If determinant is near zero, ray lies in plane of triangle
|
||||
// or ray is parallel to plane of triangle
|
||||
if (std::fabs(det) < (FLT_EPSILON * 10.f))
|
||||
continue;
|
||||
float invDet = 1.f / det;
|
||||
|
||||
// Calculate distance from V1 to ray origin
|
||||
zeus::CVector3f T = line.origin - triangle.GetVert(0);
|
||||
|
||||
// Calculate u parameter and test bound
|
||||
float u = invDet * T.dot(P);
|
||||
|
||||
// The intersection lies outside of the triangle
|
||||
if (u < 0.f || u > 1.f)
|
||||
continue;
|
||||
|
||||
// Prepare to test v parameter
|
||||
zeus::CVector3f Q = T.cross(e0);
|
||||
|
||||
// Calculate T parameter and test bound
|
||||
float t = invDet * Q.dot(e1);
|
||||
if (t >= highT || t < lowT)
|
||||
continue;
|
||||
|
||||
// Calculate V parameter and test bound
|
||||
float v = invDet * Q.dot(line.dir);
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
continue;
|
||||
|
||||
// Do material filter
|
||||
CMaterialList matList(triangle.GetSurfaceFlags());
|
||||
if (filter.Passes(matList))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (x20_nodeType == ETreeType::Branch)
|
||||
{
|
||||
if (GetChildFlags() == 0xA) // 2 leaves
|
||||
{
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
{
|
||||
Node child = GetChild(i);
|
||||
float tf1 = lT;
|
||||
float tf2 = hT;
|
||||
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2))
|
||||
if (!LineTestInternal(line, filter, tf1, tf2, maxT, vec))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
zeus::CVector3f center = x0_aabb.center();
|
||||
|
||||
zeus::CVector3f r6 = line.origin + lT * line.dir;
|
||||
zeus::CVector3f r7 = line.origin + hT * line.dir;
|
||||
zeus::CVector3f r9 = vec * (center - line.origin);
|
||||
|
||||
int r28 = 0;
|
||||
int r25 = 0;
|
||||
int r26 = 0;
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (r6[i] >= center[i])
|
||||
r28 |= SomeIndexA[i];
|
||||
if (r7[i] >= center[i])
|
||||
r25 |= SomeIndexA[i];
|
||||
if (r9[i] < r9[SomeIndexB[i]])
|
||||
r26 |= SomeIndexA[i];
|
||||
}
|
||||
|
||||
float f21 = lT;
|
||||
int r26b = r28;
|
||||
const std::pair<int, std::array<int, 3>>& idx = SubdivIndex[SomeIndexC[r26][r28 ^ r25]];
|
||||
for (int i=0 ; i<=idx.first ; ++i)
|
||||
{
|
||||
float f22 = (i < idx.first) ? r9[idx.second[i]] : hT;
|
||||
if (f22 > lowT && f21 <= f22)
|
||||
{
|
||||
Node child = GetChild(r26b);
|
||||
if (child.x20_nodeType != ETreeType::Invalid)
|
||||
if (!LineTestInternal(line, filter, f21, f22, maxT, vec))
|
||||
return false;
|
||||
}
|
||||
if (i < idx.first)
|
||||
r26b ^= 1 << idx.second[i];
|
||||
f21 = f22;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAreaOctTree::Node::LineTestEx(const zeus::CLineSeg&, const CMaterialFilter&, SRayResult&, float) const
|
||||
void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMaterialFilter& filter,
|
||||
SRayResult& res, float lT, float hT, float maxT,
|
||||
const zeus::CVector3f& vec) const
|
||||
{
|
||||
return false;
|
||||
float lowT = (1.f - FLT_EPSILON * 100.f) * lT;
|
||||
float highT = (1.f + FLT_EPSILON * 100.f) * hT;
|
||||
if (maxT != 0.f)
|
||||
{
|
||||
if (lowT < 0.f)
|
||||
lowT = 0.f;
|
||||
if (highT > maxT)
|
||||
highT = maxT;
|
||||
if (lowT > highT)
|
||||
return;
|
||||
}
|
||||
|
||||
if (x20_nodeType == ETreeType::Leaf)
|
||||
{
|
||||
TriListReference triList = GetTriangleArray();
|
||||
float f30 = highT;
|
||||
bool foundTriangle = false;
|
||||
SRayResult tmpRes;
|
||||
|
||||
for (u16 i=0 ; i<triList.GetSize() ; ++i)
|
||||
{
|
||||
CCollisionSurface triangle = x1c_owner.GetMasterListTriangle(triList.GetAt(i));
|
||||
|
||||
// https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm
|
||||
// Find vectors for two edges sharing V0
|
||||
zeus::CVector3f e0 = triangle.GetVert(1) - triangle.GetVert(0);
|
||||
zeus::CVector3f e1 = triangle.GetVert(2) - triangle.GetVert(0);
|
||||
|
||||
// Begin calculating determinant - also used to calculate u parameter
|
||||
zeus::CVector3f P = line.dir.cross(e1);
|
||||
float det = P.dot(e0);
|
||||
|
||||
// If determinant is near zero, ray lies in plane of triangle
|
||||
// or ray is parallel to plane of triangle
|
||||
if (std::fabs(det) < (FLT_EPSILON * 10.f))
|
||||
continue;
|
||||
float invDet = 1.f / det;
|
||||
|
||||
// Calculate distance from V1 to ray origin
|
||||
zeus::CVector3f T = line.origin - triangle.GetVert(0);
|
||||
|
||||
// Calculate u parameter and test bound
|
||||
float u = invDet * T.dot(P);
|
||||
|
||||
// The intersection lies outside of the triangle
|
||||
if (u < 0.f || u > 1.f)
|
||||
continue;
|
||||
|
||||
// Prepare to test v parameter
|
||||
zeus::CVector3f Q = T.cross(e0);
|
||||
|
||||
// Calculate T parameter and test bound
|
||||
float t = invDet * Q.dot(e1);
|
||||
if (t >= f30 || t < lowT)
|
||||
continue;
|
||||
|
||||
// Calculate V parameter and test bound
|
||||
float v = invDet * Q.dot(line.dir);
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
continue;
|
||||
|
||||
// Do material filter
|
||||
CMaterialList matList(triangle.GetSurfaceFlags());
|
||||
if (filter.Passes(matList) && t <= f30)
|
||||
{
|
||||
f30 = t;
|
||||
foundTriangle = true;
|
||||
tmpRes.x10_surface.emplace(triangle);
|
||||
tmpRes.x3c_t = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundTriangle)
|
||||
{
|
||||
res = tmpRes;
|
||||
res.x0_plane = res.x10_surface->GetPlane();
|
||||
}
|
||||
}
|
||||
else if (x20_nodeType == ETreeType::Branch)
|
||||
{
|
||||
if (GetChildFlags() == 0xA) // 2 leaves
|
||||
{
|
||||
SRayResult tmpRes[2];
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
{
|
||||
Node child = GetChild(i);
|
||||
float tf1 = lT;
|
||||
float tf2 = hT;
|
||||
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2))
|
||||
LineTestExInternal(line, filter, tmpRes[i], tf1, tf2, maxT, vec);
|
||||
}
|
||||
|
||||
if (!tmpRes[0].x10_surface && !tmpRes[1].x10_surface)
|
||||
{
|
||||
res = SRayResult();
|
||||
}
|
||||
else if (tmpRes[0].x10_surface && tmpRes[1].x10_surface)
|
||||
{
|
||||
if (tmpRes[0].x3c_t < tmpRes[1].x3c_t)
|
||||
res = tmpRes[0];
|
||||
else
|
||||
res = tmpRes[1];
|
||||
}
|
||||
else if (tmpRes[0].x10_surface)
|
||||
{
|
||||
res = tmpRes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
res = tmpRes[1];
|
||||
}
|
||||
|
||||
if (res.x3c_t > highT)
|
||||
res = SRayResult();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
zeus::CVector3f center = x0_aabb.center(); // r26
|
||||
|
||||
zeus::CVector3f r25 = line.origin + lT * line.dir;
|
||||
zeus::CVector3f r24 = line.origin + hT * line.dir;
|
||||
int r19[] = {-1, -1, -1, 0};
|
||||
float r20[3];
|
||||
|
||||
int r17 = 0;
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (r25[i] < center[i] || r24[i] <= center[i])
|
||||
if (r24[i] >= center[i] || r25[i] <= center[i])
|
||||
continue;
|
||||
if (_close_enough(line.dir[i], 0.f, 0.000099999997f))
|
||||
continue;
|
||||
r19[r17++] = i;
|
||||
r20[i] = vec[i] * (center[i] - line.origin[i]);
|
||||
}
|
||||
|
||||
switch (r17)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
case 0:
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if (r20[r19[1]] < r20[r19[0]])
|
||||
std::swap(r19[1], r19[0]);
|
||||
break;
|
||||
case 3:
|
||||
if (r20[0] < r20[1])
|
||||
{
|
||||
if (r20[0] >= r20[2])
|
||||
{
|
||||
r19[0] = 2;
|
||||
r19[1] = 0;
|
||||
r19[2] = 1;
|
||||
}
|
||||
else if (r20[1] < r20[2])
|
||||
{
|
||||
r19[0] = 0;
|
||||
r19[1] = 1;
|
||||
r19[2] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
r19[0] = 0;
|
||||
r19[1] = 2;
|
||||
r19[2] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r20[1] >= r20[2])
|
||||
{
|
||||
r19[0] = 2;
|
||||
r19[1] = 1;
|
||||
r19[2] = 0;
|
||||
}
|
||||
else if (r20[0] < r20[2])
|
||||
{
|
||||
r19[0] = 1;
|
||||
r19[1] = 0;
|
||||
r19[2] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
r19[0] = 1;
|
||||
r19[1] = 2;
|
||||
r19[2] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
zeus::CVector3f lineEnd = line.origin + (lT * line.dir);
|
||||
int selector = 0;
|
||||
if (lineEnd.x >= center.x)
|
||||
selector = 1;
|
||||
if (lineEnd.y >= center.y)
|
||||
selector |= 1 << 1;
|
||||
if (lineEnd.z >= center.z)
|
||||
selector |= 1 << 2;
|
||||
|
||||
float loT = lT;
|
||||
for (int i=-1 ; i<r17 ; ++i)
|
||||
{
|
||||
if (i >= 0)
|
||||
selector ^= 1 << r19[i];
|
||||
float hiT = (i < r17-1) ? hiT = r20[r19[i+1]] : hiT = hT;
|
||||
if (hiT > lowT && loT <= hiT)
|
||||
{
|
||||
Node child = GetChild(selector);
|
||||
if (child.x20_nodeType != ETreeType::Invalid)
|
||||
LineTestExInternal(line, filter, res, loT, hiT, maxT, vec);
|
||||
if (res.x10_surface)
|
||||
if (res.x3c_t > highT)
|
||||
res = SRayResult();
|
||||
}
|
||||
loT = hiT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CAreaOctTree::Node::LineTest(const zeus::CLine& line, const CMaterialFilter& filter, float length) const
|
||||
{
|
||||
if (x20_nodeType == ETreeType::Invalid)
|
||||
return true;
|
||||
|
||||
float f1 = 0.f;
|
||||
float f2 = 0.f;
|
||||
if (!BoxLineTest(x0_aabb, line, f1, f2))
|
||||
return true;
|
||||
|
||||
zeus::CVector3f recip = 1.f / line.dir;
|
||||
return LineTestInternal(line, filter, f1 - 0.000099999997f, f2 + 0.000099999997f, length, recip);
|
||||
}
|
||||
|
||||
void CAreaOctTree::Node::LineTestEx(const zeus::CLine& line, const CMaterialFilter& filter,
|
||||
SRayResult& res, float length) const
|
||||
{
|
||||
if (x20_nodeType == ETreeType::Invalid)
|
||||
return;
|
||||
|
||||
float f1 = 0.f;
|
||||
float f2 = 0.f;
|
||||
if (!BoxLineTest(x0_aabb, line, f1, f2))
|
||||
return;
|
||||
|
||||
zeus::CVector3f recip = 1.f / line.dir;
|
||||
LineTestExInternal(line, filter, res, f1 - 0.000099999997f, f2 + 0.000099999997f, length, recip);
|
||||
}
|
||||
|
||||
CAreaOctTree::Node CAreaOctTree::Node::GetChild(int idx) const
|
||||
{
|
||||
u16 flags = *reinterpret_cast<const u16*>(m_ptr);
|
||||
const u32* offsets = reinterpret_cast<const u32*>(m_ptr + 4);
|
||||
u16 flags = *reinterpret_cast<const u16*>(x18_ptr);
|
||||
const u32* offsets = reinterpret_cast<const u32*>(x18_ptr + 4);
|
||||
ETreeType type = ETreeType((flags >> (2 * idx)) & 0x3);
|
||||
|
||||
if (type == ETreeType::Branch)
|
||||
{
|
||||
zeus::CAABox pos, neg, res;
|
||||
m_aabb.splitZ(pos, neg);
|
||||
x0_aabb.splitZ(pos, neg);
|
||||
if (idx & 4)
|
||||
{
|
||||
pos.splitY(pos, neg);
|
||||
|
@ -76,17 +520,17 @@ CAreaOctTree::Node CAreaOctTree::Node::GetChild(int idx) const
|
|||
}
|
||||
}
|
||||
|
||||
return Node(m_ptr + offsets[idx] + 36, res, m_owner, ETreeType::Branch);
|
||||
return Node(x18_ptr + offsets[idx] + 36, res, x1c_owner, ETreeType::Branch);
|
||||
}
|
||||
else if (type == ETreeType::Leaf)
|
||||
{
|
||||
const float* aabb = reinterpret_cast<const float*>(m_ptr + offsets[idx] + 36);
|
||||
const float* aabb = reinterpret_cast<const float*>(x18_ptr + offsets[idx] + 36);
|
||||
zeus::CAABox aabbObj(aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]);
|
||||
return Node(aabb, aabbObj, m_owner, ETreeType::Leaf);
|
||||
return Node(aabb, aabbObj, x1c_owner, ETreeType::Leaf);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Node(nullptr, zeus::CAABox::skNullBox, m_owner, ETreeType::Invalid);
|
||||
return Node(nullptr, zeus::CAABox::skNullBox, x1c_owner, ETreeType::Invalid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,4 +644,22 @@ std::unique_ptr<CAreaOctTree> CAreaOctTree::MakeFromMemory(const u8* buf, unsign
|
|||
edgeCount, edgeBuf, polyCount, polyBuf, vertCount, vertBuf);
|
||||
}
|
||||
|
||||
CCollisionSurface CAreaOctTree::GetMasterListTriangle(u16 idx) const
|
||||
{
|
||||
const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx*3]];
|
||||
const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx*3+1]];
|
||||
u16 vert2 = e1.GetVertIndex2();
|
||||
if (e1.GetVertIndex1() != e0.GetVertIndex1())
|
||||
if (e1.GetVertIndex1() != e0.GetVertIndex2())
|
||||
vert2 = e1.GetVertIndex1();
|
||||
|
||||
u32 material = x28_materials[x34_polyMats[idx]];
|
||||
if (material & 0x2000000)
|
||||
return CCollisionSurface(GetVert(e0.GetVertIndex2()), GetVert(e0.GetVertIndex1()),
|
||||
GetVert(vert2), material);
|
||||
else
|
||||
return CCollisionSurface(GetVert(e0.GetVertIndex1()), GetVert(e0.GetVertIndex2()),
|
||||
GetVert(vert2), material);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "zeus/CAABox.hpp"
|
||||
#include "Collision/CCollisionEdge.hpp"
|
||||
#include "Collision/CCollisionSurface.hpp"
|
||||
#include "zeus/CLine.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ public:
|
|||
{
|
||||
zeus::CPlane x0_plane;
|
||||
rstl::optional_object<CCollisionSurface> x10_surface;
|
||||
float x3c_;
|
||||
float x3c_t;
|
||||
};
|
||||
|
||||
class TriListReference
|
||||
|
@ -47,55 +48,55 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
const u8* m_ptr;
|
||||
zeus::CAABox m_aabb;
|
||||
const CAreaOctTree& m_owner;
|
||||
ETreeType m_nodeType;
|
||||
zeus::CAABox x0_aabb;
|
||||
const u8* x18_ptr;
|
||||
const CAreaOctTree& x1c_owner;
|
||||
ETreeType x20_nodeType;
|
||||
|
||||
bool LineTestInternal(const zeus::CLineSeg&, const CMaterialFilter&, float, float, float,
|
||||
bool LineTestInternal(const zeus::CLine&, const CMaterialFilter&, float, float, float,
|
||||
const zeus::CVector3f&) const;
|
||||
bool LineTestExInternal(const zeus::CLineSeg&, const CMaterialFilter&, SRayResult&, float, float, float,
|
||||
void LineTestExInternal(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float, float, float,
|
||||
const zeus::CVector3f&) const;
|
||||
|
||||
public:
|
||||
Node(const void* ptr, const zeus::CAABox& aabb,
|
||||
const CAreaOctTree& owner, ETreeType type)
|
||||
: m_ptr(reinterpret_cast<const u8*>(ptr)), m_aabb(aabb), m_owner(owner), m_nodeType(type)
|
||||
: x0_aabb(aabb), x18_ptr(reinterpret_cast<const u8*>(ptr)), x1c_owner(owner), x20_nodeType(type)
|
||||
{
|
||||
}
|
||||
|
||||
bool LineTest(const zeus::CLineSeg&, const CMaterialFilter&, float) const;
|
||||
bool LineTestEx(const zeus::CLineSeg&, const CMaterialFilter&, SRayResult&, float) const;
|
||||
bool LineTest(const zeus::CLine&, const CMaterialFilter&, float) const;
|
||||
void LineTestEx(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float) const;
|
||||
|
||||
const CAreaOctTree& GetOwner() const
|
||||
{
|
||||
return m_owner;
|
||||
return x1c_owner;
|
||||
}
|
||||
|
||||
const zeus::CAABox& GetBoundingBox() const
|
||||
{
|
||||
return m_aabb;
|
||||
return x0_aabb;
|
||||
}
|
||||
|
||||
u16 GetChildFlags() const
|
||||
{
|
||||
return *reinterpret_cast<const u16*>(m_ptr);
|
||||
return *reinterpret_cast<const u16*>(x18_ptr);
|
||||
}
|
||||
|
||||
Node GetChild(int idx) const;
|
||||
|
||||
TriListReference GetTriangleArray() const
|
||||
{
|
||||
return TriListReference(reinterpret_cast<const u16*>(m_ptr + 24));
|
||||
return TriListReference(reinterpret_cast<const u16*>(x18_ptr + 24));
|
||||
}
|
||||
|
||||
ETreeType GetChildType(int idx) const
|
||||
{
|
||||
u16 flags = *reinterpret_cast<const u16*>(m_ptr);
|
||||
u16 flags = *reinterpret_cast<const u16*>(x18_ptr);
|
||||
return ETreeType((flags << (2 * idx)) & 0x3);
|
||||
}
|
||||
|
||||
ETreeType GetTreeType() const { return m_nodeType; }
|
||||
ETreeType GetTreeType() const { return x20_nodeType; }
|
||||
};
|
||||
|
||||
zeus::CAABox x0_aabb;
|
||||
|
@ -135,7 +136,7 @@ public:
|
|||
u32 GetNumEdges() const { return x38_edgeCount; }
|
||||
u32 GetNumVerts() const { return x48_vertCount; }
|
||||
u32 GetNumTriangles() const { return x40_polyCount; }
|
||||
const u16* GetMasterListTriangle(u16 idx) const;
|
||||
CCollisionSurface GetMasterListTriangle(u16 idx) const;
|
||||
const u16* GetTriangleVertexIndices(u16 idx) const;
|
||||
const u16* GetTriangleEdgeIndices(u16 idx) const;
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ void CCollisionPrimitive::SetMaterial(const CMaterialList& material) { x8_materi
|
|||
|
||||
const CMaterialList& CCollisionPrimitive::GetMaterial() const { return x8_material; }
|
||||
|
||||
CRayCastResult CCollisionPrimitive::CastRay(const zeus::CVector3f& start, const zeus::CVector3f& end, float d,
|
||||
CRayCastResult CCollisionPrimitive::CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter, const zeus::CTransform& xf) const
|
||||
{
|
||||
return CastRayInternal(CInternalRayCastStructure(start, end, d, xf, filter));
|
||||
return CastRayInternal(CInternalRayCastStructure(start, dir, length, xf, filter));
|
||||
}
|
||||
|
||||
void CCollisionPrimitive::InitBeginTypes()
|
||||
|
|
|
@ -111,8 +111,8 @@ public:
|
|||
virtual FourCC GetPrimType() const = 0;
|
||||
virtual ~CCollisionPrimitive() {}
|
||||
virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const = 0;
|
||||
CRayCastResult CastRay(const zeus::CVector3f&, const zeus::CVector3f&, float, const CMaterialFilter&,
|
||||
const zeus::CTransform&) const;
|
||||
CRayCastResult CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
||||
const CMaterialFilter& filter, const zeus::CTransform& xf) const;
|
||||
|
||||
static void InitBeginTypes();
|
||||
static void InitAddType(const Type& tp);
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
zeus::CVector3f GetVert(s32) const;
|
||||
zeus::CVector3f GetPoint(s32) const;
|
||||
zeus::CPlane GetPlane() const;
|
||||
u32 GetSurfaceFlags() const;
|
||||
u32 GetSurfaceFlags() const { return x24_flags; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "CMaterialList.hpp"
|
||||
#include "World/CActor.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
#include "World/CWorld.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -81,4 +83,79 @@ void CGameCollision::SendMaterialMessage(CStateManager& mgr, const CMaterialList
|
|||
|
||||
mgr.SendScriptMsg(&act, kInvalidUniqueId, msg);
|
||||
}
|
||||
|
||||
CRayCastResult
|
||||
CGameCollision::RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float length, const CMaterialFilter& filter)
|
||||
{
|
||||
CRayCastResult ret;
|
||||
float bestT = length;
|
||||
if (bestT <= 0.f)
|
||||
bestT = 100000.f;
|
||||
|
||||
zeus::CLine line(pos, dir);
|
||||
for (const CGameArea& area : *mgr.GetWorld())
|
||||
{
|
||||
CAreaOctTree::SRayResult rayRes;
|
||||
CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision;
|
||||
collision.GetRootNode().LineTestEx(line, filter, rayRes, length);
|
||||
if (!rayRes.x10_surface || (length != 0.f && length < rayRes.x3c_t))
|
||||
continue;
|
||||
|
||||
if (rayRes.x3c_t < bestT)
|
||||
{
|
||||
ret = CRayCastResult(rayRes.x3c_t, dir * rayRes.x3c_t + pos,
|
||||
rayRes.x0_plane, rayRes.x10_surface->GetSurfaceFlags());
|
||||
bestT = rayRes.x3c_t;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CRayCastResult
|
||||
CGameCollision::RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float length, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList)
|
||||
{
|
||||
CRayCastResult ret;
|
||||
float bestT = length;
|
||||
if (bestT <= 0.f)
|
||||
bestT = 100000.f;
|
||||
|
||||
for (TUniqueId id : nearList)
|
||||
{
|
||||
CEntity* ent = const_cast<CEntity*>(mgr.GetObjectById(id));
|
||||
if (TCastToPtr<CPhysicsActor> physActor = ent)
|
||||
{
|
||||
zeus::CTransform xf = physActor->GetPrimitiveTransform();
|
||||
const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive();
|
||||
CRayCastResult res = prim->CastRay(pos, dir, bestT, filter, xf);
|
||||
if (!res.IsInvalid() && res.GetT() < bestT)
|
||||
{
|
||||
bestT = res.GetT();
|
||||
ret = res;
|
||||
idOut = physActor->GetUniqueId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CRayCastResult
|
||||
CGameCollision::RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList)
|
||||
{
|
||||
CRayCastResult staticRes = RayStaticIntersection(mgr, pos, dir, mag, filter);
|
||||
CRayCastResult dynamicRes = RayDynamicIntersection(mgr, idOut, pos, dir, mag, filter, nearList);
|
||||
|
||||
if (!dynamicRes.IsInvalid() && staticRes.IsInvalid())
|
||||
return dynamicRes;
|
||||
else if (staticRes.GetT() >= dynamicRes.GetT())
|
||||
return dynamicRes;
|
||||
else
|
||||
return staticRes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#ifndef __URDE_CGAMECOLLISION_HPP__
|
||||
#define __URDE_CGAMECOLLISION_HPP__
|
||||
#include "zeus/CVector3f.hpp"
|
||||
#include "zeus/CPlane.hpp"
|
||||
#include "rstl.hpp"
|
||||
#include "RetroTypes.hpp"
|
||||
#include "CRayCastResult.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CInternalCollisionStructure
|
||||
{
|
||||
zeus::CVector3f x0_pos;
|
||||
float xc_radius;
|
||||
};
|
||||
|
||||
class CActor;
|
||||
|
@ -19,6 +19,7 @@ class CCollisionInfoList;
|
|||
class CMaterialList;
|
||||
class CStateManager;
|
||||
class CPhysicsActor;
|
||||
class CMaterialFilter;
|
||||
|
||||
class CGameCollision
|
||||
{
|
||||
|
@ -35,6 +36,14 @@ public:
|
|||
static bool CanBlock(const CMaterialList&, const zeus::CVector3f&);
|
||||
static bool IsFloor(const CMaterialList&, const zeus::CVector3f&);
|
||||
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 CRayCastResult RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
static CRayCastResult RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ class CInternalRayCastStructure
|
|||
zeus::CTransform x3c_xf;
|
||||
CMaterialFilter x6c_filter;
|
||||
public:
|
||||
CInternalRayCastStructure(const zeus::CVector3f& start, const zeus::CVector3f& end, float d, const zeus::CTransform& xf,
|
||||
const CMaterialFilter& filter)
|
||||
: x0_ray(start, end, d),
|
||||
CInternalRayCastStructure(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length,
|
||||
const zeus::CTransform& xf, const CMaterialFilter& filter)
|
||||
: x0_ray(start, dir, length),
|
||||
x3c_xf(xf),
|
||||
x6c_filter(filter)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ public:
|
|||
|
||||
const zeus::CMRay& GetRay() const { return x0_ray; }
|
||||
const zeus::CVector3f& GetStart() const { return x0_ray.start; }
|
||||
const zeus::CVector3f& GetNormal() const { return x0_ray.normal; }
|
||||
const zeus::CVector3f& GetNormal() const { return x0_ray.end; }
|
||||
float GetMaxTime() const { return x38_maxTime; }
|
||||
const zeus::CTransform& GetTransform() const { return x3c_xf; }
|
||||
const CMaterialFilter& GetFilter() const { return x6c_filter; }
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
|
||||
const CMaterialList& GetIncludeList() const { return x0_include; }
|
||||
const CMaterialList& GetExcludeList() const { return x8_exclude; }
|
||||
bool Passes(const CMaterialList&) const { return false;}
|
||||
bool Passes(const CMaterialList&) const { return false; }
|
||||
};
|
||||
}
|
||||
#endif // __CMATERIALFILTER_HPP__
|
||||
|
|
|
@ -17,31 +17,6 @@ void CRayCastResult::MakeInvalid()
|
|||
x20_invalid = EInvalid::Invalid;
|
||||
}
|
||||
|
||||
bool CRayCastResult::IsInvalid() const
|
||||
{
|
||||
return x20_invalid == EInvalid::Invalid;
|
||||
}
|
||||
|
||||
float CRayCastResult::GetTime() const
|
||||
{
|
||||
return x0_time;
|
||||
}
|
||||
|
||||
const zeus::CVector3f&CRayCastResult::GetPoint() const
|
||||
{
|
||||
return x4_point;
|
||||
}
|
||||
|
||||
const zeus::CPlane&CRayCastResult::GetPlane() const
|
||||
{
|
||||
return x10_plane;
|
||||
}
|
||||
|
||||
const CMaterialList&CRayCastResult::GetMaterial() const
|
||||
{
|
||||
return x28_material;
|
||||
}
|
||||
|
||||
void CRayCastResult::Transform(const zeus::CTransform& xf)
|
||||
{
|
||||
x4_point = xf * x4_point;
|
||||
|
|
|
@ -15,35 +15,36 @@ public:
|
|||
Valid
|
||||
};
|
||||
private:
|
||||
float x0_time;
|
||||
float x0_t = 0.f;
|
||||
zeus::CVector3f x4_point;
|
||||
zeus::CPlane x10_plane;
|
||||
EInvalid x20_invalid = EInvalid::Invalid;
|
||||
/*u32 x24_; */
|
||||
CMaterialList x28_material;
|
||||
CMaterialList x24_material;
|
||||
public:
|
||||
CRayCastResult() = default;
|
||||
CRayCastResult(const CRayCastResult& other, EInvalid invalid)
|
||||
: x0_time(other.x0_time),
|
||||
: x0_t(other.x0_t),
|
||||
x4_point(other.x4_point),
|
||||
x10_plane(other.x10_plane),
|
||||
x20_invalid(invalid),
|
||||
x28_material(other.x28_material)
|
||||
x24_material(other.x24_material)
|
||||
{
|
||||
}
|
||||
|
||||
CRayCastResult(float, const zeus::CVector3f&, const zeus::CPlane& plane, const CMaterialList& matList)
|
||||
: x28_material(matList)
|
||||
CRayCastResult(float t, const zeus::CVector3f& point,
|
||||
const zeus::CPlane& plane, const CMaterialList& matList)
|
||||
: x0_t(t), x4_point(point), x10_plane(plane),
|
||||
x20_invalid(EInvalid::Valid), x24_material(matList)
|
||||
{}
|
||||
|
||||
void MakeInvalid();
|
||||
|
||||
bool IsInvalid() const;
|
||||
bool IsInvalid() const { return x20_invalid == EInvalid::Invalid; }
|
||||
float GetT() const { return x0_t; }
|
||||
const zeus::CVector3f& GetPoint() const { return x4_point; }
|
||||
const zeus::CPlane& GetPlane() const { return x10_plane; }
|
||||
const CMaterialList& GetMaterial() const { return x24_material; }
|
||||
|
||||
float GetTime() const;
|
||||
const zeus::CVector3f& GetPoint() const;
|
||||
const zeus::CPlane& GetPlane() const;
|
||||
const CMaterialList& GetMaterial() const;
|
||||
void Transform(const zeus::CTransform&);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ enum class EGameplayResult
|
|||
|
||||
enum class EFlowState
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
None,
|
||||
WinBad,
|
||||
WinGood,
|
||||
WinBest,
|
||||
LoseGame,
|
||||
Default,
|
||||
StateSetter,
|
||||
};
|
||||
|
||||
class IMain
|
||||
|
|
|
@ -24,7 +24,7 @@ CIOWin::EMessageReturn CAudioStateWin::OnMessage(const CArchitectureMessage& msg
|
|||
else if (msgType == EArchMsgType::QuitGameplay)
|
||||
{
|
||||
if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled ||
|
||||
m->GetFlowState() != EFlowState::Zero)
|
||||
m->GetFlowState() != EFlowState::None)
|
||||
{
|
||||
CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default);
|
||||
CSfxManager::KillAll(CSfxManager::ESfxChannels::Game);
|
||||
|
|
|
@ -105,7 +105,7 @@ CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArch
|
|||
{
|
||||
if (x14_stateManager->GetPlayer().IsPlayerDeadEnough())
|
||||
{
|
||||
static_cast<CMain&>(*g_Main).SetFlowState(EFlowState::Four);
|
||||
static_cast<CMain&>(*g_Main).SetFlowState(EFlowState::LoseGame);
|
||||
queue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game));
|
||||
}
|
||||
else
|
||||
|
@ -285,8 +285,8 @@ CMFGameLoader::CMFGameLoader() : CMFGameLoaderBase("CMFGameLoader")
|
|||
CMain* m = static_cast<CMain*>(g_Main);
|
||||
switch (m->GetFlowState())
|
||||
{
|
||||
case EFlowState::Five:
|
||||
case EFlowState::Six:
|
||||
case EFlowState::Default:
|
||||
case EFlowState::StateSetter:
|
||||
{
|
||||
ResId mlvlId = g_GameState->CurrentWorldAssetId();
|
||||
if (g_MemoryCardSys->HasSaveWorldMemory(mlvlId))
|
||||
|
|
|
@ -35,8 +35,8 @@ void CMainFlow::AdvanceGameState(CArchitectureQueue& queue)
|
|||
case EClientFlowStates::GameExit:
|
||||
{
|
||||
MP1::CMain* main = static_cast<MP1::CMain*>(g_Main);
|
||||
if (main->GetFlowState() != EFlowState::Zero &&
|
||||
main->GetFlowState() != EFlowState::Six)
|
||||
if (main->GetFlowState() != EFlowState::None &&
|
||||
main->GetFlowState() != EFlowState::StateSetter)
|
||||
main->SetX30(true);
|
||||
}
|
||||
case EClientFlowStates::Unspecified:
|
||||
|
@ -56,15 +56,15 @@ void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue)
|
|||
{
|
||||
switch (main->GetFlowState())
|
||||
{
|
||||
case EFlowState::One:
|
||||
case EFlowState::Two:
|
||||
case EFlowState::Three:
|
||||
case EFlowState::WinBad:
|
||||
case EFlowState::WinGood:
|
||||
case EFlowState::WinBest:
|
||||
queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11,
|
||||
std::make_shared<CCredits>()));
|
||||
break;
|
||||
case EFlowState::Four:
|
||||
case EFlowState::LoseGame:
|
||||
queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11,
|
||||
std::make_shared<CPlayMovie>(CPlayMovie::EWhichMovie::AfterCredits)));
|
||||
std::make_shared<CPlayMovie>(CPlayMovie::EWhichMovie::LoseGame)));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue)
|
|||
}
|
||||
case EClientFlowStates::PreFrontEnd:
|
||||
{
|
||||
if (main->GetFlowState() == EFlowState::Zero)
|
||||
if (main->GetFlowState() == EFlowState::None)
|
||||
return;
|
||||
queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11,
|
||||
std::make_shared<CPreFrontEnd>()));
|
||||
|
@ -83,14 +83,14 @@ void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue)
|
|||
std::shared_ptr<CIOWin> nextIOWin;
|
||||
switch (main->GetFlowState())
|
||||
{
|
||||
case EFlowState::Six:
|
||||
case EFlowState::StateSetter:
|
||||
nextIOWin = std::make_shared<CStateSetterFlow>();
|
||||
break;
|
||||
case EFlowState::One:
|
||||
case EFlowState::Two:
|
||||
case EFlowState::Three:
|
||||
case EFlowState::Four:
|
||||
case EFlowState::Five:
|
||||
case EFlowState::WinBad:
|
||||
case EFlowState::WinGood:
|
||||
case EFlowState::WinBest:
|
||||
case EFlowState::LoseGame:
|
||||
case EFlowState::Default:
|
||||
nextIOWin = std::make_shared<CFrontEndUI>();
|
||||
break;
|
||||
default: return;
|
||||
|
@ -102,7 +102,7 @@ void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue)
|
|||
case EClientFlowStates::Game:
|
||||
{
|
||||
g_GameState->GameOptions().EnsureSettings();
|
||||
main->SetFlowState(EFlowState::Five);
|
||||
main->SetFlowState(EFlowState::Default);
|
||||
queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 10, 1000,
|
||||
std::make_shared<CMFGameLoader>()));
|
||||
break;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "CPlayMovie.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
namespace MP1
|
||||
|
@ -6,8 +8,26 @@ namespace MP1
|
|||
const char* kMovies[] =
|
||||
{
|
||||
"Video/wingame.thp",
|
||||
"Video/losegame.thp"
|
||||
"Video/wingame_best.thp",
|
||||
"Video/wingame_best.thp",
|
||||
"Video/losegame.thp",
|
||||
"Video/05_tallonText.thp",
|
||||
"Video/AfterCredits.thp",
|
||||
"Video/SpecialEnding.thp",
|
||||
"Video/creditBG.thp"
|
||||
};
|
||||
|
||||
bool CPlayMovie::IsResultsScreen(EWhichMovie which)
|
||||
{
|
||||
return int(which) <= 2;
|
||||
}
|
||||
|
||||
CPlayMovie::CPlayMovie(EWhichMovie which)
|
||||
: CPlayMovieBase("CPlayMovie", kMovies[int(which)]), x18_which(which)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,28 +2,43 @@
|
|||
#define __URDE_CPLAYMOVIE_HPP__
|
||||
|
||||
#include "CPlayMovieBase.hpp"
|
||||
#include "RetroTypes.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
namespace MP1
|
||||
{
|
||||
|
||||
extern const char* kMovies[];
|
||||
|
||||
class CPlayMovie : public CPlayMovieBase
|
||||
{
|
||||
public:
|
||||
enum class EWhichMovie
|
||||
{
|
||||
WinGame,
|
||||
WinGameBad,
|
||||
WinGameGood,
|
||||
WinGameBest,
|
||||
LoseGame,
|
||||
Two,
|
||||
AfterCredits
|
||||
TalonTest,
|
||||
AfterCredits,
|
||||
SpecialEnding,
|
||||
CreditBG
|
||||
};
|
||||
private:
|
||||
EWhichMovie x14_which;
|
||||
EWhichMovie x18_which;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x78_24_ : 1;
|
||||
bool x78_25_ : 1;
|
||||
bool x78_26_resultsScreen : 1;
|
||||
bool x78_27_ : 1;
|
||||
};
|
||||
u16 _dummy = 0;
|
||||
};
|
||||
static bool IsResultsScreen(EWhichMovie which);
|
||||
public:
|
||||
CPlayMovie(EWhichMovie which) : CPlayMovieBase("CPlayMovie", kMovies[int(which)]), x14_which(which) {}
|
||||
CPlayMovie(EWhichMovie which);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
EQuitAction Update(float dt);
|
||||
void Draw();
|
||||
void ProcessUserInput(const CFinalInput& input);
|
||||
CQuitGameScreen(EQuitType pos);
|
||||
CQuitGameScreen(EQuitType type);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ private:
|
|||
/* urde addition: these are simply initialized along with everything else */
|
||||
CGameGlobalObjects x128_globalObjects;
|
||||
|
||||
EFlowState x12c_flowState = EFlowState::Five;
|
||||
EFlowState x12c_flowState = EFlowState::Default;
|
||||
|
||||
u32 x130_[10] = { 1000000 };
|
||||
|
||||
|
|
|
@ -6,6 +6,12 @@ CFluidPlane::CFluidPlane(u32, u32, u32, EFluidType, float, const urde::CFluidUVM
|
|||
{
|
||||
}
|
||||
|
||||
void CFluidPlane::Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||
CScriptWater& water, CStateManager& mgr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFluidPlane::Update()
|
||||
{
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ namespace urde
|
|||
{
|
||||
class CFluidUVMotion;
|
||||
class CRippleManager;
|
||||
class CScriptWater;
|
||||
class CStateManager;
|
||||
class CFluidPlane
|
||||
{
|
||||
public:
|
||||
|
@ -29,6 +31,8 @@ private:
|
|||
public:
|
||||
CFluidPlane(u32, u32, u32, EFluidType, float, const CFluidUVMotion&, float);
|
||||
|
||||
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||
CScriptWater& water, CStateManager& mgr);
|
||||
virtual void Update();
|
||||
float GetAlpha() const;
|
||||
EFluidType GetFluidType() const;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#include "CFluidPlaneManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CFluidPlaneManager::CFluidProfile CFluidPlaneManager::sProfile = {};
|
||||
|
||||
CFluidPlaneManager::CFluidPlaneManager()
|
||||
: x0_rippleManager(20, 0.5f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::CFluidProfile::Clear()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::StartFrame(bool b)
|
||||
{
|
||||
x121_ = b;
|
||||
sProfile.Clear();
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::Update(float dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float CFluidPlaneManager::GetLastRippleDeltaTime(TUniqueId rippler) const
|
||||
{
|
||||
return x0_rippleManager.GetLastRippleDeltaTime(rippler);
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
|
||||
const zeus::CVector3f& pos, float factor, bool)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,17 @@
|
|||
#ifndef __URDE_CFLUIDPLANEMANAGER_HPP__
|
||||
#define __URDE_CFLUIDPLANEMANAGER_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "CRippleManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class CStateManager;
|
||||
class CScriptWater;
|
||||
|
||||
class CFluidPlaneManager
|
||||
{
|
||||
CRippleManager x0_rippleManager;
|
||||
bool x121_;
|
||||
class CFluidProfile
|
||||
{
|
||||
|
@ -14,9 +20,13 @@ class CFluidPlaneManager
|
|||
};
|
||||
static CFluidProfile sProfile;
|
||||
public:
|
||||
CFluidPlaneManager();
|
||||
void StartFrame(bool);
|
||||
void EndFrame() { x121_ = false; }
|
||||
void Update(float dt);
|
||||
float GetLastRippleDeltaTime(TUniqueId rippler) const;
|
||||
void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
|
||||
const zeus::CVector3f& pos, float factor, bool);
|
||||
};
|
||||
|
||||
}
|
|
@ -125,6 +125,30 @@ class CGameArea : public IGameArea
|
|||
|
||||
public:
|
||||
|
||||
class CChainIterator
|
||||
{
|
||||
CGameArea* m_area;
|
||||
public:
|
||||
CChainIterator(CGameArea* area) : m_area(area) {}
|
||||
CGameArea& operator*() const { return *m_area; }
|
||||
CGameArea* operator->() const { return m_area; }
|
||||
CChainIterator& operator++() { m_area = m_area->GetNext(); return *this; }
|
||||
bool operator!=(const CChainIterator& other) const { return m_area != other.m_area; }
|
||||
bool operator==(const CChainIterator& other) const { return m_area == other.m_area; }
|
||||
};
|
||||
|
||||
class CConstChainIterator
|
||||
{
|
||||
const CGameArea* m_area;
|
||||
public:
|
||||
CConstChainIterator(const CGameArea* area) : m_area(area) {}
|
||||
const CGameArea& operator*() const { return *m_area; }
|
||||
const CGameArea* operator->() const { return m_area; }
|
||||
CConstChainIterator& operator++() { m_area = m_area->GetNext(); return *this; }
|
||||
bool operator!=(const CConstChainIterator& other) const { return m_area != other.m_area; }
|
||||
bool operator==(const CConstChainIterator& other) const { return m_area == other.m_area; }
|
||||
};
|
||||
|
||||
class CAreaObjectList : public CObjectList
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -100,6 +100,7 @@ set(WORLD_SOURCES
|
|||
CAnimationParameters.hpp
|
||||
CDamageInfo.hpp CDamageInfo.cpp
|
||||
CDamageVulnerability.hpp CDamageVulnerability.cpp
|
||||
CFluidPlaneManager.hpp CFluidPlaneManager.cpp
|
||||
CFluidUVMotion.hpp CFluidUVMotion.cpp
|
||||
CPatternedInfo.hpp CPatternedInfo.cpp
|
||||
CHealthInfo.hpp CHealthInfo.cpp
|
||||
|
|
|
@ -12,15 +12,13 @@ namespace urde
|
|||
void CMorphBallShadow::GatherAreas(const CStateManager& mgr)
|
||||
{
|
||||
x18_areas.clear();
|
||||
for (const CGameArea* area = mgr.GetWorld()->GetChainHead(EChain::Alive);
|
||||
area != CWorld::GetAliveAreasEnd();
|
||||
area = area->GetNext())
|
||||
for (const CGameArea& area : *mgr.GetWorld())
|
||||
{
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
|
||||
if (area->IsPostConstructed())
|
||||
occState = area->GetPostConstructed()->x10dc_occlusionState;
|
||||
if (area.IsPostConstructed())
|
||||
occState = area.GetPostConstructed()->x10dc_occlusionState;
|
||||
if (occState == CGameArea::EOcclusionState::Occluded)
|
||||
x18_areas.push_back(area->GetAreaId());
|
||||
x18_areas.push_back(area.GetAreaId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,18 +102,16 @@ void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, const CStateMana
|
|||
bool CMorphBallShadow::AreasValid(const CStateManager& mgr) const
|
||||
{
|
||||
auto it = x18_areas.begin();
|
||||
for (const CGameArea* area = mgr.GetWorld()->GetChainHead(EChain::Alive);
|
||||
area != CWorld::GetAliveAreasEnd();
|
||||
area = area->GetNext())
|
||||
for (const CGameArea& area : *mgr.GetWorld())
|
||||
{
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
|
||||
if (area->IsPostConstructed())
|
||||
occState = area->GetPostConstructed()->x10dc_occlusionState;
|
||||
if (area.IsPostConstructed())
|
||||
occState = area.GetPostConstructed()->x10dc_occlusionState;
|
||||
if (occState != CGameArea::EOcclusionState::Occluded)
|
||||
continue;
|
||||
if (it == x18_areas.end())
|
||||
return false;
|
||||
if (*it != area->GetAreaId())
|
||||
if (*it != area.GetAreaId())
|
||||
return false;
|
||||
++it;
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ void CPlayer::Update(float, CStateManager& mgr) {}
|
|||
bool CPlayer::IsPlayerDeadEnough() const
|
||||
{
|
||||
if (x2f8_morphTransState == CPlayer::EPlayerMorphBallState::Unmorphed)
|
||||
return x9f4_deathTime < 2.5f;
|
||||
return x9f4_deathTime > 2.5f;
|
||||
else if (x2f8_morphTransState == CPlayer::EPlayerMorphBallState::Morphed)
|
||||
return x9f4_deathTime < 6.f;
|
||||
return x9f4_deathTime > 6.f;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace urde
|
|||
class CRipple
|
||||
{
|
||||
private:
|
||||
TUniqueId x0_;
|
||||
float x4_ = 0.f;
|
||||
TUniqueId x0_id;
|
||||
float x4_time = 0.f;
|
||||
zeus::CVector3f x8_;
|
||||
float x14_ = 2.f;
|
||||
float x18_ = 12.f;
|
||||
|
@ -21,10 +21,10 @@ private:
|
|||
public:
|
||||
CRipple(TUniqueId, const zeus::CVector3f&, float);
|
||||
|
||||
void SetTime(float);
|
||||
float GetTime() const;
|
||||
void SetTime(float t) { x4_time = t; }
|
||||
float GetTime() const { return x4_time; }
|
||||
float GetTimeFalloff() const;
|
||||
TUniqueId GetUniqueId() const;
|
||||
TUniqueId GetUniqueId() const { return x0_id; }
|
||||
float GetFequency() const;
|
||||
float GetAmplitude() const;
|
||||
float GetOODistanceFalloff() const;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
#include "CRippleManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CRippleManager::CRippleManager(int maxRipples, float f1)
|
||||
: x14_(f1)
|
||||
{
|
||||
Init(maxRipples);
|
||||
}
|
||||
|
||||
void CRippleManager::Init(int maxRipples)
|
||||
{
|
||||
x4_ripples.resize(maxRipples, CRipple(kInvalidUniqueId, zeus::CVector3f::skZero, 0.f));
|
||||
for (CRipple& r : x4_ripples)
|
||||
r.SetTime(9999.f);
|
||||
}
|
||||
|
||||
void CRippleManager::SetTime(float)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CRippleManager::Ripples()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CRippleManager::GetRipples() const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CRippleManager::Update(float dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float CRippleManager::GetLastRippleDeltaTime(TUniqueId rippler) const
|
||||
{
|
||||
float res = 9999.f;
|
||||
for (const CRipple& r : x4_ripples)
|
||||
if (r.GetUniqueId() == rippler)
|
||||
if (r.GetTime() < res)
|
||||
res = r.GetTime();
|
||||
return res;
|
||||
}
|
||||
|
||||
void CRippleManager::AddRipple(const CRipple& ripple)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CRippleManager::SetMaxTimeFalloff(float time)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float CRippleManager::GetMaxTimeFalloff() const
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef __URDE_CRIPPLEMANAGER_HPP__
|
||||
#define __URDE_CRIPPLEMANAGER_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "CRipple.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CRippleManager
|
||||
{
|
||||
float x0_ = 0.f;
|
||||
std::vector<CRipple> x4_ripples;
|
||||
float x14_;
|
||||
public:
|
||||
CRippleManager(int maxRipples, float);
|
||||
void Init(int maxRipples);
|
||||
void SetTime(float);
|
||||
void Ripples();
|
||||
void GetRipples() const;
|
||||
void Update(float dt);
|
||||
float GetLastRippleDeltaTime(TUniqueId rippler) const;
|
||||
void AddRipple(const CRipple& ripple);
|
||||
void SetMaxTimeFalloff(float time);
|
||||
float GetMaxTimeFalloff() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __URDE_CRIPPLEMANAGER_HPP__
|
|
@ -14,7 +14,7 @@ class CScriptWater : public CScriptTrigger
|
|||
private:
|
||||
static const float kSplashScales[6];
|
||||
u32 x150_ = 0;
|
||||
std::unique_ptr<CFluidPlaneCPU> x1b4_;
|
||||
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
|
||||
zeus::CVector3f x1b8_;
|
||||
float x1f4_;
|
||||
float x1f8_ = 0.f;
|
||||
|
@ -73,6 +73,7 @@ public:
|
|||
zeus::CColor GetSplashColor() const;
|
||||
void SetFrustumPlanes(const zeus::CFrustum& frustum);
|
||||
const zeus::CFrustum& GetFrustumPlanes() const;
|
||||
CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -520,8 +520,8 @@ void CWorld::TravelToArea(TAreaId aid, CStateManager& mgr, bool skipLoadOther)
|
|||
|
||||
void CWorld::SetPauseState(bool paused)
|
||||
{
|
||||
for (CGameArea* headArea = x4c_chainHeads[2] ; headArea != skGlobalEnd ; headArea = headArea->x130_next)
|
||||
headArea->SetPauseState(paused);
|
||||
for (auto it = GetChainHead(EChain::Two) ; it != AliveAreasEnd() ; ++it)
|
||||
it->SetPauseState(paused);
|
||||
x70_25_paused = paused;
|
||||
}
|
||||
|
||||
|
@ -541,24 +541,20 @@ void CWorld::PropogateAreaChain(CGameArea::EOcclusionState occlusionState, CGame
|
|||
if (occlusionState == CGameArea::EOcclusionState::Occluded)
|
||||
area->SetOcclusionState(CGameArea::EOcclusionState::Occluded);
|
||||
|
||||
for (CGameArea* areaItr = world->GetChainHead(EChain::Alive);
|
||||
areaItr != skGlobalNonConstEnd;
|
||||
areaItr = areaItr->x130_next)
|
||||
for (CGameArea& areaItr : *world)
|
||||
{
|
||||
if (areaItr == area)
|
||||
if (&areaItr == area)
|
||||
continue;
|
||||
if (areaItr->IsPostConstructed() && areaItr->GetOcclusionState() == CGameArea::EOcclusionState::Occluded)
|
||||
areaItr->PrepTokens();
|
||||
if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::Occluded)
|
||||
areaItr.PrepTokens();
|
||||
}
|
||||
|
||||
for (CGameArea* areaItr = world->GetChainHead(EChain::Alive);
|
||||
areaItr != skGlobalNonConstEnd;
|
||||
areaItr = areaItr->x130_next)
|
||||
for (CGameArea& areaItr : *world)
|
||||
{
|
||||
if (areaItr == area)
|
||||
if (&areaItr == area)
|
||||
continue;
|
||||
if (area->IsPostConstructed() && areaItr->GetOcclusionState() == CGameArea::EOcclusionState::NotOccluded)
|
||||
areaItr->PrepTokens();
|
||||
if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::NotOccluded)
|
||||
areaItr.PrepTokens();
|
||||
}
|
||||
|
||||
if (occlusionState == CGameArea::EOcclusionState::NotOccluded)
|
||||
|
|
|
@ -155,8 +155,12 @@ public:
|
|||
void MoveToChain(CGameArea* area, EChain chain);
|
||||
void MoveAreaToChain3(TAreaId aid);
|
||||
bool CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId);
|
||||
CGameArea* GetChainHead(EChain chain) { return x4c_chainHeads[int(chain)]; }
|
||||
const CGameArea* GetChainHead(EChain chain) const { return x4c_chainHeads[int(chain)]; }
|
||||
CGameArea::CChainIterator GetChainHead(EChain chain) { return {x4c_chainHeads[int(chain)]}; }
|
||||
CGameArea::CConstChainIterator GetChainHead(EChain chain) const { return {x4c_chainHeads[int(chain)]}; }
|
||||
CGameArea::CChainIterator begin() { return GetChainHead(EChain::Alive); }
|
||||
CGameArea::CChainIterator end() { return AliveAreasEnd(); }
|
||||
CGameArea::CConstChainIterator begin() const { return GetChainHead(EChain::Alive); }
|
||||
CGameArea::CConstChainIterator end() const { return GetAliveAreasEnd(); }
|
||||
bool ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr);
|
||||
void TravelToArea(TAreaId aid, CStateManager& mgr, bool);
|
||||
void SetPauseState(bool paused);
|
||||
|
@ -185,8 +189,8 @@ public:
|
|||
int IGetAreaCount() const;
|
||||
|
||||
static void PropogateAreaChain(CGameArea::EOcclusionState, CGameArea*, CWorld*);
|
||||
static const CGameArea* GetAliveAreasEnd() { return skGlobalEnd; }
|
||||
static CGameArea* AliveAreasEnd() { return skGlobalNonConstEnd; }
|
||||
static CGameArea::CConstChainIterator GetAliveAreasEnd() { return {skGlobalEnd}; }
|
||||
static CGameArea::CChainIterator AliveAreasEnd() { return {skGlobalNonConstEnd}; }
|
||||
|
||||
void Update(float dt);
|
||||
void PreRender();
|
||||
|
|
2
specter
2
specter
|
@ -1 +1 @@
|
|||
Subproject commit 5c98a6ee00491839eb7357355614caecc6942f1f
|
||||
Subproject commit 7daecc680d57562a563b8d9120f4c64ade9b3cbf
|
Loading…
Reference in New Issue