Largely match m_shadow (#20)

* Largely match m_shadow

---------

Co-authored-by: elijah-thomas774 <elijahthomas774@gmail.com>
This commit is contained in:
robojumper
2024-09-13 20:51:33 +02:00
committed by GitHub
parent 4c6262aecd
commit 3b8392aeac
21 changed files with 990 additions and 70 deletions
+8
View File
@@ -376,6 +376,14 @@ m/m3d/m_scnleaf.cpp:
.text start:0x802EBBD0 end:0x802EBFF8
.data start:0x80542708 end:0x8054272C
m/m3d/m_shadow.cpp:
.text start:0x802EC000 end:0x802EDF2C
.ctors start:0x804DB8C8 end:0x804DB8CC
.data start:0x80542730 end:0x805427EC
.sdata start:0x80573FC8 end:0x80573FCC
.sbss start:0x80575BF0 end:0x80575C04
.sdata2 start:0x8057CD68 end:0x8057CD90
m/m3d/m_smdl.cpp:
.text start:0x802EDF30 end:0x802EE094
.data start:0x805427F0 end:0x80542820
+53 -53
View File
@@ -17655,40 +17655,40 @@ calc__Q23m3d9scnLeaf_cFb = .text:0x802EBE20; // type:function size:0x78
calcVtx__Q23m3d9scnLeaf_cFb = .text:0x802EBEA0; // type:function size:0x78
calcView__Q23m3d9scnLeaf_cFPvb = .text:0x802EBF20; // type:function size:0x84
setPriorityDraw__Q23m3d9scnLeaf_cFii = .text:0x802EBFB0; // type:function size:0x48
fn_802EC000 = .text:0x802EC000; // type:function size:0x88
fn_802EC090 = .text:0x802EC090; // type:function size:0x7C
fn_802EC110 = .text:0x802EC110; // type:function size:0x1E8
fn_802EC300 = .text:0x802EC300; // type:function size:0x2C
fn_802EC330 = .text:0x802EC330; // type:function size:0xD4
fn_802EC410 = .text:0x802EC410; // type:function size:0x8C
fn_802EC4A0 = .text:0x802EC4A0; // type:function size:0x1DC
fn_802EC680 = .text:0x802EC680; // type:function size:0x9C
fn_802EC720 = .text:0x802EC720; // type:function size:0x24
fn_802EC750 = .text:0x802EC750; // type:function size:0x28
fn_802EC780 = .text:0x802EC780; // type:function size:0xA4
fn_802EC830 = .text:0x802EC830; // type:function size:0x368
fn_802ECBA0 = .text:0x802ECBA0; // type:function size:0x170
fn_802ECD10 = .text:0x802ECD10; // type:function size:0x3E4
fn_802ED100 = .text:0x802ED100; // type:function size:0xE8
fn_802ED1F0 = .text:0x802ED1F0; // type:function size:0x20
fn_802ED210 = .text:0x802ED210; // type:function size:0x20
fn_802ED230 = .text:0x802ED230; // type:function size:0x20
fn_802ED250 = .text:0x802ED250; // type:function size:0x78
fn_802ED2D0 = .text:0x802ED2D0; // type:function size:0x60
fn_802ED330 = .text:0x802ED330; // type:function size:0x9C
fn_802ED3D0 = .text:0x802ED3D0; // type:function size:0x7C
fn_802ED450 = .text:0x802ED450; // type:function size:0x40
fn_802ED490 = .text:0x802ED490; // type:function size:0x16C
fn_802ED600 = .text:0x802ED600; // type:function size:0xF8
fn_802ED700 = .text:0x802ED700; // type:function size:0x148
fn_802ED850 = .text:0x802ED850; // type:function size:0x24C
fn_802EDAA0 = .text:0x802EDAA0; // type:function size:0x108
fn_802EDBB0 = .text:0x802EDBB0; // type:function size:0x68
fn_802EDC20 = .text:0x802EDC20; // type:function size:0x58
fn_802EDC80 = .text:0x802EDC80; // type:function size:0x8
fn_802EDC90 = .text:0x802EDC90; // type:function size:0x17C
fn_802EDE10 = .text:0x802EDE10; // type:function size:0x10C
fn_802EDF20 = .text:0x802EDF20; // type:function size:0xC
__dt__Q23m3d9mShadow_cFv = .text:0x802EC000; // type:function size:0x88
drawOpa__Q23m3d9mShadow_cFv = .text:0x802EC090; // type:function size:0x7C
create__Q23m3d9mShadow_cFiUciUsUlQ34nw4r3g3d6ResMdlUl = .text:0x802EC110; // type:function size:0x1E8
__ct__Q23m3d14mShadowChild_cFv = .text:0x802EC300; // type:function size:0x2C
remove__Q23m3d9mShadow_cFv = .text:0x802EC330; // type:function size:0xD4
reset__Q23m3d9mShadow_cFv = .text:0x802EC410; // type:function size:0x8C
addCircle__Q23m3d9mShadow_cFPQ23m3d15mShadowCircle_cUlUl = .text:0x802EC4A0; // type:function size:0x1DC
drawMdl__Q23m3d9mShadow_cFPQ23m3d15mShadowCircle_cUlRQ23m3d9scnLeaf_cRC7mQuat_cR7mVec3_c6mColorUlf = .text:0x802EC680; // type:function size:0x9C
addMdlToCircle__Q23m3d9mShadow_cFPQ23m3d15mShadowCircle_cRQ23m3d9scnLeaf_cRC7mQuat_c = .text:0x802EC720; // type:function size:0x24
removeCircle__Q23m3d9mShadow_cFPQ23m3d15mShadowCircle_c = .text:0x802EC750; // type:function size:0x28
drawTexObj__Q23m3d9mShadow_cFPQ23m3d15mShadowCircle_cUlPC9_GXTexObjRC6mMtx_cRC7mQuat_cR7mVec3_c6mColorUlf = .text:0x802EC780; // type:function size:0xA4
drawSub2__3m3dFPvUc = .text:0x802EC830; // type:function size:0x368 scope:local
drawSub1__3m3dFPvUc = .text:0x802ECBA0; // type:function size:0x170 scope:local
drawAllShadows__Q23m3d9mShadow_cFv = .text:0x802ECD10; // type:function size:0x3E4
create__Q23m3d9mShadow_cFPCQ23m3d19mShadowCircleConfigQ34nw4r3g3d6ResMdlPQ23EGG4Heap = .text:0x802ED100; // type:function size:0xE8
beforeDraw__Q23m3d9mShadow_cFv = .text:0x802ED1F0; // type:function size:0x20
draw__Q23m3d9mShadow_cFRC6mMtx_cUl = .text:0x802ED210; // type:function size:0x20
afterDraw__Q23m3d9mShadow_cFv = .text:0x802ED230; // type:function size:0x20
swapHeaps__Q23m3d9mShadow_cFv = .text:0x802ED250; // type:function size:0x78
destroy__Q23m3d9mShadow_cFv = .text:0x802ED2D0; // type:function size:0x60
__dt__Q23m3d14mShadowChild_cFv = .text:0x802ED330; // type:function size:0x9C
create__Q23m3d14mShadowChild_cFUcPQ23EGG4Heap = .text:0x802ED3D0; // type:function size:0x7C
set__Q23m3d14mShadowChild_cFRC7mVec3_cf6mColor = .text:0x802ED450; // type:function size:0x40
addMdl__Q23m3d14mShadowChild_cFRQ23m3d9scnLeaf_cRC7mQuat_c = .text:0x802ED490; // type:function size:0x16C
setGeom__Q23m3d14mShadowChild_cFPC9_GXTexObjRC6mMtx_cRC7mQuat_c = .text:0x802ED600; // type:function size:0xF8
updateMtx__Q23m3d14mShadowChild_cFv = .text:0x802ED700; // type:function size:0x148
drawMdl__Q23m3d14mShadowChild_cFv = .text:0x802ED850; // type:function size:0x24C
draw__Q23m3d14mShadowChild_cFv = .text:0x802EDAA0; // type:function size:0x108
__dt__Q23m3d15mShadowCircle_cFv = .text:0x802EDBB0; // type:function size:0x68
__dt__Q23m3d15mCustomShadow_cFv = .text:0x802EDC20; // type:function size:0x58
getType__Q23m3d15mCustomShadow_cCFv = .text:0x802EDC80; // type:function size:0x8
draw__Q23m3d15mCustomShadow_cFRC6mMtx_c = .text:0x802EDC90; // type:function size:0x17C
calc__Q23m3d15mCustomShadow_cF6mMtx_cR6mMtx_c = .text:0x802EDE10; // type:function size:0x10C
__sinit_\m_shadow_cpp = .text:0x802EDF20; // type:function size:0xC scope:local
__ct__Q23m3d6smdl_cFv = .text:0x802EDF30; // type:function size:0x4C
__dt__Q23m3d6smdl_cFv = .text:0x802EDF80; // type:function size:0x58
create__Q23m3d6smdl_cFQ34nw4r3g3d6ResMdlP12mAllocator_cUliPUl = .text:0x802EDFE0; // type:function size:0xB4
@@ -17865,7 +17865,7 @@ __arraydtor$4414 = .text:0x802F2310; // type:function size:0x1C
fn_802F2330 = .text:0x802F2330; // type:function size:0x120
fn_802F2450 = .text:0x802F2450; // type:function size:0x18C
fn_802F25E0 = .text:0x802F25E0; // type:function size:0x19C
fn_802F2780 = .text:0x802F2780; // type:function size:0x198
fn_802F2780__7mQuat_cFRC7mQuat_c = .text:0x802F2780; // type:function size:0x198
fn_802F2920 = .text:0x802F2920; // type:function size:0x48
fn_802F2970 = .text:0x802F2970; // type:function size:0x110
fn_802F2A80 = .text:0x802F2A80; // type:function size:0xF0
@@ -24732,7 +24732,7 @@ fn_8044E680 = .text:0x8044E680; // type:function size:0x50
fn_8044E6D0 = .text:0x8044E6D0; // type:function size:0x16C
fn_8044E840 = .text:0x8044E840; // type:function size:0x270
fn_8044EAB0 = .text:0x8044EAB0; // type:function size:0x494
fn_8044EF50 = .text:0x8044EF50; // type:function size:0x8A4
Draw1Mat1ShpDirectly__Q24nw4r3g3dFQ34nw4r3g3d6ResMatQ34nw4r3g3d6ResShpPCQ34nw4r4math5MTX34PCQ34nw4r4math5MTX34UlPQ34nw4r3g3d16Draw1Mat1ShpSwapPQ44nw4r3g3d8G3DState8IndMtxOp = .text:0x8044EF50; // type:function size:0x8A4
fn_8044F800 = .text:0x8044F800; // type:function size:0xC0
fn_8044F8C0 = .text:0x8044F8C0; // type:function size:0xD8
fn_8044F9A0 = .text:0x8044F9A0; // type:function size:0x260
@@ -26234,8 +26234,8 @@ resizeForMBlock__Q23EGG7FrmHeapFPvUl = .text:0x804962B0; // type:function size:0
getTotalFreeSize__Q23EGG7FrmHeapFv = .text:0x804962C0; // type:function size:0x14
getAllocatableSize__Q23EGG7FrmHeapFl = .text:0x804962E0; // type:function size:0x8
adjust__Q23EGG7FrmHeapFv = .text:0x804962F0; // type:function size:0x78
FUN_80496370 = .text:0x80496370; // type:function size:0x8
FUN_80496380 = .text:0x80496380; // type:function size:0x8
recordState__Q23EGG7FrmHeapFUl = .text:0x80496370; // type:function size:0x8
freeState__Q23EGG7FrmHeapFUl = .text:0x80496380; // type:function size:0x8
getHeapKind__Q23EGG7FrmHeapCFv = .text:0x80496390; // type:function size:0x8
__ct__Q23EGG10AssertHeapFP12MEMiHeapHead = .text:0x804963A0; // type:function size:0x3C
__dt__Q23EGG10AssertHeapFv = .text:0x804963E0; // type:function size:0x74
@@ -35707,14 +35707,14 @@ __vt__Q23m3d6fanm_c = .data:0x805426A8; // type:object size:0x18
__vt__Q23m3d5mdl_c = .data:0x805426C0; // type:object size:0x2C
__vt__Q33m3d5mdl_c13mdlCallback_c = .data:0x805426F0; // type:object size:0x18
__vt__Q23m3d9scnLeaf_c = .data:0x80542708; // type:object size:0x24
lbl_80542730 = .data:0x80542730; // type:object size:0x10
lbl_80542740 = .data:0x80542740; // type:object size:0x20
lbl_80542760 = .data:0x80542760; // type:object size:0x10
lbl_80542770 = .data:0x80542770; // type:object size:0x10
lbl_80542780 = .data:0x80542780; // type:object size:0x28
lbl_805427A8 = .data:0x805427A8; // type:object size:0x2C
lbl_805427D4 = .data:0x805427D4; // type:object size:0xC
lbl_805427E0 = .data:0x805427E0; // type:object size:0x10
lbl_80542730 = .data:0x80542730; // type:object size:0xA scope:local data:string
sTexMtx__3m3d = .data:0x80542740; // type:object size:0x20 scope:local
sColors__3m3d = .data:0x80542760; // type:object size:0x10 scope:local
sChans__3m3d = .data:0x80542770; // type:object size:0x10 scope:local
__vt__Q23m3d15mCustomShadow_c = .data:0x80542780; // type:object size:0x28
__vt__Q23m3d9mShadow_c = .data:0x805427A8; // type:object size:0x2C
__vt__Q23m3d15mShadowCircle_c = .data:0x805427D4; // type:object size:0xC
__vt__Q23m3d14mShadowChild_c = .data:0x805427E0; // type:object size:0xC
__vt__Q23m3d6smdl_c = .data:0x805427F0; // type:object size:0x2C
__vt__16mHeapAllocator_c = .data:0x80542820; // type:object size:0x14
__vt__12mAllocator_c = .data:0x80542834; // type:object size:0x14
@@ -39073,7 +39073,7 @@ lbl_80573FB0 = .sdata:0x80573FB0; // type:object size:0x4 data:4byte
lbl_80573FB4 = .sdata:0x80573FB4; // type:object size:0x4 data:4byte
m_rootUniqueID__7fBase_c = .sdata:0x80573FB8; // type:object size:0x4 data:4byte
m_nowLoopProc__10fManager_c = .sdata:0x80573FC0; // type:object size:0x4 data:4byte
lbl_80573FC8 = .sdata:0x80573FC8; // type:object size:0x8 data:4byte
STEP__3m3d = .sdata:0x80573FC8; // type:object size:0x4 data:4byte
lbl_80573FD0 = .sdata:0x80573FD0; // type:object size:0x4
lbl_80573FD4 = .sdata:0x80573FD4; // type:object size:0x1 data:byte
lbl_80573FD8 = .sdata:0x80573FD8; // type:object size:0x4 data:4byte
@@ -40303,11 +40303,11 @@ l_lightMgr_pp__Q23m3d8internal = .sbss:0x80575BDC; // type:object size:0x4 data:
l_numFogMgr__Q23m3d8internal = .sbss:0x80575BE0; // type:object size:0x4 data:4byte
l_fogMgr_pp__Q23m3d8internal = .sbss:0x80575BE4; // type:object size:0x4 data:4byte
l_alignment__Q23m3d8internal = .sbss:0x80575BE8; // type:object size:0x4 data:4byte
lbl_80575BF0 = .sbss:0x80575BF0; // type:object size:0x4 data:4byte
lbl_80575BF4 = .sbss:0x80575BF4; // type:object size:0x4 data:4byte
lbl_80575BF8 = .sbss:0x80575BF8; // type:object size:0x4 data:4byte
lbl_80575BFC = .sbss:0x80575BFC; // type:object size:0x1 data:byte
lbl_80575C00 = .sbss:0x80575C00; // type:object size:0x8 data:4byte
sInstance__Q23m3d9mShadow_c = .sbss:0x80575BF0; // type:object size:0x4 data:4byte
sTexObj__Q23m3d9mShadow_c = .sbss:0x80575BF4; // type:object size:0x4 data:4byte
sResShp__Q23m3d9mShadow_c = .sbss:0x80575BF8; // type:object size:0x4 data:4byte
@GUARD@draw__Q23m3d15mCustomShadow_cFRC6mMtx_c@nullMat = .sbss:0x80575BFC; // type:object size:0x1 data:byte
@LOCAL@draw__Q23m3d15mCustomShadow_cFRC6mMtx_c@nullMat = .sbss:0x80575C00; // type:object size:0x4 data:4byte
Zero__7mAng3_c = .sbss:0x80575C08; // type:object size:0x6 data:2byte
somePtr__4mDvd = .sbss:0x80575C10; // type:object size:0x4 data:4byte
someNumber__4mDvd = .sbss:0x80575C14; // type:object size:0x4 data:4byte
@@ -49129,7 +49129,7 @@ l_param__4mDvd = .bss:0x805CAF68; // type:object size:0x30
lbl_805CAF98 = .bss:0x805CAF98; // type:object size:0xC
@LOCAL@loadToMainRAM__4mDvdFiPcPQ23EGG4HeapQ33EGG9DvdRipper15EAllocDirectionlPUlPUlUl@DvdFile = .bss:0x805CAFA8; // type:object size:0xD0
g_gameHeaps__5mHeap = .bss:0x805CB078; // type:object size:0x10 data:4byte
lbl_805CB088 = .bss:0x805CB088; // type:object size:0x30 data:4byte
Identity__6mMtx_c = .bss:0x805CB088; // type:object size:0x30 data:4byte
g_core__4mPad = .bss:0x805CB0B8; // type:object size:0x10 data:4byte
lbl_805CB0C8 = .bss:0x805CB0C8; // type:object size:0xC
g_PadAdditionalData__4mPad = .bss:0x805CB0D8; // type:object size:0x60 data:float
+1
View File
@@ -372,6 +372,7 @@ config.libs = [
Object(Matching, "m/m3d/m_calc_ratio.cpp"),
Object(Matching, "m/m3d/m_fanm.cpp"),
Object(Matching, "m/m3d/m_mdl.cpp"),
Object(NonMatching, "m/m3d/m_shadow.cpp"),
Object(Matching, "m/m3d/m_scnleaf.cpp"),
Object(Matching, "m/m3d/m_smdl.cpp"),
Object(Matching, "m/m2d.cpp"),
+1 -2
View File
@@ -6,10 +6,9 @@
namespace EGG {
struct Quatf : Vector3f {
struct Quatf : public Vector3f {
Quatf() {}
Quatf(f32 f, Vector3f v) : w(f), Vector3f(v) {}
~Quatf() {}
friend Quatf operator*(const Quatf &q, const Vector3f &vec) {
+5 -1
View File
@@ -49,8 +49,12 @@ public:
void setPriorityDraw(int, int);
inline nw4r::g3d::ScnLeaf *getG3dObject() {
return mpScnLeaf;
}
protected:
nw4r::g3d::ScnLeaf *mpScnLeaf;
/* 0x14 */ nw4r::g3d::ScnLeaf *mpScnLeaf;
};
} // namespace m3d
+187
View File
@@ -0,0 +1,187 @@
#ifndef M3D_M_SHADOW_H
#define M3D_M_SHADOW_H
#include <egg/core/eggFrmHeap.h>
#include <egg/core/eggHeap.h>
#include <m/m3d/m_proc.h>
#include <m/m_color.h>
#include <m/m_frustum.h>
#include <m/m_heap.h>
#include <m/m_mtx.h>
#include <m/m_quat.h>
#include <m/m_vec.h>
namespace m3d {
/**
* A configuration struct for our global shadow manager.
* The game uses one for most rooms and one for the Koloktos boss fight.
*/
struct mShadowCircleConfig {
u32 heapSize;
u8 count;
u8 unk1;
u8 unk2;
u8 texBufferSize;
u8 drawOpaPriority;
};
/**
* A callback that allows the stage manager to customize parts of
* the shadow pipeline.
*/
class mShadowCallback_c {
public:
virtual ~mShadowCallback_c() {}
virtual void beforeDraw() = 0;
virtual void draw(const mMtx_c &, u32) = 0;
virtual void afterDraw() = 0;
};
class mShadowCircle_c;
/**
* Represents an internal shadow circle.
*/
class mShadowChild_c {
friend class mShadow_c;
public:
nw4r::ut::Node mNode;
mShadowChild_c() : mpCircle(nullptr), mpLeaves(nullptr), field_0x154(0), mNumLeaves(0) {}
/* vt at 0x08 */
virtual ~mShadowChild_c();
bool create(u8, EGG::Heap *);
void set(const mVec3_c &pos, f32 dist, mColor color);
bool setGeom(const GXTexObj *texObj, const mMtx_c &mtx, const mQuat_c &quat);
void draw();
void updateMtx();
void drawMdl();
bool addMdl(scnLeaf_c &mdl, const mQuat_c &quat);
void set0x154(UNKWORD arg) {
field_0x154 = arg;
}
private:
/* 0x00C */ EGG::Heap *mpHeap;
/* 0x010 */ mShadowCircle_c *mpCircle;
/* 0x014 */ u32 mPriorityMaybe;
/* 0x018 */ GXTexObj mTexObj;
/* 0x038 */ mColor mShadowColor;
/* 0x03C */ mQuat_c mQuat;
/* 0x04C */ mFrustum_c mFrustum;
/* 0x13C */ f32 field_0x13C;
/* 0x140 */ scnLeaf_c **mpLeaves;
/* 0x144 */ mVec3_c mPositionMaybe;
/* 0x150 */ f32 mOffsetMaybe;
/* 0x154 */ UNKWORD field_0x154;
/* 0x158 */ u8 mMaxNumLeaves;
/* 0x159 */ u8 mNumLeaves;
/* 0x15A */ u8 mColorChanIdx;
};
/**
* An RAII handle to a shadow circle.
*/
class mShadowCircle_c {
friend class mShadow_c;
friend class mShadowChild_c;
public:
mShadowCircle_c() : mpChild(nullptr) {}
virtual ~mShadowCircle_c();
private:
mShadowChild_c *mpChild;
};
/**
* The global shadow circle manager.
*/
class mShadow_c : public proc_c {
friend class mShadowCircle_c;
friend class mShadowChild_c;
public:
mShadow_c(EGG::Heap *heap)
: mpHeap(heap), mpCurrentHeap(nullptr), mpChilds(nullptr), mpTexBuf(nullptr), mpCallback(nullptr),
mCurrentHeapIdx(0), mFreeChildIdx(0), field_0x66(true) {
nw4r::ut::List_Init(&mList, 0);
}
virtual ~mShadow_c();
virtual void remove() override;
virtual void drawOpa() override;
bool drawMdl(mShadowCircle_c *circle, u32 priority, scnLeaf_c &mdl, const mQuat_c &quat, mVec3_c &pos, mColor color,
u32 param9, f32 dist);
bool drawTexObj(mShadowCircle_c *circle, u32 priority, const GXTexObj *texObj, const mMtx_c &mtx,
const mQuat_c &quat, mVec3_c &pos, mColor color, u32 param9, f32 dist);
bool addMdlToCircle(mShadowCircle_c *circle, scnLeaf_c &mdl, const mQuat_c &quat);
void beforeDraw();
void draw(const mMtx_c &, u32);
void afterDraw();
EGG::FrmHeap *changeHeap(int index) {
mCurrentHeapIdx = index % 2;
mpCurrentHeap = mpFrmHeaps[mCurrentHeapIdx];
}
void swapHeaps();
void create(int count, u8 unk1, int unk2, u16 texBufferSize, u32 drawOpaPriority, nw4r::g3d::ResMdl mdl,
u32 heapSize);
void reset();
bool addCircle(mShadowCircle_c *circle, u32 priority, u32 unk);
void removeCircle(mShadowCircle_c *circle);
void drawAllShadows();
static void create(const mShadowCircleConfig *, nw4r::g3d::ResMdl mdl, EGG::Heap *heap);
static void destroy();
static mShadow_c *sInstance;
private:
/* 0x18 */ EGG::Heap *mpHeap;
/* 0x1C */ mAllocator_c mAllocator;
/* 0x38 */ EGG::FrmHeap *mpFrmHeaps[2];
/* 0x40 */ EGG::FrmHeap *mpCurrentHeap;
/* 0x44 */ nw4r::ut::List mList;
/* 0x50 */ mShadowChild_c *mpChilds;
/* 0x54 */ void *mpTexBuf;
/* 0x58 */ u32 mTexBufferSize;
/* 0x5C */ mShadowCallback_c *mpCallback;
/* 0x60 */ u8 mCurrentHeapIdx;
/* 0x61 */ u8 mChildCount;
/* 0x62 */ u8 mFreeChildIdx;
/* 0x63 */ u8 mNumTexBuffers;
/* 0x64 */ u8 mFreeTexIdx;
/* 0x65 */ u8 mTexSize;
/* 0x66 */ bool field_0x66;
public:
static GXTexObj *sTexObj;
static nw4r::g3d::ResShp sResShp;
};
class mCustomShadow_c : public scnLeaf_c {
public:
virtual ~mCustomShadow_c();
virtual int getType() const override;
/* 0x24 */ virtual void draw(const mMtx_c &);
void calc(mMtx_c, mMtx_c &);
/* 0x18 */ mMtx_c mMtx;
/* 0x48 */ f32 field_0x48;
/* 0x4C */ f32 field_0x4C;
};
} // namespace m3d
#endif
+21 -1
View File
@@ -2,7 +2,27 @@
#define M_FRUSTUM_H
#include <common.h>
#include <m/m_mtx.h>
#include <nw4r/math/math_geometry.h>
class mFrustum_c {};
// Bunch of untested assumptions in here
class mFrustum_c {
public:
void set(f32, f32, f32, f32, f32 near, f32 far, const mMtx_c &mtx, bool);
/* 0x00 */ mMtx_c mView;
/* 0x30 */ nw4r::math::PLANE mPlane_0x30;
/* 0x40 */ nw4r::math::PLANE mPlane_0x40;
/* 0x50 */ nw4r::math::PLANE mPlane_0x50;
/* 0x60 */ nw4r::math::PLANE mPlane_0x60;
/* 0x70 */ f32 mNear;
/* 0x74 */ f32 mFar;
/* 0x78 */ nw4r::math::AABB mAabb;
/* 0x90 */ nw4r::math::PLANE mPlane_0x90;
/* 0xA0 */ nw4r::math::PLANE mPlane_0xA0;
/* 0xB0 */ nw4r::math::PLANE mPlane_0xB0;
/* 0xC0 */ nw4r::math::PLANE mPlane_0xC0;
/* 0xD0 */ nw4r::math::PLANE mPlane_0xD0;
/* 0xE0 */ nw4r::math::PLANE mPlane_0xE0;
};
#endif
+34 -4
View File
@@ -11,11 +11,45 @@
#pragma push
#pragma warning off(10402)
class mMtx_c {
typedef f32 (*MtxRef)[4];
typedef const f32 (*MtxRefConst)[4];
public:
mMtx_c(){};
/* 802f1660 */ mMtx_c(f32 xx, f32 xy, f32 xz, f32 xw, f32 yx, f32 yy, f32 yz, f32 yw, f32 zx, f32 zy, f32 zz,
f32 zw);
// not sure if this breaks anything but we need a matrix type
// with an inline copy assignment operator
mMtx_c &operator=(const mMtx_c &r) {
xx = r.xx;
xy = r.xy;
xz = r.xz;
xw = r.xw;
yx = r.yx;
yy = r.yy;
yz = r.yz;
yw = r.yw;
zx = r.zx;
zy = r.zy;
zz = r.zz;
zw = r.zw;
return *this;
}
inline operator MtxRef() {
return m;
}
inline operator MtxRefConst() const {
return m;
}
operator nw4r::math::MTX34 *() {
return &nw4rm;
}
/* 802f16b0 */ void XrotS(const mAng &angle); ///< Generates a rotation matrix for the X axis with the given angle.
/* 802f1770 */ void XrotM(const mAng &angle); ///< Rotates the matrix on the X axis by the given angle.
/* 802f17c0 */ void YrotS(const mAng &angle); ///< Generates a rotation matrix for the Y axis with the given angle.
@@ -40,10 +74,6 @@ public:
/* 802f1c40 */ void rot(int, int); // does some werrd operation to rotate the matrix
/* 802f1e60 */ bool quatRelated();
operator nw4r::math::MTX34 *() {
return &nw4rm;
}
public:
union {
EGG::Matrix34f mat;
+12
View File
@@ -0,0 +1,12 @@
#ifndef M_QUAT_H
#define M_QUAT_H
#include <egg/math/eggQuat.h>
#include <m/m_vec.h>
class mQuat_c : public EGG::Quatf {
public:
void fn_802F2780(const mQuat_c &other);
};
#endif
+3 -2
View File
@@ -5,8 +5,9 @@
namespace nw4r {
namespace g3d {
void CalcView(math::MTX34 *, math::MTX33 *, const math::MTX34 *, const u32 *, u32, const math::MTX34 *, ResMdl,
math::MTX34 *);
void CalcView(math::MTX34 *pViewPosArray, math::MTX33 *pViewNrmArray, const math::MTX34 *pModelMtxArray,
const u32 *pModelMtxAttribArray, u32 numMtx, const math::MTX34 *pView, ResMdl resMdl,
math::MTX34 *pVewTexMtxArray);
}
} // namespace nw4r
+2 -2
View File
@@ -7,8 +7,8 @@ namespace nw4r {
namespace g3d {
struct DrawResMdlReplacement {};
void DrawResMdlDirectly(ResMdl, const math::MTX34 *, const math::MTX33 *, const math::MTX34 *, const u8 *, const u8 *,
DrawResMdlReplacement *, u32);
void DrawResMdlDirectly(ResMdl mdl, const math::MTX34 *pViewPos, const math::MTX33 *pViewNrm,
const math::MTX34 *pViewEnv, const u8 *pOpa, const u8 *pXlu, DrawResMdlReplacement *pRep, u32 resMdlDrawMode);
} // namespace g3d
} // namespace nw4r
+15
View File
@@ -123,6 +123,15 @@ struct ResGenMode : public ResCommon<ResGenModeData> {
void GXSetCullMode(GXCullMode);
};
struct ResTexObjData {};
struct ResTexObj {
ResCommon<ResTexObjData> mTexObj;
inline ResTexObj(void *vptr) : mTexObj(vptr) {}
GXTexObj *GetTexObj(GXTexMapID);
};
struct ResMatData {
u32 size; // offset 0x0, size 0x4
s32 toResMdlData; // offset 0x4, size 0x4
@@ -144,6 +153,8 @@ struct ResMatData {
};
struct ResMat : public ResCommon<ResMatData> {
ResMat(void *ptr) : ResCommon<ResMatData>(ptr) {}
ResMatTevColor GetResMatTevColor() {
return ResMatTevColor(&ofs_to_ptr<ResMatDLData>(ref().toResMatDLData)->dlTevColor);
}
@@ -160,6 +171,10 @@ struct ResMat : public ResCommon<ResMatData> {
return ResTexSrt(&ref().texSrtData);
}
ResTexObj GetResTexObj() {
return ResTexObj(&ref().texObjData);
}
ResMatTexCoordGen GetResMatTexCoordGen() {
return ResMatTexCoordGen(&ofs_to_ptr<ResMatDLData>(ref().toResMatDLData)->dlTexCoordGen);
}
+14
View File
@@ -7,6 +7,20 @@
namespace nw4r {
namespace g3d {
enum ResMdlDrawMode {
RESMDL_DRAWMODE_SORT_OPA_NONE = 0,
RESMDL_DRAWMODE_SORT_OPA_Z = 1,
RESMDL_DRAWMODE_SORT_XLU_NONE = 0,
RESMDL_DRAWMODE_SORT_XLU_Z = 2,
RESMDL_DRAWMODE_IGNORE_MATERIAL = 4,
RESMDL_DRAWMODE_FORCE_LIGHTOFF = 8,
RESMDL_DRAWMODE_NOPPCSYNC = 16,
RESMDL_DRAWMODE_DEFAULT = 2,
REDMDL_DRAWMODE_SORT_NONE = 0,
RESMDL_DRAWMODE_SORT_Z = 3,
};
struct ResMdlData {
char mMagic[4]; // "MDL0"
u32 INT_0x4;
+3 -2
View File
@@ -3,7 +3,8 @@
#include "nw4r/g3d/g3d_rescommon.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/g3d_resvtx.h"
#include <GXAttr.h>#include "common.h"
#include <rvl/GX.h>
#include "common.h"
namespace nw4r {
@@ -70,7 +71,7 @@ struct ResShpPrePrim {
struct ResShp {
ResCommon<ResShpData> mShp;
inline ResShp() : mShp((void*)nullptr) {}
inline ResShp(void *vptr) : mShp(vptr) {}
bool IsValid() const {
return mShp.IsValid();
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef NW4R_G3D_RESVTX_H
#define NW4R_G3D_RESVTX_H
#include <GXAttr.h>
#include <rvl/GX.h>
#include "nw4r/g3d/g3d_rescommon.h"
namespace nw4r
+1 -1
View File
@@ -35,7 +35,7 @@ public:
}
private:
char UNK_0x118[0x144 - 0x118];
char UNK_0x120[0x144 - 0x120];
DrawResMdlReplacement mDrawMdlReplace; // at 0x144
NW4R_G3D_TYPE_OBJ_DECL(ScnMdl);
+4
View File
@@ -41,6 +41,10 @@ inline f32 SinRad(f32 rad) {
*/
f32 CosFIdx(f32 fidx);
inline f32 CosIdx(u16 idx) {
return CosFIdx(NW4R_MATH_IDX_TO_FIDX(U16ToF32(idx)));
}
inline f32 CosDeg(f32 deg) {
return CosFIdx(NW4R_MATH_DEG_TO_FIDX(deg));
}
+7
View File
@@ -30,6 +30,13 @@ void GXSetDispCopyDst(u16 width, u16 height);
u32 GXSetDispCopyYScale(f32 scale);
void GXCopyDisp(void *data, GXBool bUpdate);
void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height);
void GXSetTexCopyDst(u16 left, u16 top, GXTexFmt fmt, u8 mipmap);
void GXCopyTex(void *data, GXBool bUpdate);
// Not sure where this belongs
void GXPixModeSync();
extern GXRenderModeObj GXNtsc480IntDf;
extern GXRenderModeObj GXMpal480IntDf;
extern GXRenderModeObj GXPal528IntDf;
+2
View File
@@ -27,6 +27,8 @@ void GXGetTexObjAll(const GXTexObj *pTexObj, void **pImage, u16 *width, u16 *hei
void GXGetTexObjLODAll(const GXTexObj *pTexObj, GXTexFilter *minFilter, GXTexFilter *magFilter, f32 *minLOD,
f32 *maxLOD, f32 *LODBias, u8 *biasClampEnable, u8 *edgeLODEnable, GXAnisotropy *anisotropy);
u32 GXGetTexObjTlut(GXTexObj *);
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool arg3, u8 arg4);
void GXInvalidateTexAll();
#ifdef __cplusplus
}
+1 -1
View File
@@ -15,7 +15,7 @@ void GXLoadPosMtxIndx(u16 index, u32 id);
void GXLoadNrmMtxImm(const Mtx mtx, u32 id);
void GXLoadNrmMtxIndx3x3(u16 index, u32 id);
void GXSetCurrentMtx(u32 id);
void GXLoadTexMtxImm(const Mtx mtx, u32 id, GXMtxType type);
void GXLoadTexMtxImm(const f32 mtx[][4], u32 id, GXMtxType type);
void GXSetViewportJitter(f32 ox, f32 oy, f32 sx, f32 sy, f32 near, f32 far, u32 nextField);
void GXSetViewport(f32 ox, f32 oy, f32 sx, f32 sy, f32 near, f32 far);
void GXGetViewportv(f32 view[6]);
+615
View File
@@ -0,0 +1,615 @@
#include <m/m3d/m_shadow.h>
#include <nw4r/g3d/g3d_calcview.h>
#include <nw4r/g3d/g3d_draw.h>
#include <nw4r/g3d/g3d_draw1mat1shp.h>
#include <nw4r/g3d/g3d_resmat.h>
#include <nw4r/g3d/g3d_resmdl.h>
#include <nw4r/g3d/g3d_resshp.h>
#include <nw4r/g3d/g3d_scnmdl.h>
#include <nw4r/g3d/g3d_scnmdlsmpl.h>
#include <nw4r/g3d/g3d_state.h>
// All of this is completely made up, as we don't have symbols for this TU
// (contrary to the rest of m3d and most of nw4r::g3d)
#define FRM_HEAP_STATE 'tag0'
namespace m3d {
mShadow_c *mShadow_c::sInstance;
GXTexObj *mShadow_c::sTexObj;
nw4r::g3d::ResShp mShadow_c::sResShp;
mShadow_c::~mShadow_c() {
remove();
}
void mShadow_c::drawOpa() {
if (field_0x66) {
beforeDraw();
mShadowChild_c *child = static_cast<mShadowChild_c *>(nw4r::ut::List_GetFirst(&mList));
while (child != nullptr) {
child->draw();
child = static_cast<mShadowChild_c *>(nw4r::ut::List_GetNext(&mList, child));
}
afterDraw();
}
}
void mShadow_c::create(int count, u8 unk1, int unk2, u16 texSize, u32 drawOpaPriority, nw4r::g3d::ResMdl mdl,
u32 heapSize) {
// Regswaps
mAllocator.attach(mpHeap, 0x20);
proc_c::create(&mAllocator, nullptr);
u32 bufSize = GXGetTexBufferSize(texSize, texSize, GX_TF_RGB565, false, 0);
mTexBufferSize = bufSize;
u32 numTexBuffers = (unk2 + 2) / 3;
mpTexBuf = mpHeap->alloc(bufSize * numTexBuffers, 0x20);
// Maybe an Inline?
EGG::FrmHeap **heap = mpFrmHeaps;
for (int i = 0; i < 2; i++) {
heap[0] = mHeap::createFrmHeap(heapSize, mpHeap, "ShadowTmp", 0x4, 0);
heap[0]->recordState(FRM_HEAP_STATE);
heap++;
}
swapHeaps();
mShadowChild_c *childs = new (mpHeap, 0x04) mShadowChild_c[count];
mpChilds = childs;
for (int i = 0; i < count; i++) {
childs->create(unk1, mpHeap);
childs++;
}
setPriorityDraw(drawOpaPriority, 0);
setOption(/* DISABLE_DRAW_XLU */ 0x07, 1);
mChildCount = count;
mFreeChildIdx = 0;
mNumTexBuffers = numTexBuffers * 3;
mFreeTexIdx = 0;
mTexSize = texSize;
nw4r::g3d::ResMat mat = mdl.GetResMat(0);
sResShp = mdl.GetResShp(0);
sTexObj = mat.GetResTexObj().GetTexObj(GX_TEXMAP0);
}
void mShadow_c::remove() {
if (mpHeap != nullptr) {
if (mpChilds != nullptr) {
delete[] mpChilds;
mpChilds = nullptr;
}
EGG::FrmHeap **heap = mpFrmHeaps;
for (int i = 0; i < 2; i++) {
if (heap[i] != nullptr) {
mHeap::destroyFrmHeap(heap[i]);
heap[i] = nullptr;
}
}
if (mpTexBuf != nullptr) {
mpHeap->free(mpTexBuf);
mpTexBuf = nullptr;
}
scnLeaf_c::remove();
mpHeap = nullptr;
}
}
void mShadow_c::reset() {
mShadowChild_c *iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetFirst(&mList));
while (iter != nullptr) {
iter->mNumLeaves = 0;
mShadowCircle_c *circle = iter->mpCircle;
iter->mpCircle = nullptr;
circle->mpChild = nullptr;
iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetNext(&mList, iter));
}
mFreeChildIdx = 0;
mFreeTexIdx = 0;
nw4r::ut::List_Init(&mList, 0);
swapHeaps();
}
bool mShadow_c::addCircle(mShadowCircle_c *circle, u32 priority, u32 isMdl) {
if (circle->mpChild != nullptr) {
// Already linked, OK
return true;
}
mShadowChild_c *childPtr;
if (mFreeChildIdx < mChildCount && (!isMdl || mFreeTexIdx < mNumTexBuffers)) {
// There are free entries in our buffer, so just add a new child
childPtr = &mpChilds[mFreeChildIdx];
if (mFreeChildIdx++ == 0) {
entry();
}
if (isMdl) {
mFreeTexIdx++;
}
} else {
// There are no free entries in our buffer, so replace an existing entry?
childPtr = static_cast<mShadowChild_c *>(nw4r::ut::List_GetLast(&mList));
if (priority >= childPtr->mPriorityMaybe) {
return false;
}
if (isMdl) {
if (mFreeTexIdx >= mNumTexBuffers) {
while (childPtr->mNumLeaves == 0) {
childPtr = static_cast<mShadowChild_c *>(nw4r::ut::List_GetPrev(&mList, childPtr));
if (priority >= childPtr->mPriorityMaybe) {
return false;
}
}
} else {
mFreeTexIdx++;
}
}
childPtr->mNumLeaves = 0;
childPtr->mpCircle->mpChild = nullptr;
nw4r::ut::List_Remove(&mList, childPtr);
}
circle->mpChild = childPtr;
childPtr->mpCircle = circle;
childPtr->mPriorityMaybe = priority;
mShadowChild_c *iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetFirst(&mList));
if (iter == nullptr) {
nw4r::ut::List_Append(&mList, childPtr);
return true;
} else {
do {
if (childPtr->mPriorityMaybe < iter->mPriorityMaybe) {
nw4r::ut::List_Insert(&mList, iter, childPtr);
return true;
}
iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetNext(&mList, iter));
} while (iter != nullptr);
nw4r::ut::List_Append(&mList, childPtr);
}
return true;
}
bool mShadow_c::drawMdl(mShadowCircle_c *circle, u32 priority, scnLeaf_c &mdl, const mQuat_c &quat, mVec3_c &pos,
mColor color, u32 param9, f32 dist) {
if (!addCircle(circle, priority, 1)) {
return false;
}
mShadowChild_c *child = circle->mpChild;
child->set(pos, dist, color);
child->set0x154(param9);
return child->addMdl(mdl, quat);
}
bool mShadow_c::addMdlToCircle(mShadowCircle_c *circle, scnLeaf_c &mdl, const mQuat_c &quat) {
if (circle->mpChild == nullptr) {
return false;
}
return circle->mpChild->addMdl(mdl, quat);
}
void mShadow_c::removeCircle(mShadowCircle_c *circle) {
mShadowChild_c *child = circle->mpChild;
if (child == nullptr) {
return;
}
circle->mpChild = nullptr;
child->mpCircle = nullptr;
nw4r::ut::List_Remove(&mList, child);
}
static f32 sTexMtx[2][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}};
static u32 STEP = 0x2492;
static GXColor sColors[] = {
{0xFF, 0x00, 0x00, 0x00},
{0x00, 0xFF, 0x00, 0x00},
{0x00, 0x00, 0xFF, 0x00},
{0x00, 0x00, 0x00, 0x00},
};
bool mShadow_c::drawTexObj(mShadowCircle_c *circle, u32 priority, const GXTexObj *texObj, const mMtx_c &mtx,
const mQuat_c &quat, mVec3_c &pos, mColor color, u32 param9, f32 dist) {
if (!addCircle(circle, priority, 0)) {
return false;
}
mShadowChild_c *child = circle->mpChild;
child->set(pos, dist, color);
child->set0x154(param9);
return child->setGeom(texObj, mtx, quat);
}
static void drawSub2(void *data, u8 i) {
s16 ang;
u32 wid = i * 2;
GXSetTexCopySrc(0, 0, wid, wid);
GXSetTexCopyDst(i, i, GX_TF_RGB565, 1);
GXCopyTex(data, false);
GXPixModeSync();
GXInvalidateTexAll();
GXTexObj obj;
GXInitTexObj(&obj, data, i, i, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, 0);
GXInitTexObjLOD(&obj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);
GXLoadTexObj(&obj, GX_TEXMAP0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBX8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 0);
GXSetNumChans(0);
GXSetNumTexGens(8);
GXSetNumTevStages(8);
GXSetTevColor(GX_TEVREG1, nw4r::ut::Color(0, 0, 0, 0x20));
ang = 0;
for (int id = GX_TEXCOORD0, idx = GX_TEXMTX0; id < GX_MAX_TEXCOORD;
id += 1, idx += (GX_TEXMTX1 - GX_TEXMTX0), ang += STEP) {
GXSetTexCoordGen2((GXTexCoordID)id, GX_TG_MTX2x4, GX_TG_TEX0, idx, FALSE, GX_DUALMTX_IDENT);
sTexMtx[0][3] = 0.01f * nw4r::math::CosIdx(ang);
sTexMtx[1][3] = 0.01f * nw4r::math::SinIdx(ang);
GXLoadTexMtxImm(sTexMtx, idx, GX_MTX_2x4);
}
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A0, GX_CC_ZERO);
for (int id = GX_TEVSTAGE1; id < GX_TEVSTAGE8; id++) {
GXSetTevSwapMode((GXTevStageID)id, GX_TEV_SWAP0, GX_TEV_SWAP0);
GXSetTevOrder((GXTevStageID)id, (GXTexCoordID)id, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn((GXTevStageID)id, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_CPREV);
GXSetTevColorOp((GXTevStageID)id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GXSetTevAlphaIn((GXTevStageID)id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp((GXTevStageID)id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
}
GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_SET);
GXLoadPosMtxImm(mMtx_c::Identity, 0);
GXSetCurrentMtx(0);
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition2u16(0, 0);
GXPosition2u8(0, 0);
GXPosition2u16(wid, 0);
GXPosition2u8(1, 0);
GXPosition2u16(wid, wid);
GXPosition2u8(1, 1);
GXPosition2u16(0, wid);
GXPosition2u8(0, 1);
// GXEnd();
}
static void drawSub1(void *data, u8 i) {
Mtx44 mtx;
u16 wid = i * 2;
f32 wid2 = i * 2;
C_MTXOrtho(mtx, 0.0f, wid2, 0.0f, wid2, 0.0f, 1.0f);
GXSetProjection(mtx, GX_ORTHOGRAPHIC);
drawSub2(data, i);
GXSetNumChans(1);
GXSetNumTexGens(0);
GXSetNumTevStages(1);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXBegin(GX_LINESTRIP, GX_VTXFMT0, 5);
GXPosition2u16(0, 0);
GXPosition2u16(wid, 0);
GXPosition2u16(wid, wid);
GXPosition2u16(0, wid);
GXPosition2u16(0, 0);
// GXEnd();
GXSetZMode(true, GX_ALWAYS, true);
GXSetTexCopySrc(0, 0, wid, wid);
GXSetTexCopyDst(i, i, GX_TF_RGB565, 1);
GXCopyTex(data, true);
GXPixModeSync();
GXInvalidateTexAll();
}
void mShadow_c::drawAllShadows() {
mShadowChild_c *iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetFirst(&mList));
if (iter != nullptr) {
f32 wid = mTexSize * 2;
u16 wid2 = mTexSize * 2;
GXSetViewport(0.0f, 0.0f, wid, wid, 0.0f, 1.0f);
GXSetScissor(0, 0, wid2, wid2);
GXSetScissorBoxOffset(0, 0);
GXLoadTexObj(mShadow_c::sTexObj, GX_TEXMAP1);
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(0);
GXSetNumTevStages(1);
GXSetNumIndStages(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GXSetZCompLoc(1);
GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_SET);
GXSetZMode(false, GX_ALWAYS, false);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
GXColor clr = {0};
GXSetFog(GX_FOG_NONE, clr, 0.0f, 0.0f, 0.0f, 0.0f);
GXSetFogRangeAdj(0, 0, 0);
GXSetCullMode(GX_CULL_BACK);
GXSetDither(0);
GXSetClipMode(GX_CLIP_DISABLE);
GXLoadPosMtxImm(mMtx_c::Identity.m, 0);
GXSetCurrentMtx(0);
Mtx44 mtx;
C_MTXOrtho(mtx, 0.0f, wid, 0.0f, wid, 0.0f, 1.0f);
GXSetProjection(mtx, GX_ORTHOGRAPHIC);
GXSetLineWidth(0x18, 0);
int i = 0;
void *imgData = mpTexBuf;
do {
iter->updateMtx();
if (iter->mNumLeaves != 0) {
if (i == 0) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_U16, 0);
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition2u16(0, 0);
GXPosition2u16(wid2, 0);
GXPosition2u16(wid2, wid2);
GXPosition2u16(0, wid2);
// GXEnd();
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0);
GXSetBlendMode(GX_BM_LOGIC, GX_BL_ONE, GX_BL_ONE, GX_LO_OR);
}
iter->mColorChanIdx = i;
GXInitTexObj(&iter->mTexObj, imgData, mTexSize, mTexSize, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, false);
GXInitTexObjLOD(&iter->mTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);
iter->drawMdl();
i = (i + 1) % 3;
if (i == 0) {
drawSub1(imgData, mTexSize);
imgData = (void *)((u8 *)imgData + mTexBufferSize);
}
}
iter = static_cast<mShadowChild_c *>(nw4r::ut::List_GetNext(&mList, iter));
} while (iter != nullptr);
if (i != 0) {
drawSub1(imgData, mTexSize);
}
GXSetClipMode(GX_CLIP_ENABLE);
GXSetDither(true);
nw4r::g3d::G3DState::Invalidate(0x7FF);
}
}
void mShadow_c::create(const mShadowCircleConfig *config, nw4r::g3d::ResMdl mdl, EGG::Heap *heap) {
mShadow_c::sInstance = new (heap, 0x04) mShadow_c(heap);
mShadow_c::sInstance->create(config->count, config->unk1, config->unk2, config->texBufferSize,
config->drawOpaPriority, mdl, config->heapSize);
}
void mShadow_c::beforeDraw() {
if (mpCallback != nullptr) {
mpCallback->beforeDraw();
}
}
void mShadow_c::draw(const mMtx_c &mtx, u32 unk) {
if (mpCallback != nullptr) {
mpCallback->draw(mtx, unk);
}
}
void mShadow_c::afterDraw() {
if (mpCallback != nullptr) {
mpCallback->afterDraw();
}
}
void mShadow_c::swapHeaps() {
changeHeap(mCurrentHeapIdx + 1);
mpCurrentHeap->freeState(FRM_HEAP_STATE);
mpCurrentHeap->recordState(FRM_HEAP_STATE);
}
void mShadow_c::destroy() {
if (mShadow_c::sInstance != nullptr) {
mShadow_c::sInstance->remove();
delete mShadow_c::sInstance;
mShadow_c::sInstance = nullptr;
}
}
mShadowChild_c::~mShadowChild_c() {
if (mpCircle != nullptr) {
mpCircle->mpChild = nullptr;
mpCircle = nullptr;
}
if (mpLeaves != nullptr) {
mpHeap->free(mpLeaves);
mpLeaves = nullptr;
}
}
bool mShadowChild_c::create(u8 maxNum, EGG::Heap *heap) {
if ((mpLeaves = static_cast<scnLeaf_c **>(heap->alloc(maxNum * sizeof(scnLeaf_c *), 0x04))) == nullptr) {
return false;
}
mpHeap = heap;
mMaxNumLeaves = maxNum;
return true;
}
void mShadowChild_c::set(const mVec3_c &pos, f32 dist, mColor color) {
mPositionMaybe = pos;
mOffsetMaybe = dist;
mShadowColor = color;
}
bool mShadowChild_c::addMdl(scnLeaf_c &mdl, const mQuat_c &quat) {
if (!(mNumLeaves < mMaxNumLeaves)) {
return false;
}
mMtx_c mtx;
if (mdl.getType() == 0) {
mdl.getLocalMtx(mtx);
} else {
mtx = static_cast<mCustomShadow_c &>(mdl).mMtx;
}
// TODO this copy is a bit weird (reads members in a different order)
mQuat_c q = quat;
PSMTXMultVec(mtx.m, q, q);
if (mNumLeaves == 0) {
mQuat = q;
} else {
mQuat.fn_802F2780(q);
}
mpLeaves[mNumLeaves++] = &mdl;
return true;
}
bool mShadowChild_c::setGeom(const GXTexObj *texObj, const mMtx_c &mtx, const mQuat_c &quat) {
mQuat = quat;
PSMTXMultVec(mtx.m, mQuat, mQuat);
if (texObj == nullptr) {
mTexObj = *mShadow_c::sTexObj;
} else {
mTexObj = *texObj;
}
return true;
}
void mShadowChild_c::updateMtx() {
// TODO all of this is broken
mVec3_c a = *(mVec3_c *)(&mQuat) + mPositionMaybe * mOffsetMaybe;
mVec3_c b = *(mVec3_c *)(&mQuat) - mPositionMaybe * field_0x13C;
mMtx_c mtx;
C_MTXLookAt(mtx.m, b,
*(fabsf((a.x - b.x) * (a.x - b.x) + (a.z - b.z) * (a.z - b.z)) <= FLT_EPSILON ? &mVec3_c::Ez :
&mVec3_c::Ey),
a);
f32 f = field_0x13C;
mFrustum.set(f, -f, -f, f, f, f + mOffsetMaybe, mtx, true);
}
void mShadowChild_c::drawMdl() {
// TODO maybe roughly equivalent
using namespace nw4r;
mMtx_c mtx;
GXSetTevColor(GX_TEVREG0, sColors[mColorChanIdx]);
C_MTXOrtho(mtx.m, field_0x13C, -field_0x13C, -field_0x13C, field_0x13C, 0.0f, 100.0f + (-mFrustum.mFar));
GXSetProjection(mtx.m, GX_ORTHOGRAPHIC);
g3d::G3DState::Invalidate(0x7FF);
for (scnLeaf_c **leaf = &mpLeaves[mNumLeaves - 1]; leaf >= &mpLeaves[0]; leaf--) {
scnLeaf_c *lf = *leaf;
if (lf->getType() == 0 /* Model */) {
g3d::ScnMdlSimple *mdl = g3d::G3dObj::DynamicCast<g3d::ScnMdlSimple>(lf->getG3dObject());
u32 bufSize = mdl->GetNumViewMtx() * sizeof(math::MTX34);
math::MTX34 *viewPosArray = static_cast<math::MTX34 *>(mShadow_c::sInstance->mpHeap->alloc(bufSize, 0x20));
g3d::CalcView(viewPosArray, nullptr, mdl->GetWldMtxArray(), mdl->GetWldMtxAttribArray(),
mdl->GetNumViewMtx(), mFrustum.mView, mdl->GetResMdl(), nullptr);
DCStoreRange(viewPosArray, bufSize);
g3d::ScnMdl *mdl2 = g3d::G3dObj::DynamicCast<g3d::ScnMdl>(lf->getG3dObject());
g3d::DrawResMdlReplacement *pRep = mdl2 ? mdl2->GetDrawResMdlReplacement() : nullptr;
g3d::DrawResMdlDirectly(mdl->GetResMdl(), viewPosArray, nullptr, nullptr,
mdl2->GetByteCode(g3d::ScnMdlSimple::BYTE_CODE_DRAW_OPA), nullptr, pRep,
g3d::RESMDL_DRAWMODE_FORCE_LIGHTOFF | g3d::RESMDL_DRAWMODE_IGNORE_MATERIAL);
GXInvalidateVtxCache();
} else {
// this happens with bomb bag, and goes to 0x802EDC90 (mCustomShadow_c::draw)
static_cast<mCustomShadow_c *>(lf)->draw(mFrustum.mView);
}
}
}
static GXTevColorChan sChans[] = {GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA};
void mShadowChild_c::draw() {
if (mNumLeaves != 0) {
GXTevColorChan chan = sChans[mColorChanIdx];
GXSetTevSwapModeTable(GX_TEV_SWAP0, chan, chan, chan, chan);
} else {
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
}
GXLoadTexObj(&mTexObj, GX_TEXMAP0);
GXSetTevColor(GX_TEVREG0, mShadowColor);
Mtx mtx;
C_MTXLightOrtho(mtx, field_0x13C, -field_0x13C, -field_0x13C, field_0x13C, 0.5f, -0.5f, 0.5f, 0.5f);
PSMTXConcat(mtx, mFrustum.mView.m, mtx);
GXLoadTexMtxImm(mtx, GX_TEXMTX0, GX_MTX_3x4);
mShadow_c::sInstance->draw(mFrustum.mView, field_0x154);
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
}
mShadowCircle_c::~mShadowCircle_c() {
mShadow_c::sInstance->removeCircle(this);
}
mCustomShadow_c::~mCustomShadow_c() {}
int mCustomShadow_c::getType() const {
return 0x2;
}
void mCustomShadow_c::draw(const mMtx_c &arg) {
nw4r::g3d::G3DState::Invalidate(0x7FF);
GXSetNumTexGens(1);
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3C, false, 0x7D);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
mMtx_c result;
calc(arg, result);
static nw4r::g3d::ResMat nullMat(nullptr);
nw4r::g3d::Draw1Mat1ShpDirectly(nullMat, mShadow_c::sResShp, result, result, 0x18, nullptr, nullptr);
GXSetNumTexGens(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0);
}
void mCustomShadow_c::calc(mMtx_c mtx, mMtx_c &mtx2) {
// TODO some shuffles
mVec3_c trans;
mtx2 = mMtx;
mVec3_c offset(0.0f, 0.0f, 0.0f);
offset.y = field_0x48;
PSMTXMultVec(mtx2, offset, trans);
PSMTXMultVec(mtx, trans, trans);
PSMTXTrans(mtx2, trans.x, trans.y, trans.z);
mMtx_c scaleMtx;
PSMTXScale(scaleMtx, field_0x4C, field_0x4C, field_0x4C);
PSMTXConcat(mtx2, scaleMtx, mtx2);
}
} // namespace m3d