diff options
| author | robojumper <robojumper@gmail.com> | 2024-09-12 22:36:34 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-12 16:36:34 -0400 |
| commit | 1180e1f4860d62bccd64bfa2a29eaeebd2c4b019 (patch) | |
| tree | ce6e231ef46aacbdad52ad7f6cbcd9d02dba555e /src | |
| parent | e2c4bb7be7fa731a335bce4bc22283d899133e39 (diff) | |
m3d (#13)
* Initial M3d Pass
* `m_bmdl` and `m_bline` left
---------
Co-authored-by: elijah-thomas774 <elijahthomas774@gmail.com>
Co-authored-by: Elijah Thomas <42302100+elijah-thomas774@users.noreply.github.com>
Diffstat (limited to 'src')
33 files changed, 2912 insertions, 15 deletions
diff --git a/src/REL/d/a/e/d_a_e_hb_leaf.cpp b/src/REL/d/a/e/d_a_e_hb_leaf.cpp index e69de29b..e055631e 100644 --- a/src/REL/d/a/e/d_a_e_hb_leaf.cpp +++ b/src/REL/d/a/e/d_a_e_hb_leaf.cpp @@ -0,0 +1,109 @@ +#include <d/a/e/d_a_e_hb_leaf.h> + +const f32 dAcEhb_leaf_c::unkFloat0 = 0.0f; +const f32 dAcEhb_leaf_c::unkFloat1 = -0.0f; + +SPECIAL_ACTOR_PROFILE(E_HB_LEAF, dAcEhb_leaf_c, fProfile::E_HB_LEAF, 0x100, 0, 3); + +bool dAcEhb_leaf_c::createHeap() { + // This is ever so slightly weird but our m_anmMdl really doesn't take ResFile by value + // but only ever a single pointer. + void *fp = getOarcResFile("Degubaba"); + TRY_CREATE(mModel.create(fp, "degubaba_leaf", "shake2", &heap_allocator, 0x123)); + nw4r::g3d::ResFile f = fp; + nw4r::g3d::ResMdl mdl = f.GetResMdl("degubaba_leaf"); + nw4r::g3d::ResAnmTexPat anm = f.GetResAnmTexPat("degubaba_leaf"); + TRY_CREATE(mAnm.create(mdl, anm, &heap_allocator, nullptr, 1)); + mModel.getModel().setAnm(mAnm); + return true; +} + +int dAcEhb_leaf_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcEhb_leaf_c::m_allocator", 0x20)) { + return FAILED; + } + + setBoundingBox(mVec3_c(-100.0f, -100.0f, -100.0f), mVec3_c(100.0f, 100.0f, 100.0f)); + + rotation.y = cM::rndF(65535.0f); + someRot = rotation.y.mVal; + + switch (getParam1()) { + case 0: + case 7: + mType = 0; + break; + case 1: + mType = 1; + break; + case 2: + mType = 2; + break; + case 3: + case 4: + case 5: + rotation.z = -0x8000; + break; + default: + break; + } + + if (mType == 0) { + u32 param2 = getParam2(); + if (param2 == 1) { + mType = 1; + } else if (param2 == 2) { + mType = 2; + } + } + + if (mType == 2) { + field_0x3CC = 1; + someFloat = 1.0f; + } + + if (mType != 0) { + actor_properties &= ~1; + } + + mStartingPos = position; + + return SUCCEEDED; +} + +int dAcEhb_leaf_c::doDelete() { + return 1; +} + +int dAcEhb_leaf_c::actorExecute() { + if (mType != 0) { + doCheck(); + if (isNearZero()) { + return 1; + } + } + + updateMatrix(); + if (mType != 0) { + Mtx m; + PSMTXScale(m, someFloat, someFloat, someFloat); + PSMTXConcat(worldMatrix.m, m, worldMatrix.m); + } + mModel.getModel().setLocalMtx(worldMatrix); + mModel.getModel().calc(false); + someRot++; + + return 1; +} + +int dAcEhb_leaf_c::draw() { + if (!isHidden()) { + drawModelType1(&mModel.getModel()); + } + + return 1; +} + +void dAcEhb_leaf_c::setAnm(const char *anm, f32 pos) { + mModel.setAnm(anm, m3d::PLAY_MODE_4, pos); +} diff --git a/src/REL/d/a/obj/d_a_obj_lava_F200.cpp b/src/REL/d/a/obj/d_a_obj_lava_F200.cpp index e69de29b..78ad3147 100644 --- a/src/REL/d/a/obj/d_a_obj_lava_F200.cpp +++ b/src/REL/d/a/obj/d_a_obj_lava_F200.cpp @@ -0,0 +1,66 @@ +#include <d/a/obj/d_a_obj_lava_F200.h> +#include <toBeSorted/room_manager.h> + +SPECIAL_ACTOR_PROFILE(OBJ_LAVA_F200, dAcOlavaF200_c, fProfile::OBJ_LAVA_F200, 0x0214, 0, 0); + +bool dAcOlavaF200_c::createHeap() { + mBrres = getOarcResFile("LavaF200"); + RoomManager::bindStageResToFile(&mBrres); + + nw4r::g3d::ResMdl mdl0 = mBrres.GetResMdl("LavaF200"); + TRY_CREATE(mModels[0].create(mdl0, &heap_allocator, 0x32C)); + nw4r::g3d::ResAnmTexSrt anmTex0 = mBrres.GetResAnmTexSrt("LavaF200"); + TRY_CREATE(mTexAnms[0].create(mdl0, anmTex0, &heap_allocator, nullptr, 1)); + nw4r::g3d::ResAnmClr anmClr0 = mBrres.GetResAnmClr("LavaF200"); + TRY_CREATE(mClrAnms[0].create(mdl0, anmClr0, &heap_allocator, nullptr, 1)); + + nw4r::g3d::ResMdl mdl1 = mBrres.GetResMdl("LavaF200_s"); + TRY_CREATE(mModels[1].create(mdl1, &heap_allocator, 0x32C)); + nw4r::g3d::ResAnmTexSrt anmTex1 = mBrres.GetResAnmTexSrt("LavaF200_s"); + TRY_CREATE(mTexAnms[1].create(mdl1, anmTex1, &heap_allocator, nullptr, 1)); + nw4r::g3d::ResAnmClr anmClr1 = mBrres.GetResAnmClr("LavaF200_s"); + TRY_CREATE(mClrAnms[1].create(mdl1, anmClr1, &heap_allocator, nullptr, 1)); + + return true; +} + +int dAcOlavaF200_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcOlavaF200_c::m_allocator", 0x20)) { + return FAILED; + } + + mModels[0].setAnm(mTexAnms[0]); + mModels[1].setAnm(mTexAnms[1]); + mModels[0].setAnm(mClrAnms[0]); + mModels[1].setAnm(mClrAnms[1]); + + updateMatrix(); + for (int i = 0; i < 2; i++) { + mModels[i].setLocalMtx(worldMatrix); + } + + mModels[0].setPriorityDraw(0x1C, 9); + mModels[1].setPriorityDraw(0x22, 9); + setBoundingBox(mVec3_c(-0.0f, -0.0f, -0.0f), mVec3_c(0.0f, 0.0f, 0.0f)); + + return SUCCEEDED; +} + +int dAcOlavaF200_c::doDelete() { + return 1; +} + +int dAcOlavaF200_c::actorExecute() { + mTexAnms[0].play(); + mTexAnms[1].play(); + mClrAnms[0].play(); + mClrAnms[1].play(); + return 1; +} + +int dAcOlavaF200_c::draw() { + for (int i = 0; i < 2; i++) { + drawModelType1(&mModels[i]); + } + return 1; +} diff --git a/src/REL/d/a/obj/d_a_obj_mole_soil.cpp b/src/REL/d/a/obj/d_a_obj_mole_soil.cpp index e69de29b..92d688fc 100644 --- a/src/REL/d/a/obj/d_a_obj_mole_soil.cpp +++ b/src/REL/d/a/obj/d_a_obj_mole_soil.cpp @@ -0,0 +1,120 @@ +#include <d/a/obj/d_a_obj_mole_soil.h> +#include <s/s_Math.h> + +SPECIAL_ACTOR_PROFILE(OBJ_MOLE_SOIL, dAcOmoleSoil_c, fProfile::OBJ_MOLE_SOIL, 0x008B, 0, 6); + +STATE_DEFINE(dAcOmoleSoil_c, Wait); +STATE_DEFINE(dAcOmoleSoil_c, Appear); +STATE_DEFINE(dAcOmoleSoil_c, DisAppear); + +const f32 dAcOmoleSoil_c::sHalfScale = 0.5f; +const f32 dAcOmoleSoil_c::sFullScale = 1.0f; + +bool dAcOmoleSoil_c::createHeap() { + nw4r::g3d::ResFile file = getOarcResFile("MogumaMud"); + if (!file.mFile.IsValid()) { + return false; + } + mBrres = file; + nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("MogumaMud"); + TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x120, 1, nullptr)); + mModel.setPriorityDraw(0x1c, 9); + return true; +} + +bool intToBool(int a) { + return a; +} + +int dAcOmoleSoil_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcOmoleSoil_c::m_allocator", 0x20)) { + return FAILED; + } + + mScale = sHalfScale; + scale.set(sHalfScale, sHalfScale, sHalfScale); + mStateMgr.changeState(StateID_Wait); + + setBoundingBox(mVec3_c(-100.0f, -0.0f, -100.0f), mVec3_c(100.0f, 100.0f, 100.0f)); + return SUCCEEDED; +} + +int dAcOmoleSoil_c::doDelete() { + return 1; +} + +int dAcOmoleSoil_c::actorExecute() { + switch (getNextState()) { + case 1: + if (!mStateMgr.isState(StateID_Appear)) { + mStateMgr.changeState(StateID_Appear); + } + break; + case 2: + if (!mStateMgr.isState(StateID_DisAppear)) { + mStateMgr.changeState(StateID_DisAppear); + } + break; + case 3: + if (!mStateMgr.isState(StateID_Appear)) { + mStateMgr.changeState(StateID_Appear); + } + break; + } + mStateMgr.executeState(); + updateMatrix(); + mModel.setLocalMtx(worldMatrix); + return 1; +} + +int dAcOmoleSoil_c::draw() { + if (field_0x391) { + drawModelType1(&mModel); + } + return 1; +} + +void dAcOmoleSoil_c::initializeState_Wait() { + mDesiredNextState = 0; +} +void dAcOmoleSoil_c::executeState_Wait() {} +void dAcOmoleSoil_c::finalizeState_Wait() {} + +void dAcOmoleSoil_c::initializeState_Appear() { + field_0x391 = true; +} +void dAcOmoleSoil_c::executeState_Appear() { + f32 stepSize = 0.05f; + if (sLib::chase(&mScale, sFullScale, stepSize)) { + mStateMgr.changeState(StateID_Wait); + } else { + mModel.setScale(mScale, mScale, mScale); + } +} +void dAcOmoleSoil_c::finalizeState_Appear() { + mDesiredNextState = 0; + mScale = sFullScale; + mModel.setScale(sFullScale, sFullScale, sFullScale); +} + +void dAcOmoleSoil_c::initializeState_DisAppear() { + field_0x391 = true; +} + +void dAcOmoleSoil_c::executeState_DisAppear() { + // Nothing about this makes sense but this creates the necessary casts + // and operations. Note that Ghidra constant-folds this despite + // all the stack operations for the cast. + int scalar = 0; + f32 stepSize = 0.01f * scalar + 0.05f; + if (sLib::chase(&mScale, sHalfScale, stepSize)) { + mStateMgr.changeState(StateID_Wait); + } else { + mModel.setScale(mScale, mScale, mScale); + } +} +void dAcOmoleSoil_c::finalizeState_DisAppear() { + mDesiredNextState = 0; + mScale = sHalfScale; + mModel.setScale(sHalfScale, sHalfScale, sHalfScale); +} diff --git a/src/REL/d/a/obj/d_a_obj_ring.cpp b/src/REL/d/a/obj/d_a_obj_ring.cpp index e69de29b..c6885766 100644 --- a/src/REL/d/a/obj/d_a_obj_ring.cpp +++ b/src/REL/d/a/obj/d_a_obj_ring.cpp @@ -0,0 +1,72 @@ +#include <d/a/obj/d_a_obj_ring.h> +#include <d/d_player.h> + +SPECIAL_ACTOR_PROFILE(OBJ_RING, dAcOring_c, fProfile::OBJ_RING, 0x00f2, 0, 0x103); + +STATE_DEFINE(dAcOring_c, Move); + +bool dAcOring_c::createHeap() { + nw4r::g3d::ResFile f = getOarcResFile("PRing"); + nw4r::g3d::ResMdl mdl = f.GetResMdl("PeehatRing"); + // This matches but in a really weird way. Maybe an inline function? + TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x20, 1, nullptr)); + return true; +} + +int dAcOring_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcOring_c::m_allocator", 0x20)) { + return FAILED; + } + + field_0x388 = getArgFromParams(); + + setBoundingBox(mVec3_c(-100.0f, -100.0f, -100.0f), mVec3_c(100.0f, 100.0f, 100.0f)); + updateMatrix(); + mModel.setScale(scale); + mModel.setLocalMtx(worldMatrix); + forwardAccel = -5.0f; + forwardMaxSpeed = -40.0f; + field_0x38C = dPlayer::LINK->position.y; + mStateMgr.changeState(StateID_Move); + return SUCCEEDED; +} + +int dAcOring_c::doDelete() { + return 1; +} + +int dAcOring_c::actorExecute() { + mStateMgr.executeState(); + calcVelocity(); + position += velocity; + position += posIncrements; + updateMatrix(); + mModel.setLocalMtx(worldMatrix); + return 1; +} + +int dAcOring_c::draw() { + drawModelType1(&mModel); + return 1; +} + +void dAcOring_c::initializeState_Move() {} + +u32 dAcOring_c::ROT_PER_TICK = 0x1000; + +void dAcOring_c::executeState_Move() { + bool isCarried = false; + if (mActorCarryInfo.isCarried == 1 && mActorCarryInfo.carryType == 7) { + isCarried = true; + } + + if (isCarried) { + return; + } + rotation.x.mVal += ROT_PER_TICK; + if (field_0x38C >= position.y) { + deleteRequest(); + } +} + +void dAcOring_c::finalizeState_Move() {} diff --git a/src/REL/d/a/obj/d_a_obj_smoke.cpp b/src/REL/d/a/obj/d_a_obj_smoke.cpp index e69de29b..36c1e232 100644 --- a/src/REL/d/a/obj/d_a_obj_smoke.cpp +++ b/src/REL/d/a/obj/d_a_obj_smoke.cpp @@ -0,0 +1,60 @@ +#include <d/a/obj/d_a_obj_smoke.h> + +static const char *const sSmokeNames1[] = { + "SmokeF200", + "SmokeF202", +}; + +static const char *const sSmokeNames2[] = { + "SmokeF200", + "SmokeF202", +}; + +SPECIAL_ACTOR_PROFILE(OBJ_SMOKE, dAcOsmoke_c, fProfile::OBJ_SMOKE, 0x01DB, 0, 4); + +STATE_DEFINE(dAcOsmoke_c, Wait); + +bool dAcOsmoke_c::createHeap() { + mType = params & 3; + mBrres = getOarcResFile(sSmokeNames1[mType]); + nw4r::g3d::ResMdl mdl = mBrres.GetResMdl(sSmokeNames2[mType]); + TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x324)); + nw4r::g3d::ResAnmTexSrt srt = mBrres.GetResAnmTexSrt(sSmokeNames1[mType]); + TRY_CREATE(mTexAnm.create(mdl, srt, &heap_allocator, nullptr, 1)); + return true; +} + +int dAcOsmoke_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcOsmoke_c::m_allocator", 0x20)) { + return FAILED; + } + + mModel.setAnm(mTexAnm); + updateMatrix(); + mModel.setLocalMtx(worldMatrix); + mStateMgr.changeState(StateID_Wait); + mModel.setPriorityDraw(0x1C, 9); + setBoundingBox(mVec3_c(-0.0f, -0.0f, -0.0f), mVec3_c(0.0f, 0.0f, 0.0f)); + return SUCCEEDED; +} + +int dAcOsmoke_c::doDelete() { + return 1; +} + +int dAcOsmoke_c::actorExecute() { + mStateMgr.executeState(); + mTexAnm.play(); + return 1; +} + +int dAcOsmoke_c::draw() { + drawModelType1(&mModel); + return 1; +} + +void dAcOsmoke_c::initializeState_Wait() {} + +void dAcOsmoke_c::executeState_Wait() {} + +void dAcOsmoke_c::finalizeState_Wait() {} diff --git a/src/REL/d/a/obj/d_a_obj_sun_light.cpp b/src/REL/d/a/obj/d_a_obj_sun_light.cpp index e69de29b..d1983877 100644 --- a/src/REL/d/a/obj/d_a_obj_sun_light.cpp +++ b/src/REL/d/a/obj/d_a_obj_sun_light.cpp @@ -0,0 +1,64 @@ +#include <d/a/obj/d_a_obj_sun_light.h> +#include <toBeSorted/arc_managers/current_stage_arc_manager.h> +#include <toBeSorted/room_manager.h> +#include <toBeSorted/scgame.h> + +SPECIAL_ACTOR_PROFILE(OBJ_SUN_LIGHT, dAcOsunLight_c, fProfile::OBJ_SUN_LIGHT, 0x0219, 0, 3); + +STATE_DEFINE(dAcOsunLight_c, Wait); + +bool dAcOsunLight_c::createHeap() { + mBrres = CurrentStageArcManager::sInstance->getData("g3d/stage.brres"); + RoomManager::bindStageResToFile(&mBrres); + RoomManager::bindSkyCmnToResFile(&mBrres); + nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("StageF000Light"); + TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x120)); + nw4r::g3d::ResAnmTexSrt srt = mBrres.GetResAnmTexSrt("StageF000Light"); + TRY_CREATE(mTexAnm.create(mdl, srt, &heap_allocator, nullptr, 1)); + return true; +} + +int dAcOsunLight_c::create() { + if (!initAllocatorWork1Heap(-1, "dAcOsunLight_c::m_allocator", 0x20)) { + return FAILED; + } + + mModel.setAnm(mTexAnm); + mStateMgr.changeState(StateID_Wait); + mModel.setPriorityDraw(0x1C, 9); + setBoundingBox(mVec3_c(-200.0f, -100.0f, -200.0f), mVec3_c(200.0f, 600.0f, 500.0f)); + return SUCCEEDED; +} + +int dAcOsunLight_c::doDelete() { + return 1; +} + +int dAcOsunLight_c::actorExecute() { + mStateMgr.executeState(); + if (isDay()) { + mTexAnm.play(); + } + updateMatrix(); + mModel.setLocalMtx(worldMatrix); + return 1; +} + +int dAcOsunLight_c::draw() { + if (isDay()) { + drawModelType1(&mModel); + } + return 1; +} + +void dAcOsunLight_c::initializeState_Wait() {} + +void dAcOsunLight_c::executeState_Wait() {} + +void dAcOsunLight_c::finalizeState_Wait() {} + +bool dAcOsunLight_c::isDay() { + // return !ScGame::currentSpawnInfo.isNight(); + // TODO TempFix? + return !(u8)ScGame::currentSpawnInfo.night; +} diff --git a/src/REL/d/t/d_t_rock_boat.cpp b/src/REL/d/t/d_t_rock_boat.cpp index c22d2b7c..7af93533 100644 --- a/src/REL/d/t/d_t_rock_boat.cpp +++ b/src/REL/d/t/d_t_rock_boat.cpp @@ -8,7 +8,7 @@ STATE_DEFINE(dTgRockBoat_c, Wait); int dTgRockBoat_c::create() { mStateMgr.changeState(StateID_Wait); cooldown = 1; - return 1; + return SUCCEEDED; } int dTgRockBoat_c::doDelete() { diff --git a/src/REL/d/t/d_t_sound_area.cpp b/src/REL/d/t/d_t_sound_area.cpp index 83aa1907..66159477 100644 --- a/src/REL/d/t/d_t_sound_area.cpp +++ b/src/REL/d/t/d_t_sound_area.cpp @@ -40,7 +40,7 @@ int dTgSndAr_c::create() { ac->setBit_field_0xE8(params & 0xFF); } } - return 1; + return SUCCEEDED; } int dTgSndAr_c::doDelete() { diff --git a/src/REL/d/t/d_t_sound_area_mgr.cpp b/src/REL/d/t/d_t_sound_area_mgr.cpp index 26da7f90..ef4eea02 100644 --- a/src/REL/d/t/d_t_sound_area_mgr.cpp +++ b/src/REL/d/t/d_t_sound_area_mgr.cpp @@ -7,7 +7,7 @@ int dTgSndMg_c::create() { s8 tmpRoomId = roomid; addActorToRoom(-1); roomid = tmpRoomId; - return 1; + return SUCCEEDED; } int dTgSndMg_c::doDelete() { diff --git a/src/REL/d/t/d_t_timer.cpp b/src/REL/d/t/d_t_timer.cpp index 4eef47a2..540e9ee2 100644 --- a/src/REL/d/t/d_t_timer.cpp +++ b/src/REL/d/t/d_t_timer.cpp @@ -27,7 +27,7 @@ int dTgTimer_c::create() { break; } resetTimer(); - return 1; + return SUCCEEDED; } int dTgTimer_c::actorExecute() { diff --git a/src/REL/d/t/d_t_tumble_weed.cpp b/src/REL/d/t/d_t_tumble_weed.cpp index 5534cb98..671073f3 100644 --- a/src/REL/d/t/d_t_tumble_weed.cpp +++ b/src/REL/d/t/d_t_tumble_weed.cpp @@ -12,7 +12,7 @@ int dTgTumbleWeed_c::create() { tumbleweedTimer = 0; windTimer = 0x96; mStateMgr.changeState(StateID_AreaOut); - return 1; + return SUCCEEDED; } u16 decr(u16 *num); 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(); } diff --git a/src/s/s_StateID.cpp b/src/s/s_StateID.cpp index bf9100ec..c03ca5a7 100644 --- a/src/s/s_StateID.cpp +++ b/src/s/s_StateID.cpp @@ -25,11 +25,11 @@ bool sStateID_c::isEqual(const sStateIDIf_c &other) const { return number() == other.number(); } -bool sStateID_c::operator==(const sStateIDIf_c &other) const { +BOOL sStateID_c::operator==(const sStateIDIf_c &other) const { return isEqual(other); } -bool sStateID_c::operator!=(const sStateIDIf_c &other) const { +BOOL sStateID_c::operator!=(const sStateIDIf_c &other) const { return !isEqual(other); } |
