mirror of
https://github.com/zeldaret/ss
synced 2026-05-30 00:46:41 -04:00
277 lines
8.5 KiB
C++
277 lines
8.5 KiB
C++
#include "d/col/cc/d_cc_mass_s.h"
|
|
|
|
#include "common.h"
|
|
#include "m/m_vec.h"
|
|
#include "rvl/MTX/vec.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Obj
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
dCcMassS_Obj::dCcMassS_Obj() {}
|
|
|
|
dCcMassS_Obj::~dCcMassS_Obj() {}
|
|
|
|
void dCcMassS_Obj::Set(cCcD_Obj *p_obj, u8 priority, dCcMassS_ObjCallback callback) {
|
|
mpObj = p_obj;
|
|
mPriority = priority;
|
|
mpCallback = callback;
|
|
}
|
|
|
|
void dCcMassS_Obj::Clear() {
|
|
mpObj = nullptr;
|
|
mPriority = 5;
|
|
mpCallback = nullptr;
|
|
mDivideInfo.Set(0, 0, 0);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Hit Info
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
dCcMassS_HitInf::dCcMassS_HitInf() {}
|
|
|
|
dCcMassS_HitInf::~dCcMassS_HitInf() {}
|
|
|
|
void dCcMassS_HitInf::ClearPointer() {
|
|
mpArea = nullptr;
|
|
mpAtObj = nullptr;
|
|
mpCoObj = nullptr;
|
|
mCoHitLen = 0.0f;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Manager
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
dCcMassS_Mng::dCcMassS_Mng() {
|
|
Ct();
|
|
}
|
|
|
|
dCcMassS_Mng ::~dCcMassS_Mng() {}
|
|
|
|
void dCcMassS_Mng::Ct() {
|
|
field_0x3AA = 0;
|
|
mResultCam = 0;
|
|
mCamTopPos.x = 0.0f;
|
|
mCamTopPos.y = -1000000000.0f;
|
|
mCamTopPos.z = 0.0f;
|
|
|
|
mCamBottomPos.x = 0.0f;
|
|
mCamBottomPos.y = -1000000000.0f;
|
|
mCamBottomPos.z = 0.0f;
|
|
|
|
Clear();
|
|
}
|
|
|
|
void dCcMassS_Mng::SetAttr(f32 radius, f32 height, u8 param_2, u8 param_3) {
|
|
mCylAttr.SetR(radius);
|
|
mCylAttr.SetH(height);
|
|
field_0x3A8 = param_2;
|
|
field_0x3A9 = param_3;
|
|
}
|
|
|
|
void dCcMassS_Mng::Prepare() {
|
|
cM3dGAab aab;
|
|
aab.ClearForMinMax();
|
|
|
|
for (dCcMassS_Obj *pObj = mMassObjs; pObj < mMassObjs + mMassObjCount; ++pObj) {
|
|
cCcD_ShapeAttr *objShape = pObj->GetObj()->GetShapeAttr();
|
|
objShape->CalcAabBox();
|
|
aab.SetMinMax(objShape->GetWorkAab());
|
|
}
|
|
|
|
for (dCcMassS_Obj *pObj = mMassAreas; pObj < mMassAreas + mMassAreaCount; ++pObj) {
|
|
cCcD_ShapeAttr *objShape = pObj->GetObj()->GetShapeAttr();
|
|
objShape->CalcAabBox();
|
|
aab.SetMinMax(objShape->GetWorkAab());
|
|
}
|
|
|
|
if (field_0x3AA & 1) {
|
|
mCpsAttr.CalcAabBox();
|
|
aab.SetMinMax(mCpsAttr.GetWorkAab());
|
|
}
|
|
|
|
mDivideArea.SetArea(aab);
|
|
for (dCcMassS_Obj *pObj = mMassObjs; pObj < mMassObjs + mMassObjCount; ++pObj) {
|
|
cCcD_ShapeAttr *objShape = pObj->GetObj()->GetShapeAttr();
|
|
cCcD_DivideInfo *divideInfo = &pObj->GetDivideInfo();
|
|
mDivideArea.CalcDivideInfo(divideInfo, objShape->GetWorkAab());
|
|
}
|
|
|
|
for (dCcMassS_Obj *pObj = mMassAreas; pObj < mMassAreas + mMassAreaCount; ++pObj) {
|
|
cCcD_ShapeAttr *objShape = pObj->GetObj()->GetShapeAttr();
|
|
cCcD_DivideInfo *divideInfo = &pObj->GetDivideInfo();
|
|
mDivideArea.CalcDivideInfo(divideInfo, objShape->GetWorkAab());
|
|
}
|
|
|
|
if (field_0x3AA & 1) {
|
|
mDivideArea.CalcDivideInfo(&mDivideInfo, mCpsAttr.GetWorkAab());
|
|
}
|
|
|
|
mCamTopPos.x = 0.0f;
|
|
mCamTopPos.y = -1000000000.0f;
|
|
mCamTopPos.z = 0.0f;
|
|
mCamTopDist = 1000000000.0f;
|
|
|
|
mCamBottomPos.x = 0.0f;
|
|
mCamBottomPos.y = -1000000000.0f;
|
|
mCamBottomPos.z = 0.0f;
|
|
mCamBottomDist = 1000000000.0f;
|
|
}
|
|
|
|
u32 dCcMassS_Mng::Chk(mVec3_c *p_xyz, dAcObjBase_c **p_actor, dCcMassS_HitInf *p_hitInf) {
|
|
cCcD_DivideInfo divideInfo;
|
|
u32 flagsMaybe = 0;
|
|
*p_actor = NULL;
|
|
|
|
mCylAttr.SetC(*p_xyz);
|
|
mCylAttr.CalcAabBox();
|
|
|
|
mDivideArea.CalcDivideInfoOverArea(÷Info, mCylAttr.GetWorkAab());
|
|
p_hitInf->ClearPointer();
|
|
|
|
if (field_0x3A8 & 8) {
|
|
for (dCcMassS_Obj *massObj = mMassAreas; massObj < mMassAreas + mMassAreaCount; ++massObj) {
|
|
if (massObj->GetDivideInfo().Chk(divideInfo)) {
|
|
cCcD_Obj *obj = massObj->GetObj();
|
|
cCcD_ShapeAttr *objShape = obj->GetShapeAttr();
|
|
f32 f;
|
|
if (obj->ChkCoSet() && mCylAttr.CrossCo(*objShape, &f)) {
|
|
flagsMaybe |= 4;
|
|
*p_actor = obj->GetStts()->GetAc();
|
|
if (p_hitInf != NULL) {
|
|
p_hitInf->SetAreaHitObj(obj);
|
|
}
|
|
|
|
if (massObj->GetCallback() != NULL) {
|
|
massObj->GetCallback()(obj->GetStts()->GetAc(), p_xyz, field_0x3A9);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (dCcMassS_Obj *massObj = mMassObjs; massObj < mMassObjs + mMassObjCount; ++massObj) {
|
|
if (massObj->GetDivideInfo().Chk(divideInfo)) {
|
|
cCcD_Obj *obj = massObj->GetObj();
|
|
cCcD_ShapeAttr *objShape = obj->GetShapeAttr();
|
|
mVec3_c unusedVec;
|
|
if (obj->ChkAtSet() && !obj->ChkAtNoMass() && (field_0x3A8 & 1)) {
|
|
*p_actor = obj->GetStts()->GetAc();
|
|
}
|
|
if (obj->ChkAtSet() && !obj->ChkAtNoMass() && mCylAttr.CrossAtTg(*objShape, &unusedVec) &&
|
|
(field_0x3A8 & 1)) {
|
|
flagsMaybe |= 1;
|
|
*p_actor = obj->GetStts()->GetAc();
|
|
if (p_hitInf != NULL) {
|
|
p_hitInf->SetAtHitObj(obj);
|
|
}
|
|
}
|
|
|
|
f32 f;
|
|
if (obj->ChkCoSet() && mCylAttr.CrossCo(*objShape, &f) && (field_0x3A8 & 2)) {
|
|
flagsMaybe |= 2;
|
|
*p_actor = obj->GetStts()->GetAc();
|
|
|
|
if (field_0x3A8 & 0x10) {
|
|
mVec3_c vec;
|
|
VECSubtract((*p_actor)->getPosition(), *p_xyz, vec);
|
|
vec.y = 0;
|
|
f32 vecMag = VECMag(vec);
|
|
if (cM3d_IsZero(vecMag)) {
|
|
vec.x = 1;
|
|
} else {
|
|
VECScale(vec, vec, f / vecMag);
|
|
}
|
|
obj->GetStts()->PlusCcMove(vec.x, vec.y, vec.z);
|
|
}
|
|
|
|
if (p_hitInf != NULL) {
|
|
p_hitInf->SetCoHitObj(obj);
|
|
p_hitInf->SetCoHitLen(f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 f;
|
|
if ((field_0x3AA & 1) && mDivideInfo.Chk(divideInfo) && mCylAttr.CrossCo(mCpsAttr, &f)) {
|
|
mResultCam |= 1;
|
|
mResultCam |= 1 << (field_0x3A9 + 1);
|
|
|
|
if ((mResultCam & 2) || (mResultCam & 8)) {
|
|
Vec tmpVec;
|
|
f32 plusH = p_xyz->y + mCylAttr.GetH();
|
|
tmpVec.x = p_xyz->x;
|
|
tmpVec.y = plusH;
|
|
tmpVec.z = p_xyz->z;
|
|
|
|
if (mCamTopPos.y < (20.0f + plusH)) {
|
|
f32 newCamTopDist = VECSquareDistance(&tmpVec, *mCpsAttr.GetStartP());
|
|
if (mCamTopDist > newCamTopDist) {
|
|
mCamTopDist = newCamTopDist;
|
|
mCamTopPos = tmpVec;
|
|
}
|
|
}
|
|
|
|
if (mCamBottomPos.y < (20.0f + plusH)) {
|
|
f32 newCamBottomDist = VECSquareDistance(&tmpVec, *mCpsAttr.GetEndP());
|
|
if (mCamBottomDist > newCamBottomDist) {
|
|
mCamBottomDist = newCamBottomDist;
|
|
mCamBottomPos = tmpVec;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return flagsMaybe;
|
|
}
|
|
|
|
void dCcMassS_Mng::Clear() {
|
|
mMassObjCount = 0;
|
|
mMassAreaCount = 0;
|
|
|
|
for (int i = 0; i < (s32)ARRAY_LENGTH(mMassObjs); ++i) {
|
|
mMassObjs[i].Clear();
|
|
}
|
|
|
|
for (int i = 0; i < (s32)ARRAY_LENGTH(mMassAreas); ++i) {
|
|
mMassAreas[i].Clear();
|
|
}
|
|
|
|
mCylAttr.SetR(0.0f);
|
|
mCylAttr.SetH(0.0f);
|
|
field_0x3A8 = 0;
|
|
field_0x3A9 = 4;
|
|
}
|
|
|
|
void dCcMassS_Mng::SetObj(cCcD_Obj *p_obj, u8 priority) {
|
|
if (mMassObjCount >= (s32)ARRAY_LENGTH(mMassObjs)) {
|
|
for (int i = 0; i < (s32)ARRAY_LENGTH(mMassObjs); ++i) {
|
|
int prevPrio = mMassObjs[i].GetPriority();
|
|
if (prevPrio > priority || (prevPrio == priority)) {
|
|
mMassObjs[i].Set(p_obj, priority, nullptr);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
mMassObjs[mMassObjCount].Set(p_obj, priority, nullptr);
|
|
mMassObjCount++;
|
|
}
|
|
}
|
|
|
|
void dCcMassS_Mng::SetArea(cCcD_Obj *p_obj, u8 priority, dCcMassS_ObjCallback callback) {
|
|
if (mMassAreaCount >= (s32)ARRAY_LENGTH(mMassAreas)) {
|
|
for (int i = 0; i < (s32)ARRAY_LENGTH(mMassAreas); ++i) {
|
|
if (mMassAreas[i].GetPriority() > priority) {
|
|
mMassAreas[i].Set(p_obj, priority, callback);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
mMassAreas[mMassAreaCount].Set(p_obj, priority, callback);
|
|
mMassAreaCount++;
|
|
}
|
|
}
|