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 data->narrowScopeLocal(pos / scale, radius / scale, mask);
30bool CourseColMgr::checkPointPartial(f32 scale, KColData *data,
const EGG::Vector3f &v0,
31 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
32 KCLTypeMask *maskOut) {
39 data->lookupPoint(v0 / scale, v1 / scale, mask);
42 return doCheckWithPartialInfo(data, &KColData::checkPointCollision, info, maskOut);
45 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
49bool CourseColMgr::checkPointPartialPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
50 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
51 KCLTypeMask *maskOut) {
58 data->lookupPoint(v0 / scale, v1 / scale, mask);
61 return doCheckWithPartialInfoPush(data, &KColData::checkPointCollision, info, maskOut);
63 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
67bool CourseColMgr::checkPointFull(f32 scale, KColData *data,
const EGG::Vector3f &v0,
68 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
75 data->lookupPoint(v0 / scale, v1 / scale, mask);
78 return doCheckWithFullInfo(data, &KColData::checkPointCollision, info, maskOut);
80 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
84bool CourseColMgr::checkPointFullPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
85 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
92 data->lookupPoint(v0 / scale, v1 / scale, mask);
95 return doCheckWithFullInfoPush(data, &KColData::checkPointCollision, info, maskOut);
97 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
101bool CourseColMgr::checkSpherePartial(f32 scale, f32 radius, KColData *data,
103 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
110 data->lookupSphere(radius, v0 / scale, v1 / scale, mask);
113 return doCheckWithPartialInfo(data, &KColData::checkSphereCollision, info, maskOut);
115 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
119bool CourseColMgr::checkSpherePartialPush(f32 scale, f32 radius, KColData *data,
121 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
128 data->lookupSphere(radius, v0 / scale, v1 / scale, mask);
131 return doCheckWithPartialInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
133 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
137bool CourseColMgr::checkSphereFull(f32 scalar, f32 radius, KColData *data,
const EGG::Vector3f &v0,
138 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
145 data->lookupSphere(radius, v0 / scalar, v1 / scalar, mask);
148 return doCheckWithFullInfo(data, &KColData::checkSphereCollision, info, maskOut);
150 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
154bool CourseColMgr::checkSphereFullPush(f32 scalar, f32 radius, KColData *data,
156 KCLTypeMask *maskOut) {
163 data->lookupSphere(radius, v0 / scalar, v1 / scalar, mask);
166 return doCheckWithFullInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
168 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
172bool CourseColMgr::checkPointCachedPartial(f32 scale, KColData *data,
const EGG::Vector3f &v0,
173 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
174 KCLTypeMask *maskOut) {
181 data->lookupPoint(v0 / scale, v1 / scale, mask);
184 return doCheckWithPartialInfo(data, &KColData::checkPointCollision, info, maskOut);
186 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
190bool CourseColMgr::checkPointCachedPartialPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
191 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfoPartial *info,
192 KCLTypeMask *maskOut) {
197 if (data->prismCache(0) == 0) {
203 data->lookupPoint(v0 / scale, v1 / scale, mask);
206 return doCheckWithPartialInfoPush(data, &KColData::checkPointCollision, info, maskOut);
208 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
212bool CourseColMgr::checkPointCachedFull(f32 scale, KColData *data,
const EGG::Vector3f &v0,
213 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *pInfo, KCLTypeMask *maskOut) {
218 if (data->prismCache(0) == 0) {
224 data->lookupPoint(v0 / scale, v1 / scale, mask);
227 return doCheckWithFullInfo(data, &KColData::checkPointCollision, pInfo, maskOut);
229 return doCheckMaskOnly(data, &KColData::checkPointCollision, maskOut);
233bool CourseColMgr::checkPointCachedFullPush(f32 scale, KColData *data,
const EGG::Vector3f &v0,
234 const EGG::Vector3f &v1, KCLTypeMask mask, CollisionInfo *pInfo, KCLTypeMask *maskOut) {
239 if (data->prismCache(0) == 0) {
245 data->lookupPoint(v0 / scale, v1 / scale, mask);
248 return doCheckWithFullInfoPush(data, &KColData::checkPointCollision, pInfo, maskOut);
250 return doCheckMaskOnlyPush(data, &KColData::checkPointCollision, maskOut);
254bool CourseColMgr::checkSphereCachedPartial(f32 scale, f32 radius, KColData *data,
256 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
261 if (data->prismCache(0) == 0) {
267 data->lookupSphereCached(pos / scale, prevPos / scale, mask, radius / scale);
270 return doCheckWithPartialInfo(data, &KColData::checkSphereCollision, info, maskOut);
273 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
277bool CourseColMgr::checkSphereCachedPartialPush(f32 scale, f32 radius, KColData *data,
279 CollisionInfoPartial *info, KCLTypeMask *maskOut) {
284 if (data->prismCache(0) == 0) {
290 data->lookupSphereCached(pos / scale, prevPos / scale, mask, radius / scale);
293 return doCheckWithPartialInfoPush(data, &KColData::checkSphereCollision, info, maskOut);
296 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
300bool CourseColMgr::checkSphereCachedFull(f32 scale, f32 radius, KColData *data,
302 CollisionInfo *pInfo, KCLTypeMask *maskOut) {
307 if (data->prismCache(0) == 0) {
313 data->lookupSphereCached(pos / scale, prevPos / scale, mask, radius / scale);
316 return doCheckWithFullInfo(data, &KColData::checkSphereCollision, pInfo, maskOut);
319 return doCheckMaskOnly(data, &KColData::checkSphereCollision, maskOut);
323bool CourseColMgr::checkSphereCachedFullPush(f32 scale, f32 radius, KColData *data,
325 CollisionInfo *colInfo, KCLTypeMask *maskOut) {
330 if (data->prismCache(0) == 0) {
336 data->lookupSphereCached(pos / scale, prevPos / scale, mask, radius / scale);
339 return doCheckWithFullInfoPush(data, &KColData::checkSphereCollision, colInfo, maskOut);
342 return doCheckMaskOnlyPush(data, &KColData::checkSphereCollision, maskOut);
347 auto *resMgr = System::ResourceManager::Instance();
348 return resMgr->getFile(filename,
nullptr, System::ArchiveId::Course);
359void CourseColMgr::DestroyInstance() {
361 auto *instance = s_instance;
362 s_instance =
nullptr;
367CourseColMgr::CourseColMgr()
368 : m_data(nullptr), m_kclScale(1.0f), m_noBounceWallInfo(nullptr), m_localMtx(nullptr) {}
371CourseColMgr::~CourseColMgr() {
373 s_instance =
nullptr;
374 WARN(
"CourseColMgr instance not explicitly handled!");
382bool CourseColMgr::doCheckWithPartialInfo(KColData *data, CollisionCheckFunc collisionCheckFunc,
383 CollisionInfoPartial *info, KCLTypeMask *typeMask) {
389 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
393 if (m_noBounceWallInfo && (attribute & KCL_SOFT_WALL_MASK)) {
398 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
399 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
400 if (m_noBounceWallInfo->dist < dist) {
401 m_noBounceWallInfo->dist = dist;
402 m_noBounceWallInfo->fnrm = fnrm;
407 *typeMask = *typeMask | flags;
411 info->bbox.min = info->bbox.min.
minimize(offset);
412 info->bbox.max = info->bbox.max.
maximize(offset);
417 m_localMtx =
nullptr;
423bool CourseColMgr::doCheckWithPartialInfoPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
424 CollisionInfoPartial *info, KCLTypeMask *typeMask) {
430 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
434 if (!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) {
437 CollisionDirector::Instance()->pushCollisionEntry(dist, typeMask, flags, attribute);
441 info->bbox.min = info->bbox.min.
minimize(offset);
442 info->bbox.max = info->bbox.max.
maximize(offset);
449 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
450 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
451 if (m_noBounceWallInfo->dist < dist) {
452 m_noBounceWallInfo->dist = dist;
453 m_noBounceWallInfo->fnrm = fnrm;
458 m_localMtx =
nullptr;
464bool CourseColMgr::doCheckWithFullInfo(KColData *data, CollisionCheckFunc collisionCheckFunc,
465 CollisionInfo *colInfo, KCLTypeMask *flagsOut) {
471 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
474 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
479 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
480 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
481 if (m_noBounceWallInfo->dist < dist) {
482 m_noBounceWallInfo->dist = dist;
483 m_noBounceWallInfo->fnrm = fnrm;
488 *flagsOut |= kclAttributeTypeBit;
491 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
498 m_localMtx =
nullptr;
504bool CourseColMgr::doCheckWithFullInfoPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
505 CollisionInfo *colInfo, KCLTypeMask *flagsOut) {
511 while ((data->*collisionCheckFunc)(&dist, &fnrm, &attribute)) {
514 if (m_noBounceWallInfo && attribute & KCL_SOFT_WALL_MASK) {
519 m_noBounceWallInfo->bbox.min = m_noBounceWallInfo->bbox.min.
minimize(offset);
520 m_noBounceWallInfo->bbox.max = m_noBounceWallInfo->bbox.max.
maximize(offset);
521 if (m_noBounceWallInfo->dist < dist) {
522 m_noBounceWallInfo->dist = dist;
523 m_noBounceWallInfo->fnrm = fnrm;
528 CollisionDirector::Instance()->pushCollisionEntry(dist, flagsOut,
529 kclAttributeTypeBit, attribute);
532 colInfo->update(dist, fnrm * dist, fnrm, kclAttributeTypeBit);
539 m_localMtx =
nullptr;
544bool CourseColMgr::doCheckMaskOnly(KColData *data, CollisionCheckFunc collisionCheckFunc,
545 KCLTypeMask *maskOut) {
550 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
551 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
560bool CourseColMgr::doCheckMaskOnlyPush(KColData *data, CollisionCheckFunc collisionCheckFunc,
561 KCLTypeMask *maskOut) {
566 while ((data->*collisionCheckFunc)(&dist,
nullptr, &attribute)) {
567 if ((!m_noBounceWallInfo || !(attribute & KCL_SOFT_WALL_MASK)) && maskOut) {
568 CollisionDirector::Instance()->pushCollisionEntry(dist, maskOut,
577CourseColMgr *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.