SMG-Decomp
A decompilation of Super Mario Galaxy 1
Loading...
Searching...
No Matches
ParallelGravity.cpp
1#include "Game/Gravity.hpp"
2#include "Game/Util.hpp"
3#include "JSystem/JMath.hpp"
4#include "Inline.hpp"
5
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)
12{
13 mCylinderHeight = 1000.0f;
14 mCylinderRadius = 500.0f;
15 mBaseDistance = 2000.0f;
16 mRangeType = RangeType_Sphere;
17 mDistanceCalcType = DistanceCalcType_Default;
18 mLocalMtx.identity();
19 mWorldMtx.identity();
20}
21
22bool ParallelGravity::calcOwnGravityVector(TVec3f *pDest, f32 *pScalar, const TVec3f &rPosition) const {
23 if (!isInRange(rPosition, pScalar)) {
24 return false;
25 }
26
27 if (pDest) {
28 *pDest = -mWorldPlaneUpVec;
29 }
30
31 return true;
32}
33
34#ifdef NON_MATCHING
35void ParallelGravity::updateMtx(const TPos3f &rMtx) {
36 rMtx.mult33Inline(mPlaneUpVec, mWorldPlaneUpVec);
37 rMtx.mult(mPlanePosition, mWorldPlanePosition);
38 MR::normalizeOrZero(&mWorldPlaneUpVec);
39
40 if (mRangeType == RangeType_Box) {
41 mWorldMtx.concat(rMtx, mLocalMtx);
42
43 TVec3f tempDir;
44 mWorldMtx.getXDir(tempDir);
45 mExtentX = tempDir.squared();
46 mWorldMtx.getYDir(tempDir);
47 mExtentY = tempDir.squared();
48 mWorldMtx.getZDir(tempDir);
49 mExtentZ = tempDir.squared();
50 }
51}
52#endif
53
54void ParallelGravity::setPlane(const TVec3f &rPlaneUp, const TVec3f &rPlanePos) {
55 // Up vector
56 mPlaneUpVec.setInline(rPlaneUp);
57 VECMag(reinterpret_cast<const Vec*>(&mPlaneUpVec)); // unused result
58 VECNormalize(reinterpret_cast<const Vec*>(&mPlaneUpVec), reinterpret_cast<Vec*>(&mPlaneUpVec));
59
60 // Position
61 mPlanePosition = rPlanePos;
62}
63
64#ifdef NON_MATCHING
65void ParallelGravity::setRangeBox(const TPos3f &rMtx) {
66 const u64* pSrc = reinterpret_cast<const u64*>(&rMtx);
67 u64* pDest = reinterpret_cast<u64*>(&mLocalMtx);
68
69 for (s32 i = 6; i >= 1; i--) {
70 *pDest++ = *pSrc++;
71 }
72
73 updateIdentityMtx();
74}
75#endif
76
77void ParallelGravity::setRangeCylinder(f32 radius, f32 height) {
78 mCylinderRadius = radius;
79 mCylinderHeight = height;
80}
81
82void ParallelGravity::setRangeType(RANGE_TYPE rangeType) {
83 mRangeType = rangeType;
84}
85
86void ParallelGravity::setBaseDistance(f32 val) {
87 if (val >= 0.0f) {
88 mBaseDistance = val;
89 }
90 else {
91 mBaseDistance = 0.0f;
92 }
93}
94
95void ParallelGravity::setDistanceCalcType(DISTANCE_CALC_TYPE distanceCalcType) {
96 mDistanceCalcType = distanceCalcType;
97}
98
99bool ParallelGravity::isInSphereRange(const TVec3f &rPosition, f32 *pScalar) const {
100 if (pScalar) {
101 *pScalar = mBaseDistance;
102 }
103
104 if (mRange < 0.0f) {
105 return true;
106 }
107 else {
108 TVec3f dirToCenter(mWorldPlanePosition - rPosition);
109 f32 range = mRange;
110 return dirToCenter.squared() < range * range;
111 }
112}
113
114bool ParallelGravity::isInBoxRange(const TVec3f &rPosition, f32 *pScalar) const {
115 // Get direction to center
116 TVec3f translation;
117 mWorldMtx.getTransInline(translation);
118 TVec3f dirToCenter(rPosition - translation);
119
120 // Check in X direction
121 TVec3f dirX;
122 mWorldMtx.getXDir(dirX);
123 f32 dotX = dirToCenter.dot(dirX);
124
125 if (dotX < -mExtentX || mExtentX < dotX)
126 return false;
127
128 // Check in Y direction
129 TVec3f dirY;
130 mWorldMtx.getYDir(dirY);
131 f32 dotY = dirToCenter.dot(dirY);
132
133 if (dotY < -mExtentY || mExtentY < dotY)
134 return false;
135
136 // Check in Z direction
137 TVec3f dirZ;
138 mWorldMtx.getYDir(dirZ);
139 f32 dotZ = dirToCenter.dot(dirZ);
140
141 if (dotZ < -mExtentZ || mExtentZ < dotZ)
142 return false;
143
144 // Calculate distance scalar
145 if (pScalar) {
146 f32 abs;
147 switch (mDistanceCalcType) {
148 case DistanceCalcType_X:
149 abs = __fabsf(dotX);
150 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentX);
151 break;
152 case DistanceCalcType_Y:
153 abs = __fabsf(dotY);
154 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentY);
155 break;
156 case DistanceCalcType_Z:
157 abs = __fabsf(dotZ);
158 *pScalar = mBaseDistance + abs / MR::sqrt(mExtentZ);
159 break;
160 case DistanceCalcType_Default:
161 *pScalar = mBaseDistance;
162 break;
163 }
164 }
165
166 return true;
167}
168
169bool ParallelGravity::isInCylinderRange(const TVec3f &rPosition, f32 *pScalar) const {
170 TVec3f v12;
171
172 // Check height range
173 TVec3f v11(rPosition - mWorldPlanePosition);
174 f32 v6 = mWorldPlaneUpVec.dot(v11);
175
176 if (v6 < 0.0f || mCylinderHeight < v6) {
177 return false;
178 }
179
180 // Check radius range
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);
184
185 f32 radius = VECMag(reinterpret_cast<const Vec*>(&v12));
186
187 if (radius > mCylinderRadius)
188 return false;
189
190 // Set speed
191 *pScalar = mBaseDistance + radius;
192
193 return true;
194}
195
196bool ParallelGravity::isInRange(const TVec3f &rPosition, f32 *pScalar) const {
197 switch (mRangeType) {
198 case RangeType_Sphere:
199 return isInSphereRange(rPosition, pScalar);
200 case RangeType_Box:
201 return isInBoxRange(rPosition, pScalar);
202 case RangeType_Cylinder:
203 return isInCylinderRange(rPosition, pScalar);
204 }
205
206 return false;
207}