mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-05-10 01:09:26 +00:00
267 lines
8.1 KiB
C++
267 lines
8.1 KiB
C++
#include "Library/Area/AreaShapes.h"
|
|
|
|
#include "Library/Math/MathUtil.h"
|
|
|
|
namespace al {
|
|
AreaShapeCube::AreaShapeCube(AreaShapeCube::OriginType originType) : mOriginType(originType) {}
|
|
|
|
bool AreaShapeCube::calcLocalBoundingBox(sead::BoundBox3f* out) const {
|
|
out->setUndef();
|
|
|
|
out->addPoint({-500.0f, calcBottom(), -500.0f});
|
|
out->addPoint({500.0f, calcTop(), 500.0f});
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeCube::isInVolume(const sead::Vector3f& trans) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
|
|
return isInLocalVolume(localPos);
|
|
}
|
|
|
|
bool AreaShapeCube::isInVolumeOffset(const sead::Vector3f& trans, f32 offset) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
|
|
f32 bottom = calcBottom();
|
|
f32 top = calcTop();
|
|
|
|
sead::Vector3f scale = getScale();
|
|
if (isNearZero(scale.x) || isNearZero(scale.y) || isNearZero(scale.z))
|
|
return false;
|
|
|
|
scale.x = offset / scale.x;
|
|
scale.y = offset / scale.y;
|
|
scale.z = offset / scale.z;
|
|
|
|
if (localPos.y < bottom - scale.y || top + scale.y < localPos.y)
|
|
return false;
|
|
|
|
if (localPos.x < -500.0f - scale.x || 500.0f + scale.x < localPos.x)
|
|
return false;
|
|
|
|
if (localPos.z < -500.0f - scale.z || 500.0f + scale.z < localPos.z)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeCube::isInLocalVolume(const sead::Vector3f& trans) const {
|
|
sead::Vector3f min = {-500.0f, calcBottom(), -500.0f};
|
|
sead::Vector3f max = {500.0f, calcTop(), 500.0f};
|
|
|
|
if ((trans.y < min.y || max.y < trans.y) || (trans.x < min.x || max.x < trans.x) ||
|
|
(trans.z < min.z || max.z < trans.z))
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
AreaShapeSphere::AreaShapeSphere() = default;
|
|
|
|
bool AreaShapeSphere::calcLocalBoundingBox(sead::BoundBox3f* out) const {
|
|
out->set({-500.0f, -500.0f, -500.0f}, {500.0f, 500.0f, 500.0f});
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeSphere::isInVolume(const sead::Vector3f& trans) const {
|
|
sead::Vector3f baseTrans;
|
|
calcTrans(&baseTrans);
|
|
sead::Vector3f offsetTrans = trans - baseTrans;
|
|
f32 radius = getScale().x * 500.0f;
|
|
|
|
return offsetTrans.squaredLength() <= sead::Mathf::square(radius);
|
|
}
|
|
|
|
bool AreaShapeSphere::isInVolumeOffset(const sead::Vector3f& trans, f32 offset) const {
|
|
sead::Vector3f baseTrans;
|
|
calcTrans(&baseTrans);
|
|
sead::Vector3f offsetTrans = trans - baseTrans;
|
|
f32 radius = getScale().x * 500.0f + offset;
|
|
|
|
return offsetTrans.squaredLength() <= sead::Mathf::square(radius);
|
|
}
|
|
|
|
bool AreaShapeSphere::calcNearestEdgePoint(sead::Vector3f* out, const sead::Vector3f& trans) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
f32 length = localPos.length();
|
|
|
|
if (length > 0.0f)
|
|
localPos *= 500.0f / length;
|
|
|
|
calcWorldPos(out, localPos);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeSphere::checkArrowCollision(sead::Vector3f* outTrans, sead::Vector3f* outDir,
|
|
const sead::Vector3f& pos1,
|
|
const sead::Vector3f& pos2) const {
|
|
return false;
|
|
}
|
|
|
|
AreaShapeOval::AreaShapeOval() = default;
|
|
|
|
bool AreaShapeOval::isInVolume(const sead::Vector3f& trans) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
|
|
return localPos.squaredLength() <= sead::Mathf::square(500.0f);
|
|
}
|
|
|
|
bool AreaShapeOval::isInVolumeOffset(const sead::Vector3f& trans, f32 offset) const {
|
|
sead::Vector3f scale = getScale();
|
|
|
|
// has to be this way around to match
|
|
if (scale.x == scale.y && scale.y == scale.z) {
|
|
sead::Vector3f baseTrans;
|
|
calcTrans(&baseTrans);
|
|
sead::Vector3f offsetTrans = trans - baseTrans;
|
|
f32 radius = scale.x * 500.0f + offset;
|
|
|
|
return offsetTrans.squaredLength() <= sead::Mathf::square(radius);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AreaShapeOval::calcNearestEdgePoint(sead::Vector3f* out, const sead::Vector3f& trans) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
f32 length = localPos.length();
|
|
|
|
if (length > 0.0f)
|
|
localPos *= 500.0f / length;
|
|
|
|
calcWorldPos(out, localPos);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeOval::checkArrowCollision(sead::Vector3f* outPos, sead::Vector3f* outNormal,
|
|
const sead::Vector3f& pos1,
|
|
const sead::Vector3f& pos2) const {
|
|
sead::Vector3f localPos1 = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos1, pos1);
|
|
sead::Vector3f localPos2 = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos2, pos2);
|
|
|
|
sead::Vector3f worldPos1 = {0, 0, 0};
|
|
sead::Vector3f worldPos2 = {0, 0, 0};
|
|
calcWorldPos(&worldPos1, localPos1);
|
|
calcWorldPos(&worldPos2, localPos2);
|
|
|
|
if (!checkHitSegmentSphere(sead::Vector3f::zero, localPos1, localPos2, 500.0f, outNormal,
|
|
outPos))
|
|
return false;
|
|
|
|
calcWorldPos(outPos, *outPos);
|
|
calcWorldDir(outNormal, *outNormal);
|
|
*outNormal *= -1.0f;
|
|
|
|
return true;
|
|
}
|
|
|
|
AreaShapeCylinder::AreaShapeCylinder(AreaShapeCylinder::OriginType originType)
|
|
: mOriginType(originType) {}
|
|
|
|
bool AreaShapeCylinder::calcLocalBoundingBox(sead::BoundBox3f* out) const {
|
|
out->setUndef();
|
|
|
|
out->addPoint({-500.0f, calcBottom(), -500.0f});
|
|
out->addPoint({500.0f, calcTop(), 500.0f});
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeCylinder::isInVolume(const sead::Vector3f& trans) const {
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
|
|
f32 bottom = calcBottom();
|
|
f32 top = calcTop();
|
|
|
|
if (localPos.y < bottom || top < localPos.y)
|
|
return false;
|
|
|
|
return sead::Mathf::square(localPos.x) + sead::Mathf::square(localPos.z) <=
|
|
sead::Mathf::square(500.0f);
|
|
}
|
|
|
|
bool AreaShapeCylinder::isInVolumeOffset(const sead::Vector3f& trans, f32 offset) const {
|
|
sead::Vector3f scale = getScale();
|
|
if (isNearZero(scale.x) || isNearZero(scale.y) || isNearZero(scale.z))
|
|
return false;
|
|
|
|
scale.y = offset / scale.y;
|
|
|
|
sead::Vector3f localPos = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos, trans);
|
|
|
|
f32 bottom = calcBottom();
|
|
f32 top = calcTop();
|
|
|
|
scale.x = offset / scale.x + 500.0f;
|
|
if (localPos.y < bottom - scale.y || scale.y + top < localPos.y)
|
|
return false;
|
|
|
|
return sead::Mathf::square(localPos.x) + sead::Mathf::square(localPos.z) <=
|
|
sead::Mathf::square(scale.x);
|
|
}
|
|
|
|
bool AreaShapeCylinder::checkArrowCollision(sead::Vector3f* outPos, sead::Vector3f* outNormal,
|
|
const sead::Vector3f& pos1,
|
|
const sead::Vector3f& pos2) const {
|
|
sead::Vector3f localPos1 = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos1, pos1);
|
|
sead::Vector3f localPos2 = sead::Vector3f::zero;
|
|
calcLocalPos(&localPos2, pos2);
|
|
|
|
sead::Vector3f bottomPos = sead::Vector3f::zero;
|
|
bottomPos.y = calcBottom();
|
|
if (!checkHitSegmentCylinder(bottomPos, 500.0f, sead::Vector3f::ey, 500.0f, localPos1,
|
|
localPos2, outPos, outNormal))
|
|
return false;
|
|
|
|
if (outPos)
|
|
calcWorldPos(outPos, *outPos);
|
|
if (outNormal)
|
|
calcWorldDir(outNormal, *outNormal);
|
|
|
|
return true;
|
|
}
|
|
|
|
AreaShapeInfinite::AreaShapeInfinite() = default;
|
|
|
|
bool AreaShapeInfinite::isInVolume(const sead::Vector3f& trans) const {
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeInfinite::isInVolumeOffset(const sead::Vector3f& trans, f32 offset) const {
|
|
return true;
|
|
}
|
|
|
|
bool AreaShapeInfinite::calcNearestEdgePoint(sead::Vector3f* out,
|
|
const sead::Vector3f& trans) const {
|
|
return false;
|
|
}
|
|
|
|
bool AreaShapeInfinite::checkArrowCollision(sead::Vector3f* outPos, sead::Vector3f* outNormal,
|
|
const sead::Vector3f& pos1,
|
|
const sead::Vector3f& pos2) const {
|
|
return false;
|
|
}
|
|
|
|
bool AreaShapeInfinite::calcLocalBoundingBox(sead::BoundBox3f* out) const {
|
|
return false;
|
|
}
|
|
|
|
bool AreaShapeOval::calcLocalBoundingBox(sead::BoundBox3f* out) const {
|
|
return false;
|
|
}
|
|
} // namespace al
|