NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
ef_drawstrategyimpl.h
1#ifndef NW4R_EF_DRAW_STRATEGY_DRAW_STRATEGY_IMPL_H
2#define NW4R_EF_DRAW_STRATEGY_DRAW_STRATEGY_IMPL_H
3#include <nw4r/types_nw4r.h>
4
5#include <nw4r/ef/ef_drawstrategy.h>
6#include <nw4r/ef/ef_types.h>
7
8#include <nw4r/math.h>
9
10#include <revolution/GX.h>
11
12#include <limits>
13
14namespace nw4r {
15namespace ef {
16
17// Forward declarations
18class Particle;
19class ParticleManager;
20struct TextureData;
21
22class DrawStrategyImpl : public DrawStrategy {
23public:
24 typedef Particle* (*GetFirstDrawParticleFunc)(ParticleManager* pManager);
25 typedef Particle* (*GetNextDrawParticleFunc)(ParticleManager* pManager,
26 Particle* pParticle);
27
28 enum ParticleDrawOrder { DRAWORDER_YOUNGERS_FIRST, DRAWORDER_ELDERS_FIRST };
29
30 struct AheadContext {
31 struct {
32 ParticleManager* mParticleManager; // at 0x0
33 const math::MTX34* mViewMtx; // at 0x4
34 math::MTX34 mEmitterMtx; // at 0x8
35 math::MTX34 mParticleManagerMtx; // at 0x38
36 math::MTX34 mParticleManagerMtxInv; // at 0x68
37 math::VEC3 mEmitterAxisY; // at 0x98
38 math::VEC3 mEmitterCenter; // at 0xA4
39 } mCommon; // at 0x0
40
41 struct {
42 math::_VEC3 mWorldYAxis; // at 0x0
43 } mNoDesign; // at 0xB0
44
45 AheadContext(const math::MTX34& rViewMtx, ParticleManager* pManager);
46 };
47
48 typedef void (*CalcAheadFunc)(math::VEC3* pAxisY, AheadContext* pContext,
49 Particle* pParticle);
50
51 struct PrevTexture {
52 const TextureData* data; // at 0x0
53 f32 scaleS; // at 0x4
54 f32 scaleT; // at 0x8
55 f32 transS; // at 0xC
56 f32 transT; // at 0x10
57 GXTexWrapMode wrapS; // at 0x14
58 GXTexWrapMode wrapT; // at 0x18
59 math::VEC2 scale; // at 0x1C
60 f32 rotate; // at 0x24
61 math::VEC2 translate; // at 0x28
62
63 PrevTexture() {
64 data = NULL;
65 scaleS = 1.0f;
66 scaleT = 1.0f;
67 transS = 1.0f;
68 transT = 1.0f;
69 wrapS = GX_CLAMP;
70 wrapT = GX_CLAMP;
71 scale.x = 1.0f;
72 scale.y = 1.0f;
73 rotate = 0.0f;
74 translate.x = 0.0f;
75 translate.y = 0.0f;
76 }
77
78 bool IsEqual(const TextureData* _pData, f32 _scaleS, f32 _scaleT,
79 f32 _transS, f32 _transT, GXTexWrapMode _wrapS,
80 GXTexWrapMode _wrapT, math::VEC2 _scale, f32 _rotate,
81 math::VEC2 _translate) {
82
83 if (data != _pData || scaleS != _scaleS || scaleT != _scaleT ||
84 transS != _transS || transT != _transT || wrapS != _wrapS ||
85 wrapT != _wrapT || scale.x != _scale.x || scale.y != _scale.y ||
86 rotate != _rotate || translate.x != _translate.x ||
87 translate.y != _translate.y) {
88 return false;
89 }
90
91 return true;
92 }
93
94 void Set(const TextureData* _pData, f32 _scaleS, f32 _scaleT,
95 f32 _transS, f32 _transT, GXTexWrapMode _wrapS,
96 GXTexWrapMode _wrapT, math::VEC2 _scale, f32 _rotate,
97 math::VEC2 _translate) {
98
99 data = _pData;
100 scaleS = _scaleS;
101 scaleT = _scaleT;
102 transS = _transS;
103 transT = _transT;
104 wrapS = _wrapS;
105 wrapT = _wrapT;
106 scale.x = _scale.x;
107 scale.y = _scale.y;
108 rotate = _rotate;
109 translate.x = _translate.x;
110 translate.y = _translate.y;
111 }
112 };
113
114public:
115 DrawStrategyImpl();
116
117 virtual GetFirstDrawParticleFunc
118 GetGetFirstDrawParticleFunc(int drawOrder); // at 0x10
119
120 virtual GetNextDrawParticleFunc
121 GetGetNextDrawParticleFunc(int drawOrder); // at 0x14
122
123protected:
124 void InitTexture(const EmitterDrawSetting& rSetting);
125 void InitTev(const EmitterDrawSetting& rSetting, const DrawInfo& rInfo);
126 void InitColor(ParticleManager* pManager,
127 const EmitterDrawSetting& rSetting, const DrawInfo& rInfo);
128
129 void SetupGP(Particle* pParticle, const EmitterDrawSetting& rSetting,
130 const DrawInfo& rInfo, bool first, bool xfDirty);
131
132 static void CalcAhead_Speed(math::VEC3* pAxisY, AheadContext* pContext,
133 Particle* pParticle) {
134
135 pParticle->GetMoveDir(pAxisY);
136
137 if (!Normalize(pAxisY)) {
138 *pAxisY = pContext->mCommon.mEmitterAxisY;
139 }
140 }
141
142 static void CalcAhead_EmitterCenter(math::VEC3* pAxisY,
143 AheadContext* pContext,
144 Particle* pParticle) {
145
146 math::VEC3Sub(pAxisY, &pParticle->mParameter.mPosition,
147 &pContext->mCommon.mEmitterCenter);
148
149 if (!Normalize(pAxisY)) {
150 *pAxisY = pContext->mCommon.mEmitterAxisY;
151 }
152 }
153
154 static void CalcAhead_EmitterDesign(math::VEC3* pAxisY,
155 AheadContext* pContext) {
156
157 *pAxisY = pContext->mCommon.mEmitterAxisY;
158 }
159
160 static void CalcAhead_Particle(math::VEC3* pAxisY, AheadContext* pContext,
161 Particle* pParticle) {
162
163 Particle* pElder =
164 GetElderDrawParticle(pContext->mCommon.mParticleManager, pParticle);
165
166 if (pElder != NULL) {
167 math::VEC3Sub(pAxisY, &pElder->mParameter.mPosition,
168 &pParticle->mParameter.mPosition);
169 } else {
170 math::VEC3Sub(pAxisY, &pParticle->mParameter.mPosition,
171 &pContext->mCommon.mEmitterCenter);
172 }
173
174 if (!Normalize(pAxisY)) {
175 *pAxisY = pContext->mCommon.mEmitterAxisY;
176 }
177 }
178
179 static void CalcAhead_NoDesign(math::VEC3* pAxisY, AheadContext* pContext) {
180 *pAxisY = math::VEC3(pContext->mNoDesign.mWorldYAxis);
181 }
182
183 static void CalcAhead_ParticleBoth(math::VEC3* pAxisY,
184 AheadContext* pContext,
185 Particle* pParticle) {
186
187 Particle* pElder =
188 GetElderDrawParticle(pContext->mCommon.mParticleManager, pParticle);
189
190 Particle* pYounger = GetYoungerDrawParticle(
191 pContext->mCommon.mParticleManager, pParticle);
192
193 math::VEC3 elderPos(0.0f, 0.0f, 0.0f);
194
195 if (pElder != NULL) {
196 math::VEC3Sub(&elderPos, &pElder->mParameter.mPosition,
197 &pParticle->mParameter.mPosition);
198
199 if (!Normalize(&elderPos)) {
200 elderPos = math::VEC3(0.0f, 0.0f, 0.0f);
201 }
202 }
203
204 math::VEC3 youngerPos(0.0f, 0.0f, 0.0f);
205
206 if (pYounger != NULL) {
207 math::VEC3Sub(&youngerPos, &pYounger->mParameter.mPosition,
208 &pParticle->mParameter.mPosition);
209
210 if (!Normalize(&youngerPos)) {
211 youngerPos = math::VEC3(0.0f, 0.0f, 0.0f);
212 }
213 }
214
215 math::VEC3Sub(pAxisY, &elderPos, &youngerPos);
216
217 if (!Normalize(pAxisY)) {
218 *pAxisY = pContext->mCommon.mEmitterAxisY;
219 }
220 }
221
222 int GetNumDrawParticle(ParticleManager* pManager) {
223 return pManager->mActivityList.GetNumActive();
224 }
225
226 static Particle* GetElderParticle(ParticleManager* pManager,
227 Particle* pParticle) {
228
229 return static_cast<Particle*>(
230 NW4R_UT_LIST_GET_LINK(pManager->mActivityList.mActiveList,
231 pParticle)
232 ->prevObject);
233 }
234 static Particle* GetYoungerParticle(ParticleManager* pManager,
235 Particle* pParticle) {
236
237 return static_cast<Particle*>(
238 NW4R_UT_LIST_GET_LINK(pManager->mActivityList.mActiveList,
239 pParticle)
240 ->nextObject);
241 }
242
243 static Particle* GetOldestParticle(ParticleManager* pManager) {
244 return static_cast<Particle*>(
245 pManager->mActivityList.mActiveList.headObject);
246 }
247 static Particle* GetYoungestParticle(ParticleManager* pManager) {
248 return static_cast<Particle*>(
249 pManager->mActivityList.mActiveList.tailObject);
250 }
251
252 static Particle* GetElderDrawParticle(ParticleManager* pManager,
253 Particle* pParticle) {
254
255 Particle* pIt = GetElderParticle(pManager, pParticle);
256
257 while (pIt != NULL &&
258 pIt->GetLifeStatus() != ReferencedObject::NW4R_EF_LS_ACTIVE) {
259
260 pIt = GetElderParticle(pManager, pIt);
261 }
262
263 return pIt;
264 }
265 static Particle* GetYoungerDrawParticle(ParticleManager* pManager,
266 Particle* pParticle) {
267
268 Particle* pIt = GetYoungerParticle(pManager, pParticle);
269
270 while (pIt != NULL &&
271 pIt->GetLifeStatus() != ReferencedObject::NW4R_EF_LS_ACTIVE) {
272
273 pIt = GetYoungerParticle(pManager, pIt);
274 }
275
276 return pIt;
277 }
278
279 static Particle* GetOldestDrawParticle(ParticleManager* pManager) {
280 Particle* pIt = GetOldestParticle(pManager);
281
282 while (pIt != NULL &&
283 pIt->GetLifeStatus() != ReferencedObject::NW4R_EF_LS_ACTIVE) {
284
285 pIt = GetYoungerParticle(pManager, pIt);
286 }
287
288 return pIt;
289 }
290 static Particle* GetYoungestDrawParticle(ParticleManager* pManager) {
291 Particle* pIt = GetYoungestParticle(pManager);
292
293 while (pIt != NULL &&
294 pIt->GetLifeStatus() != ReferencedObject::NW4R_EF_LS_ACTIVE) {
295
296 pIt = GetElderDrawParticle(pManager, pIt);
297 }
298
299 return pIt;
300 }
301
302 static bool Normalize(math::VEC3* pVec) {
303 f32 sqMag = math::VEC3Dot(pVec, pVec);
304
305 if (sqMag < std::numeric_limits<f32>::epsilon()) {
306 return false;
307 }
308
309 *pVec /= math::FSqrt(sqMag);
310 return true;
311 }
312
313 static const math::VEC3& GetXUnitVec() {
314 return mXUnitVec;
315 }
316 static const math::VEC3& GetYUnitVec() {
317 return mYUnitVec;
318 }
319 static const math::VEC3& GetZUnitVec() {
320 return mZUnitVec;
321 }
322
323private:
324 bool _SetupACmp(Particle* pParticle, const EmitterDrawSetting& rSetting,
325 bool first);
326 bool _SetupTevReg(Particle* pParticle, const EmitterDrawSetting& rSetting,
327 bool first);
328 bool _SetupTexture(Particle* pParticle, const EmitterDrawSetting& rSetting,
329 const DrawInfo& rInfo, bool first);
330
331 static Particle*
332 GetFirstDrawParticle_EldersFirst(ParticleManager* pManager);
333
334 static Particle*
335 GetFirstDrawParticle_YoungersFirst(ParticleManager* pManager);
336
337 static Particle* GetNextDrawParticle_EldersFirst(ParticleManager* pManager,
338 Particle* pParticle);
339
340 static Particle*
341 GetNextDrawParticle_YoungersFirst(ParticleManager* pManager,
342 Particle* pParticle);
343
344protected:
345 PrevTexture mPrevTexture[TEX_LAYER_MAX]; // at 0x4
346 GXColor mPrevColor[COLOR_LAYER_MAX][COLOR_IDX_MAX]; // at 0x94
347 int mPrevARef0; // at 0xA4
348 int mPrevARef1; // at 0xA8
349 bool mUseColor1; // at 0xAC
350 bool mUseColor2; // at 0xAD
351 u8 mNumTexmap; // at 0xAE
352 int mTexmapMap[TEX_LAYER_MAX]; // at 0xB0
353
354 static const math::VEC3 mXUnitVec;
355 static const math::VEC3 mYUnitVec;
356 static const math::VEC3 mZUnitVec;
357
358 static const math::VEC3 mZeroVec;
359 static const math::MTX34 mIdentityMtx;
360};
361
362} // namespace ef
363} // namespace nw4r
364
365#endif