SMG-Decomp
A decompilation of Super Mario Galaxy 1
Loading...
Searching...
No Matches
CubeGravity.cpp
1#include "Game/Gravity.hpp"
2#include "Game/Util/MathUtil.hpp"
3#include "JSystem/JMath/JMath.hpp"
4
5template<>
6bool TVec3f::isZero() const {
7 register const TVec3f *rSrc = this;
8 register f32 sum;
9
10 __asm {
11 psq_l f1, 0(rSrc), 0, 0
12 lfs sum, 8(rSrc)
13 ps_mul f1, f1, f1
14 ps_madd sum, sum, sum, f1
15 ps_sum0 sum, sum, f1, f1
16 };
17
18 return sum <= 0.0000038146973f;
19}
20
21template<>
22float TVec3f::normalize(const TVec3f& rSrc) {
23 x = rSrc.x;
24 y = rSrc.y;
25 z = rSrc.z;
26 float magnitude = PSVECMag(toCVec());
27 PSVECNormalize(toCVec(), toVec());
28 return magnitude;
29}
30
31CubeGravity::CubeGravity() : PlanetGravity() {
32
33 lenX = 1.0;
34 lenY = 1.0;
35 lenZ = 1.0;
36 mActiveFaces = 63;
37
38 mCube.identity();
39 mPosition.identity();
40}
41
42void CubeGravity::setCube(const TPos3f & cube) {
43 mCube = cube;
44
45 updateIdentityMtx();
46}
47
48void CubeGravity::updateMtx(const TPos3f &rMtx) {
49 mPosition.concat(rMtx, mCube);
50 TVec3f dir;
51 mPosition.getXDir(dir);
52 lenX = VECMag(dir.toCVec());
53 mPosition.getYDir(dir);
54 lenY = VECMag(dir.toCVec());
55 mPosition.getZDir(dir);
56 lenZ = VECMag(dir.toCVec());
57}
58
59bool CubeGravity::calcOwnGravityVector(TVec3f *pDest, f32 *pScalar, const TVec3f &rPosition) const {
60 int area = calcGravityArea(rPosition);
61 if(area < 0) return false;
62 TVec3f gravityForce;
63 float scalar;
64 if (
65 !calcFaceGravity(rPosition, area, &gravityForce, &scalar)
66 && !calcCornerGravity(rPosition, area, &gravityForce, &scalar)
67 && !calcEdgeGravity(rPosition, area, &gravityForce, &scalar)
68 ) return false;
69
70 if(isInRangeDistance(scalar)) return false;
71
72 if(pDest != NULL)
73 *pDest = gravityForce;
74
75 if(pScalar != NULL)
76 *pScalar = scalar;
77 return true;
78}
79
80int CubeGravity::calcGravityArea(const TVec3f &rPosition) const { // Area as in region, not area as in Area = Base * h
81 TVec3f dirX, dirY, dirZ, trans;
82 mPosition.getXDir(dirX);
83 mPosition.getYDir(dirY);
84 mPosition.getZDir(dirZ);
85 mPosition.getTrans(trans);
86 TVec3f relativePosition = rPosition - trans;
87 int area; // Region of the cube
88 float xDirDistance = relativePosition.dot(dirX) / lenX, yDirDistance = relativePosition.dot(dirY) / lenY, zDirDistance = relativePosition.dot(dirZ) / lenZ;
89
90 if(xDirDistance < -lenX) {
91 if((mActiveFaces & 2) != 2) return -1;
92 area = 0;
93 }
94 else {
95 if(xDirDistance <= lenX) {
96 area = 1;
97 }
98 else {
99 if((mActiveFaces & 1) != 1) return -1;
100 area = 2;
101 }
102 }
103
104 if(yDirDistance < -lenY) {
105 if((mActiveFaces & 8) != 8) return -1;
106 }
107 else {
108 if(yDirDistance <= lenY) {
109 area += 3;
110 }
111 else {
112 if((mActiveFaces & 4) != 4) return -1;
113 area += 6;
114 }
115 }
116
117 if(zDirDistance < -lenZ) {
118 if((mActiveFaces & 32) != 32) return -1;
119 }
120 else {
121 if(zDirDistance <= lenZ) {
122 area += 9;
123 }
124 else {
125 if((mActiveFaces & 16) != 16) return -1;
126 area += 18;
127 }
128 }
129
130 return area;
131}
132
133bool CubeGravity::calcFaceGravity(const TVec3f &rPosition, s32 area, TVec3f *pDest, f32 *pScalar) const {
134 TVec3f antiFaceDir; // Negative of the normal vector of the face an object is on
135 switch(area) {
136 case 4:
137 mPosition.getZDir(antiFaceDir);
138 break;
139 case 10:
140 mPosition.getYDir(antiFaceDir);
141 break;
142 case 12:
143 mPosition.getXDir(antiFaceDir);
144 break;
145 case 14:
146 mPosition.getXDir(antiFaceDir);
147 JGeometry::negateInternal(&antiFaceDir.x, &antiFaceDir.x);
148 break;
149 case 16:
150 mPosition.getYDir(antiFaceDir);
151 JGeometry::negateInternal(&antiFaceDir.x, &antiFaceDir.x);
152 break;
153 case 22:
154 mPosition.getZDir(antiFaceDir);
155 JGeometry::negateInternal(&antiFaceDir.x, &antiFaceDir.x);
156 break;
157 default:
158 return false;
159
160 }
161 TVec3f trans;
162 f32 distance; // Double-check what this really is
163 mPosition.getTrans(trans);
164 MR::separateScalarAndDirection(&distance, &antiFaceDir, antiFaceDir);
165 float gravityMagnitude = antiFaceDir.dot(trans - rPosition) / distance;
166 if(gravityMagnitude < 0.f) gravityMagnitude = 0.f;
167 *pDest = antiFaceDir;
168 *pScalar = gravityMagnitude;
169 return true;
170}
171
172void helperFunc1(const TVec3f& a, TVec3f& b, const TVec3f& c) {
173 JMAVECScaleAdd(a.toCVec(), c.toCVec(), b.toVec(), -a.dot(c));
174}
175
176
177/*TVec3f translate(const TVec3f& a, const TVec3f& b) {
178 TVec3f tmp = a;
179 tmp += b;
180 return tmp;
181}*/
182
183TVec3f negate(const TVec3f& in) {
184 TVec3f tmp;
185 JGeometry::negateInternal(&in.x, &tmp.x);
186 return tmp;
187}
188
189bool CubeGravity::calcEdgeGravity(const TVec3f &rPosition, s32 area, TVec3f *pDest, f32 *pScalar) const {
190 if(!(((area & 1) ^ ((area & 0x80000000) >> 31)) - ((area & 0x80000000) >> 31)) || area == 13) return false;
191 TVec3f stack_140, stack_134, xDir, yDir, zDir, trans, stack_f8;
192 mPosition.getXDir(xDir);
193 mPosition.getYDir(yDir);
194 mPosition.getZDir(zDir);
195 switch(area) {
196 case 1:
197 stack_140 = xDir;
198 stack_134 = negate(yDir) - zDir;
199 break;
200 case 3:
201 stack_140 = yDir;
202 stack_134 = negate(xDir) - zDir;
203 break;
204 case 5:
205 stack_140 = yDir;
206 stack_134 = xDir - zDir;
207 break;
208 case 7:
209 stack_140 = xDir;
210 stack_134 = yDir - zDir;
211 break;
212 case 9:
213 stack_140 = zDir;
214 stack_134 = negate(xDir) - yDir;
215 break;
216 case 11:
217 stack_140 = zDir;
218 stack_134 = xDir + yDir;
219 break;
220 case 15:
221 stack_140 = zDir;
222 stack_134 = negate(xDir).translate(yDir);
223 break;
224 case 17:
225 stack_140 = zDir;
226 stack_134 = xDir.translate(yDir);
227 break;
228 case 19:
229 stack_140 = xDir;
230 stack_134 = negate(yDir).translate(zDir);
231 break;
232 case 21:
233 stack_140 = yDir;
234 stack_134 = negate(xDir).translate(zDir);
235 break;
236 case 23:
237 stack_140 = yDir;
238 stack_134 = xDir.translate(zDir);
239 break;
240 case 25:
241 stack_140 = xDir;
242 stack_134 = yDir.translate(zDir);
243 break;
244 default:
245 return false;
246 }
247 mPosition.getTrans(trans);
248 stack_134 += trans;
249 MR::normalizeOrZero(&stack_140);
250 helperFunc1(stack_140, stack_f8, stack_134 - rPosition);
251 if(stack_f8.isZero()) {
252 pDest -> normalize(stack_134 - trans);
253 *pScalar = 0.0;
254 }
255 else {
256 *pScalar = pDest -> normalize(stack_f8);
257 }
258 return true;
259
260}
261
262bool CubeGravity::calcCornerGravity(const TVec3f &rPosition, s32 area, TVec3f *pDest, f32 *pScalar) const {
263 TVec3f stack_140, xDir, yDir, zDir, trans;
264 mPosition.getXDir(xDir);
265 mPosition.getYDir(yDir);
266 mPosition.getZDir(zDir);
267 switch(area) {
268 case 0:
269 stack_140 = negate(xDir) - yDir - zDir;
270 break;
271 case 2:
272 stack_140 = xDir - yDir - zDir;
273 break;
274 case 6:
275 stack_140 = negate(xDir).translate(yDir) - zDir;
276 break;
277 case 8:
278 stack_140 = xDir.translate(yDir) - zDir;
279 break;
280 case 18:
281 stack_140 = (negate(xDir) - yDir).translate(zDir);
282 break;
283 case 20:
284 stack_140 = (xDir - yDir).translate(zDir);
285 break;
286 case 24:
287 stack_140 = negate(xDir).translate(yDir).translate(zDir);
288 break;
289 case 26:
290 stack_140 = xDir.translate(yDir).translate(zDir);
291 break;
292 default:
293 return false;
294 }
295 mPosition.getTrans(trans);
296 stack_140 += trans;
297 TVec3f stack_104 = stack_140 - rPosition;
298 if(stack_104.isZero()) {
299 *pScalar = 0.0;
300 pDest -> normalize(stack_140 - trans);
301 }
302 else {
303 *pScalar = pDest -> normalize(stack_104);
304 }
305 return true;
306}