1#include "CourseColMgr.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/ResourceManager.hh"
12void CourseColMgr::init() {
16 m_data =
new KColData(file);
20void CourseColMgr::scaledNarrowScopeLocal(f32 scale, f32 radius, KColData *data,
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,
32 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
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,
52 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
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,
108 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
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,
127 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
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,
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,
182 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
183 KCLTypeMask *maskOut) {
190 f32 invScale = 1.0f / scale;
191 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
194 return doCheckWithPartialInfo(data, &KColData::checkPointCollision, info, maskOut);
196 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
200bool CourseColMgr::checkPointCachedPartialPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
201 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
202 KCLTypeMask *maskOut) {
207 if (data->prismCache(0) == 0) {
213 f32 invScale = 1.0f / scale;
214 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
217 return doCheckWithPartialInfoPush(data, &KColData::checkPointCollision, info, maskOut);
219 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
223bool CourseColMgr::checkPointCachedFull(f32 scale, KColData *data,
const EGG::Vector3f &v0,
224 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *pInfo, KCLTypeMask *maskOut) {
229 if (data->prismCache(0) == 0) {
235 f32 invScale = 1.0f / scale;
236 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
239 return doCheckWithFullInfo(data, &KColData::checkPointCollision, pInfo, maskOut);
241 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
245bool CourseColMgr::checkPointCachedFullPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
246 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *pInfo, KCLTypeMask *maskOut) {
251 if (data->prismCache(0) == 0) {
257 f32 invScale = 1.0f / scale;
258 data->lookupPoint(v0 * invScale, v1 * invScale, mask);
261 return doCheckWithFullInfoPush(data, &KColData::checkPointCollision, pInfo, maskOut);
263 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
267bool CourseColMgr::checkSphereCachedPartial(f32 scale, f32 radius, KColData *data,
269 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
274 if (data->prismCache(0) == 0) {
280 f32 invScale = 1.0f / scale;
281 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
284 return doCheckWithPartialInfo(data, &KColData::checkSphereCollision, info, maskOut);
287 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
291bool CourseColMgr::checkSphereCachedPartialPush(f32 scale, f32 radius, KColData *data,
293 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
298 if (data->prismCache(0) == 0) {
304 f32 invScale = 1.0f / scale;
305 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
308 return doCheckWithPartialInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
311 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
315bool CourseColMgr::checkSphereCachedFull(f32 scale, f32 radius, KColData *data,
317 CollisionInfo *pInfo, KCLTypeMask *maskOut) {
322 if (data->prismCache(0) == 0) {
328 f32 invScale = 1.0f / scale;
329 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
332 return doCheckWithFullInfo(data, &KColData::checkSphereCollision, pInfo, maskOut);
335 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
339bool CourseColMgr::checkSphereCachedFullPush(f32 scale, f32 radius, KColData *data,
341 CollisionInfo *colInfo, KCLTypeMask *maskOut) {
346 if (data->prismCache(0) == 0) {
352 f32 invScale = 1.0f / scale;
353 data->lookupSphereCached(pos * invScale, prevPos * invScale, mask, radius * invScale);
356 return doCheckWithFullInfoPush(data, &KColData::checkSphereCollision, colInfo, maskOut);
359 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
364 auto *resMgr = System::ResourceManager::Instance();
365 return resMgr->getFile(filename,
nullptr, System::ArchiveId::Course);
376void CourseColMgr::DestroyInstance() {
378 auto *instance = s_instance;
379 s_instance =
nullptr;
384CourseColMgr::CourseColMgr()
385 : m_data(nullptr), m_kclScale(1.0f), m_noBounceWallInfo(nullptr), m_localMtx(nullptr) {}
388CourseColMgr::~CourseColMgr() {
390 s_instance =
nullptr;
391 WARN(
"CourseColMgr instance not explicitly handled!");
399bool CourseColMgr::doCheckWithPartialInfo(KColData *data, CollisionCheckFunc collisionCheckFunc,
400 CollisionInfoPartial *info, KCLTypeMask *typeMask) {
406 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
410 if (m_noBounceWallInfo && (attribute & KCL_SOFT_WALL_MASK)) {
415 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
416 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
417 if (m_noBounceWallInfo->dist < dist) {
418 m_noBounceWallInfo->dist = dist;
419 m_noBounceWallInfo->fnrm = fnrm;
424 *typeMask = *typeMask | flags;
428 info->bbox.min = info->bbox.min.
minimize(offset);
429 info->bbox.max = info->bbox.max.
maximize(offset);
434 m_localMtx =
nullptr;
440bool CourseColMgr::doCheckWithPartialInfoPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
441 CollisionInfoPartial *info, KCLTypeMask *typeMask) {
447 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
451 if (!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) {
454 CollisionDirector::Instance()->pushCollisionEntry(dist, typeMask, flags, attribute);
458 info->bbox.min = info->bbox.min.
minimize(offset);
459 info->bbox.max = info->bbox.max.
maximize(offset);
466 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
467 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
468 if (m_noBounceWallInfo->dist < dist) {
469 m_noBounceWallInfo->dist = dist;
470 m_noBounceWallInfo->fnrm = fnrm;
475 m_localMtx =
nullptr;
481bool CourseColMgr::doCheckWithFullInfo(KColData *data, CollisionCheckFunc collisionCheckFunc,
482 CollisionInfo *colInfo, KCLTypeMask *flagsOut) {
488 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
491 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
496 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
497 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
498 if (m_noBounceWallInfo->dist < dist) {
499 m_noBounceWallInfo->dist = dist;
500 m_noBounceWallInfo->fnrm = fnrm;
505 *flagsOut |= kclAttributeTypeBit;
508 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
515 m_localMtx =
nullptr;
521bool CourseColMgr::doCheckWithFullInfoPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
522 CollisionInfo *colInfo, KCLTypeMask *flagsOut) {
528 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
531 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
536 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
537 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
538 if (m_noBounceWallInfo->dist < dist) {
539 m_noBounceWallInfo->dist = dist;
540 m_noBounceWallInfo->fnrm = fnrm;
545 CollisionDirector::Instance()->pushCollisionEntry(dist, flagsOut,
546 kclAttributeTypeBit, attribute);
549 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
556 m_localMtx =
nullptr;
561bool CourseColMgr::doCheckMaskOnly(KColData *data, CollisionCheckFunc collisionCheckFunc,
562 KCLTypeMask *maskOut) {
567 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
568 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
577bool CourseColMgr::doCheckMaskOnlyPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
578 KCLTypeMask *maskOut) {
583 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
584 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
585 CollisionDirector::Instance()->pushCollisionEntry(dist, maskOut,
594CourseColMgr *CourseColMgr::s_instance =
nullptr;
#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
Vector3f multVector33(const Vector3f &vec) const
Multiplies a 3x3 matrix by a vector.
Manager for course KCL interactions.
static void * LoadFile(const char *filename)
Loads a particular section of a .szs file.
Vector3f maximize(const Vector3f &rhs) const
Returns a vector whose elements are the max of the elements of both vectors.
Vector3f minimize(const Vector3f &rhs) const
Returns a vector whose elements are the min of the elements of both vectors.