#include "d/col/c/c_cc_d.h" #include "c/c_math.h" #include "common.h" #include "d/a/obj/d_a_obj_base.h" #include "d/col/c/c_m3d.h" #include "d/col/c/c_m3d_g_aab.h" #include "d/col/c/c_m3d_g_cyl.h" #include "d/col/c/c_m3d_g_lin.h" #include "d/col/c/c_m3d_g_unk.h" #include "egg/math/eggMath.h" #include "egg/math/eggVector.h" #include "m/m_angle.h" #include "m/m_mtx.h" #include "m/m_vec.h" #include "nw4r/types_nw4r.h" #include "s/s_Math.h" #include "rvl/MTX.h" // IWYU pragma: export static inline void MtxTransMinusXYZ(mMtx_c &mtx, f32 x, f32 y, f32 z) { PSMTXTrans(mtx, -x, -y, -z); } mVec3_c cCcD_ShapeAttr::sVirtualCenter = mVec3_c::Zero; cCcD_DivideInfo::cCcD_DivideInfo() {} cCcD_DivideInfo::~cCcD_DivideInfo() {} cCcD_DivideArea::cCcD_DivideArea() {} cCcD_DivideArea::~cCcD_DivideArea() {} void cCcD_DivideArea::SetArea(cM3dGAab const &aab) { Set(aab.mMin, aab.mMax); mScaledXDiff = 1.0f / 32.0f * (GetMaxP()->x - GetMinP()->x); mXDiffIsZero = cM3d_IsZero(mScaledXDiff); if (!mXDiffIsZero) { mInvScaledXDiff = 1.0f / mScaledXDiff; } mScaledYDiff = 1.0f / 32.0f * (GetMaxP()->y - GetMinP()->y); mYDiffIsZero = cM3d_IsZero(mScaledYDiff); if (!mYDiffIsZero) { mInvScaledYDiff = 1.0f / mScaledYDiff; } mScaledZDiff = 1.0f / 32.0f * (GetMaxP()->z - GetMinP()->z); mZDiffIsZero = cM3d_IsZero(mScaledZDiff); if (!mZDiffIsZero) { mInvScaledZDiff = 1.0f / mScaledZDiff; } } static const u32 l_base[32] = { 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, }; void cCcD_DivideArea::CalcDivideInfo(cCcD_DivideInfo *pDivideInfo, const cM3dGAab &aab) { u32 xDivInfo, yDivInfo, zDivInfo; if (!mXDiffIsZero) { s32 var1 = mInvScaledXDiff * (aab.GetMinP()->x - GetMinP()->x); s32 var3 = mInvScaledXDiff * (aab.GetMaxP()->x - GetMinP()->x); if (31 < var3) { var3 = 31; } xDivInfo = l_base[var3]; if (0 < var1) { var1--; xDivInfo &= ~l_base[var1]; } } else { xDivInfo = 0xFFFFFFFF; } if (!mYDiffIsZero) { s32 var1 = mInvScaledYDiff * (aab.GetMinP()->y - GetMinP()->y); s32 var3 = mInvScaledYDiff * (aab.GetMaxP()->y - GetMinP()->y); if (31 < var3) { var3 = 31; } yDivInfo = l_base[var3]; if (0 < var1) { var1--; yDivInfo &= ~l_base[var1]; } } else { yDivInfo = 0xFFFFFFFF; } if (!mZDiffIsZero) { s32 var1 = mInvScaledZDiff * (aab.GetMinP()->z - GetMinP()->z); s32 var3 = mInvScaledZDiff * (aab.GetMaxP()->z - GetMinP()->z); if (31 < var3) { var3 = 31; } zDivInfo = l_base[var3]; if (0 < var1) { var1--; zDivInfo &= ~l_base[var1]; } } else { zDivInfo = 0xFFFFFFFF; } pDivideInfo->Set(xDivInfo, yDivInfo, zDivInfo); } void cCcD_DivideArea::CalcDivideInfoOverArea(cCcD_DivideInfo *pDivideInfo, const cM3dGAab &aab) { u32 xDivInfo, yDivInfo, zDivInfo; if (!mXDiffIsZero) { s32 var1 = mInvScaledXDiff * (aab.GetMinP()->x - GetMinP()->x); s32 var3 = mInvScaledXDiff * (aab.GetMaxP()->x - GetMinP()->x); if (var3 < 0 || 31 < var1) { xDivInfo = 0; } else { if (31 < var3) { var3 = 31; } xDivInfo = l_base[var3]; if (0 < var1) { var1--; xDivInfo &= ~l_base[var1]; } } } else { xDivInfo = 0xFFFFFFFF; } if (!mYDiffIsZero) { s32 var1 = mInvScaledYDiff * (aab.GetMinP()->y - GetMinP()->y); s32 var3 = mInvScaledYDiff * (aab.GetMaxP()->y - GetMinP()->y); if (var3 < 0 || 31 < var1) { yDivInfo = 0; } else { if (31 < var3) { var3 = 31; } yDivInfo = l_base[var3]; if (0 < var1) { var1--; yDivInfo &= ~l_base[var1]; } } } else { yDivInfo = 0xFFFFFFFF; } if (!mZDiffIsZero) { s32 var1 = mInvScaledZDiff * (aab.GetMinP()->z - GetMinP()->z); s32 var3 = mInvScaledZDiff * (aab.GetMaxP()->z - GetMinP()->z); if (var3 < 0 || 31 < var1) { zDivInfo = 0; } else { if (31 < var3) { var3 = 31; } zDivInfo = l_base[var3]; if (0 < var1) { var1--; zDivInfo &= ~l_base[var1]; } } } else { zDivInfo = 0xFFFFFFFF; } pDivideInfo->Set(xDivInfo, yDivInfo, zDivInfo); } cCcD_Stts::cCcD_Stts(dAcObjBase_c *pObj) { mAtApid = 0; mAtOldApid = 0; mTgApid = 0; mTgOldApid = 0; mRank = 0; mpActor = pObj; ClrCcMove(); } void cCcD_Stts::Move() { mAtOldApid = mAtApid; mAtApid = 0; mTgOldApid = mTgApid; mTgApid = 0; } int cCcD_Stts::GetID() const { if (mpActor) { return mpActor->getID(); } return 0; } void cCcD_Stts::PlusCcMove(f32 x, f32 y, f32 z) { if (field_0x10.x > x) { field_0x10.x = x; } else if (field_0x1C.x < x) { field_0x1C.x = x; } if (field_0x10.y > y) { field_0x10.y = y; } else if (field_0x1C.y < y) { field_0x1C.y = y; } if (field_0x10.z > z) { field_0x10.z = z; } else if (field_0x1C.z < z) { field_0x1C.z = z; } mCcMove.x = field_0x10.x + field_0x1C.x; mCcMove.y = field_0x10.y + field_0x1C.y; mCcMove.z = field_0x10.z + field_0x1C.z; } void cCcD_Stts::ClrCcMove() { field_0x10 = mVec3_c::Zero; field_0x1C = mVec3_c::Zero; mCcMove = mVec3_c::Zero; } static const u32 l_ranks[3] = {75, 90, 100}; int cCcD_Stts::GetWeight(int inRank) const { // Current Rank is highest and in is lowest // - No effect if (mRank == 13 || inRank == 0) { return 0; } // Current Rank is lowest and in is highest // - Fill effect if (mRank == 0 || inRank == 13) { return 100; } if (mRank == inRank) { return 50; } if (mRank == 12 || inRank == 1) { return 0; } if (mRank == 1 || inRank == 12) { return 100; } if (inRank != 12) { int diff = inRank - mRank; int idx; if (diff > 0) { idx = 3; if (diff <= 3) { idx = diff; } return l_ranks[idx - 1]; } else { idx = 3; if (-diff <= 3) { idx = -diff; } return 100 - l_ranks[idx - 1]; } } // Shouldnt reach here... return mRank; } cCcD_GAtTgCoCommonBase::cCcD_GAtTgCoCommonBase() : mHit_cb(nullptr), mEffCounter(0), mAc(), mRPrm(0) {} cCcD_GAtTgCoCommonBase::~cCcD_GAtTgCoCommonBase() { ClrActorInfo(); mRPrm = 0; ClrActorInfo(); SubtractEffCounter(); mHit_cb = nullptr; } void cCcD_GAtTgCoCommonBase::ClrActorInfo() { mAc.unlink(); } void cCcD_GAtTgCoCommonBase::SetHitActor(dAcObjBase_c *pActor) { mRPrm |= 1; mAc.link(pActor); } dAcObjBase_c *cCcD_GAtTgCoCommonBase::GetActor() { return mAc.get(); } void cCcD_GAtTgCoCommonBase::SubtractEffCounter() { if (mEffCounter <= 0) { return; } mEffCounter--; } /////////////////////////////////////////////////////////////////////////////// // Collision Object /////////////////////////////////////////////////////////////////////////////// cCcD_Obj::cCcD_Obj() : mStts(0), field_0x108(0) {} cCcD_Obj::~cCcD_Obj() { mStts = 0; } bool cCcD_Obj::fn_80328ad0(dAcObjBase_c *pObj, u32 attype) { bool ret = false; if (pObj && pObj->isActorPlayer() && attype == 2) { ret = true; } return ret; } void cCcD_Obj::ClrSet() { mAt.mSrc.mSPrm &= ~1; mTg.mSrc.mSPrm &= ~1; mCo.mSrc.mSPrm &= ~1; } void cCcD_Obj::Set(const cCcD_SrcGObj &src) { mAt.Set(src.mObjAt); mTg.Set(src.mObjTg); mCo.Set(src.mObjCo); } void cCcD_Obj::ClrAtHit() { mAt.mRPrm = 0; mAt.ClrActorInfo(); mAt.SubtractEffCounter(); mAt.ClrEffCounter(); } void cCcD_Obj::ClrTgHit() { mTg.mRPrm = 0; mTg.ClrActorInfo(); mTg.SubtractEffCounter(); mTg.ClrEffCounter(); } void cCcD_Obj::ClrCoHit() { mCo.mRPrm = 0; mCo.ClrActorInfo(); mCo.SubtractEffCounter(); mCo.ClrEffCounter(); } const mVec3_c &cCcD_Obj::GetAtHitPos() const { return mAt.mHitPos; } mVec3_c &cCcD_Obj::GetAtHitPos() { return mAt.mHitPos; } bool cCcD_Obj::GetAtFlag0x2() const { return mAt.MskRPrm(2); } bool cCcD_Obj::GetAtFlag0x4() const { return mAt.MskRPrm(4); } bool cCcD_Obj::GetAtFlag0x8() const { return mAt.MskRPrm(8); } const mVec3_c &cCcD_Obj::GetTgHitPos() const { return mTg.mHitPos; } mVec3_c &cCcD_Obj::GetTgHitPos() { return mTg.mHitPos; } bool cCcD_Obj::GetTgFlag0x4() const { return mTg.MskRPrm(4); } bool cCcD_Obj::GetTgFlag0x8() const { return mTg.MskRPrm(0x8); } cCcD_ObjInf *cCcD_Obj::GetGObjInfo() { return (cCcD_ObjInf *)this; } bool cCcD_Obj::ChkAtClawshot() const { return mAt.MskTgHitSPrm(0x80000); } bool cCcD_Obj::ChkAtClawshotDebug() const { return false; } bool cCcD_Obj::ChkAtElectrified() const { return mAt.MskTgHitSPrm(0x40000); } bool cCcD_Obj::ChkAtElectrifiedExtra() const { return mAt.MskTgHitSPrm(0x8000000); } bool cCcD_Obj::ChkAtWhippable() const { return mAt.MskTgHitSPrm(0x800000); } bool cCcD_Obj::ChkAtBit24() const { return mAt.MskTgHitSPrm(0x1000000); } bool cCcD_Obj::ChkAtArrowStick() const { return mAt.MskTgHitSPrm(0x2000000); } bool cCcD_Obj::ChkAtWaterScaleBonk() const { return mAt.MskTgHitSPrm(0x4000000); } bool cCcD_Obj::ChkAtSwordBonk() const { return mAt.MskTgHitSPrm(0x10000); } dAcObjBase_c *cCcD_Obj::GetAtActor() { return mAt.GetActor(); } bool cCcD_Obj::ChkTgAtHitType(u32 mask) const { return mTg.mAtHitSrc.mType & mask; } u32 cCcD_Obj::GetTgAtHitType() const { return mTg.mAtHitSrc.mType; } bool cCcD_Obj::ChkTgBit14() const { return mTg.MskAtHitSPrm(0x4000); } u8 cCcD_Obj::GetTgDamage() const { return mTg.mAtHitSrc.mDamage; } u16 cCcD_Obj::GetTgDamageFlags() const { return mTg.mAtHitSrc.mInfo.mModifier; } bool cCcD_Obj::ChkTgSkywardStrike() const { return mTg.MskAtHitSPrm(0x10000); } bool cCcD_Obj::ChkTgBit17() const { return mTg.MskAtHitSPrm(0x20000); } bool cCcD_Obj::ChkTgBit18() const { return mTg.MskAtHitSPrm(0x40000); } bool cCcD_Obj::ChkTgBit19() const { return mTg.MskAtHitSPrm(0x80000); } bool cCcD_Obj::ChkTgBit23() const { return mTg.MskAtHitSPrm(0x800000); } bool cCcD_Obj::ChkTgBit20() const { return mTg.MskAtHitSPrm(0x100000); } bool cCcD_Obj::ChkTgBit24() const { return mTg.MskAtHitSPrm(0x1000000); } bool cCcD_Obj::ChkTgBit25() const { return mTg.MskAtHitSPrm(0x2000000); } u16 cCcD_Obj::GetTgSoundID() const { return mTg.mAtHitSrc.field_0x10; } s16 cCcD_Obj::GetTg_0x6A() const { return mTg.mAtHitSrc.field_0x12; } bool cCcD_Obj::ChkTgBit8() const { return mTg.MskAtHitSPrm(0x100); } u8 cCcD_Obj::GetTg_0x4A() const { return mTg.field_0x4A; } dAcObjBase_c *cCcD_Obj::GetTgActor() { return mTg.GetActor(); } const mVec3_c &cCcD_Obj::GetTgAtHitDir() const { return mTg.mAtHitDir; } dAcObjBase_c *cCcD_Obj::GetCoActor() { return mCo.GetActor(); } bool cCcD_Obj::ChkCoBit4() const { return mCo.mCoHitSrc.mSPrm >> 4 & 1; } void cCcD_Obj::SetAtFlagsUpper(u32 flags) { mAt.OffSPrm(0x3FF0000); mAt.OnSPrm(flags); } bool cCcD_Obj::ChkTgBit1() const { return mTg.MskRPrm(2); } void cCcD_Obj::AdjustHitPos(f32 x, f32 z) { mAt.AdjustHitPos(x, z); mTg.AdjustHitPos(x, z); mCo.AdjustHitPos(x, z); } /////////////////////////////////////////////////////////////////////////////// // Base Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_ShapeAttr::cCcD_ShapeAttr() {} cCcD_ShapeAttr::~cCcD_ShapeAttr() {} bool cCcD_ShapeAttr::Calc(const mVec3_c &, const mVec3_c &, mVec3_c *pOut) { return false; } void cCcD_ShapeAttr::GetShapeAccess(cCcD_ShapeAttr::Shape *pShape) const { pShape->field_0x00 = 4; pShape->field_0x04 = mVec3_c::Zero; pShape->field_0x10 = mVec3_c::Zero; pShape->field_0x1C = mVec3_c::Zero; } bool cCcD_ShapeAttr::GetPosBool(mVec3_c *pOut) const { return false; } bool cCcD_ShapeAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return false; } bool cCcD_ShapeAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return false; } mVec3_c &cCcD_ShapeAttr::GetCoP() { return sVirtualCenter; } /////////////////////////////////////////////////////////////////////////////// // Triangle Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_TriAttr::cCcD_TriAttr() {} cCcD_TriAttr::~cCcD_TriAttr() {} bool cCcD_TriAttr::Calc(const mVec3_c &start, const mVec3_c &end, mVec3_c *pOut) { bool bVar1 = false; mVec3_c tmp0, tmp1; if (!CrossInfLin(start, end, *pOut)) { bVar1 = true; } else { mVec3_c a = GetPntA() - *pOut; mVec3_c b = GetPntB() - *pOut; mVec3_c c = GetPntC() - *pOut; mVec3_c a_x_b = a.cross(b); mVec3_c b_x_c = b.cross(c); mVec3_c c_x_a = c.cross(a); f32 dot0 = a_x_b.dot(b_x_c); f32 dot1 = b_x_c.dot(c_x_a); f32 dot2 = c_x_a.dot(a_x_b); if (!(dot0 > 0.0f && dot1 > 0.0f && dot2 > 0.0f)) { if (dot0 <= 0.f && dot1 <= 0.0f && dot2 <= 0.0f) { bVar1 = true; } else if (dot0 > 0.0f) { tmp0 = GetPntA(); tmp1 = GetPntC(); } else if (dot1 > 0.0f) { tmp0 = GetPntA(); tmp1 = GetPntB(); } else { tmp0 = GetPntC(); tmp1 = GetPntB(); } mVec3_c tmp2 = tmp1 - tmp0; f32 mag = tmp2.squaredLength(); if (cM::isZero(mag)) { bVar1 = true; } else { mag = tmp2.dot(*pOut - tmp0) / mag; f32 scale = mag < 0.0f ? 0.0f : mag > 1.0f ? 1.0f : mag; tmp2 *= scale; *pOut = tmp0 + tmp2; } } } if (bVar1) { *pOut = (GetPntA() + GetPntB() + GetPntC()) * (1.f / 3.f); } } bool cCcD_TriAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return shapeAttr.CrossAtTg(*this, pOut); } bool cCcD_TriAttr::CrossAtTg(cCcD_CpsAttr &cpsAttr, mVec3_c *pOut) { return cM3d_Cross_CpsTri(cpsAttr, *this, pOut); } bool cCcD_TriAttr::CrossAtTg(cCcD_CylAttr &cylAttr, mVec3_c *pOut) { return cM3d_Cross_CylTri(cylAttr, *this, pOut); } bool cCcD_TriAttr::CrossAtTg(cCcD_SphAttr &sphAttr, mVec3_c *pOut) { return cM3d_Cross_SphTri(sphAttr, *this, pOut, nullptr, nullptr); } bool cCcD_TriAttr::CrossAtTg(cCcD_TriAttr &triAttr, mVec3_c *pOut) { return cM3d_Cross_TriTri(*this, triAttr, pOut); } bool cCcD_TriAttr::CrossAtTg(cCcD_UnkAttr &unkAttr, mVec3_c *pOut) { return cM3d_Cross_UnkTri(unkAttr, *this, pOut); } bool cCcD_TriAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return shapeAttr.CrossCo(*this, pOut); } bool cCcD_TriAttr::CrossCo(cCcD_CpsAttr &cpsAttr, f32 *pOut) { return false; } bool cCcD_TriAttr::CrossCo(cCcD_TriAttr &triAttr, f32 *pOut) { return false; } bool cCcD_TriAttr::CrossCo(cCcD_UnkAttr &unkAttr, f32 *pOut) { return false; } bool cCcD_TriAttr::CrossCo(cCcD_CylAttr &cylAttr, f32 *pOut) { return false; } bool cCcD_TriAttr::CrossCo(cCcD_SphAttr &sphAttr, f32 *pOut) { return false; } void cCcD_TriAttr::CalcAabBox() { mVec3_c a, b, c; mAab.ClearForMinMax(); a = GetPntA(); mAab.SetMinMax(a); b = GetPntB(); mAab.SetMinMax(b); c = GetPntC(); mAab.SetMinMax(c); } bool cCcD_TriAttr::GetNVec(const mVec3_c &pnt, mVec3_c *pOut) const { if (getPlaneFunc(pnt) >= 0.f) { *pOut = GetN(); } else { *pOut = GetN(); PSVECScale(*pOut, *pOut, -1.0f); } return true; } void cCcD_TriAttr::GetShapeAccess(cCcD_ShapeAttr::Shape *pShape) const { pShape->field_0x00 = SHAPE_TRIANGLE; pShape->field_0x04 = GetPntA(); pShape->field_0x10 = GetPntB(); pShape->field_0x1C = GetPntC(); } void cCcD_TriAttr::GetPos(nw4r::math::VEC3 *pOut) const { *pOut = GetPntA(); } void cCcD_TriAttr::TranslateXZ(f32 x, f32 z) { mA.x += x; mA.z += z; mB.x += x; mB.z += z; mC.x += x; mC.z += z; } /////////////////////////////////////////////////////////////////////////////// // Unk Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_UnkAttr::cCcD_UnkAttr() {} cCcD_UnkAttr::~cCcD_UnkAttr() {} bool cCcD_UnkAttr::Calc(const mVec3_c &start, const mVec3_c &end, mVec3_c *pOut) { mVec3_c tmp0, tmp1; const mMtx_c &inv = mInvMtx; PSMTXMultVec(inv, start, tmp0); PSMTXMultVec(inv, end, tmp1); for (int i = 0; i < 3; i++) { bool tmp0Min = tmp0(i) < mMin(i); bool tmp0Max = tmp0(i) > mMax(i); bool tmp1Min = tmp1(i) < mMin(i); bool tmp1Max = tmp1(i) > mMax(i); if (tmp0Min) { if (tmp1Max) { f32 t = (tmp0(i) + tmp1(i)) * 0.5f; (*pOut)(i) = t < mMin(i) ? mMin(i) : t > mMax(i) ? mMax(i) : t; } else { (*pOut)(i) = mMin(i); } } else if (tmp0Max) { if (tmp1Min) { f32 t = (tmp0(i) + tmp1(i)) * 0.5f; (*pOut)(i) = t < mMin(i) ? mMin(i) : t > mMax(i) ? mMax(i) : t; } else { (*pOut)(i) = mMax(i); } } else if (tmp1Min) { (*pOut)(i) = mMin(i); } else if (tmp1Max) { (*pOut)(i) = mMax(i); } else { (*pOut)(i) = (tmp0(i) + tmp1(i)) * 0.5f; } } PSMTXMultVec(mMtx, *pOut, *pOut); return true; } bool cCcD_UnkAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return shapeAttr.CrossAtTg(*this, pOut); } bool cCcD_UnkAttr::CrossAtTg(cCcD_CpsAttr &cpsAttr, mVec3_c *pOut) { return Cross(cpsAttr, pOut); } bool cCcD_UnkAttr::CrossAtTg(cCcD_TriAttr &triAttr, mVec3_c *pOut) { return Cross(triAttr, pOut); } bool cCcD_UnkAttr::CrossAtTg(cCcD_UnkAttr &unkAttr, mVec3_c *pOut) { return Cross(unkAttr, pOut); } bool cCcD_UnkAttr::CrossAtTg(cCcD_CylAttr &cylAttr, mVec3_c *pOut) { return Cross(cylAttr, pOut); } bool cCcD_UnkAttr::CrossAtTg(cCcD_SphAttr &sphAttr, mVec3_c *pOut) { return Cross(sphAttr, pOut); } bool cCcD_UnkAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return shapeAttr.CrossCo(*this, pOut); } bool cCcD_UnkAttr::CrossCo(cCcD_CpsAttr &cpsAttr, f32 *pOut) { mVec3_c pos; if (cM3dGUnk::Cross(cpsAttr, &pos)) { cpsAttr.SetVirtCenter(&pos); *pOut = cpsAttr.CrossCoCommon(*this, field_0xC4); field_0xC4 = 0.0f; } return false; } bool cCcD_UnkAttr::CrossCo(cCcD_TriAttr &triAttr, f32 *pOut) { return false; } bool cCcD_UnkAttr::CrossCo(cCcD_UnkAttr &unkAttr, f32 *pOut) { return false; } bool cCcD_UnkAttr::CrossCo(cCcD_CylAttr &cylAttr, f32 *pOut) { return cM3dGUnk::Cross(cylAttr, pOut); } bool cCcD_UnkAttr::CrossCo(cCcD_SphAttr &sphAttr, f32 *pOut) { return cM3dGUnk::Cross(sphAttr, pOut); } void cCcD_UnkAttr::CalcAabBox() { mAab.ClearForMinMax(); mVec3_c start, end; GetStartEnd(start, end); mMtx_c &mtx = mMtx; mVec3_c a; a = start; PSMTXMultVec(mtx, a, a); mAab.SetMinMax(a); a = end; PSMTXMultVec(mtx, a, a); mAab.SetMinMax(a); a.x = start.x; a.y = start.y; a.z = end.z; PSMTXMultVec(mtx, a, a); mAab.SetMinMax(a); a.x = end.x; a.y = end.y; a.z = start.z; PSMTXMultVec(mtx, a, a); mAab.SetMinMax(a); } bool cCcD_UnkAttr::GetNVec(const mVec3_c &, mVec3_c *pOut) const { pOut->set(0.f, 0.f, 0.f); return false; } void cCcD_UnkAttr::GetPos(nw4r::math::VEC3 *pPos) const { *pPos = mLin.GetStart(); } void cCcD_UnkAttr::Set(const cCcD_SrcUnkAttr &src) { mVec3_c min = src.getMin(); mVec3_c max = src.getMax(); cM3dGUnk::Set(min, max); } mVec3_c &cCcD_UnkAttr::GetCoP() { return mVirtCenter; } void cCcD_UnkAttr::TranslateXZ(f32 x, f32 z) { cM3dGUnk::fn_80338f30(x, z); } /////////////////////////////////////////////////////////////////////////////// // Capsule Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_CpsAttr::cCcD_CpsAttr() {} cCcD_CpsAttr::~cCcD_CpsAttr() {} void cCcD_CpsAttr::Set(const cCcD_SrcCpsAttr &src) { cM3dGCps::SetR(src.mRadius); // I dont like this nw4r::math::VEC3 a; a.z = 0.0f; a.y = 0.0f; a.x = 0.0f; GetEnd() = GetStart() = a; } mVec3_c &cCcD_CpsAttr::GetCoP() { return mVirtCenter; } bool cCcD_CpsAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return shapeAttr.CrossAtTg(*this, pOut); } bool cCcD_CpsAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return shapeAttr.CrossCo(*this, pOut); } bool cCcD_CpsAttr::CrossCo(cCcD_TriAttr &triAttr, f32 *pOut) { return false; } void CalcCyl(const cM3dGCyl &cyl, const mVec3_c &start, const mVec3_c &end, mVec3_c *pOut) { cM3dGLin lin; mVec3_c pos; lin.Set(start, end); f32 radius = cyl.GetR(); f32 height = cyl.GetC().y + cyl.GetH(); if (cM3d_Cross_CylLin(cyl, lin, *pOut, pos)) { return; } if (height < start.y && height < end.y) { pOut->y = height; } else if (cyl.GetC().y > start.y && cyl.GetC().y > end.y) { pOut->y = cyl.GetC().y; } else { bool startValid = sLib::isInRange(start.y, cyl.GetC().y, height); bool endValid = sLib::isInRange(end.y, cyl.GetC().y, height); if (startValid && endValid) { pOut->y = (start.y + end.y) * 0.5f; } else if (startValid) { pOut->y = start.y; } else { pOut->y = end.y; } } mVec3_c start_center = start - cyl.GetC(); f32 start_dist = EGG::Math::sqrt(start_center.x * start_center.x + start_center.z * start_center.z); mVec3_c end_center = end - cyl.GetC(); f32 end_dist = EGG::Math::sqrt(end_center.x * end_center.x + end_center.z * end_center.z); if (start_dist < radius) { if (end_dist < radius) { pOut->x = (start.x + end.x) * 0.5f; pOut->z = (start.z + end.z) * 0.5f; } else { pOut->x = start.x; pOut->z = start.z; } } else if (end_dist < radius) { pOut->x = end.x; pOut->z = end.z; } else if (start_dist < end_dist) { start_center.normalize(); start_center *= radius; pOut->x = start_center.x + cyl.GetC().x; pOut->z = start_center.z + cyl.GetC().z; } else { end_center.normalize(); end_center *= radius; pOut->x = end_center.x + cyl.GetC().x; pOut->z = end_center.z + cyl.GetC().z; } } bool cCcD_CpsAttr::Calc(const mVec3_c &start, const mVec3_c &end, mVec3_c *pOut) { const mVec3_c &startRef = GetStart(); const mVec3_c &endRef = GetEnd(); mMtx_c mtx0; mVec3_c tmp0 = GetEnd() - GetStart(); mVec3_c tmp1; mVec3_c tmp2; mVec3_c tmp3; mVec3_c tmp4; cM3dGCyl cyl; bool bInverse; f32 dist = EGG::Math::sqrt(tmp0.x * tmp0.x + tmp0.z * tmp0.z); if (cM::isZero(dist)) { tmp1 = start; tmp2 = end; if (endRef.y > startRef.y) { tmp3 = startRef; tmp4 = endRef; } else { tmp3 = endRef; tmp4 = startRef; } bInverse = false; } else { PSMTXTrans(mtx0, startRef.x, startRef.y, startRef.z); mtx0.XrotM(mAng::atan2s(-dist, tmp0.y)); mtx0.YrotM(mAng::atan2s(-tmp0.x, tmp0.z)); mMtx_c mtx1; MtxTransMinusXYZ(mtx1, startRef.x, startRef.y, startRef.z); PSMTXConcat(mtx0, mtx1, mtx0); PSMTXMultVec(mtx0, start, tmp1); PSMTXMultVec(mtx0, end, tmp2); tmp3 = GetStart(); PSMTXMultVec(mtx0, GetEnd(), tmp4); bInverse = true; } tmp3.y -= GetR() * 0.5f; tmp4.y += GetR() * 0.5f; cyl.SetC(tmp3, GetR(), tmp4.y - tmp3.y); CalcCyl(cyl, tmp1, tmp2, pOut); if (bInverse) { PSMTXInverse(mtx0, mtx0); PSMTXMultVec(mtx0, *pOut, *pOut); } return true; } bool cCcD_CpsAttr::CrossAtTg(cCcD_CpsAttr &cpsAttr, mVec3_c *pOut) { return cM3d_Cross_CpsCps(*this, cpsAttr, pOut, nullptr, nullptr); } bool cCcD_CpsAttr::CrossAtTg(cCcD_CylAttr &cylAttr, mVec3_c *pOut) { return cM3d_Cross_CpsCyl(*this, cylAttr, pOut); } bool cCcD_CpsAttr::CrossAtTg(cCcD_SphAttr &sphAttr, mVec3_c *pOut) { return cM3d_Cross_CpsSph(*this, sphAttr, pOut); } bool cCcD_CpsAttr::CrossAtTg(cCcD_TriAttr &triAttr, mVec3_c *pOut) { return cM3d_Cross_CpsTri(*this, triAttr, pOut); } bool cCcD_CpsAttr::CrossAtTg(cCcD_UnkAttr &unkAttr, mVec3_c *pOut) { return cM3dGCps::Cross(unkAttr, pOut); } void cCcD_CpsAttr::SetVirtCenter(mVec3_c *pOut) { if (field_0x20) { mVirtCenter = *pOut; field_0x20 = 0; } else { f32 dist = cM3d_lineVsPosSuisenCross(*this, *pOut, &mVirtCenter); if (dist < 0.f) { mVirtCenter = GetStart(); } else if (dist > 1.f) { mVirtCenter = GetEnd(); } } } f32 cCcD_CpsAttr::CrossCoCommon(cCcD_ShapeAttr &attr, f32 r) { mVec3_c tmp = mVirtCenter - attr.GetCoP(); f32 mag = (r + field_0x1C) - EGG::Math::sqrt(tmp.x * tmp.x + tmp.z * tmp.z); if (mag < 0.0f) { mag = 0.0f; } Set_0x1C(mRadius); return mag; } bool cCcD_CpsAttr::CrossCo(cCcD_CpsAttr &cpsAttr, f32 *pOut) { mVec3_c pos; if (cM3d_Cross_CpsCps(*this, cpsAttr, &pos, nullptr, nullptr)) { SetVirtCenter(&pos); cpsAttr.SetVirtCenter(&pos); *pOut = CrossCoCommon(cpsAttr, cpsAttr.field_0x1C); cpsAttr.Set_0x1C(cpsAttr.GetR()); return true; } return false; } bool cCcD_CpsAttr::CrossCo(cCcD_CylAttr &cylAttr, f32 *pOut) { mVec3_c pos; if (cM3d_Cross_CpsCyl(*this, cylAttr, &pos)) { SetVirtCenter(&pos); *pOut = CrossCoCommon(cylAttr, cylAttr.GetR()); return true; } return false; } bool cCcD_CpsAttr::CrossCo(cCcD_SphAttr &sphAttr, f32 *pOut) { mVec3_c pos; if (cM3d_Cross_CpsSph(*this, sphAttr, &pos)) { SetVirtCenter(&pos); *pOut = CrossCoCommon(sphAttr, sphAttr.GetYDist(pos.y)); return true; } return false; } bool cCcD_CpsAttr::CrossCo(cCcD_UnkAttr &unkAttr, f32 *pOut) { mVec3_c pos; if (cM3dGCps::Cross(unkAttr, &pos)) { SetVirtCenter(&pos); *pOut = CrossCoCommon(unkAttr, unkAttr.field_0xC4); unkAttr.field_0xC4 = 0.0f; return true; } return false; } void cCcD_CpsAttr::CalcAabBox() { mAab.ClearForMinMax(); mAab.SetMinMax(GetStart()); mAab.SetMinMax(GetEnd()); mAab.PlusR(GetR()); } bool cCcD_CpsAttr::GetNVec(const mVec3_c ¶m0, mVec3_c *pOut) const { mVec3_c tmp1; PSVECSubtract(GetEnd(), GetStart(), tmp1); f32 sqMag = PSVECDotProduct(tmp1, tmp1); if (cM3d_IsZero(sqMag)) { return false; } mVec3_c tmp2; PSVECSubtract(param0, GetStart(), tmp2); f32 sqDist = PSVECDotProduct(tmp2, tmp1) / sqMag; mVec3_c tmp3; if (sqDist < 0.f) { tmp3 = GetStart(); } else if (sqDist > 1.f) { tmp3 = GetEnd(); } else { PSVECScale(tmp1, tmp1, sqDist); PSVECAdd(tmp1, GetStart(), tmp3); } PSVECSubtract(param0, tmp3, *pOut); if (cM3d_IsZero(PSVECMag(*pOut))) { pOut->set(0.f, 0.f, 0.f); return false; } else { PSVECNormalize(*pOut, *pOut); return true; } } void cCcD_CpsAttr::GetPos(nw4r::math::VEC3 *pOut) const { *pOut = GetStart(); } void cCcD_CpsAttr::GetShapeAccess(cCcD_ShapeAttr::Shape *pShape) const { pShape->field_0x00 = SHAPE_CAPSULE; pShape->field_0x04 = GetStart(); pShape->field_0x10 = GetEnd(); pShape->field_0x1C.set(GetR(), 0.f, 0.f); } void cCcD_CpsAttr::TranslateXZ(f32 x, f32 z) { GetStart().x += x; GetStart().z += z; GetEnd().x += x; GetEnd().z += z; } /////////////////////////////////////////////////////////////////////////////// // Cylinder Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_CylAttr::cCcD_CylAttr() {} cCcD_CylAttr::~cCcD_CylAttr() {} void cCcD_CylAttr::Set(const cCcD_SrcCylAttr &src) { SetR(src.mRadius); SetH(src.mHeight); mVec3_c a; a.z = 0.0f; a.y = 0.0f; a.x = 0.0f; SetC(a); } mVec3_c &cCcD_CylAttr::GetCoP() { return mCenter; } bool cCcD_CylAttr::Calc(const mVec3_c ¶m0, const mVec3_c ¶m1, mVec3_c *pOut) { CalcCyl(*this, param0, param1, pOut); return true; } bool cCcD_CylAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return shapeAttr.CrossAtTg(*this, pOut); } bool cCcD_CylAttr::CrossAtTg(cCcD_CpsAttr &cpsAttr, mVec3_c *pOut) { return cM3d_Cross_CpsCyl(cpsAttr, *this, pOut); } bool cCcD_CylAttr::CrossAtTg(cCcD_CylAttr &cylAttr, mVec3_c *pOut) { return cM3d_Cross_CylCyl(*this, cylAttr, pOut); } bool cCcD_CylAttr::CrossAtTg(cCcD_SphAttr &sphAttr, mVec3_c *pOut) { f32 f; return cM3d_Cross_CylSph(*this, sphAttr, pOut, &f); } bool cCcD_CylAttr::CrossAtTg(cCcD_TriAttr &triAttr, mVec3_c *pOut) { return cM3d_Cross_CylTri(*this, triAttr, pOut); } bool cCcD_CylAttr::CrossAtTg(cCcD_UnkAttr &unkAttr, mVec3_c *pOut) { return cM3dGCyl::Cross(unkAttr, pOut); } bool cCcD_CylAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return shapeAttr.CrossCo(*this, pOut); } bool cCcD_CylAttr::CrossCo(cCcD_TriAttr &triAttr, f32 *pOut) { return false; } bool cCcD_CylAttr::CrossCo(cCcD_CylAttr &cylAttr, f32 *pOut) { return cM3d_Cross_CylCyl(*this, cylAttr, pOut); } bool cCcD_CylAttr::CrossCo(cCcD_SphAttr &sphAttr, f32 *pOut) { return cM3d_Cross_CylSph(*this, sphAttr, pOut); } bool cCcD_CylAttr::CrossCo(cCcD_CpsAttr &cpsAttr, f32 *pOut) { mVec3_c pos; if (cM3d_Cross_CpsCyl(cpsAttr, *this, &pos)) { cpsAttr.SetVirtCenter(&pos); *pOut = cpsAttr.CrossCoCommon(*this, GetR()); return true; } return false; } bool cCcD_CylAttr::CrossCo(cCcD_UnkAttr &unkAttr, f32 *pOut) { return cM3dGCyl::Cross(unkAttr, pOut); } void cCcD_CylAttr::CalcAabBox() { mVec3_c max; mVec3_c min; min.x = GetC().x - GetR(); min.y = GetC().y; min.z = GetC().z - GetR(); max.x = GetC().x + GetR(); max.y = GetC().y + GetH(); max.z = GetC().z + GetR(); mAab.Set(min, max); } bool cCcD_CylAttr::GetNVec(const mVec3_c ¶m0, mVec3_c *pOut) const { mVec3_c vec; if (GetC().y > param0.y) { vec = GetC(); } else if (GetC().y + GetH() < param0.y) { vec = GetC(); vec.y = GetC().y + GetH(); } else { vec = GetC(); vec.y = param0.y; } PSVECSubtract(param0, vec, *pOut); if (cM3d_IsZero(PSVECMag(*pOut))) { pOut->set(0.f, 0.f, 0.f); return false; } else { PSVECNormalize(*pOut, *pOut); return true; } } void cCcD_CylAttr::GetShapeAccess(cCcD_ShapeAttr::Shape *pShape) const { pShape->field_0x00 = SHAPE_CYLINDER; pShape->field_0x04 = GetC(); pShape->field_0x10 = mVec3_c::Zero; pShape->field_0x1C.set(GetR(), GetH(), 0.f); } void cCcD_CylAttr::GetPos(nw4r::math::VEC3 *pOut) const { *pOut = GetC(); } void cCcD_CylAttr::TranslateXZ(f32 x, f32 z) { GetC().x += x; GetC().z += z; } /////////////////////////////////////////////////////////////////////////////// // Sphere Shape Attribute /////////////////////////////////////////////////////////////////////////////// cCcD_SphAttr::cCcD_SphAttr() {} cCcD_SphAttr::~cCcD_SphAttr() {} void cCcD_SphAttr::Set(const cCcD_SrcSphAttr &src) { SetR(src.mRadius); mVec3_c a; a.z = 0.0f; a.y = 0.0f; a.x = 0.0f; SetC(a); } mVec3_c &cCcD_SphAttr::GetCoP() { return mCenter; } bool cCcD_SphAttr::Calc(const mVec3_c ¶m0, const mVec3_c ¶m1, mVec3_c *pOut) { cM3dGLin lin; mVec3_c vec; lin.Set(param0, param1); if (!cM3d_Cross_LinSph_CrossPos(*this, lin, pOut, &vec)) { mVec3_c a = (param0 + param1) * 0.5f; f32 f; cM3d_Len3dSqPntAndSegLine(lin, GetC(), &a, &f, nullptr); a -= GetC(); a.normalize(); f32 radius = GetR(); *pOut = GetC() + a * radius; } return true; } bool cCcD_SphAttr::CrossAtTg(cCcD_ShapeAttr &shapeAttr, mVec3_c *pOut) { return shapeAttr.CrossAtTg(*this, pOut); } bool cCcD_SphAttr::CrossAtTg(cCcD_CpsAttr &cpsAttr, mVec3_c *pOut) { return cM3d_Cross_CpsSph(cpsAttr, *this, pOut); } bool cCcD_SphAttr::CrossAtTg(cCcD_CylAttr &cylAttr, mVec3_c *pOut) { f32 f; return cM3d_Cross_CylSph(cylAttr, *this, pOut, &f); } bool cCcD_SphAttr::CrossAtTg(cCcD_SphAttr &sphAttr, mVec3_c *pOut) { return cM3d_Cross_SphSph(sphAttr, *this, pOut); } bool cCcD_SphAttr::CrossAtTg(cCcD_TriAttr &triAttr, mVec3_c *pOut) { return cM3d_Cross_SphTri(*this, triAttr, pOut, nullptr, nullptr); } bool cCcD_SphAttr::CrossAtTg(cCcD_UnkAttr &unkAttr, mVec3_c *pOut) { return cM3dGSph::Cross(unkAttr, pOut); } bool cCcD_SphAttr::CrossCo(cCcD_ShapeAttr &shapeAttr, f32 *pOut) { return shapeAttr.CrossCo(*this, pOut); } bool cCcD_SphAttr::CrossCo(cCcD_TriAttr &triAttr, f32 *pOut) { return false; } bool cCcD_SphAttr::CrossCo(cCcD_CylAttr &cylAttr, f32 *pOut) { return cM3d_Cross_CylSph(cylAttr, *this, pOut); } bool cCcD_SphAttr::CrossCo(cCcD_SphAttr &sphAttr, f32 *pOut) { return cM3d_Cross_SphSph(*this, sphAttr, pOut); } bool cCcD_SphAttr::CrossCo(cCcD_CpsAttr &cpsAttr, f32 *pOut) { mVec3_c pos; if (cM3d_Cross_CpsSph(cpsAttr, *this, &pos)) { cpsAttr.SetVirtCenter(&pos); *pOut = cpsAttr.CrossCoCommon(*this, cM3dGSph::GetYDist(pos.y)); return true; } return false; } bool cCcD_SphAttr::CrossCo(cCcD_UnkAttr &unkAttr, f32 *pOut) { return cM3dGSph::Cross(unkAttr, pOut); } void cCcD_SphAttr::CalcAabBox() { mAab.Set(*this); } bool cCcD_SphAttr::GetNVec(const mVec3_c ¶m0, mVec3_c *param1) const { param1->x = param0.x - GetC().x; param1->y = param0.y - GetC().y; param1->z = param0.z - GetC().z; if (cM3d_IsZero(PSVECMag(*param1))) { param1->set(0.0f, 0.0f, 0.0f); return false; } else { PSVECNormalize(*param1, *param1); return true; } } void cCcD_SphAttr::GetShapeAccess(cCcD_ShapeAttr::Shape *pShape) const { pShape->field_0x00 = SHAPE_SPHERE; pShape->field_0x04 = GetC(); pShape->field_0x10 = mVec3_c::Zero; pShape->field_0x1C.set(GetR(), 0.0f, 0.0f); } void cCcD_SphAttr::GetPos(nw4r::math::VEC3 *pPos) const { *pPos = GetC(); } bool cCcD_SphAttr::GetPosBool(mVec3_c *pPos) const { *pPos = GetC(); return true; } void cCcD_SphAttr::TranslateXZ(f32 x, f32 z) { GetC().x += x; GetC().z += z; } /////////////////////////////////////////////////////////////////////////////// // Attack/Defense/Collide Object Info /////////////////////////////////////////////////////////////////////////////// cCcD_ObjAt::cCcD_ObjAt() { field_0x58 = 0; } cCcD_ObjAt::~cCcD_ObjAt() {} void cCcD_ObjAt::Set(const cCcD_SrcGObjAt &info) { mEffCounter = 0; mSrc = info; mHitPos = mVec3_c::Zero; } void cCcD_ObjAt::SetAtFlag(u32 flag) { mSrc.mSPrm = mSrc.mSPrm & ~0x3E | flag; } void cCcD_ObjAt::AdjustHitPos(f32 x, f32 z) { mHitPos.x += x; mHitPos.z += z; } cCcD_ObjTg::cCcD_ObjTg() : mShieldFrontRangeYAngle(nullptr), field_0x4A(0), field_0x4B(0), field_0x4C(0), field_0x50(0), field_0x54(0), field_0x6C(0.f, 0.f, 0.f), field_0x78(0) {} cCcD_ObjTg::~cCcD_ObjTg() {} void cCcD_ObjTg::Set(const cCcD_SrcGObjTg &src) { mEffCounter = 0; mSrc = src; field_0x4C = 0; mHitPos = mVec3_c::Zero; mShieldFrontRangeYAngle = nullptr; mShieldRange = 0x4000; } void cCcD_ObjTg::AdjustHitPos(f32 x, f32 z) { mHitPos.x += x; mHitPos.z += z; field_0x6C.x += x; field_0x6C.z += z; } cCcD_ObjCo::cCcD_ObjCo() { mGrp = 0; field_0x28_callback = 0; } cCcD_ObjCo::~cCcD_ObjCo() {} void cCcD_ObjCo::Set(const cCcD_SrcGObjCo &src) { mEffCounter = 0; mSrc = src; SetGrp(mSrc.mSPrm & 0x1e0); } void cCcD_ObjCo::SetGrp(u32 flag) { mSrc.mSPrm = mSrc.mSPrm & ~0x1E0 | flag; mGrp = (mSrc.mSPrm & 0x1E0) >> 4; } void cCcD_ObjCo::AdjustHitPos(f32, f32) {}