1#include "Game/Gravity.hpp"
2#include "Game/Util.hpp"
3#include "JSystem/JMath.hpp"
6ParallelGravity::ParallelGravity() :
8 mPlanePosition(0, 0, 0),
9 CALL_INLINE_FUNC(mPlaneUpVec, 0.0f, 1.0f, 0.0f),
10 mWorldPlanePosition(0, 0, 0),
11 CALL_INLINE_FUNC(mWorldPlaneUpVec, 0.0f, 1.0f, 0.0f)
13 mCylinderHeight = 1000.0f;
14 mCylinderRadius = 500.0f;
15 mBaseDistance = 2000.0f;
16 mRangeType = RangeType_Sphere;
17 mDistanceCalcType = DistanceCalcType_Default;
22bool ParallelGravity::calcOwnGravityVector(TVec3f *pDest, f32 *pScalar,
const TVec3f &rPosition)
const {
23 if (!isInRange(rPosition, pScalar)) {
28 *pDest = -mWorldPlaneUpVec;
35void ParallelGravity::updateMtx(
const TPos3f &rMtx) {
36 rMtx.mult33Inline(mPlaneUpVec, mWorldPlaneUpVec);
37 rMtx.mult(mPlanePosition, mWorldPlanePosition);
38 MR::normalizeOrZero(&mWorldPlaneUpVec);
40 if (mRangeType == RangeType_Box) {
41 mWorldMtx.concat(rMtx, mLocalMtx);
44 mWorldMtx.getXDir(tempDir);
45 mExtentX = tempDir.squared();
46 mWorldMtx.getYDir(tempDir);
47 mExtentY = tempDir.squared();
48 mWorldMtx.getZDir(tempDir);
49 mExtentZ = tempDir.squared();
54void ParallelGravity::setPlane(
const TVec3f &rPlaneUp,
const TVec3f &rPlanePos) {
56 mPlaneUpVec.setInline(rPlaneUp);
57 VECMag(
reinterpret_cast<const Vec*
>(&mPlaneUpVec));
58 VECNormalize(
reinterpret_cast<const Vec*
>(&mPlaneUpVec),
reinterpret_cast<Vec*
>(&mPlaneUpVec));
61 mPlanePosition = rPlanePos;
65void ParallelGravity::setRangeBox(
const TPos3f &rMtx) {
66 const u64* pSrc =
reinterpret_cast<const u64*
>(&rMtx);
67 u64* pDest =
reinterpret_cast<u64*
>(&mLocalMtx);
69 for (s32 i = 6; i >= 1; i--) {
77void ParallelGravity::setRangeCylinder(f32 radius, f32 height) {
78 mCylinderRadius = radius;
79 mCylinderHeight = height;
82void ParallelGravity::setRangeType(RANGE_TYPE rangeType) {
83 mRangeType = rangeType;
86void ParallelGravity::setBaseDistance(f32 val) {
95void ParallelGravity::setDistanceCalcType(DISTANCE_CALC_TYPE distanceCalcType) {
96 mDistanceCalcType = distanceCalcType;
99bool ParallelGravity::isInSphereRange(
const TVec3f &rPosition, f32 *pScalar)
const {
101 *pScalar = mBaseDistance;
108 TVec3f dirToCenter(mWorldPlanePosition - rPosition);
110 return dirToCenter.squared() < range * range;
114bool ParallelGravity::isInBoxRange(
const TVec3f &rPosition, f32 *pScalar)
const {
117 mWorldMtx.getTransInline(translation);
118 TVec3f dirToCenter(rPosition - translation);
122 mWorldMtx.getXDir(dirX);
123 f32 dotX = dirToCenter.dot(dirX);
125 if (dotX < -mExtentX || mExtentX < dotX)
130 mWorldMtx.getYDir(dirY);
131 f32 dotY = dirToCenter.dot(dirY);
133 if (dotY < -mExtentY || mExtentY < dotY)
138 mWorldMtx.getYDir(dirZ);
139 f32 dotZ = dirToCenter.dot(dirZ);
141 if (dotZ < -mExtentZ || mExtentZ < dotZ)
147 switch (mDistanceCalcType) {
148 case DistanceCalcType_X:
150 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentX);
152 case DistanceCalcType_Y:
154 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentY);
156 case DistanceCalcType_Z:
158 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentZ);
160 case DistanceCalcType_Default:
161 *pScalar = mBaseDistance;
169bool ParallelGravity::isInCylinderRange(
const TVec3f &rPosition, f32 *pScalar)
const {
173 TVec3f v11(rPosition - mWorldPlanePosition);
174 f32 v6 = mWorldPlaneUpVec.dot(v11);
176 if (v6 < 0.0f || mCylinderHeight < v6) {
181 TVec3f v10(rPosition - mWorldPlanePosition);
182 f32 v8 = mWorldPlaneUpVec.dot(v10);
183 JMAVECScaleAdd(
reinterpret_cast<const Vec*
>(&mWorldPlaneUpVec),
reinterpret_cast<const Vec*
>(&v10),
reinterpret_cast<Vec*
>(&v12), -v8);
185 f32 radius = VECMag(
reinterpret_cast<const Vec*
>(&v12));
187 if (radius > mCylinderRadius)
191 *pScalar = mBaseDistance + radius;
196bool ParallelGravity::isInRange(
const TVec3f &rPosition, f32 *pScalar)
const {
197 switch (mRangeType) {
198 case RangeType_Sphere:
199 return isInSphereRange(rPosition, pScalar);
201 return isInBoxRange(rPosition, pScalar);
202 case RangeType_Cylinder:
203 return isInCylinderRange(rPosition, pScalar);