summaryrefslogtreecommitdiff
path: root/src/m
diff options
context:
space:
mode:
Diffstat (limited to 'src/m')
-rw-r--r--src/m/m3d/m3d.cpp281
-rw-r--r--src/m/m3d/m_anmchr.cpp82
-rw-r--r--src/m/m3d/m_anmchrblend.cpp56
-rw-r--r--src/m/m3d/m_anmmatclr.cpp203
-rw-r--r--src/m/m3d/m_anmmdl.cpp77
-rw-r--r--src/m/m3d/m_anmshp.cpp60
-rw-r--r--src/m/m3d/m_anmtexpat.cpp191
-rw-r--r--src/m/m3d/m_anmtexsrt.cpp214
-rw-r--r--src/m/m3d/m_anmvis.cpp57
-rw-r--r--src/m/m3d/m_banm.cpp61
-rw-r--r--src/m/m3d/m_bline.cpp252
-rw-r--r--src/m/m3d/m_bmdl.cpp228
-rw-r--r--src/m/m3d/m_calc_ratio.cpp73
-rw-r--r--src/m/m3d/m_fanm.cpp133
-rw-r--r--src/m/m3d/m_mdl.cpp239
-rw-r--r--src/m/m3d/m_proc.cpp46
-rw-r--r--src/m/m3d/m_scnLeaf.cpp108
-rw-r--r--src/m/m3d/m_smdl.cpp35
-rw-r--r--src/m/m3d/m_video.cpp13
-rw-r--r--src/m/m_allocator.cpp2
-rw-r--r--src/m/m_fader.cpp11
21 files changed, 2414 insertions, 8 deletions
diff --git a/src/m/m3d/m3d.cpp b/src/m/m3d/m3d.cpp
new file mode 100644
index 00000000..e4ec66b8
--- /dev/null
+++ b/src/m/m3d/m3d.cpp
@@ -0,0 +1,281 @@
+#include <egg/gfx/eggDrawGX.h>
+#include <egg/gfx/eggGfxEngine.h>
+#include <egg/gfx/eggScreen.h>
+#include <egg/gfx/eggStateGX.h>
+
+#include <nw4r/g3d/g3d_camera.h>
+#include <nw4r/g3d/g3d_init.h>
+#include <nw4r/g3d/g3d_resmat.h>
+#include <nw4r/g3d/g3d_resmdl.h>
+#include <nw4r/g3d/g3d_state.h>
+
+#include <m/m3d/m3d.h>
+#include <m/m_heap.h>
+#include <m/m_video.h>
+
+#include <rvl/GX.h>
+
+namespace m3d {
+
+namespace internal {
+
+mAllocator_c *l_allocator_p;
+nw4r::g3d::ScnRoot *l_scnRoot_p;
+u32 l_numLightMgr;
+EGG::LightManager **l_lightMgr_pp;
+u32 l_numFogMgr;
+EGG::FogManager **l_fogMgr_pp;
+size_t l_alignment;
+
+} // namespace internal
+
+bool create(EGG::Heap *pHeap, u32 maxNumChildren, u32 maxNumScnObj, u32 numLightObj, u32 numLightSet) {
+ internal::l_allocator_p = new (pHeap) mAllocator_c();
+
+ if (!internal::l_allocator_p) {
+ return false;
+ }
+
+ internal::l_allocator_p->attach(pHeap, 0x20);
+ nw4r::g3d::G3dInit(true);
+ nw4r::g3d::G3DState::SetRenderModeObj(*mVideo::m_video->pRenderMode);
+ u32 allocedSize;
+ internal::l_scnRoot_p = nw4r::g3d::ScnRoot::Construct(internal::l_allocator_p, &allocedSize, maxNumChildren,
+ maxNumScnObj, numLightObj, numLightSet);
+ if (internal::l_scnRoot_p == nullptr) {
+ delete internal::l_allocator_p;
+ internal::l_allocator_p = nullptr;
+ return false;
+ }
+ return true;
+}
+
+bool create(EGG::Heap *pHeap, GXPixelFmt pxlFmt, GXColor clearColor, u32 maxNumChildren, u32 maxNumScnObj,
+ u32 numLightObj, u32 numLightSet, u32 numLightMgr, u32 numFogMgr) {
+ if (internal::l_lightMgr_pp && internal::l_fogMgr_pp) {
+ return false;
+ }
+ EGG::GfxEngine::Configuration config = EGG::GfxEngine::Configuration();
+
+ u16 temp1[2] = {config.field_0x14, config.field_0x16};
+ u16 temp2[2] = {config.efbHeight, config.efbHeight};
+
+ EGG::StateGX::initialize(config.efbWidth, config.efbHeight, clearColor, pxlFmt);
+ EGG::Screen::Initialize(temp1, temp2, nullptr);
+ EGG::Screen::SetTVModeDefault();
+ EGG::DrawGX::Initialize(pHeap);
+
+ EGG::LightTexture::initialize(0x20, pHeap);
+
+ internal::l_lightMgr_pp = new (pHeap) EGG::LightManager *[numLightMgr];
+ if (internal::l_lightMgr_pp) {
+ internal::l_numLightMgr = numLightMgr;
+ internal::l_fogMgr_pp = new (pHeap) EGG::FogManager *[numFogMgr];
+ if (internal::l_fogMgr_pp) {
+ internal::l_numFogMgr = numFogMgr;
+ memset(internal::l_lightMgr_pp, 0, numLightMgr * 4);
+ memset(internal::l_fogMgr_pp, 0, numFogMgr * 4);
+
+ if (create(pHeap, maxNumChildren, maxNumScnObj, numLightObj, numLightSet)) {
+ return true;
+ }
+ }
+ }
+
+ // Creation failed :(
+ delete[] internal::l_lightMgr_pp;
+ internal::l_lightMgr_pp = nullptr;
+ delete[] internal::l_fogMgr_pp;
+ internal::l_fogMgr_pp = nullptr;
+ return false;
+}
+
+bool createLightMgr(EGG::Heap *pHeap, u16 p2, u16 p3, u8 p4, bool bCreateFogMgr, int idx) {
+ using namespace internal;
+
+ if (!l_lightMgr_pp || (idx < 0 || idx >= l_numLightMgr || idx >= l_numFogMgr) ||
+ (l_lightMgr_pp[idx] || l_fogMgr_pp[idx])) {
+ return false;
+ }
+
+ EGG::Heap *prevHeap = mHeap::setCurrentHeap(pHeap);
+ EGG::LightManager *lightMgr = new (pHeap) EGG::LightManager(p2, p3, p4);
+ mHeap::setCurrentHeap(prevHeap);
+
+ if (lightMgr) {
+ if (!bCreateFogMgr || createFogMgr(pHeap, 0x20, idx)) {
+ l_lightMgr_pp[idx] = lightMgr;
+ return true;
+ }
+ }
+ delete lightMgr;
+ return false;
+
+ u8 input;
+ u8 *output;
+ switch (input % 8) {
+ do {
+ case 0:
+ *output++ = input;
+ case 1:
+ *output++ = input;
+ case 2:
+ *output++ = input;
+ } while (true);
+ }
+}
+
+bool createFogMgr(EGG::Heap *pHeap, int numFog, int idx) {
+ using namespace internal;
+
+ if (idx < 0 || idx >= l_numFogMgr || l_fogMgr_pp[idx]) {
+ return false;
+ }
+
+ EGG::FogManager *fogMgr;
+ {
+ mHeap heap(pHeap);
+ fogMgr = new (pHeap) EGG::FogManager(numFog);
+ }
+
+ if (!fogMgr) {
+ return false;
+ }
+ l_fogMgr_pp[idx] = fogMgr;
+ return true;
+}
+
+nw4r::g3d::ScnRoot *getScnRoot() {
+ return internal::l_scnRoot_p;
+}
+
+nw4r::g3d::Camera getCamera(int id) {
+ return internal::l_scnRoot_p->GetCamera(id);
+}
+
+nw4r::g3d::Camera getCurrentCamera() {
+ return internal::l_scnRoot_p->GetCurrentCamera();
+}
+
+int getCurrentCameraID() {
+ return internal::l_scnRoot_p->GetCurrentCameraID();
+}
+
+void setCurrentCamera(int id) {
+ internal::l_scnRoot_p->SetCurrentCamera(id);
+}
+
+nw4r::g3d::LightSetting *getLightSettingP() {
+ return internal::l_scnRoot_p->getLightSetting();
+}
+
+EGG::LightManager *getLightMgr(int idx) {
+ return internal::l_lightMgr_pp[idx];
+}
+
+EGG::FogManager *getFogMgr(int idx) {
+ return internal::l_fogMgr_pp[idx];
+}
+
+void drawDone(int idx) {
+ if (internal::l_lightMgr_pp && internal::l_lightMgr_pp[idx]) {
+ internal::l_lightMgr_pp[idx]->DoneDraw();
+ }
+ if (internal::l_fogMgr_pp && internal::l_fogMgr_pp[idx]) {
+ internal::l_fogMgr_pp[idx]->mFlag &= 0xFB;
+ }
+}
+
+void drawLightMapTexture(int idx) {
+ using namespace internal;
+
+ if (!l_lightMgr_pp) {
+ return;
+ }
+ if (!l_lightMgr_pp[idx]) {
+ return;
+ }
+
+ l_lightMgr_pp[idx]->GetTextureMgr()->drawAndCaptureTexture(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void calcWorld(int idx) {
+ if (internal::l_lightMgr_pp && internal::l_lightMgr_pp[idx]) {
+ internal::l_lightMgr_pp[idx]->Calc(internal::l_scnRoot_p);
+ }
+ if (internal::l_fogMgr_pp && internal::l_fogMgr_pp[idx]) {
+ internal::l_fogMgr_pp[idx]->Calc();
+ }
+ internal::l_scnRoot_p->CalcWorld();
+}
+
+void calcMaterial() {
+ internal::l_scnRoot_p->CalcMaterial();
+}
+
+void calcView(int idx) {
+ if (internal::l_lightMgr_pp && internal::l_lightMgr_pp[idx]) {
+ nw4r::math::MTX34 camMtx;
+ getCurrentCamera().GetCameraMtx(&camMtx);
+ internal::l_lightMgr_pp[idx]->CalcView(camMtx, getCurrentCameraID(), internal::l_scnRoot_p);
+ }
+ if (internal::l_fogMgr_pp && internal::l_fogMgr_pp[idx]) {
+ internal::l_fogMgr_pp[idx]->CopyToG3D(internal::l_scnRoot_p);
+ }
+
+ internal::l_scnRoot_p->CalcView();
+ internal::l_scnRoot_p->GatherDrawScnObj();
+ internal::l_scnRoot_p->ZSort();
+}
+
+void drawOpa() {
+ internal::l_scnRoot_p->DrawOpa();
+}
+
+void drawXlu() {
+ internal::l_scnRoot_p->DrawXlu();
+}
+
+bool pushBack(nw4r::g3d::ScnObj *obj) {
+ return internal::l_scnRoot_p->PushBack(obj);
+}
+
+void clear() {
+ internal::l_scnRoot_p->Clear();
+}
+
+void reset() {
+ nw4r::g3d::G3dReset();
+ if (internal::l_lightMgr_pp || internal::l_fogMgr_pp) {
+ EGG::StateGX::resetGXCache();
+ }
+}
+
+int getMatID(nw4r::g3d::ResMdl mdl, const char *name) {
+ if (mdl.IsValid()) {
+ nw4r::g3d::ResMat mat = mdl.GetResMat(name);
+ if (mat.IsValid()) {
+ return mat.ref().id;
+ }
+ }
+ return -1;
+}
+
+int getNodeID(nw4r::g3d::ResMdl mdl, const char *name) {
+ if (mdl.IsValid()) {
+ nw4r::g3d::ResNode node = mdl.GetResNode(name);
+ if (node.IsValid()) {
+ return node.GetID();
+ }
+ }
+ return -1;
+}
+
+void resetMaterial() {
+ GXSetNumIndStages(0);
+ for (int i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) {
+ GXSetTevDirect((GXTevStageID)i);
+ }
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmchr.cpp b/src/m/m3d/m_anmchr.cpp
new file mode 100644
index 00000000..985ef9d6
--- /dev/null
+++ b/src/m/m3d/m_anmchr.cpp
@@ -0,0 +1,82 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmchr.h>
+#include <nw4r/g3d/g3d_anmchr.h>
+#include <nw4r/g3d/g3d_resanmchr.h>
+
+namespace m3d {
+
+anmChr_c::~anmChr_c() {}
+int anmChr_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_CHR;
+}
+
+bool anmChr_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmChr anm, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ nw4r::g3d::AnmObjChrRes::Construct(nullptr, pSize, anm, mdl, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjChrRes::Construct(&mAllocator, &size, anm, mdl, false);
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ }
+
+ setFrmCtrlDefault(anm, PLAY_MODE_4);
+ return true;
+}
+
+void anmChr_c::setAnm(bmdl_c &mdl, nw4r::g3d::ResAnmChr anm, playMode_e mode) {
+ mdl.removeAnm((nw4r::g3d::ScnMdlSimple::AnmObjType)getType());
+ setAnmAfter(mdl, anm, mode);
+}
+
+void anmChr_c::setAnmAfter(bmdl_c &mdl, nw4r::g3d::ResAnmChr anm, playMode_e mode) {
+ nw4r::g3d::AnmObjChrNode *node;
+ nw4r::g3d::G3dObj *parent = mpAnmObj->GetParent();
+ f32 weight;
+ int idx;
+ if (parent != nullptr) {
+ node = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrNode>(parent);
+ int size = node->Size();
+ idx = 0;
+ for (int i = 0; i < size; i++, idx++) {
+ if (node->GetNode(i) == mpAnmObj) {
+ break;
+ }
+ }
+ weight = node->GetWeight(idx);
+ node->Detach(idx);
+ }
+ mpAnmObj->Release();
+ mpAnmObj->Destroy();
+ mpFrameHeap->free(3);
+ u32 tmp;
+ mpAnmObj = nw4r::g3d::AnmObjChrRes::Construct(&mAllocator, &tmp, anm, mdl.getResMdl(), false);
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(anm, mode);
+
+ if (parent != nullptr) {
+ nw4r::g3d::AnmObjChrRes *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrRes>(mpAnmObj);
+ node->SetWeight(idx, weight);
+ node->Attach(idx, o);
+ }
+}
+
+void anmChr_c::setFrmCtrlDefault(nw4r::g3d::ResAnmChr &anm, m3d::playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = anm.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(anm.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmchrblend.cpp b/src/m/m3d/m_anmchrblend.cpp
new file mode 100644
index 00000000..2c7d67ef
--- /dev/null
+++ b/src/m/m3d/m_anmchrblend.cpp
@@ -0,0 +1,56 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmchrblend.h>
+#include <nw4r/g3d/g3d_anmchr.h>
+#include <nw4r/g3d/g3d_resanmchr.h>
+
+namespace m3d {
+
+anmChrBlend_c::~anmChrBlend_c() {}
+
+int anmChrBlend_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_CHR;
+}
+
+bool anmChrBlend_c::create(nw4r::g3d::ResMdl mdl, int num, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ nw4r::g3d::AnmObjChrBlend::Construct(nullptr, pSize, mdl, num);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjChrBlend::Construct(&mAllocator, &size, mdl, num);
+ return true;
+}
+
+void anmChrBlend_c::attach(int idx, nw4r::g3d::AnmObjChrRes *anm, f32 weight) {
+ nw4r::g3d::AnmObjChrBlend *obj = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrBlend>(mpAnmObj);
+ obj->SetWeight(idx, weight);
+ obj->Attach(idx, anm);
+}
+
+void anmChrBlend_c::attach(int idx, anmChr_c *anm, f32 weight) {
+ nw4r::g3d::AnmObjChrRes *res = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrRes>(anm->getAnimObj());
+ attach(idx, res, weight);
+}
+
+void anmChrBlend_c::detach(int idx) {
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrBlend>(mpAnmObj)->Detach(idx);
+}
+
+void anmChrBlend_c::setWeight(int idx, f32 weight) {
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrBlend>(mpAnmObj)->SetWeight(idx, weight);
+}
+
+f32 anmChrBlend_c::getWeight(int idx) const {
+ return nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjChrBlend>(mpAnmObj)->GetWeight(idx);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmmatclr.cpp b/src/m/m3d/m_anmmatclr.cpp
new file mode 100644
index 00000000..35ecd8f3
--- /dev/null
+++ b/src/m/m3d/m_anmmatclr.cpp
@@ -0,0 +1,203 @@
+#include <egg/core/eggFrmHeap.h>
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmmatclr.h>
+#include <m/m_heap.h>
+
+namespace m3d {
+
+anmMatClr_c::child_c::~child_c() {}
+
+int anmMatClr_c::child_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_MATCLR;
+}
+
+u32 anmMatClr_c::child_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmClr clr, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjMatClrRes::Construct(nullptr, &size, clr, mdl, false);
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmMatClr_c::child_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmClr clr, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = child_c::heapCost(mdl, clr, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjMatClrRes::Construct(&mAllocator, nullptr, clr, mdl, false);
+
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ }
+ setFrmCtrlDefault(clr, PLAY_MODE_4);
+ return true;
+}
+
+void anmMatClr_c::child_c::setAnm(m3d::bmdl_c &mdl, nw4r::g3d::ResAnmClr clr, m3d::playMode_e mode) {
+ releaseAnm();
+ mpAnmObj = nw4r::g3d::AnmObjMatClrRes::Construct(&mAllocator, nullptr, clr, mdl.getResMdl(), false);
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(clr, mode);
+}
+
+void anmMatClr_c::child_c::releaseAnm() {
+ if (mpAnmObj != nullptr) {
+ mpAnmObj->Release();
+ mpFrameHeap->free(3);
+ mpAnmObj = nullptr;
+ }
+}
+
+void anmMatClr_c::child_c::setFrmCtrlDefault(nw4r::g3d::ResAnmClr &clr, playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = clr.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(clr.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+u32 anmMatClr_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmClr clr, s32 num, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjMatClrOverride::Construct(nullptr, &size, mdl, num);
+ size += ROUND_UP(num * sizeof(child_c), 0x20);
+ u32 childCost = child_c::heapCost(mdl, clr, true);
+ size += num * ROUND_UP(childCost, 0x20);
+
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmMatClr_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmClr clr, mAllocator_c *alloc, u32 *pSize, s32 num) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size = 0;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = heapCost(mdl, clr, num, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjMatClrOverride::Construct(&mAllocator, nullptr, mdl, num);
+
+ // TODO inline?
+ mpChildren = (child_c *)MEMAllocFromAllocator(&mAllocator, ROUND_UP(num * sizeof(child_c), 0x20));
+
+ nw4r::g3d::AnmObjMatClrOverride *obj = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrOverride>(mpAnmObj);
+ child_c *child = mpChildren;
+ for (int i = 0; i < num; i++) {
+ new (child) child_c();
+ if (!child->create(mdl, clr, &mAllocator, nullptr)) {
+ mHeap::destroyFrmHeap(mpFrameHeap);
+ return false;
+ }
+
+ if (i == 0) {
+ obj->Attach(i, nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrRes>(child->getAnimObj()));
+ } else {
+ child->releaseAnm();
+ }
+ child++;
+ }
+
+ return true;
+}
+
+anmMatClr_c::~anmMatClr_c() {
+ anmMatClr_c::remove();
+}
+
+int anmMatClr_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_MATCLR;
+}
+
+void anmMatClr_c::remove() {
+ nw4r::g3d::AnmObjMatClrOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrOverride>(mpAnmObj);
+ if (o != nullptr && mpChildren != 0) {
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ mpChildren[i].remove();
+ }
+ mpChildren = nullptr;
+ }
+ banm_c::remove();
+}
+
+void anmMatClr_c::setAnm(bmdl_c &mdl, nw4r::g3d::ResAnmClr clr, s32 idx, playMode_e mode) {
+ nw4r::g3d::AnmObjMatClrOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrOverride>(mpAnmObj);
+ o->Detach(idx);
+ mpChildren[idx].setAnm(mdl, clr, mode);
+
+ nw4r::g3d::AnmObjMatClrRes *res =
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrRes>(mpChildren[idx].getAnimObj());
+ o->Attach(idx, res);
+}
+
+void anmMatClr_c::play() {
+ nw4r::g3d::AnmObjMatClrOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjMatClrOverride>(mpAnmObj);
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ play(i);
+ }
+}
+
+void anmMatClr_c::play(s32 idx) {
+ if (mpChildren[idx].IsBound()) {
+ mpChildren[idx].play();
+ }
+}
+
+f32 anmMatClr_c::getFrame(s32 idx) const {
+ return mpChildren[idx].getFrame();
+}
+
+void anmMatClr_c::setFrame(f32 f, s32 idx) {
+ mpChildren[idx].setFrameOnly(f);
+}
+
+f32 anmMatClr_c::getRate(s32 idx) const {
+ return mpChildren[idx].getRate();
+}
+
+void anmMatClr_c::setRate(f32 f, s32 idx) {
+ mpChildren[idx].setRate(f);
+}
+
+bool anmMatClr_c::isStop(s32 idx) const {
+ return mpChildren[idx].isStop();
+}
+
+bool anmMatClr_c::checkFrame(f32 f, s32 idx) const {
+ return mpChildren[idx].checkFrame(f);
+}
+
+void anmMatClr_c::setPlayMode(playMode_e mode, s32 idx) {
+ mpChildren[idx].setPlayState(mode);
+}
+
+f32 anmMatClr_c::getFrameMax(s32 idx) const {
+ return mpChildren[idx].getEndFrame();
+}
+
+f32 anmMatClr_c::getFrameStart(s32 idx) const {
+ return mpChildren[idx].getStartFrame();
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmmdl.cpp b/src/m/m3d/m_anmmdl.cpp
new file mode 100644
index 00000000..70c49fe8
--- /dev/null
+++ b/src/m/m3d/m_anmmdl.cpp
@@ -0,0 +1,77 @@
+#include <m/m3d/m_anmmdl.h>
+
+namespace m3d {
+
+mdlAnmChr::~mdlAnmChr() {}
+
+void mdlAnmChr::play() {
+ mMdl.play();
+}
+
+void mdlAnmChr::setFrame(f32 f) {
+ mAnm.setFrameOnly(f);
+}
+
+void mdlAnmChr::setAnm(const char *name, playMode_e mode) {
+ setAnm(name, mode, 0.0f);
+}
+
+void mdlAnmChr::setRate(f32 rate) {
+ mAnm.setRate(rate);
+}
+
+bool mdlAnmChr::create(void *mdlFile, void *anmFile, const char *mdlName, const char *anmName, mAllocator_c *alloc,
+ u32 bufferOption, int nView, u32 *pSize) {
+ return create(mdlFile, anmFile, mdlName, anmName, nullptr, alloc, bufferOption, nView, pSize);
+}
+
+bool mdlAnmChr::create2(void *mdlFile, void *anmFile, const char *mdlName, const char *anmName, mAllocator_c *alloc,
+ u32 bufferOption, int nView, u32 *pSize) {
+ return create(mdlFile, anmFile, mdlName, anmName, alloc, bufferOption, nView, pSize);
+}
+
+bool mdlAnmChr::create(void *mdlFile, void *anmFile, const char *mdlName, const char *anmName,
+ mdl_c::mdlCallback_c *callback, mAllocator_c *alloc, u32 bufferOption, int nView, u32 *pSize) {
+ mMdlFile = mdlFile;
+ mAnmFile = anmFile;
+
+ nw4r::g3d::ResMdl resMdl = mMdlFile.GetResMdl(mdlName);
+ if (!mMdl.create(resMdl, callback, alloc, bufferOption, nView, pSize)) {
+ return false;
+ }
+
+ nw4r::g3d::ResAnmChr resAnm = mAnmFile.GetResAnmChr(anmName);
+ if (!resAnm.mAnmChr.IsValid()) {
+ resAnm = mMdlFile.GetResAnmChr(anmName);
+ }
+ u32 oldSize;
+ if (pSize != nullptr) {
+ oldSize = *pSize;
+ }
+
+ if (!mAnm.create(resMdl, resAnm, alloc, pSize)) {
+ mMdl.remove();
+ return false;
+ }
+
+ if (pSize != nullptr) {
+ *pSize += oldSize;
+ }
+ return true;
+}
+
+bool mdlAnmChr::create(void *resFile, const char *mdlName, const char *anmName, mAllocator_c *alloc, u32 bufferOption,
+ int nView, u32 *pSize) {
+ return create(resFile, resFile, mdlName, anmName, nullptr, alloc, bufferOption, nView, pSize);
+}
+
+void mdlAnmChr::setAnm(const char *name, playMode_e mode, f32 blend) {
+ nw4r::g3d::ResAnmChr anm = mAnmFile.GetResAnmChr(name);
+ if (!anm.mAnmChr.IsValid()) {
+ anm = mMdlFile.GetResAnmChr(name);
+ }
+ mAnm.setAnm(mMdl, anm, mode);
+ mMdl.setAnm(mAnm, blend);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmshp.cpp b/src/m/m3d/m_anmshp.cpp
new file mode 100644
index 00000000..18ac5f48
--- /dev/null
+++ b/src/m/m3d/m_anmshp.cpp
@@ -0,0 +1,60 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmshp.h>
+#include <nw4r/g3d/g3d_anmshp.h>
+
+namespace m3d {
+
+anmShp_c::~anmShp_c() {}
+
+int anmShp_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_SHP;
+}
+
+bool anmShp_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmShp anm, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 tmp;
+ if (pSize == nullptr) {
+ pSize = &tmp;
+ }
+
+ // This might be an nw4r inline? Note that some of the roundings
+ // are no-ops that still emit instructions because mwcc doesn't do
+ // math
+ u32 numEntries = mdl.GetResVtxPosNumEntries();
+ *pSize = ROUND_UP(ROUND_UP(numEntries * 2 + 0x38, 0x04) + numEntries * 0x0C, 0x04);
+
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjShpRes::Construct(&mAllocator, &tmp, anm, mdl, 0);
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ } else {
+ setFrmCtrlDefault(anm, PLAY_MODE_4);
+ return true;
+ }
+}
+
+void anmShp_c::setAnm(m3d::bmdl_c &mdl, nw4r::g3d::ResAnmShp anm, m3d::playMode_e mode) {
+ mdl.removeAnm((nw4r::g3d::ScnMdlSimple::AnmObjType)getType());
+ mpAnmObj->Release();
+ mpFrameHeap->free(0x3);
+ u32 tmp;
+ mpAnmObj = nw4r::g3d::AnmObjShpRes::Construct(&mAllocator, &tmp, anm, mdl.getResMdl(), 0);
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(anm, mode);
+}
+
+void anmShp_c::setFrmCtrlDefault(nw4r::g3d::ResAnmShp &anm, m3d::playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = anm.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(anm.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmtexpat.cpp b/src/m/m3d/m_anmtexpat.cpp
new file mode 100644
index 00000000..60c96097
--- /dev/null
+++ b/src/m/m3d/m_anmtexpat.cpp
@@ -0,0 +1,191 @@
+#include <egg/core/eggFrmHeap.h>
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmtexpat.h>
+#include <m/m_heap.h>
+
+namespace m3d {
+
+int anmTexPat_c::child_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_TEXPAT;
+}
+
+anmTexPat_c::child_c::~child_c() {}
+
+u32 anmTexPat_c::child_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexPat pat, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjTexPatRes::Construct(nullptr, &size, pat, mdl, false);
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmTexPat_c::child_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexPat pat, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = child_c::heapCost(mdl, pat, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjTexPatRes::Construct(&mAllocator, nullptr, pat, mdl, false);
+
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ }
+ setFrmCtrlDefault(pat, PLAY_MODE_4);
+ return true;
+}
+
+void anmTexPat_c::child_c::setAnm(m3d::bmdl_c &mdl, nw4r::g3d::ResAnmTexPat pat, m3d::playMode_e mode) {
+ releaseAnm();
+ mpAnmObj = nw4r::g3d::AnmObjTexPatRes::Construct(&mAllocator, nullptr, pat, mdl.getResMdl(), false);
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(pat, mode);
+}
+
+void anmTexPat_c::child_c::releaseAnm() {
+ if (mpAnmObj != nullptr) {
+ mpAnmObj->Release();
+ mpFrameHeap->free(3);
+ mpAnmObj = nullptr;
+ }
+}
+
+void anmTexPat_c::child_c::setFrmCtrlDefault(nw4r::g3d::ResAnmTexPat &pat, playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = pat.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(pat.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+u32 anmTexPat_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexPat pat, s32 num, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjTexPatOverride::Construct(nullptr, &size, mdl, num);
+ size += ROUND_UP(num * sizeof(child_c), 0x20);
+ u32 childCost = child_c::heapCost(mdl, pat, true);
+ size += num * ROUND_UP(childCost, 0x20);
+
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmTexPat_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexPat pat, mAllocator_c *alloc, u32 *pSize, s32 num) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size = 0;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = heapCost(mdl, pat, num, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjTexPatOverride::Construct(&mAllocator, nullptr, mdl, num);
+
+ // TODO inline?
+ mpChildren = (child_c *)MEMAllocFromAllocator(&mAllocator, ROUND_UP(num * sizeof(child_c), 0x20));
+
+ nw4r::g3d::AnmObjTexPatOverride *obj = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatOverride>(mpAnmObj);
+ child_c *child = mpChildren;
+ for (int i = 0; i < num; i++) {
+ new (child) child_c();
+ if (!child->create(mdl, pat, &mAllocator, nullptr)) {
+ mHeap::destroyFrmHeap(mpFrameHeap);
+ return false;
+ }
+
+ if (i == 0) {
+ obj->Attach(i, nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatRes>(child->getAnimObj()));
+ } else {
+ child->releaseAnm();
+ }
+ child++;
+ }
+
+ return true;
+}
+
+anmTexPat_c::~anmTexPat_c() {
+ anmTexPat_c::remove();
+}
+
+int anmTexPat_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_TEXPAT;
+}
+
+void anmTexPat_c::remove() {
+ nw4r::g3d::AnmObjTexPatOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatOverride>(mpAnmObj);
+ if (o != nullptr && mpChildren != 0) {
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ mpChildren[i].remove();
+ }
+ mpChildren = nullptr;
+ }
+ banm_c::remove();
+}
+
+void anmTexPat_c::setAnm(bmdl_c &mdl, nw4r::g3d::ResAnmTexPat pat, s32 idx, playMode_e mode) {
+ nw4r::g3d::AnmObjTexPatOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatOverride>(mpAnmObj);
+ o->Detach(idx);
+ mpChildren[idx].setAnm(mdl, pat, mode);
+
+ nw4r::g3d::AnmObjTexPatRes *res =
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatRes>(mpChildren[idx].getAnimObj());
+ o->Attach(idx, res);
+}
+
+void anmTexPat_c::play() {
+ nw4r::g3d::AnmObjTexPatOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexPatOverride>(mpAnmObj);
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ play(i);
+ }
+}
+
+void anmTexPat_c::play(s32 idx) {
+ if (mpChildren[idx].IsBound()) {
+ mpChildren[idx].play();
+ }
+}
+
+f32 anmTexPat_c::getFrame(s32 idx) const {
+ return mpChildren[idx].getFrame();
+}
+
+void anmTexPat_c::setFrame(f32 f, s32 idx) {
+ mpChildren[idx].setFrameOnly(f);
+}
+
+void anmTexPat_c::setRate(f32 f, s32 idx) {
+ mpChildren[idx].setRate(f);
+}
+
+bool anmTexPat_c::isStop(s32 idx) const {
+ return mpChildren[idx].isStop();
+}
+
+f32 anmTexPat_c::getFrameMax(s32 idx) const {
+ return mpChildren[idx].getEndFrame();
+}
+
+void anmTexPat_c::setFrameStart(f32 f, s32 idx) {
+ mpChildren[idx].setStartFrame(f);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmtexsrt.cpp b/src/m/m3d/m_anmtexsrt.cpp
new file mode 100644
index 00000000..c45d8be0
--- /dev/null
+++ b/src/m/m3d/m_anmtexsrt.cpp
@@ -0,0 +1,214 @@
+#include <egg/core/eggFrmHeap.h>
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmtexsrt.h>
+#include <m/m_heap.h>
+
+namespace m3d {
+
+int anmTexSrt_c::child_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_TEXSRT;
+}
+
+anmTexSrt_c::child_c::~child_c() {}
+
+u32 anmTexSrt_c::child_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexSrt srt, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjTexSrtRes::Construct(nullptr, &size, srt, mdl, false);
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmTexSrt_c::child_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexSrt srt, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = child_c::heapCost(mdl, srt, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjTexSrtRes::Construct(&mAllocator, nullptr, srt, mdl, false);
+ if (!mpAnmObj) {
+ return false;
+ }
+
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ }
+ setFrmCtrlDefault(srt, PLAY_MODE_4);
+ return true;
+}
+
+void anmTexSrt_c::child_c::setAnm(m3d::bmdl_c &mdl, nw4r::g3d::ResAnmTexSrt srt, m3d::playMode_e mode) {
+ releaseAnm();
+ mpAnmObj = nw4r::g3d::AnmObjTexSrtRes::Construct(&mAllocator, nullptr, srt, mdl.getResMdl(), false);
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(srt, mode);
+}
+
+void anmTexSrt_c::child_c::releaseAnm() {
+ if (mpAnmObj != nullptr) {
+ mpAnmObj->Release();
+ mpFrameHeap->free(3);
+ mpAnmObj = nullptr;
+ }
+}
+
+void anmTexSrt_c::child_c::setFrmCtrlDefault(nw4r::g3d::ResAnmTexSrt &srt, playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = srt.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(srt.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+u32 anmTexSrt_c::heapCost(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexSrt srt, s32 num, bool b) {
+ u32 size = 0;
+ nw4r::g3d::AnmObjTexSrtOverride::Construct(nullptr, &size, mdl, num);
+ size += ROUND_UP(num * sizeof(child_c), 0x20);
+ u32 childCost = child_c::heapCost(mdl, srt, true);
+ size += num * ROUND_UP(childCost, 0x20);
+
+ if (b) {
+ size = ROUND_UP(mHeap::frmHeapCost(size, 0x20), 0x20);
+ }
+ return size;
+}
+
+bool anmTexSrt_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmTexSrt srt, mAllocator_c *alloc, u32 *pSize, s32 num) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size = 0;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ *pSize = heapCost(mdl, srt, num, false);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjTexSrtOverride::Construct(&mAllocator, nullptr, mdl, num);
+ if (!mpAnmObj) {
+ return false;
+ }
+
+ // TODO inline?
+ mpChildren = (child_c *)MEMAllocFromAllocator(&mAllocator, ROUND_UP(num * sizeof(child_c), 0x20));
+ if (!mpChildren) {
+ remove();
+ return false;
+ }
+
+ nw4r::g3d::AnmObjTexSrtOverride *obj = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtOverride>(mpAnmObj);
+ child_c *child = mpChildren;
+ for (int i = 0; i < num; i++) {
+ new (child) child_c();
+ if (!child->create(mdl, srt, &mAllocator, nullptr)) {
+ mHeap::destroyFrmHeap(mpFrameHeap);
+ EGG::Heap::free(mpFrameHeap, nullptr);
+ return false;
+ }
+
+ if (i == 0) {
+ obj->Attach(i, nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtRes>(child->getAnimObj()));
+ } else {
+ child->releaseAnm();
+ }
+ child++;
+ }
+
+ return true;
+}
+
+anmTexSrt_c::~anmTexSrt_c() {
+ anmTexSrt_c::remove();
+}
+
+int anmTexSrt_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_TEXSRT;
+}
+
+void anmTexSrt_c::remove() {
+ nw4r::g3d::AnmObjTexSrtOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtOverride>(mpAnmObj);
+ if (o != nullptr && mpChildren != 0) {
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ mpChildren[i].remove();
+ }
+ mpChildren = nullptr;
+ }
+ banm_c::remove();
+}
+
+void anmTexSrt_c::setAnm(bmdl_c &mdl, nw4r::g3d::ResAnmTexSrt srt, s32 idx, playMode_e mode) {
+ nw4r::g3d::AnmObjTexSrtOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtOverride>(mpAnmObj);
+ o->Detach(idx);
+ mpChildren[idx].setAnm(mdl, srt, mode);
+
+ nw4r::g3d::AnmObjTexSrtRes *res =
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtRes>(mpChildren[idx].getAnimObj());
+ o->Attach(idx, res);
+}
+
+void anmTexSrt_c::play() {
+ nw4r::g3d::AnmObjTexSrtOverride *o = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::AnmObjTexSrtOverride>(mpAnmObj);
+ int size = o->Size();
+ for (int i = 0; i < size; i++) {
+ play(i);
+ }
+}
+
+void anmTexSrt_c::play(s32 idx) {
+ if (mpChildren[idx].IsBound()) {
+ mpChildren[idx].play();
+ }
+}
+
+f32 anmTexSrt_c::getFrame(s32 idx) const {
+ return mpChildren[idx].getFrame();
+}
+
+void anmTexSrt_c::setFrame(f32 f, s32 idx) {
+ mpChildren[idx].setFrameOnly(f);
+}
+
+void anmTexSrt_c::setRate(f32 f, s32 idx) {
+ mpChildren[idx].setRate(f);
+}
+
+bool anmTexSrt_c::isStop(s32 idx) const {
+ return mpChildren[idx].isStop();
+}
+
+bool anmTexSrt_c::checkFrame(f32 f, s32 idx) const {
+ return mpChildren[idx].checkFrame(f);
+}
+
+void anmTexSrt_c::setPlayMode(playMode_e mode, s32 idx) {
+ mpChildren[idx].setPlayState(mode);
+}
+
+f32 anmTexSrt_c::getFrameMax(s32 idx) const {
+ return mpChildren[idx].getEndFrame();
+}
+
+void anmTexSrt_c::setFrameStart(f32 f, s32 idx) {
+ mpChildren[idx].setStartFrame(f);
+}
+
+f32 anmTexSrt_c::getFrameStart(s32 idx) const {
+ return mpChildren[idx].getStartFrame();
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_anmvis.cpp b/src/m/m3d/m_anmvis.cpp
new file mode 100644
index 00000000..68d4bd21
--- /dev/null
+++ b/src/m/m3d/m_anmvis.cpp
@@ -0,0 +1,57 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_anmvis.h>
+#include <nw4r/g3d/g3d_anmvis.h>
+#include <nw4r/g3d/g3d_resanmvis.h>
+#include <nw4r/g3d/g3d_resmdl.h>
+
+namespace m3d {
+
+anmVis_c::~anmVis_c() {}
+
+int anmVis_c::getType() const {
+ return nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_VIS;
+}
+
+bool anmVis_c::create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmVis anm, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 tmp;
+ if (pSize == nullptr) {
+ pSize = &tmp;
+ }
+
+ nw4r::g3d::AnmObjVisRes::Construct(nullptr, pSize, anm, mdl);
+ if (!createAllocator(alloc, pSize)) {
+ return false;
+ }
+
+ mpAnmObj = nw4r::g3d::AnmObjVisRes::Construct(&mAllocator, &tmp, anm, mdl);
+ if (!mpAnmObj->Bind(mdl)) {
+ remove();
+ return false;
+ } else {
+ setFrmCtrlDefault(anm, PLAY_MODE_4);
+ return true;
+ }
+}
+
+void anmVis_c::setAnm(m3d::bmdl_c &mdl, nw4r::g3d::ResAnmVis anm, m3d::playMode_e mode) {
+ mdl.removeAnm((nw4r::g3d::ScnMdlSimple::AnmObjType)getType());
+ mpAnmObj->Release();
+ mpFrameHeap->free(0x3);
+ u32 tmp;
+ mpAnmObj = nw4r::g3d::AnmObjVisRes::Construct(&mAllocator, &tmp, anm, mdl.getResMdl());
+ mpAnmObj->Bind(mdl.getResMdl());
+ setFrmCtrlDefault(anm, mode);
+}
+
+void anmVis_c::setFrmCtrlDefault(nw4r::g3d::ResAnmVis &anm, m3d::playMode_e mode) {
+ if (mode == PLAY_MODE_4) {
+ mode = anm.GetAnmPolicy() == nw4r::g3d::ANM_POLICY_ONETIME ? PLAY_MODE_1 : PLAY_MODE_0;
+ }
+ set(anm.GetNumFrame(), mode, 1.0f, -1.0f);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_banm.cpp b/src/m/m3d/m_banm.cpp
new file mode 100644
index 00000000..026eaf45
--- /dev/null
+++ b/src/m/m3d/m_banm.cpp
@@ -0,0 +1,61 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_banm.h>
+#include <m/m_heap.h>
+
+namespace m3d {
+banm_c::~banm_c() {
+ banm_c::remove();
+}
+
+void banm_c::remove() {
+ if (mpAnmObj != nullptr) {
+ mpAnmObj->DetachFromParent();
+ mpAnmObj->Destroy();
+ mpAnmObj = nullptr;
+ }
+
+ if (mpFrameHeap != nullptr) {
+ mHeap::destroyFrmHeap(mpFrameHeap);
+ mpFrameHeap = nullptr;
+ }
+}
+
+bool banm_c::createAllocator(mAllocator_c *alloc, u32 *pStart) {
+ // TODO understand this maybe?
+ int i1 = mHeap::frmHeapCost(*pStart, 0x20);
+ int i2 = mHeap::frmHeapCost(0, 0x20);
+ i2 = ROUND_UP(i1, 0x20) - i2;
+ i1 = mHeap::frmHeapCost(i2, 0x20);
+ *pStart = ROUND_UP(i1, 0x20);
+ mpFrameHeap = mHeap::createFrmHeap(i2, (EGG::Heap *)alloc->mHeap, "アニメ切り替え用アロケータ(m3d::banm_c::m_heap)",
+ internal::l_alignment, 0);
+ mAllocator.attach(mpFrameHeap, 0x20);
+ return true;
+}
+
+bool banm_c::IsBound() const {
+ if (mpAnmObj == nullptr) {
+ return false;
+ }
+ return mpAnmObj->TestAnmFlag(nw4r::g3d::AnmObj::ANMFLAG_ISBOUND);
+}
+
+void banm_c::play() {}
+
+f32 banm_c::getFrame() const {
+ return mpAnmObj->GetFrame();
+}
+
+void banm_c::setFrameOnly(f32 frame) {
+ mpAnmObj->SetFrame(frame);
+}
+
+f32 banm_c::getRate() const {
+ return mpAnmObj->GetUpdateRate();
+}
+
+void banm_c::setRate(f32 f) {
+ mpAnmObj->SetUpdateRate(f);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_bline.cpp b/src/m/m3d/m_bline.cpp
new file mode 100644
index 00000000..326ae6c1
--- /dev/null
+++ b/src/m/m3d/m_bline.cpp
@@ -0,0 +1,252 @@
+#include <egg/core/eggColorFader.h>
+#include <egg/core/eggHeap.h>
+#include <egg/gfx/eggDrawGX.h>
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_bline.h>
+#include <nw4r/g3d/g3d_light.h>
+#include <nw4r/g3d/g3d_state.h>
+
+namespace m3d {
+
+blineMat_c::~blineMat_c() {
+ remove();
+}
+
+bool blineMat_c::create(mAllocator_c *pAllocator, int numLines, u16 numLinePts, f32 width, f32 repeat,
+ nw4r::ut::Color &color, EGG::ResTIMG *pTex, bool p9) {
+ if (!proc_c::create(pAllocator, nullptr)) {
+ return false;
+ }
+ nw4r::ut::List_Init(&mLines, 0);
+ if (numLines) {
+ mpLineArr = new (pAllocator) bline_c[numLines];
+
+ if (!mpLineArr) {
+ return false;
+ }
+ bline_c *pLineArr = mpLineArr;
+ EGG::Heap *pHeap = pAllocator->mHeap;
+ for (int i = 0; i < numLines; ++i) {
+ if (!pLineArr->create(pHeap, numLinePts, width, repeat, color)) {
+ remove();
+ return false;
+ }
+ nw4r::ut::List_Append(&mLines, pLineArr);
+ pLineArr++;
+ }
+ }
+
+ mLineArrNum = numLines;
+ mpTex = pTex;
+ field_0x4A = p9;
+
+ return true;
+}
+
+void blineMat_c::remove() {
+ if (mpLineArr) {
+ delete[] mpLineArr;
+ mpLineArr = nullptr;
+ }
+ scnLeaf_c::remove();
+}
+
+void blineMat_c::update() {
+ nw4r::math::MTX34 camMtx;
+ mVec3_c vec;
+
+ getCurrentCamera().GetCameraMtx(&camMtx);
+ PSMTXInverse(camMtx, camMtx);
+ PSMTXMultVec(camMtx, mVec3_c::zero, vec);
+
+ for (bline_c *line = (bline_c *)nw4r::ut::List_GetNext(&mLines, 0); line != nullptr;
+ line = (bline_c *)nw4r::ut::List_GetNext(&mLines, line)) {
+ if ((line->mFlags & 1) == 0) {
+ line->update(&vec);
+ }
+ }
+}
+
+bline_c *blineMat_c::getLine(u16 idx) {
+ return (bline_c *)nw4r::ut::List_GetNth(&mLines, idx);
+}
+
+void blineMat_c::setupGX(bool bTransparent) {
+ EGG::DrawGX::LoadTexture(mpTex, GX_TEXMAP0);
+ if (field_0x4A) {
+ u32 mask_diff_color, mask_diff_alpha, mask_spec_color, mask_spec_alpha;
+ nw4r::g3d::AmbLightObj ambObj;
+
+ nw4r::g3d::G3DState::LoadLightSet(0, &mask_diff_color, &mask_diff_alpha, &mask_spec_color, &mask_spec_alpha,
+ &ambObj);
+
+ nw4r::ut::Color ambColor(0xFF, 0xFF, 0xFF, 0xFF);
+ nw4r::ut::Color matColor(0xFF, 0xFF, 0xFF, 0xFF);
+ GXSetChanMatColor(GX_COLOR0, matColor);
+
+ ambColor.r = ambObj.r;
+ ambColor.g = ambObj.g;
+ ambColor.b = ambObj.b;
+ ambColor.a = ambObj.a;
+ GXSetChanAmbColor(GX_COLOR0, ambColor);
+
+ GXSetNumChans(1);
+ GXSetChanCtrl(GX_COLOR0, TRUE, GX_SRC_REG, GX_SRC_REG, (GXLightID)mask_diff_color, GX_DF_CLAMP, GX_AF_NONE);
+ GXSetChanCtrl(GX_ALPHA0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
+ GXSetNumTevStages(2);
+ GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
+ GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO);
+ GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
+ GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
+ } else {
+ GXSetNumChans(0);
+ GXSetNumTevStages(1);
+ }
+ GXSetNumTexGens(1);
+ GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX_IDENT, 0, GX_DUALMTX_IDENT);
+ GXSetNumIndStages(0);
+ GXSetTevDirect(GX_TEVSTAGE0);
+ GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
+ GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
+ GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
+ GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
+ GXSetZCompLoc(1);
+ if (!bTransparent) {
+ GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_SET);
+ GXSetZMode(TRUE, GX_LEQUAL, TRUE);
+ } else {
+ GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
+ GXSetZMode(TRUE, GX_LEQUAL, FALSE);
+ }
+ GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
+ nw4r::ut::Color fogColor = 0x0;
+ GXSetFog(GX_FOG_NONE, fogColor, 0.0f, 0.0f, 0.0f, 0.0f);
+ GXSetFogRangeAdj(FALSE, 0, NULL);
+ GXSetCullMode(GX_CULL_BACK);
+ GXSetDither(1);
+ GXSetClipMode(GX_CLIP_ENABLE);
+ GXClearVtxDesc();
+ GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_CLR_RGB, GX_RGB8, 6);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0);
+
+ nw4r::math::MTX34 camMtx;
+ getCurrentCamera().GetCameraMtx(&camMtx);
+ GXLoadPosMtxImm(camMtx, 0);
+ GXLoadNrmMtxImm(camMtx, 0);
+ GXSetCurrentMtx(0);
+}
+
+void blineMat_c::drawOpa() {
+ update();
+ setupGX(false);
+ for (bline_c *line = (bline_c *)nw4r::ut::List_GetNext(&mLines, 0); line != nullptr;
+ line = (bline_c *)nw4r::ut::List_GetNext(&mLines, line)) {
+ if ((line->mFlags & 1) == 0 && line->mColor.a == 0xFF) {
+ line->draw();
+ }
+ }
+}
+
+void blineMat_c::drawXlu() {
+ update();
+ setupGX(true);
+ for (bline_c *line = (bline_c *)nw4r::ut::List_GetNext(&mLines, 0); line != nullptr;
+ line = (bline_c *)nw4r::ut::List_GetNext(&mLines, line)) {
+ if ((line->mFlags & 1) == 0 && line->mColor.a != 0xFF) {
+ line->draw();
+ }
+ }
+}
+
+bline_c::~bline_c() {
+ remove();
+}
+
+bool bline_c::create(EGG::Heap *pHeap, u16 numPts, f32 width, f32 repeat, const nw4r::ut::Color &color) {
+ mpPathArr = new (pHeap) mVec3_c[numPts];
+ if (!mpPathArr) {
+ return false;
+ }
+
+ mpVtxPosArr = new (pHeap) VtxPos[numPts];
+ if (!mpVtxPosArr) {
+ remove();
+ return false;
+ }
+
+ mpVtxNrmArr = new (pHeap) VtxNrm[numPts];
+ if (!mpVtxNrmArr) {
+ remove();
+ return false;
+ }
+
+ mpVtxTexArr = new (pHeap) VtxTex[numPts];
+ if (!mpVtxTexArr) {
+ remove();
+ return false;
+ }
+
+ mPathNum = numPts;
+ mVtxNum = numPts;
+ mWidth = width;
+ mColor = color;
+ mTexRepeat = repeat;
+ field_0x2C = 0;
+
+ return true;
+}
+
+void bline_c::remove() {
+ if (mpPathArr) {
+ delete[] mpPathArr;
+ mpPathArr = nullptr;
+ }
+ if (mpVtxPosArr) {
+ delete[] mpVtxPosArr;
+ mpVtxPosArr = nullptr;
+ }
+ if (mpVtxNrmArr) {
+ delete[] mpVtxNrmArr;
+ mpVtxNrmArr = nullptr;
+ }
+ if (mpVtxTexArr) {
+ delete[] mpVtxTexArr;
+ mpVtxTexArr = nullptr;
+ }
+}
+
+void bline_c::update(mVec3_c *startPos) {}
+
+void bline_c::draw() {
+ GXSetTevColor(GX_TEVREG0, mColor);
+
+ VtxPos *vtxPos = mpVtxPosArr;
+ VtxNrm *vtxNrm = mpVtxNrmArr;
+ VtxTex *vtxTex = mpVtxTexArr;
+
+ GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, mVtxNum * 2);
+
+ for (int i = 0; i < mVtxNum; i++) {
+ // First Vtx
+ GXPosition3f32(vtxPos->pos1.x, vtxPos->pos1.y, vtxPos->pos1.z);
+ GXNormal3s8(vtxNrm->nrm1.x, vtxNrm->nrm1.y, vtxNrm->nrm1.z);
+ GXTexCoord2f32(0.0f, vtxTex->tex);
+
+ // Second Vtx
+ GXPosition3f32(vtxPos->pos2.x, vtxPos->pos2.y, vtxPos->pos2.z);
+ GXNormal3s8(vtxNrm->nrm2.x, vtxNrm->nrm2.y, vtxNrm->nrm2.z);
+ GXTexCoord2f32(0.0f, vtxTex->tex);
+
+ vtxPos++;
+ vtxNrm++;
+ vtxTex++;
+ }
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_bmdl.cpp b/src/m/m3d/m_bmdl.cpp
new file mode 100644
index 00000000..c565fb5b
--- /dev/null
+++ b/src/m/m3d/m_bmdl.cpp
@@ -0,0 +1,228 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_bmdl.h>
+#include <nw4r/g3d/g3d_scnmdl.h>
+
+namespace m3d {
+
+bmdl_c::~bmdl_c() {
+ remove();
+}
+
+int bmdl_c::getType() const {
+ return SCN_LEAF_MODEL;
+}
+
+int bmdl_c::getMatID(const char *name) const {
+ return m3d::getMatID(getResMdl(), name);
+}
+
+int bmdl_c::getNodeID(const char *name) const {
+ return m3d::getNodeID(getResMdl(), name);
+}
+
+bool bmdl_c::getNodeWorldMtx(u32 p1, nw4r::math::MTX34 *out) const {
+ return nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf)->GetScnMtxPos(out,
+ nw4r::g3d::ScnObj::MTX_TYPE_WORLD, p1);
+}
+
+bool bmdl_c::getNodeWorldMtxMultVecZero(u32 p1, nw4r::math::VEC3 &out) const {
+ nw4r::math::MTX34 mtx;
+ if (!getNodeWorldMtx(p1, &mtx)) {
+ return false;
+ } else {
+ out.x = mtx[0][3];
+ out.y = mtx[1][3];
+ out.z = mtx[2][3];
+ return true;
+ }
+}
+
+bool bmdl_c::getNodeWorldMtxMultVec(u32 p1, nw4r::math::VEC3 &in, nw4r::math::VEC3 &out) const {
+ nw4r::math::MTX34 mtx;
+ if (!getNodeWorldMtx(p1, &mtx)) {
+ return false;
+ } else {
+ PSMTXMultVec(mtx, in, out);
+ return true;
+ }
+}
+
+void bmdl_c::setAnm(banm_c &anm) {
+ nw4r::g3d::ScnMdlSimple *mdl;
+ if (anm.getType() == nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_SHP) {
+ mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ mdl->SetAnmObj(anm.getAnimObj(), nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_NOT_SPECIFIED);
+ } else {
+ mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf);
+ if (anm.getType() == nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_CHR) {
+ mpCurrentAnm = &anm;
+ }
+ mdl->SetAnmObj(anm.getAnimObj(), nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_NOT_SPECIFIED);
+ }
+}
+
+void bmdl_c::play() {
+ if (mpCurrentAnm != nullptr) {
+ mpCurrentAnm->play();
+ }
+}
+
+nw4r::g3d::ResMdl bmdl_c::getResMdl() const {
+ return nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf)->GetResMdl();
+}
+
+nw4r::g3d::ResMat bmdl_c::getResMat(u32 index) const {
+ nw4r::g3d::ResMdl mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf)->GetResMdl();
+ return mdl.GetResMat(index);
+}
+
+void bmdl_c::removeAnm(nw4r::g3d::ScnMdlSimple::AnmObjType type) {
+ nw4r::g3d::ScnMdlSimple *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf);
+ if (type == nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_CHR) {
+ mpCurrentAnm = nullptr;
+ }
+ mdl->RemoveAnmObj(type);
+}
+
+nw4r::g3d::AnmObj *bmdl_c::getAnmObj(nw4r::g3d::ScnMdlSimple::AnmObjType type) const {
+ nw4r::g3d::ScnMdlSimple *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf);
+ return mdl->GetAnmObj(type);
+}
+
+void bmdl_c::setTevColor(u32 idx, GXTevRegID tevId, GXColor color, bool bMarkDirty) {
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+
+ if (mdl) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, idx);
+ nw4r::g3d::ResMatTevColor resMatTevClr = matAccess.GetResMatTevColor(bMarkDirty);
+ resMatTevClr.GXSetTevColor(tevId, color);
+ resMatTevClr.DCStore(false);
+ } else {
+ nw4r::g3d::ResMatTevColor resMatTevClr = getResMat(idx).GetResMatTevColor();
+ resMatTevClr.GXSetTevColor(tevId, color);
+ resMatTevClr.DCStore(false);
+ }
+}
+
+void bmdl_c::setTevColorAll(GXTevRegID tevId, GXColor color, bool bMarkDirty) {
+ nw4r::g3d::ResMdl resMdl = getResMdl();
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ if (mdl) {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, i);
+ nw4r::g3d::ResMatTevColor resMatTevClr = matAccess.GetResMatTevColor(bMarkDirty);
+ resMatTevClr.GXSetTevColor(tevId, color);
+ resMatTevClr.DCStore(false);
+ }
+ } else {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ResMatTevColor resMatTevClr = resMdl.GetResMat(i).GetResMatTevColor();
+ resMatTevClr.GXSetTevColor(tevId, color);
+ resMatTevClr.DCStore(false);
+ }
+ }
+}
+
+void bmdl_c::setTevKColor(u32 idx, GXTevKColorID tevKId, GXColor color, bool bMarkDirty) {
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+
+ if (mdl) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, idx);
+ nw4r::g3d::ResMatTevColor resMatTevClr = matAccess.GetResMatTevColor(bMarkDirty);
+ resMatTevClr.GXSetTevKColor(tevKId, color);
+ resMatTevClr.DCStore(false);
+ } else {
+ nw4r::g3d::ResMatTevColor resMatTevClr = getResMat(idx).GetResMatTevColor();
+ resMatTevClr.GXSetTevKColor(tevKId, color);
+ resMatTevClr.DCStore(false);
+ }
+}
+
+void bmdl_c::setTevKColorAll(GXTevKColorID tevKId, GXColor color, bool bMarkDirty) {
+ nw4r::g3d::ResMdl resMdl = getResMdl();
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ if (mdl) {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, i);
+ nw4r::g3d::ResMatTevColor resMatTevClr = matAccess.GetResMatTevColor(bMarkDirty);
+ resMatTevClr.GXSetTevKColor(tevKId, color);
+ resMatTevClr.DCStore(false);
+ }
+ } else {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ResMatTevColor resMatTevClr = resMdl.GetResMat(i).GetResMatTevColor();
+ resMatTevClr.GXSetTevKColor(tevKId, color);
+ resMatTevClr.DCStore(false);
+ }
+ }
+}
+
+void bmdl_c::setBlendModeAll(GXBlendMode blendMode, GXBlendFactor srcFactor, GXBlendFactor dstFactor, GXLogicOp op,
+ bool bMarkDirty) {
+ nw4r::g3d::ResMdl resMdl = getResMdl();
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ if (mdl) {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, i);
+ nw4r::g3d::ResMatPix resMatPix = matAccess.GetResMatPix(bMarkDirty);
+ resMatPix.GXSetBlendMode(blendMode, srcFactor, dstFactor, op);
+ resMatPix.DCStore(false);
+ }
+ } else {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ResMatPix resMatPix = resMdl.GetResMat(i).GetResMatPix();
+ resMatPix.GXSetBlendMode(blendMode, srcFactor, dstFactor, op);
+ resMatPix.DCStore(false);
+ }
+ }
+}
+
+void bmdl_c::setCullMode(u32 matId, GXCullMode cullMode, bool bMarkDirty) {
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ if (mdl) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, matId);
+ nw4r::g3d::ResGenMode resGenMode = matAccess.GetResGenMode(bMarkDirty);
+ resGenMode.GXSetCullMode(cullMode);
+ } else {
+ nw4r::g3d::ResGenMode resGenMode = getResMat(matId).GetResGenMode();
+ resGenMode.GXSetCullMode(cullMode);
+ }
+}
+
+void bmdl_c::setCullModeAll(GXCullMode cullMode, bool bMarkDirty) {
+ // TODO Extra stack allocation?
+ nw4r::g3d::ResMdl resMdl = getResMdl();
+ nw4r::g3d::ScnMdl *mdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdl>(mpScnLeaf);
+ if (mdl) {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ScnMdl::CopiedMatAccess matAccess(mdl, i);
+ nw4r::g3d::ResGenMode resGenMode = matAccess.GetResGenMode(bMarkDirty);
+ resGenMode.GXSetCullMode(cullMode);
+ }
+ } else {
+ for (u32 i = 0; i < resMdl.GetResMatNumEntries(); i++) {
+ nw4r::g3d::ResMat resMat = getResMat(i);
+ nw4r::g3d::ResGenMode resGenMode = resMat.GetResGenMode();
+ resGenMode.GXSetCullMode(cullMode);
+ }
+ }
+}
+
+void bmdl_c::setMatVisible(u32 matId, bool bVisble) {
+ // TODO
+}
+
+int bmdl_c::setMatTexture(char *name, GXTexObj *texObj, bool copy, void *unk, int, int) {
+ // TODO
+}
+
+bool bmdl_c::getBounds(mVec3_c *min, mVec3_c *max) {
+ // TODO
+}
+
+void bmdl_c::remove() {
+ mpCurrentAnm = nullptr;
+ scnLeaf_c::remove();
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_calc_ratio.cpp b/src/m/m3d/m_calc_ratio.cpp
new file mode 100644
index 00000000..f4ae81f6
--- /dev/null
+++ b/src/m/m3d/m_calc_ratio.cpp
@@ -0,0 +1,73 @@
+#include <m/m3d/m_calc_ratio.h>
+#include <nw4r/math/math_arithmetic.h>
+
+namespace m3d {
+
+calcRatio_c::calcRatio_c() {
+ mf1 = 0.0f;
+ mf2 = 1.0f;
+ mf3 = 0.0f;
+ mf4 = 0.0f;
+ mf5 = 1.0f;
+ mb1 = 0;
+ mb2 = 0;
+}
+
+calcRatio_c::~calcRatio_c() {}
+
+void calcRatio_c::remove() {
+ mb1 = 0;
+ reset();
+}
+
+void calcRatio_c::reset() {
+ mf1 = 0.0f;
+ mf2 = 1.0f;
+ mf4 = 0.0f;
+ mf5 = 1.0f;
+}
+
+void calcRatio_c::offUpdate() {
+ mb1 = 1;
+ mb2 = 0;
+}
+
+void calcRatio_c::set(f32 value) {
+ if (value == 0.0f) {
+ reset();
+ return;
+ }
+ mf1 = 1.0f;
+ mf2 = 0.0f;
+ mf4 = 1.0f;
+ mf5 = 0.0f;
+ mb2 = 1;
+ mf3 = 1.0f / value;
+}
+
+void calcRatio_c::calc() {
+ if (mf1 == 0.0f) {
+ return;
+ }
+
+ mf2 += mf3;
+ if (mf2 >= 1.0f) {
+ reset();
+ } else {
+ mb2 = 1;
+ f32 start = mf1;
+ f32 tmp = start - start * mf2 * mf2;
+ mf1 = tmp;
+ f32 max = 1.0f - mf1;
+ tmp = mf1 / start;
+ f32 inv = nw4r::math::FInv(tmp + max);
+ mf4 = tmp * inv;
+ mf5 = max * inv;
+ }
+}
+
+bool calcRatio_c::isEnd() const {
+ return mf1 == 0.0f;
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_fanm.cpp b/src/m/m3d/m_fanm.cpp
new file mode 100644
index 00000000..21cd0686
--- /dev/null
+++ b/src/m/m3d/m_fanm.cpp
@@ -0,0 +1,133 @@
+#include <m/m3d/m_fanm.h>
+
+namespace m3d {
+
+fanm_c::fanm_c() {
+ mEndFrame = 0.0f;
+ mCurrentFrame = 0.0f;
+ mPlayState = 0.0f;
+}
+fanm_c::~fanm_c() {}
+
+void fanm_c::play() {
+ f32 frame = mpAnmObj->GetFrame();
+ f32 rate = mpAnmObj->GetUpdateRate();
+ bool rateWasNegative = rate < 0.0f;
+ if (rateWasNegative) {
+ rate *= -1.0f;
+ }
+ mCurrentFrame = frame;
+
+ f32 newFrame;
+ if (rateWasNegative || (mPlayState & 2)) {
+ if (frame >= rate + mStartFrame) {
+ newFrame = frame - rate;
+ } else if ((mPlayState & 1) == 0) {
+ newFrame = frame + ((mEndFrame - rate) - mStartFrame);
+ } else {
+ newFrame = mStartFrame;
+ }
+ } else {
+ newFrame = frame + rate;
+ if ((mPlayState & 1) == 0) {
+ if (newFrame >= mEndFrame) {
+ newFrame = newFrame - mEndFrame;
+ }
+ } else {
+ f32 t = mEndFrame - 1.0f;
+ if (newFrame >= t) {
+ newFrame = t;
+ }
+ }
+ }
+
+ mpAnmObj->SetFrame(newFrame);
+}
+
+void fanm_c::set(f32 startFrame, playMode_e mode, f32 updateRate, f32 currentFrame) {
+ if (currentFrame < 0.0f) {
+ currentFrame = startFrame;
+ if (mode == PLAY_MODE_1) {
+ currentFrame = 0.0f;
+ } else {
+ currentFrame -= 1.0f;
+ }
+ }
+
+ mEndFrame = startFrame;
+ mStartFrame = 0.0f;
+ mpAnmObj->SetFrame(currentFrame);
+ mpAnmObj->SetUpdateRate(updateRate);
+ mPlayState = (u8)mode;
+ mCurrentFrame = currentFrame;
+}
+
+void fanm_c::set2(f32 startFrame, playMode_e mode, f32 endFrame, f32 rate, f32 currentFrame) {
+ if (currentFrame < 0.0f) {
+ currentFrame = rate < 0.0f ? endFrame - 1.0f : startFrame;
+ }
+
+ mStartFrame = startFrame;
+ mEndFrame = endFrame;
+ mpAnmObj->SetFrame(currentFrame);
+ mpAnmObj->SetUpdateRate(rate);
+ mPlayState = (u8)mode;
+ mCurrentFrame = currentFrame;
+}
+
+// assumed name
+void fanm_c::setFrameOnly(f32 frame) {
+ banm_c::setFrameOnly(frame);
+ mCurrentFrame = frame;
+}
+
+bool fanm_c::isStop() const {
+ f32 frame = mpAnmObj->GetFrame();
+ f32 rate = mpAnmObj->GetUpdateRate();
+ if (rate < 0.0f || mPlayState == PLAY_MODE_3) {
+ return frame <= mStartFrame;
+ } else if (mPlayState == PLAY_MODE_1) {
+ return frame >= mEndFrame - 1.0f;
+ }
+ return false;
+}
+
+bool fanm_c::checkFrame(f32 frame) const {
+ f32 stored = mpAnmObj->GetFrame();
+ if (mCurrentFrame == stored) {
+ return stored == frame;
+ }
+
+ f32 rate = mpAnmObj->GetUpdateRate();
+ if (rate < 0.0f || (mPlayState & 2)) {
+ if (mCurrentFrame > stored) {
+ if (mCurrentFrame > frame && stored <= frame) {
+ return true;
+ }
+ } else if (frame < mCurrentFrame || frame >= stored) {
+ return true;
+ }
+ } else {
+ if (mCurrentFrame < stored) {
+ if (mCurrentFrame < frame && stored >= frame) {
+ return true;
+ }
+ } else if (frame > mCurrentFrame || frame <= stored) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool fanm_c::unk_802EAE70() const {
+ f32 frame = mpAnmObj->GetFrame();
+ f32 rate = mpAnmObj->GetUpdateRate();
+ if (rate < 0.0f || (mPlayState & 2)) {
+ return mCurrentFrame < frame;
+ } else {
+ return mCurrentFrame > frame;
+ }
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_mdl.cpp b/src/m/m3d/m_mdl.cpp
new file mode 100644
index 00000000..a6879840
--- /dev/null
+++ b/src/m/m3d/m_mdl.cpp
@@ -0,0 +1,239 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_mdl.h>
+#include <nw4r/g3d/g3d_scnmdlsmpl.h>
+
+namespace m3d {
+
+mdl_c::mdlCallback_c::mdlCallback_c() {
+ mNumNode = 0;
+ mpNodes = nullptr;
+ mpBaseCallback = 0;
+ mpAlloc = nullptr;
+}
+mdl_c::mdlCallback_c::~mdlCallback_c() {}
+
+void mdl_c::mdlCallback_c::ExecCallbackA(nw4r::g3d::ChrAnmResult *result, nw4r::g3d::ResMdl mdl,
+ nw4r::g3d::FuncObjCalcWorld *o) {
+ u16 nodeId = o->GetNodeId();
+ nw4r::g3d::ChrAnmResult *resPtr = &mpNodes[nodeId];
+ if (mCalcRatio.is0x18() && !mCalcRatio.isEnd()) {
+ if (!mCalcRatio.is0x19()) {
+ *result = *resPtr;
+ } else {
+ u32 flags = result->mFlags;
+ f32 f2 = mCalcRatio.get0x10();
+ f32 f1 = mCalcRatio.get0x14();
+
+ // TODO clean up this code, what does it even do, why do operators
+ // break
+ if ((flags & 8) == 0) {
+ result->VEC3_0x4.x = (result->VEC3_0x4.x * f1 + resPtr->VEC3_0x4.x * f2);
+ result->VEC3_0x4.y = (result->VEC3_0x4.y * f1 + resPtr->VEC3_0x4.y * f2);
+ result->VEC3_0x4.z = (result->VEC3_0x4.z * f1 + resPtr->VEC3_0x4.z * f2);
+ } else {
+ result->VEC3_0x4.x = (f1 + resPtr->VEC3_0x4.x * f2);
+ result->VEC3_0x4.y = (f1 + resPtr->VEC3_0x4.y * f2);
+ result->VEC3_0x4.z = (f1 + resPtr->VEC3_0x4.z * f2);
+ }
+
+ nw4r::math::QUAT q1;
+ nw4r::math::QUAT q2;
+
+ C_QUATMtx(q1, resPtr->mMtx);
+ if ((flags & 0x20) == 0) {
+ C_QUATMtx(q2, result->mMtx);
+ } else {
+ q2.x = 0.0f;
+ q2.y = 0.0f;
+ q2.z = 0.0f;
+ q2.w = 1.0f;
+ }
+
+ C_QUATSlerp(q1, q2, q1, f1);
+ nw4r::math::VEC3 tmp;
+ tmp.x = result->mMtx._03;
+ tmp.y = result->mMtx._13;
+ tmp.z = result->mMtx._23;
+ PSMTXQuat(result->mMtx, q1);
+ result->mMtx._03 = tmp.x;
+ result->mMtx._13 = tmp.y;
+ result->mMtx._23 = tmp.z;
+ if ((flags & 0x40) == 0) {
+ result->mMtx._03 = tmp.x * f1;
+ result->mMtx._13 = tmp.y * f1;
+ result->mMtx._23 = tmp.z * f1;
+ }
+ result->mMtx._03 += resPtr->mMtx._03 * f2;
+ result->mMtx._13 += resPtr->mMtx._13 * f2;
+ result->mMtx._23 += resPtr->mMtx._23 * f2;
+ result->mFlags = result->mFlags & ~(0x80000000 | 0x00000040 | 0x00000020 | 0x00000008);
+ *resPtr = *result;
+ }
+ } else {
+ *resPtr = *result;
+ }
+
+ if (mpBaseCallback != nullptr) {
+ mpBaseCallback->timingA(nodeId, result, mdl);
+ }
+}
+
+void mdl_c::mdlCallback_c::ExecCallbackB(nw4r::g3d::WorldMtxManip *m, nw4r::g3d::ResMdl mdl,
+ nw4r::g3d::FuncObjCalcWorld *o) {
+ u16 nodeId = o->GetNodeId();
+ if (mpBaseCallback != nullptr) {
+ mpBaseCallback->timingB(nodeId, m, mdl);
+ }
+ // Not sure what this does
+ u32 num = mdl.GetResNodeNumEntries();
+ u32 nodeInc = nodeId + 1;
+ u32 tmp = (nodeInc / num);
+ o->SetNodeId(nodeInc - tmp * num);
+}
+
+void mdl_c::mdlCallback_c::ExecCallbackC(nw4r::math::MTX34 *mat, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *) {
+ if (mpBaseCallback != nullptr) {
+ mpBaseCallback->timingC(mat, mdl);
+ }
+ mCalcRatio.offUpdate();
+}
+
+bool mdl_c::mdlCallback_c::create(nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size = 0;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ mNumNode = mdl.GetResNodeNumEntries();
+ size_t bufSize = mNumNode * sizeof(nw4r::g3d::ChrAnmResult);
+ mpNodes = (nw4r::g3d::ChrAnmResult *)MEMAllocFromAllocator(alloc, bufSize);
+ if (mpNodes == nullptr) {
+ return false;
+ }
+
+ *pSize = ROUND_UP(bufSize + ROUND_UP(*pSize, 0x04), 0x04);
+ nw4r::g3d::ChrAnmResult *node = mpNodes;
+ for (int i = 0; i < mNumNode; i++) {
+ node->VEC3_0x4.x = 1.0f;
+ node->VEC3_0x4.y = 1.0f;
+ node->VEC3_0x4.z = 1.0f;
+ PSMTXIdentity(node->mMtx);
+ node++;
+ }
+
+ mpAlloc = alloc;
+ return true;
+}
+
+void mdl_c::mdlCallback_c::remove() {
+ mCalcRatio.remove();
+ if (mpNodes != nullptr) {
+ // Probably an m_allocator inline
+ MEMFreeToAllocator(mpAlloc, mpNodes);
+ }
+ mpNodes = nullptr;
+ mpAlloc = nullptr;
+}
+
+void mdl_c::mdlCallback_c::setBlendFrame(f32 frame) {
+ mCalcRatio.set(frame);
+}
+void mdl_c::mdlCallback_c::calcBlend() {
+ if (!mCalcRatio.isEnd()) {
+ mCalcRatio.calc();
+ }
+}
+
+mdl_c::mdl_c() : mpOwnedCallback(nullptr), mpCallback(nullptr) {}
+mdl_c::~mdl_c() {
+ remove();
+}
+
+bool mdl_c::create(nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u32 bufferOption, int nView, u32 *pSize) {
+ return create(mdl, nullptr, alloc, bufferOption, nView, pSize);
+}
+
+bool mdl_c::create(nw4r::g3d::ResMdl mdl, mdl_c::mdlCallback_c *cb, mAllocator_c *alloc, u32 bufferOption, int nView,
+ u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 tmp1;
+ u32 tmp2;
+ u32 *pSize1 = nullptr;
+ u32 *pSize2 = nullptr;
+ if (pSize != nullptr) {
+ pSize1 = &tmp1;
+ pSize2 = &tmp2;
+ }
+
+ if (!smdl_c::create(mdl, alloc, bufferOption, nView, pSize1)) {
+ return false;
+ }
+
+ if (cb == nullptr) {
+ mpOwnedCallback = (mdlCallback_c *)alloc->alloc(sizeof(mdlCallback_c));
+ if (mpOwnedCallback == nullptr) {
+ remove();
+ return false;
+ }
+
+ new (mpOwnedCallback) mdlCallback_c();
+ mpCallback = mpOwnedCallback;
+ } else {
+ mpCallback = cb;
+ }
+ if (!mpCallback->create(mdl, alloc, pSize2)) {
+ remove();
+ return false;
+ }
+
+ if (pSize != nullptr) {
+ *pSize = tmp1 + tmp2;
+ }
+ nw4r::g3d::ScnMdlSimple *sMdl;
+ sMdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf);
+ sMdl->SetCalcWorldCallback(mpCallback);
+ sMdl->EnableScnMdlCallbackTiming(nw4r::g3d::ScnObj::TIMING_ALL);
+ setCallback(nullptr);
+ return true;
+}
+
+void mdl_c::remove() {
+ if (mpOwnedCallback != nullptr) {
+ mAllocator_c *alloc = mpOwnedCallback->getAllocator();
+ mpOwnedCallback->remove();
+ mpOwnedCallback->~mdlCallback_c();
+ alloc->free(mpOwnedCallback);
+ mpOwnedCallback = nullptr;
+ mpCallback = nullptr;
+ }
+ bmdl_c::remove();
+}
+
+void mdl_c::setAnm(m3d::banm_c &anm) {
+ setAnm(anm, 0.0f);
+}
+
+void mdl_c::play() {
+ bmdl_c::play();
+ mpCallback->calcBlend();
+}
+
+void mdl_c::setAnm(m3d::banm_c &anm, f32 f) {
+ if (anm.getType() == nw4r::g3d::ScnMdlSimple::ANMOBJTYPE_CHR) {
+ mpCallback->setBlendFrame(f);
+ }
+ bmdl_c::setAnm(anm);
+}
+
+void mdl_c::setCallback(callback_c *cb) {
+ mpCallback->setBaseCallback(cb);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_proc.cpp b/src/m/m3d/m_proc.cpp
new file mode 100644
index 00000000..85ab31ec
--- /dev/null
+++ b/src/m/m3d/m_proc.cpp
@@ -0,0 +1,46 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_proc.h>
+#include <nw4r/g3d/g3d_scnproc.h>
+
+namespace m3d {
+
+void proc_c_drawProc(nw4r::g3d::ScnProc *proc, bool b) {
+ proc_c *p = static_cast<proc_c *>(proc->GetUserData());
+ if (b) {
+ p->drawOpa();
+ } else {
+ p->drawXlu();
+ }
+}
+
+proc_c::~proc_c() {}
+
+int proc_c::getType() const {
+ return SCN_LEAF_PROC;
+}
+
+void proc_c::drawOpa() {}
+void proc_c::drawXlu() {}
+
+bool proc_c::create(mAllocator_c *alloc, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 size;
+ if (pSize == nullptr) {
+ pSize = &size;
+ }
+
+ mpScnLeaf = nw4r::g3d::ScnProc::Construct(alloc, pSize, proc_c_drawProc, true, true, 0);
+ if (!mpScnLeaf) {
+ return false;
+ }
+
+ mpScnLeaf->SetPriorityDrawOpa(0x7f);
+ mpScnLeaf->SetPriorityDrawXlu(0x7f);
+ nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnProc>(mpScnLeaf)->SetUserData(this);
+ return true;
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_scnLeaf.cpp b/src/m/m3d/m_scnLeaf.cpp
new file mode 100644
index 00000000..43f83c7c
--- /dev/null
+++ b/src/m/m3d/m_scnLeaf.cpp
@@ -0,0 +1,108 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_scnleaf.h>
+
+namespace m3d {
+
+scnLeaf_c::scnLeaf_c() : mpScnLeaf(nullptr) {}
+
+scnLeaf_c::~scnLeaf_c() {
+ scnLeaf_c::remove();
+}
+
+void scnLeaf_c::remove() {
+ if (mpScnLeaf != nullptr) {
+ mpScnLeaf->Destroy();
+ mpScnLeaf = nullptr;
+ }
+}
+
+int scnLeaf_c::entry() {
+ return pushBack(mpScnLeaf);
+}
+
+void scnLeaf_c::setOption(u32 flag, u32 set) {
+ mpScnLeaf->SetScnObjOption(flag, set);
+}
+
+void scnLeaf_c::setScale(f32 x, f32 y, f32 z) {
+ mpScnLeaf->SetScale(x, y, z);
+}
+
+void scnLeaf_c::setScale(const nw4r::math::VEC3 &scale) {
+ mpScnLeaf->SetScale(scale);
+}
+
+void scnLeaf_c::getScale(nw4r::math::VEC3 *vec) const {
+ mpScnLeaf->GetScale(vec);
+}
+
+void scnLeaf_c::setLocalMtx(const nw4r::math::MTX34 *mtx) {
+ mpScnLeaf->SetMtx(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL, mtx);
+}
+
+void scnLeaf_c::getLocalMtx(nw4r::math::MTX34 *mtx) const {
+ mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL, mtx);
+}
+
+const nw4r::math::MTX34 *scnLeaf_c::getLocalMtx() const {
+ return mpScnLeaf->GetMtxPtr(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL);
+}
+
+void scnLeaf_c::getWorldMtx(nw4r::math::MTX34 *mtx) const {
+ mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_WORLD, mtx);
+}
+
+void scnLeaf_c::getViewMtx(nw4r::math::MTX34 *mtx) const {
+ mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_VIEW, mtx);
+}
+
+// unofficial
+void scnLeaf_c::setCallback(nw4r::g3d::IScnObjCallback *cb) {
+ mpScnLeaf->SetCallback(cb);
+}
+
+nw4r::g3d::IScnObjCallback *scnLeaf_c::swapCallback(nw4r::g3d::IScnObjCallback *cb) {
+ nw4r::g3d::IScnObjCallback *tmp = mpScnLeaf->GetScnObjCallback();
+ mpScnLeaf->SetCallback(cb);
+ return tmp;
+}
+
+void scnLeaf_c::enableCallbackTiming(nw4r::g3d::ScnObj::Timing timing) {
+ mpScnLeaf->EnableScnObjCallbackTiming(timing);
+}
+
+void scnLeaf_c::enableCallbackOp(nw4r::g3d::ScnObj::ExecOp op) {
+ mpScnLeaf->EnableScnObjCallbackExecOp(op);
+}
+
+void scnLeaf_c::calc(bool b) {
+ setOption(/* DISABLE_CALC_WORLD */ 0x02, false);
+ mpScnLeaf->G3dProc(1, 0, nullptr);
+ if (b == false) {
+ setOption(/* DISABLE_CALC_WORLD */ 0x02, true);
+ }
+}
+
+void scnLeaf_c::calcVtx(bool b) {
+ setOption(/* DISABLE_CALC_VTX */ 0x04, false);
+ mpScnLeaf->G3dProc(3, 0, nullptr);
+ if (b == false) {
+ setOption(/* DISABLE_CALC_VTX */ 0x04, true);
+ }
+}
+
+/** Unknown name/arg type */
+void scnLeaf_c::calcView(void *p, bool b) {
+ setOption(/* DISABLE_CALC_VIEW */ 0x05, false);
+ mpScnLeaf->G3dProc(4, 0, p);
+ if (b == false) {
+ setOption(/* DISABLE_CALC_VIEW */ 0x05, true);
+ }
+}
+
+void scnLeaf_c::setPriorityDraw(int opa, int xlu) {
+ mpScnLeaf->SetPriorityDrawOpa(opa);
+ mpScnLeaf->SetPriorityDrawXlu(xlu);
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_smdl.cpp b/src/m/m3d/m_smdl.cpp
new file mode 100644
index 00000000..e5d96425
--- /dev/null
+++ b/src/m/m3d/m_smdl.cpp
@@ -0,0 +1,35 @@
+#include <m/m3d/m3d.h>
+#include <m/m3d/m_smdl.h>
+#include <nw4r/g3d/g3d_scnmdl.h>
+#include <nw4r/g3d/g3d_scnmdlsmpl.h>
+
+namespace m3d {
+
+smdl_c::smdl_c() {}
+smdl_c::~smdl_c() {}
+
+bool smdl_c::create(nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u32 bufferOption, int nView, u32 *pSize) {
+ if (alloc == nullptr) {
+ alloc = internal::l_allocator_p;
+ }
+
+ u32 tmp;
+ if (pSize == nullptr) {
+ pSize = &tmp;
+ }
+
+ if (bufferOption != 0) {
+ mpScnLeaf = nw4r::g3d::ScnMdl::Construct(alloc, pSize, mdl, bufferOption, nView);
+ } else {
+ mpScnLeaf = nw4r::g3d::ScnMdlSimple::Construct(alloc, pSize, mdl, nView);
+ }
+
+ if (mpScnLeaf == nullptr) {
+ return false;
+ }
+ mpScnLeaf->SetPriorityDrawOpa(0x7f);
+ mpScnLeaf->SetPriorityDrawXlu(0x7f);
+ return true;
+}
+
+} // namespace m3d
diff --git a/src/m/m3d/m_video.cpp b/src/m/m3d/m_video.cpp
new file mode 100644
index 00000000..b5ef2eb6
--- /dev/null
+++ b/src/m/m3d/m_video.cpp
@@ -0,0 +1,13 @@
+#include <d/d_system.h>
+#include <m/m_video.h>
+
+// I dont know if this file actually exists, the place that the function exists is in an odd spot
+
+namespace mVideo {
+
+// 0x80065590
+void create() {
+ // TODO
+}
+
+} // namespace mVideo
diff --git a/src/m/m_allocator.cpp b/src/m/m_allocator.cpp
index e03651df..6211fa00 100644
--- a/src/m/m_allocator.cpp
+++ b/src/m/m_allocator.cpp
@@ -99,6 +99,6 @@ void mHeapAllocator_c::adjustFrmHeapRestoreCurrent() {
mHeap::adjustFrmHeap(static_cast<EGG::FrmHeap *>(getHeapOfKind(heap, EGG::Heap::HEAP_KIND_FRAME)));
}
-void *mHeapAllocator_c::allocOnHeap(u32 size, mHeapAllocator_c *allocator) {
+void *operator new[](size_t size, mAllocator_c *allocator) {
return allocator->alloc(size);
}
diff --git a/src/m/m_fader.cpp b/src/m/m_fader.cpp
index 8f88a4ab..7e537c46 100644
--- a/src/m/m_fader.cpp
+++ b/src/m/m_fader.cpp
@@ -1,13 +1,10 @@
#include <m/m_fader.h>
-
-// nw4r::g3d::G3DState::Invalidate
-extern "C" void fn_8044E3B0(u32 flags);
-// m3d::resetMaterial according to NSMBW
-extern "C" void fn_802E46D0();
+#include <m/m3d/m3d.h>
+#include <nw4r/g3d/g3d_state.h>
void mFader_c::draw() {
- fn_8044E3B0(0x7ff);
- fn_802E46D0();
+ nw4r::g3d::G3DState::Invalidate(0x7ff);
+ m3d::resetMaterial();
mpFader->draw();
}