1#include "CourseColMgr.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/ResourceManager.hh"
12void CourseColMgr::init() {
16 m_data = EGG::egg_new<KColData>(file);
20void CourseColMgr::scaledNarrowScopeLocal(f32 scale, f32 radius,
KColData *data,
21 const EGG::Vector3f &pos, KCLTypeMask mask) {
26 f32 invScale = 1.0f / scale;
27 data->narrowScopeLocal(pos * invScale, radius * invScale, mask);
31bool CourseColMgr::checkPointPartial(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
33 KCLTypeMask *maskOut) {
40 f32 invScale = 1.0f / scale;
41 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
44 return doCheckWithPartialInfo(data, &KColData::checkPointCollision, info, maskOut);
47 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
51bool CourseColMgr::checkPointPartialPush(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
53 KCLTypeMask *maskOut) {
60 f32 invScale = 1.0f / scale;
61 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
64 return doCheckWithPartialInfoPush(data, &KColData::checkPointCollision, info, maskOut);
66 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
70bool CourseColMgr::checkPointFull(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
71 const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *info, KCLTypeMask *maskOut) {
78 f32 invScale = 1.0f / scale;
79 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
82 return doCheckWithFullInfo(data, &KColData::checkPointCollision, info, maskOut);
84 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
88bool CourseColMgr::checkPointFullPush(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
89 const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *info, KCLTypeMask *maskOut) {
96 f32 invScale = 1.0f / scale;
97 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
100 return doCheckWithFullInfoPush(data, &KColData::checkPointCollision, info, maskOut);
102 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
106bool CourseColMgr::checkSpherePartial(f32 scale, f32 radius,
KColData *data,
107 const EGG::Vector3f &v0,
const EGG::Vector3f &v1, KCLTypeMask mask,
115 f32 invScale = 1.0f / scale;
116 data->lookupSphere(radius * invScale, v0 * invScale, v1 * invScale, mask);
119 return doCheckWithPartialInfo(data, &KColData::checkSphereCollision, info, maskOut);
121 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
125bool CourseColMgr::checkSpherePartialPush(f32 scale, f32 radius,
KColData *data,
126 const EGG::Vector3f &v0,
const EGG::Vector3f &v1, KCLTypeMask mask,
134 f32 invScale = 1.0f / scale;
135 data->lookupSphere(radius * invScale, v0 * invScale, v1 * invScale, mask);
138 return doCheckWithPartialInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
140 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
144bool CourseColMgr::checkSphereFull(f32 scale, f32 radius,
KColData *data,
const EGG::Vector3f &v0,
145 const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *info, KCLTypeMask *maskOut) {
152 f32 invScale = 1.0f / scale;
153 data->lookupSphere(radius * invScale, v0 * invScale, v1 * invScale, mask);
156 return doCheckWithFullInfo(data, &KColData::checkSphereCollision, info, maskOut);
158 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
162bool CourseColMgr::checkSphereFullPush(f32 scale, f32 radius,
KColData *data,
163 const EGG::Vector3f &v0,
const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *info,
164 KCLTypeMask *maskOut) {
171 f32 invScale = 1.0f / scale;
172 data->lookupSphere(radius * invScale, v0 * invScale, v1 * invScale, mask);
175 return doCheckWithFullInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
177 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
181bool CourseColMgr::checkPointCachedPartial(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
183 KCLTypeMask *maskOut) {
188 if (data->prismCache(0) == 0) {
194 f32 invScale = 1.0f / scale;
195 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
198 return doCheckWithPartialInfo(data, &KColData::checkPointCollision, info, maskOut);
200 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
204bool CourseColMgr::checkPointCachedPartialPush(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
206 KCLTypeMask *maskOut) {
211 if (data->prismCache(0) == 0) {
217 f32 invScale = 1.0f / scale;
218 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
221 return doCheckWithPartialInfoPush(data, &KColData::checkPointCollision, info, maskOut);
223 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
227bool CourseColMgr::checkPointCachedFull(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
228 const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *pInfo, KCLTypeMask *maskOut) {
233 if (data->prismCache(0) == 0) {
239 f32 invScale = 1.0f / scale;
240 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
243 return doCheckWithFullInfo(data, &KColData::checkPointCollision, pInfo, maskOut);
245 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
249bool CourseColMgr::checkPointCachedFullPush(f32 scale,
KColData *data,
const EGG::Vector3f &v0,
250 const EGG::Vector3f &v1, KCLTypeMask mask,
CollisionInfo *pInfo, KCLTypeMask *maskOut) {
255 if (data->prismCache(0) == 0) {
261 f32 invScale = 1.0f / scale;
262 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
265 return doCheckWithFullInfoPush(data, &KColData::checkPointCollision, pInfo, maskOut);
267 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
271bool CourseColMgr::checkSphereCachedPartial(f32 scale, f32 radius,
KColData *data,
272 const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos, KCLTypeMask mask,
278 if (data->prismCache(0) == 0) {
284 f32 invScale = 1.0f / scale;
285 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
288 return doCheckWithPartialInfo(data, &KColData::checkSphereCollision, info, maskOut);
291 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
295bool CourseColMgr::checkSphereCachedPartialPush(f32 scale, f32 radius,
KColData *data,
296 const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos, KCLTypeMask mask,
302 if (data->prismCache(0) == 0) {
308 f32 invScale = 1.0f / scale;
309 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
312 return doCheckWithPartialInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
315 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
319bool CourseColMgr::checkSphereCachedFull(f32 scale, f32 radius,
KColData *data,
320 const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos, KCLTypeMask mask,
326 if (data->prismCache(0) == 0) {
332 f32 invScale = 1.0f / scale;
333 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
336 return doCheckWithFullInfo(data, &KColData::checkSphereCollision, pInfo, maskOut);
339 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
343bool CourseColMgr::checkSphereCachedFullPush(f32 scale, f32 radius,
KColData *data,
344 const EGG::Vector3f &pos,
const EGG::Vector3f &prevPos, KCLTypeMask mask,
350 if (data->prismCache(0) == 0) {
356 f32 invScale = 1.0f / scale;
357 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
360 return doCheckWithFullInfoPush(data, &KColData::checkSphereCollision, colInfo, maskOut);
363 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
368 auto *resMgr = System::ResourceManager::Instance();
369 return resMgr->getFile(filename,
nullptr, System::ArchiveId::Course);
375 s_instance = EGG::egg_new<CourseColMgr>();
380void CourseColMgr::DestroyInstance() {
382 auto *instance = s_instance;
383 s_instance =
nullptr;
384 EGG::egg_delete(instance);
388CourseColMgr::CourseColMgr()
389 : m_data(nullptr), m_kclScale(1.0f), m_noBounceWallInfo(nullptr), m_localMtx(nullptr) {}
392CourseColMgr::~CourseColMgr() {
394 s_instance =
nullptr;
395 WARN(
"CourseColMgr instance not explicitly handled!");
399 EGG::egg_delete(m_data);
403bool CourseColMgr::doCheckWithPartialInfo(
KColData *data, CollisionCheckFunc collisionCheckFunc,
410 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
414 if (m_noBounceWallInfo && (attribute & KCL_SOFT_WALL_MASK)) {
416 fnrm = m_localMtx->multVector33(fnrm);
418 EGG::Vector3f offset = fnrm * dist;
419 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.minimize(offset);
420 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.maximize(offset);
421 if (m_noBounceWallInfo->dist < dist) {
422 m_noBounceWallInfo->dist = dist;
423 m_noBounceWallInfo->fnrm = fnrm;
428 *typeMask = *typeMask | flags;
431 EGG::Vector3f offset = fnrm * dist;
432 info->updateBBox(offset);
437 m_localMtx =
nullptr;
443bool CourseColMgr::doCheckWithPartialInfoPush(
KColData *data, CollisionCheckFunc collisionCheckFunc,
450 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
454 if (!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) {
457 CollisionDirector::Instance()->pushCollisionEntry(dist, typeMask, flags, attribute);
460 EGG::Vector3f offset = fnrm * dist;
461 info->updateBBox(offset);
465 fnrm = m_localMtx->multVector33(fnrm);
467 EGG::Vector3f offset = fnrm * dist;
468 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.minimize(offset);
469 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.maximize(offset);
470 if (m_noBounceWallInfo->dist < dist) {
471 m_noBounceWallInfo->dist = dist;
472 m_noBounceWallInfo->fnrm = fnrm;
477 m_localMtx =
nullptr;
483bool CourseColMgr::doCheckWithFullInfo(
KColData *data, CollisionCheckFunc collisionCheckFunc,
490 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
493 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
495 fnrm = m_localMtx->multVector33(fnrm);
497 EGG::Vector3f offset = fnrm * dist;
498 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.minimize(offset);
499 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.maximize(offset);
500 if (m_noBounceWallInfo->dist < dist) {
501 m_noBounceWallInfo->dist = dist;
502 m_noBounceWallInfo->fnrm = fnrm;
507 *flagsOut |= kclAttributeTypeBit;
510 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
517 m_localMtx =
nullptr;
523bool CourseColMgr::doCheckWithFullInfoPush(
KColData *data, CollisionCheckFunc collisionCheckFunc,
530 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
533 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
535 fnrm = m_localMtx->multVector33(fnrm);
537 EGG::Vector3f offset = fnrm * dist;
538 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.minimize(offset);
539 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.maximize(offset);
540 if (m_noBounceWallInfo->dist < dist) {
541 m_noBounceWallInfo->dist = dist;
542 m_noBounceWallInfo->fnrm = fnrm;
547 CollisionDirector::Instance()->pushCollisionEntry(dist, flagsOut,
548 kclAttributeTypeBit, attribute);
551 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
558 m_localMtx =
nullptr;
563bool CourseColMgr::doCheckMaskOnly(
KColData *data, CollisionCheckFunc collisionCheckFunc,
564 KCLTypeMask *maskOut) {
569 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
570 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
579bool CourseColMgr::doCheckMaskOnlyPush(
KColData *data, CollisionCheckFunc collisionCheckFunc,
580 KCLTypeMask *maskOut) {
585 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
586 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
587 CollisionDirector::Instance()->pushCollisionEntry(dist, maskOut,
#define KCL_ATTRIBUTE_TYPE_BIT(x)
Given the full 2 byte KCL flag for a triangle, extracts the "Base Type" portion of the flag.
#define KCL_TYPE_SOLID_SURFACE
0xF0F8FFFF
Manager for course KCL interactions.
static void * LoadFile(const char *filename)
Loads a particular section of a .szs file.
Performs lookups for KCL triangles.