1#include "ObjectObakeManager.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/RaceManager.hh"
10ObjectObakeManager::ObjectObakeManager(
const System::MapdataGeoObj ¶ms)
11 :
ObjectDrivable(params), m_blockCache({}), m_blocks(MAX_BLOCKS), m_calcBlocks(MAX_BLOCKS) {
12 static constexpr f32 BLOCK_WIDTH = 195.00002f;
13 static constexpr f32 BLOCK_HEIGHT = 130.0f;
15 m_colBox = EGG::egg_new<ObjectCollisionBox>(BLOCK_WIDTH, BLOCK_HEIGHT, BLOCK_WIDTH,
17 m_colSphere = EGG::egg_new<ObjectCollisionSphere>(1.0f, EGG::Vector3f::zero);
23ObjectObakeManager::~ObjectObakeManager() {
24 EGG::egg_delete(m_colBox);
25 EGG::egg_delete(m_colSphere);
27 for (
auto *&block : m_blocks) {
28 EGG::egg_delete(block);
33void ObjectObakeManager::calc() {
34 u32 frame = System::RaceManager::Instance()->timer();
36 for (
auto *&block : m_blocks) {
37 u32 fallFrame = block->fallFrame();
40 if (fallFrame > 0 && fallFrame <= frame &&
41 block->fallState() == ObjectObakeBlock::FallState::Rest) {
42 block->setFallState(ObjectObakeBlock::FallState::Falling);
44 m_calcBlocks.push_back(block);
48 for (
auto *&block : m_calcBlocks) {
54bool ObjectObakeManager::checkPointPartial(
const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos,
55 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
56 return checkSpherePartialImpl(0.0f, pos, prevPos, mask, info, maskOut);
60bool ObjectObakeManager::checkPointPartialPush(
const EGG::Vector3f &pos,
61 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
62 KCLTypeMask *maskOut) {
63 return checkSpherePartialPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
67bool ObjectObakeManager::checkPointFull(
const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos,
68 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
69 return checkSphereFullImpl(0.0f, pos, prevPos, mask, info, maskOut);
73bool ObjectObakeManager::checkPointFullPush(
const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos,
74 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
75 return checkSphereFullPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
79bool ObjectObakeManager::checkSpherePartial(f32 radius,
const EGG::Vector3f &pos,
80 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
81 KCLTypeMask *maskOut, u32 ) {
82 return checkSpherePartialImpl(radius, pos, prevPos, mask, info, maskOut);
86bool ObjectObakeManager::checkSpherePartialPush(f32 radius,
const EGG::Vector3f &pos,
87 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
88 KCLTypeMask *maskOut, u32 ) {
89 return checkSpherePartialPushImpl(radius, pos, prevPos, mask, info, maskOut);
93bool ObjectObakeManager::checkSphereFull(f32 radius,
const EGG::Vector3f &pos,
94 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
96 return checkSphereFullImpl(radius, pos, prevPos, mask, info, maskOut);
100bool ObjectObakeManager::checkSphereFullPush(f32 radius,
const EGG::Vector3f &pos,
101 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
103 return checkSphereFullPushImpl(radius, pos, prevPos, mask, info, maskOut);
107bool ObjectObakeManager::checkPointCachedPartial(
const EGG::Vector3f &pos,
108 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
109 KCLTypeMask *maskOut) {
110 return checkSpherePartialImpl(0.0f, pos, prevPos, mask, info, maskOut);
114bool ObjectObakeManager::checkPointCachedPartialPush(
const EGG::Vector3f &pos,
115 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
116 KCLTypeMask *maskOut) {
117 return checkSpherePartialPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
121bool ObjectObakeManager::checkPointCachedFull(
const EGG::Vector3f &pos,
122 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
123 return checkSphereFullImpl(0.0f, pos, prevPos, mask, info, maskOut);
127bool ObjectObakeManager::checkPointCachedFullPush(
const EGG::Vector3f &pos,
128 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
129 return checkSphereFullPushImpl(0.0f, pos, prevPos, mask, info, maskOut);
133bool ObjectObakeManager::checkSphereCachedPartial(f32 radius,
const EGG::Vector3f &pos,
134 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
135 KCLTypeMask *maskOut, u32 ) {
136 return checkSpherePartialImpl(radius, pos, prevPos, mask, info, maskOut);
140bool ObjectObakeManager::checkSphereCachedPartialPush(f32 radius,
const EGG::Vector3f &pos,
141 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
142 KCLTypeMask *maskOut, u32 ) {
143 return checkSpherePartialPushImpl(radius, pos, prevPos, mask, info, maskOut);
147bool ObjectObakeManager::checkSphereCachedFull(f32 radius,
const EGG::Vector3f &pos,
148 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
150 return checkSphereFullImpl(radius, pos, prevPos, mask, info, maskOut);
154bool ObjectObakeManager::checkSphereCachedFullPush(f32 radius,
const EGG::Vector3f &pos,
155 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
157 return checkSphereFullPushImpl(radius, pos, prevPos, mask, info, maskOut);
161void ObjectObakeManager::addBlock(
const System::MapdataGeoObj ¶ms) {
162 auto *block = EGG::egg_new<ObjectObakeBlock>(params);
163 m_blocks.push_back(block);
164 auto [spatialX, spatialZ] = SpatialIndex(block->pos());
165 m_blockCache[spatialZ][spatialX] = block;
169bool ObjectObakeManager::checkSpherePartialImpl(f32 radius,
const EGG::Vector3f &pos,
170 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfoPartial *info,
171 KCLTypeMask *maskOut) {
172 bool collision =
false;
173 auto [spatialX, spatialZ] = SpatialIndex(pos);
177 m_colSphere->transform(t, EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
179 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
180 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
182 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
183 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
187 auto *block = m_blockCache[i][j];
193 t.makeT(block->pos());
194 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
195 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
198 bool collided = m_colSphere->check(*m_colBox, dist);
201 EGG::Vector3f distNrm = dist;
204 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
217 collision |= collided;
221 t.makeT(block->pos());
222 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
225 bool collided = m_colSphere->check(*m_colBox, dist);
228 EGG::Vector3f distNrm = dist;
231 if (0.9f >= distNrm.y) {
244 collision |= collided;
253bool ObjectObakeManager::checkSpherePartialPushImpl(f32 radius,
const EGG::Vector3f &pos,
254 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfoPartial *info,
255 KCLTypeMask *maskOut) {
256 bool collision =
false;
257 auto [spatialX, spatialZ] = SpatialIndex(pos);
262 m_colSphere->transform(t, EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
264 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
265 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
267 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
268 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
272 auto *block = m_blockCache[i][j];
278 t.makeT(block->pos());
279 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
280 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
283 bool collided = m_colSphere->check(*m_colBox, dist);
286 EGG::Vector3f distNrm = dist;
289 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
297 auto *colDir = CollisionDirector::Instance();
298 colDir->pushCollisionEntry(dist.length(), maskOut,
300 colDir->setCurrentCollisionVariant(2);
305 collision |= collided;
309 t.makeT(block->pos());
310 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
313 bool collided = m_colSphere->check(*m_colBox, dist);
316 EGG::Vector3f distNrm = dist;
319 if (0.9f >= distNrm.y) {
327 auto *colDir = CollisionDirector::Instance();
328 colDir->pushCollisionEntry(dist.length(), maskOut,
334 collision |= collided;
343bool ObjectObakeManager::checkSphereFullImpl(f32 radius,
const EGG::Vector3f &pos,
344 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfo *info,
345 KCLTypeMask *maskOut) {
346 bool collision =
false;
347 auto [spatialX, spatialZ] = SpatialIndex(pos);
351 m_colSphere->transform(t, EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
353 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
354 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
356 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
357 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
361 auto *block = m_blockCache[i][j];
368 t.makeT(block->pos());
369 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
370 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
373 bool collided = m_colSphere->check(*m_colBox, dist);
376 EGG::Vector3f distNrm = dist;
379 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
392 collision |= collided;
396 t.makeT(block->pos());
397 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
400 bool collided = m_colSphere->check(*m_colBox, dist);
403 EGG::Vector3f distNrm = dist;
406 if (0.9f >= distNrm.y) {
419 collision |= collided;
428bool ObjectObakeManager::checkSphereFullPushImpl(f32 radius,
const EGG::Vector3f &pos,
429 const EGG::Vector3f & , KCLTypeMask mask, CollisionInfo *info,
430 KCLTypeMask *maskOut) {
431 bool collision =
false;
432 auto [spatialX, spatialZ] = SpatialIndex(pos);
436 m_colSphere->transform(t, EGG::Vector3f(radius, radius, radius), EGG::Vector3f::zero);
438 for (s32 i = spatialZ - 1; i <= spatialZ + 1; ++i) {
439 for (s32 j = spatialX - 1; j <= spatialX + 1; ++j) {
441 if (j < 0 ||
static_cast<size_t>(j) >= CACHE_SIZE_X || i < 0 ||
442 static_cast<size_t>(i) >= CACHE_SIZE_Z) {
446 auto *block = m_blockCache[i][j];
453 t.makeT(block->pos());
454 m_colBox->setBoundingRadius(SPECIAL_WALL_BOUNDING_RADIUS);
455 m_colBox->transform(t, SPECIAL_WALL_SCALE, EGG::Vector3f::zero);
458 bool collided = m_colSphere->check(*m_colBox, dist);
461 EGG::Vector3f distNrm = dist;
464 if (0.0f > distNrm.y || distNrm.y > 0.9f) {
472 auto *colDir = CollisionDirector::Instance();
473 colDir->pushCollisionEntry(dist.length(), maskOut,
475 colDir->setCurrentCollisionVariant(2);
480 collision |= collided;
484 t.makeT(block->pos());
485 m_colBox->transform(t, ROAD_SCALE, EGG::Vector3f::zero);
488 bool collided = m_colSphere->check(*m_colBox, dist);
491 EGG::Vector3f distNrm = dist;
494 if (0.9f >= distNrm.y) {
502 auto *colDir = CollisionDirector::Instance();
503 colDir->pushCollisionEntry(dist.length(), maskOut,
509 collision |= collided;
519 constexpr f32 ORIGIN_OFFSET_X = -30647.498f;
520 constexpr f32 ORIGIN_OFFSET_Z = -21092.5f;
521 constexpr f32 GRID_WIDTH = 325.0f;
522 constexpr f32 GRID_HALF_WIDTH = 162.5f;
524 s32 x = (pos.x - ORIGIN_OFFSET_X + GRID_HALF_WIDTH) / GRID_WIDTH;
525 s32 z = (pos.z - ORIGIN_OFFSET_Z + GRID_HALF_WIDTH) / GRID_WIDTH;
527 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
static std::pair< s32, s32 > SpatialIndex(const EGG::Vector3f &pos)
Helper function to return the spatial index of a given block.