1#include "ObjectObakeManager.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/RaceManager.hh"
11 : ObjectDrivable(params), m_blockCache({
nullptr}) {
12 static constexpr f32 BLOCK_WIDTH = 195.00002f;
13 static constexpr f32 BLOCK_HEIGHT = 130.0f;
14 static constexpr size_t MAX_FALLING_BLOCKS = 256;
16 m_colBox =
new ObjectCollisionBox(BLOCK_WIDTH, BLOCK_HEIGHT, BLOCK_WIDTH, EGG::Vector3f::zero);
17 m_colSphere =
new ObjectCollisionSphere(1.0f, EGG::Vector3f::zero);
22 m_calcBlocks.reserve(MAX_FALLING_BLOCKS);
26ObjectObakeManager::~ObjectObakeManager() {
30 for (
auto *&block : m_blocks) {
36void ObjectObakeManager::calc() {
37 u32 frame = System::RaceManager::Instance()->timer();
39 for (
auto *&block : m_blocks) {
40 u32 fallFrame = block->fallFrame();
43 if (fallFrame > 0 && fallFrame <= frame &&
44 block->fallState() == ObjectObakeBlock::FallState::Rest) {
45 block->setFallState(ObjectObakeBlock::FallState::Falling);
47 m_calcBlocks.push_back(block);
51 for (
auto *&block : m_calcBlocks) {
58 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
59 return checkSpherePartialImpl(0.0f, pos, prevPos, mask, info, maskOut);
63bool ObjectObakeManager::checkPointPartialPush(
const EGG::Vector3f &pos,
64 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
65 KCLTypeMask *maskOut) {
66 return checkSpherePartialPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
71 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
72 return checkSphereFullImpl(0.0f, pos, prevPos, mask, info, maskOut);
77 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
78 return checkSphereFullPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
82bool ObjectObakeManager::checkSpherePartial(f32 radius,
const EGG::Vector3f &pos,
83 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
84 KCLTypeMask *maskOut,
u32 ) {
85 return checkSpherePartialImpl(radius, pos, prevPos, mask, info, maskOut);
89bool ObjectObakeManager::checkSpherePartialPush(f32 radius,
const EGG::Vector3f &pos,
90 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
91 KCLTypeMask *maskOut,
u32 ) {
92 return checkSpherePartialPushImpl(radius, pos, prevPos, mask, info, maskOut);
96bool ObjectObakeManager::checkSphereFull(f32 radius,
const EGG::Vector3f &pos,
97 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
99 return checkSphereFullImpl(radius, pos, prevPos, mask, info, maskOut);
103bool ObjectObakeManager::checkSphereFullPush(f32 radius,
const EGG::Vector3f &pos,
104 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
106 return checkSphereFullPushImpl(radius, pos, prevPos, mask, info, maskOut);
110bool ObjectObakeManager::checkPointCachedPartial(
const EGG::Vector3f &pos,
111 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
112 KCLTypeMask *maskOut) {
113 return checkSpherePartialImpl(0.0f, pos, prevPos, mask, info, maskOut);
117bool ObjectObakeManager::checkPointCachedPartialPush(
const EGG::Vector3f &pos,
118 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
119 KCLTypeMask *maskOut) {
120 return checkSpherePartialPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
124bool ObjectObakeManager::checkPointCachedFull(
const EGG::Vector3f &pos,
125 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
126 return checkSphereFullImpl(0.0f, pos, prevPos, mask, info, maskOut);
130bool ObjectObakeManager::checkPointCachedFullPush(
const EGG::Vector3f &pos,
131 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
132 return checkSphereFullPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
136bool ObjectObakeManager::checkSphereCachedPartial(f32 radius,
const EGG::Vector3f &pos,
137 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
138 KCLTypeMask *maskOut,
u32 ) {
139 return checkSpherePartialImpl(radius, pos, prevPos, mask, info, maskOut);
143bool ObjectObakeManager::checkSphereCachedPartialPush(f32 radius,
const EGG::Vector3f &pos,
144 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
145 KCLTypeMask *maskOut,
u32 ) {
146 return checkSpherePartialPushImpl(radius, pos, prevPos, mask, info, maskOut);
150bool ObjectObakeManager::checkSphereCachedFull(f32 radius,
const EGG::Vector3f &pos,
151 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
153 return checkSphereFullImpl(radius, pos, prevPos, mask, info, maskOut);
157bool ObjectObakeManager::checkSphereCachedFullPush(f32 radius,
const EGG::Vector3f &pos,
158 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
160 return checkSphereFullPushImpl(radius, pos, prevPos, mask, info, maskOut);
165 auto *block =
new ObjectObakeBlock(params);
166 m_blocks.push_back(block);
167 auto [spatialX, spatialZ] = SpatialIndex(block->pos());
168 m_blockCache[spatialZ][spatialX] = block;
172bool ObjectObakeManager::checkSpherePartialImpl(f32 radius,
const EGG::Vector3f &pos,
173 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfoPartial *info,
174 KCLTypeMask *maskOut) {
175 bool collision =
false;
176 auto [spatialX, spatialZ] = SpatialIndex(pos);
180 m_colSphere->transform(t,
EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
182 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
183 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
185 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
186 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
190 auto *block = m_blockCache[i][j];
196 t.makeT(block->pos());
197 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
198 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
201 bool collided = m_colSphere->check(*m_colBox, dist);
207 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
220 collision |= collided;
224 t.makeT(block->pos());
225 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
228 bool collided = m_colSphere->check(*m_colBox, dist);
234 if (0.9f >= distNrm.y) {
247 collision |= collided;
256bool ObjectObakeManager::checkSpherePartialPushImpl(f32 radius,
const EGG::Vector3f &pos,
257 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfoPartial *info,
258 KCLTypeMask *maskOut) {
259 bool collision =
false;
260 auto [spatialX, spatialZ] = SpatialIndex(pos);
265 m_colSphere->transform(t,
EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
267 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
268 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
270 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
271 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
275 auto *block = m_blockCache[i][j];
281 t.makeT(block->pos());
282 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
283 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
286 bool collided = m_colSphere->check(*m_colBox, dist);
292 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
300 auto *colDir = CollisionDirector::Instance();
301 colDir->pushCollisionEntry(dist.
length(), maskOut,
303 colDir->setCurrentCollisionVariant(2);
308 collision |= collided;
312 t.makeT(block->pos());
313 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
316 bool collided = m_colSphere->check(*m_colBox, dist);
322 if (0.9f >= distNrm.y) {
330 auto *colDir = CollisionDirector::Instance();
331 colDir->pushCollisionEntry(dist.
length(), maskOut,
337 collision |= collided;
346bool ObjectObakeManager::checkSphereFullImpl(f32 radius,
const EGG::Vector3f &pos,
347 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfo *info,
348 KCLTypeMask *maskOut) {
349 bool collision =
false;
350 auto [spatialX, spatialZ] = SpatialIndex(pos);
354 m_colSphere->transform(t,
EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
356 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
357 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
359 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
360 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
364 auto *block = m_blockCache[i][j];
371 t.makeT(block->pos());
372 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
373 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
376 bool collided = m_colSphere->check(*m_colBox, dist);
382 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
395 collision |= collided;
399 t.makeT(block->pos());
400 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
403 bool collided = m_colSphere->check(*m_colBox, dist);
409 if (0.9f >= distNrm.y) {
422 collision |= collided;
431bool ObjectObakeManager::checkSphereFullPushImpl(f32 radius,
const EGG::Vector3f &pos,
432 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfo *info,
433 KCLTypeMask *maskOut) {
434 bool collision =
false;
435 auto [spatialX, spatialZ] = SpatialIndex(pos);
439 m_colSphere->transform(t,
EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
441 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
442 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
444 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
445 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
449 auto *block = m_blockCache[i][j];
456 t.makeT(block->pos());
457 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
458 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
461 bool collided = m_colSphere->check(*m_colBox, dist);
467 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
475 auto *colDir = CollisionDirector::Instance();
476 colDir->pushCollisionEntry(dist.
length(), maskOut,
478 colDir->setCurrentCollisionVariant(2);
483 collision |= collided;
487 t.makeT(block->pos());
488 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
491 bool collided = m_colSphere->check(*m_colBox, dist);
497 if (0.9f >= distNrm.y) {
505 auto *colDir = CollisionDirector::Instance();
506 colDir->pushCollisionEntry(dist.
length(), maskOut,
512 collision |= collided;
521std::pair<s32, s32> ObjectObakeManager::SpatialIndex(
const EGG::Vector3f &pos) {
522 constexpr f32 ORIGIN_OFFSET_X = -30647.498f;
523 constexpr f32 ORIGIN_OFFSET_Z = -21092.5f;
524 constexpr f32 GRID_WIDTH = 325.0f;
525 constexpr f32 GRID_HALF_WIDTH = 162.5f;
527 s32 x = (pos.x - ORIGIN_OFFSET_X + GRID_HALF_WIDTH) / GRID_WIDTH;
528 s32 z = (pos.z - ORIGIN_OFFSET_Z + GRID_HALF_WIDTH) / GRID_WIDTH;
530 return std::make_pair(x, z);
@ COL_TYPE_SPECIAL_WALL
Various other wall types, determined by variant.
@ COL_TYPE_ROAD
Default road.
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
#define KCL_TYPE_WALL
0xD010F000
f32 normalise()
Normalizes the vector and returns the original length.
f32 length() const
The square root of the vector's dot product.