NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
m_3d.cpp
1#include <game/mLib/m_3d.hpp>
2
3#include <game/mLib/m_heap.hpp>
4#include <game/mLib/m_video.hpp>
5#include <lib/egg/gfxe/eggGfxEngine.h>
6#include <lib/egg/gfxe/eggStateGX.h>
7#include <lib/egg/gfxe/eggScreen.h>
8#include <lib/egg/gfxe/eggDrawGX.h>
9#include <lib/egg/gfxe/eggLightTexture.h>
10#include <nw4r/g3d.h>
11#include <string.h>
12
13mAllocator_c *m3d::internal::l_allocator_p;
14nw4r::g3d::ScnRoot *m3d::internal::l_scnRoot_p;
15u32 m3d::internal::l_numLightMgr;
16EGG::LightManager **m3d::internal::l_lightMgr_pp;
17u32 m3d::internal::l_numFogMgr;
18EGG::FogManager **m3d::internal::l_fogMgr_pp;
19
20void m3d::initHio(const char *name) {}
21
22bool m3d::create(EGG::Heap *heap, ulong maxChildren, ulong maxScnObj, ulong numLightObj, ulong numLightSet) {
23 internal::l_allocator_p = new(heap, 4) mAllocator_c();
24 if (internal::l_allocator_p == nullptr) {
25 return false;
26 }
27 internal::l_allocator_p->attach(heap, 0x20);
28
29 nw4r::g3d::G3dInit(true);
30 nw4r::g3d::G3DState::SetRenderModeObj(mVideo::m_video->mRenderModeObj);
31
32 size_t size;
33 internal::l_scnRoot_p = nw4r::g3d::ScnRoot::Construct(
34 internal::l_allocator_p, &size,
35 maxChildren, maxScnObj, numLightObj, numLightSet
36 );
37
38 // Clean up on failure
39 if (internal::l_scnRoot_p == nullptr) {
40 delete internal::l_allocator_p;
41 internal::l_allocator_p = nullptr;
42 return false;
43 }
44
45 return true;
46}
47
48bool m3d::create(EGG::Heap *heap, GXPixelFmt fmt, GXColor col, ulong maxChildren, ulong maxScnObj,
49 ulong numLightObj, ulong numLightSet, ulong numLightMgr, ulong numFogMgr) {
50 if (internal::l_lightMgr_pp != nullptr && internal::l_fogMgr_pp != nullptr) {
51 return false;
52 }
53
55 u16 arg1[] = { cfg.x14, cfg.x16 };
56 u16 arg2[] = { cfg.x2, cfg.x2 };
57 EGG::StateGX::initialize(cfg.x0, cfg.x2, col, fmt);
58 EGG::Screen::Initialize(arg1, arg2, nullptr);
59 EGG::Screen::SetTVModeDefault();
60 EGG::DrawGX::Initialize(heap);
61 EGG::LightTexture::initialize(0x20, heap);
62
63 internal::l_lightMgr_pp = new(heap, 4) EGG::LightManager *[numLightMgr];
64 if (internal::l_lightMgr_pp != nullptr) {
65 internal::l_numLightMgr = numLightMgr;
66 internal::l_fogMgr_pp = new(heap, 4) EGG::FogManager *[numFogMgr];
67 if (internal::l_fogMgr_pp != nullptr) {
68 internal::l_numFogMgr = numFogMgr;
69
70 // Initialize the pointer array for the light and fog managers
71 memset(internal::l_lightMgr_pp, 0, numLightMgr * sizeof(void *));
72 memset(internal::l_fogMgr_pp, 0, numFogMgr * sizeof(void *));
73
74 if (create(heap, maxChildren, maxScnObj, numLightObj, numLightSet)) {
75 return true;
76 }
77 }
78 }
79
80 // Clean up on failure
81 // [Oversight: both pointers can be null]
82 delete[] internal::l_lightMgr_pp;
83 internal::l_lightMgr_pp = nullptr;
84 delete[] internal::l_fogMgr_pp;
85 internal::l_fogMgr_pp = nullptr;
86 return false;
87}
88
89bool m3d::createLightMgr(EGG::Heap *heap, u16 lmArg1, u16 lmArg2, u8 lmArg3, bool createFogMgr, int idx) {
90 if (internal::l_lightMgr_pp == nullptr ||
91
92 // Bounds checking
93 idx < 0 || idx >= internal::l_numLightMgr || idx >= internal::l_numFogMgr ||
94
95 // Light / fog manager must not already exist
96 internal::l_lightMgr_pp[idx] != nullptr || internal::l_fogMgr_pp[idx] != nullptr) {
97 return false;
98 }
99
100 EGG::Heap *prevHeap = mHeap::setCurrentHeap(heap);
101 EGG::LightManager *lm = new(heap, 4) EGG::LightManager(lmArg1, lmArg2, lmArg3);
102 mHeap::setCurrentHeap(prevHeap);
103
104 if (lm != nullptr) {
105 // Either we don't need a fog manager or the creation was successful
106 if (!createFogMgr || m3d::createFogMgr(heap, 0x20, idx)) {
107 internal::l_lightMgr_pp[idx] = lm;
108 return true;
109 }
110 }
111
112 // [Oversight: lm here can be null]
113 delete lm;
114 return false;
115}
116
117void m3d::removeLightMgr(int idx) {
118 EGG::LightManager **mgrs = internal::l_lightMgr_pp;
119
120 // [This is a bug, mgrs[idx] != nullptr should not be checked here.
121 // The way it currently is, the intended functionality of removing all
122 // light managers with idx < 0 is broken, since we cause UB here if idx < 0]
123 if (mgrs != nullptr && mgrs[idx] != nullptr) {
124 if (idx >= 0) {
125 if (mgrs[idx] != nullptr) {
126 delete mgrs[idx];
127 mgrs[idx] = nullptr;
128 }
129 } else {
130 // If idx is negative, delete all light managers
131 for (int i = 0; i < internal::l_numLightMgr; i++) {
132 if (mgrs[i] != nullptr) {
133 delete mgrs[i];
134 }
135 }
136 delete internal::l_lightMgr_pp;
137 internal::l_lightMgr_pp = nullptr;
138 }
139 }
140 removeFogMgr(idx);
141}
142
143bool m3d::createFogMgr(EGG::Heap *heap, int fmArg, int idx) {
144 if (idx < 0 || idx >= internal::l_numFogMgr || internal::l_fogMgr_pp[idx] != nullptr) {
145 return false;
146 }
147
148 EGG::FogManager *fm = new(heap, 4) EGG::FogManager(fmArg);
149 if (fm == nullptr) {
150 return false;
151 }
152
153 internal::l_fogMgr_pp[idx] = fm;
154 return true;
155}
156
157void m3d::removeFogMgr(int idx) {
158 EGG::FogManager **mgrs = internal::l_fogMgr_pp;
159 if (mgrs == nullptr) {
160 return;
161 }
162
163 // [This is wrong, see m3d::removeLightMgr]
164 if (mgrs[idx] != nullptr) {
165 if (idx >= 0) {
166 if (mgrs[idx] != nullptr) {
167 delete mgrs[idx];
168 mgrs[idx] = nullptr;
169 }
170 } else {
171 for (int i = 0; i < internal::l_numFogMgr; i++) {
172 if (mgrs[i] != nullptr) {
173 delete mgrs[i];
174 }
175 }
176 delete internal::l_fogMgr_pp;
177 internal::l_fogMgr_pp = nullptr;
178 }
179 }
180}
181
182nw4r::g3d::ScnRoot *m3d::getScnRoot() {
183 return internal::l_scnRoot_p;
184}
185
186nw4r::g3d::Camera m3d::getCamera(int idx) {
187 return internal::l_scnRoot_p->GetCamera(idx);
188}
189
190nw4r::g3d::Camera m3d::getCurrentCamera() {
191 return internal::l_scnRoot_p->GetCurrentCamera();
192}
193
194int m3d::getCurrentCameraID() {
195 return internal::l_scnRoot_p->GetCurrentCameraID();
196}
197
198void m3d::setCurrentCamera(int id) {
199 internal::l_scnRoot_p->SetCurrentCamera(id);
200}
201
202nw4r::g3d::LightSetting *m3d::getLightSettingP() {
203 return &internal::l_scnRoot_p->GetLightSetting();
204}
205
206EGG::LightManager *m3d::getLightMgr(int idx) {
207 return internal::l_lightMgr_pp[idx];
208}
209
210EGG::FogManager *m3d::getFogMgr(int idx) {
211 return internal::l_fogMgr_pp[idx];
212}
213
214void m3d::drawDone(int idx) {
215 if (internal::l_lightMgr_pp != nullptr && internal::l_lightMgr_pp[idx] != nullptr) {
216 internal::l_lightMgr_pp[idx]->DoneDraw();
217 }
218
219 if (internal::l_fogMgr_pp != nullptr && internal::l_fogMgr_pp[idx] != nullptr) {
220 internal::l_fogMgr_pp[idx]->DoneDraw();
221 }
222}
223
224void m3d::drawLightMapTexture(int idx) {
225 if (internal::l_lightMgr_pp != nullptr && internal::l_lightMgr_pp[idx] != nullptr) {
226 internal::l_lightMgr_pp[idx]->ltMgr->drawAndCaptureTexture(0, 0, 0, 0);
227 }
228}
229
230bool m3d::replaceLightMapTexture(char const *name, m3d::bmdl_c &mdl, int idx) {
231 if (internal::l_lightMgr_pp == nullptr) {
232 return false;
233 }
234
235 EGG::ModelEx mdlEx(mdl.getScn());
236 EGG::LightTextureManager *ltm = internal::l_lightMgr_pp[idx]->ltMgr;
237
238 return ltm->replaceModelTexture(ltm->getTextureIndex(name), &mdlEx);
239}
240
241void m3d::calcWorld(int idx) {
242 if (internal::l_lightMgr_pp != nullptr && internal::l_lightMgr_pp[idx] != nullptr) {
243 internal::l_lightMgr_pp[idx]->Calc(internal::l_scnRoot_p);
244 }
245 if (internal::l_fogMgr_pp != nullptr && internal::l_fogMgr_pp[idx] != nullptr) {
246 internal::l_fogMgr_pp[idx]->Calc();
247 }
248 internal::l_scnRoot_p->CalcWorld();
249}
250
251void m3d::calcMaterial() {
252 internal::l_scnRoot_p->CalcMaterial();
253}
254
255void m3d::calcView(int idx) {
256 if (internal::l_lightMgr_pp != nullptr && internal::l_lightMgr_pp[idx] != nullptr) {
258 nw4r::g3d::Camera cam = getCurrentCamera();
259 cam.GetCameraMtx(&mtx);
260
261 internal::l_lightMgr_pp[idx]->CalcView(mtx, getCurrentCameraID(), internal::l_scnRoot_p);
262 }
263
264 if (internal::l_fogMgr_pp != nullptr && internal::l_fogMgr_pp[idx] != nullptr) {
265 internal::l_fogMgr_pp[idx]->CopyToG3D(internal::l_scnRoot_p);
266 }
267
268 internal::l_scnRoot_p->CalcView();
269 internal::l_scnRoot_p->GatherDrawScnObj();
270 internal::l_scnRoot_p->ZSort();
271}
272
273void m3d::drawOpa() {
274 internal::l_scnRoot_p->DrawOpa();
275}
276
277void m3d::drawXlu() {
278 internal::l_scnRoot_p->DrawXlu();
279}
280
281void m3d::pushBack(nw4r::g3d::ScnObj *obj) {
282 internal::l_scnRoot_p->PushBack(obj);
283}
284
285void m3d::clear() {
286 nw4r::g3d::ScnRoot *scnRoot = internal::l_scnRoot_p;
287 while (scnRoot->Size() != 0) {
288 scnRoot->Remove(scnRoot->Size() - 1);
289 }
290}
291
292void m3d::reset() {
293 nw4r::g3d::G3dReset();
294 if (internal::l_lightMgr_pp != nullptr || internal::l_fogMgr_pp != nullptr) {
295 EGG::StateGX::resetGXCache();
296 }
297}
298
299int m3d::getNodeID(nw4r::g3d::ResMdl mdl, char const *name) {
300 if (mdl.IsValid()) {
301 nw4r::g3d::ResNode obj = mdl.GetResNode(name);
302 if (obj.IsValid()) {
303 return obj.GetID();
304 }
305 }
306 return -1;
307}
308
310 GXSetNumIndStages(0);
311 for (int i = 0; i < GX_MAX_TEVSTAGE; i++) {
312 GXSetTevDirect((GXTevStageID) i);
313 }
314}
315
316void m3d::proc_c_drawProc(nw4r::g3d::ScnProc *proc, bool drawOpa) {
317 m3d::proc_c *m3dProc = (m3d::proc_c *) proc->GetUserData();
318 if (drawOpa) {
319 m3dProc->drawOpa();
320 } else {
321 m3dProc->drawXlu();
322 }
323}
324
325bool m3d::proc_c::create(mAllocator_c *allocator, size_t *objSize) {
326 if (allocator == nullptr) {
327 allocator = internal::l_allocator_p;
328 }
329
330 size_t size;
331 if (objSize == nullptr) {
332 objSize = &size;
333 }
334
335 mpScn = nw4r::g3d::ScnProc::Construct(allocator, objSize, proc_c_drawProc, true, true, 0);
336 if (mpScn == nullptr) {
337 return false;
338 }
339
340 mpScn->SetPriorityDrawOpa(127);
341 mpScn->SetPriorityDrawXlu(127);
342
343 nw4r::g3d::ScnProc *p = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnProc>(mpScn);
344 p->SetUserData(this);
345 return true;
346}
An allocator class that wraps an EGG:Allocator .
void resetMaterial()
Turns off all indirect texture processing.
Definition m_3d.cpp:309