summaryrefslogtreecommitdiff
path: root/libs/JSystem/src/J3DGraphAnimator
diff options
context:
space:
mode:
authorLuke Street <luke@street.dev>2026-03-01 15:35:36 -0700
committerGitHub <noreply@github.com>2026-03-01 14:35:36 -0800
commit9649319ec4926457ef85e6094f8207474c977c2d (patch)
tree1c5cd4c7cc4c1aee03f28921213da47f2775444d /libs/JSystem/src/J3DGraphAnimator
parent6e149819e13b1f70ecbf8a4c66b030c17ffed2bb (diff)
Reorganize library code into `libs/` (#3119)
* Reorganize files into libs/{dolphin,JSystem,PowerPC_EABI_Support,revolution,TRK_MINNOW_DOLPHIN} * Update configure.py and project.py for new libs structure * Refactor `#include <dolphin/x.h>` -> `<x.h>` * Remove `__REVOLUTION_SDK__` forwards from dolphin * Fix dolphin/ references in revolution * Wrap `#include <dolphin.h>` in `!__REVOLUTION_SDK__` * Always build TRK against dolphin headers * Resolve revolution SDK header resolution issues
Diffstat (limited to 'libs/JSystem/src/J3DGraphAnimator')
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DAnimation.cpp1420
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp269
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp243
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp116
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp116
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp303
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp555
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp100
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp523
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp40
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp698
11 files changed, 4383 insertions, 0 deletions
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DAnimation.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DAnimation.cpp
new file mode 100644
index 0000000000..28b80c58f1
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DAnimation.cpp
@@ -0,0 +1,1420 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DAnimation.h"
+#include "JSystem/J3DGraphAnimator/J3DModelData.h"
+#include "JSystem/J3DGraphBase/J3DStruct.h"
+#include "JSystem/JMath/JMath.h"
+
+void J3DFrameCtrl::init(s16 endFrame) {
+ mAttribute = EMode_LOOP;
+ mState = 0;
+ mStart = 0;
+ mEnd = endFrame;
+ mLoop = 0;
+ mRate = 1.0f;
+ mFrame = 0.0f;
+}
+
+int J3DFrameCtrl::checkPass(f32 passFrame) {
+ f32 next_frame = mFrame + mRate;
+
+ switch (mAttribute) {
+ case 0:
+ case 1:
+ if (next_frame < mStart) {
+ next_frame = mStart;
+ }
+
+ if (next_frame >= mEnd) {
+ next_frame = mEnd - 0.001f;
+ }
+
+ if (mFrame <= next_frame) {
+ if (mFrame <= passFrame && passFrame < next_frame) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (next_frame <= passFrame && passFrame < mFrame) {
+ return true;
+ }
+ return false;
+ case 2:
+ if (mFrame < mStart) {
+ while (next_frame < mStart) {
+ if (mLoop - mStart <= 0.0f) {
+ break;
+ }
+ next_frame += mLoop - mStart;
+ }
+
+ if (next_frame <= passFrame && passFrame < mLoop) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mEnd <= mFrame) {
+ while (next_frame >= mEnd) {
+ if (mEnd - mLoop <= 0.0f) {
+ break;
+ }
+ next_frame -= mEnd - mLoop;
+ }
+
+ if (mLoop <= passFrame && passFrame < next_frame) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (next_frame < mStart) {
+ while (next_frame < mStart) {
+ if (mLoop - mStart <= 0.0f) {
+ break;
+ }
+ next_frame += mLoop - mStart;
+ }
+
+ if ((mStart <= passFrame && passFrame < mFrame) || (next_frame <= passFrame && passFrame < mLoop)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mEnd <= next_frame) {
+ while (next_frame >= mEnd) {
+ if (mEnd - mLoop <= 0.0f) {
+ break;
+ }
+
+ next_frame -= mEnd - mLoop;
+ }
+
+ if ((mFrame <= passFrame && passFrame < mEnd) || (mLoop <= passFrame && passFrame < next_frame)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mFrame <= next_frame) {
+ if (mFrame <= passFrame && passFrame < next_frame) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (next_frame <= passFrame && passFrame < mFrame) {
+ return true;
+ }
+ return false;
+ case 3:
+ case 4:
+ if (next_frame >= mEnd) {
+ next_frame = mEnd - 0.001f;
+ }
+
+ if (next_frame < mStart) {
+ next_frame = mStart;
+ }
+
+ if (mFrame <= next_frame) {
+ if (mFrame <= passFrame && passFrame < next_frame) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (next_frame <= passFrame && passFrame < mFrame) {
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+
+void J3DFrameCtrl::update() {
+ mState = 0;
+ mFrame += mRate;
+
+ switch (mAttribute) {
+ case EMode_NONE:
+ if (mFrame < mStart) {
+ mFrame = mStart;
+ mRate = 0.0f;
+ mState |= (u8)1;
+ }
+ if (mFrame >= mEnd) {
+ mFrame = mEnd - 0.001f;
+ mRate = 0.0f;
+ mState |= (u8)1;
+ }
+ break;
+ case EMode_RESET:
+ if (mFrame < mStart) {
+ mFrame = mStart;
+ mRate = 0.0f;
+ mState |= (u8)1;
+ }
+ if (mFrame >= mEnd) {
+ mFrame = mStart;
+ mRate = 0.0f;
+ mState |= (u8)1;
+ }
+ break;
+ case EMode_LOOP:
+ while (mFrame < mStart) {
+ mState |= (u8)2;
+ if (mLoop - mStart <= 0.0f) {
+ break;
+ }
+ mFrame += mLoop - mStart;
+ }
+ while (mFrame >= mEnd) {
+ mState |= (u8)2;
+ if (mEnd - mLoop <= 0.0f) {
+ break;
+ }
+ mFrame -= mEnd - mLoop;
+ }
+ break;
+ case EMode_REVERSE:
+ if (mFrame >= mEnd) {
+ mFrame = mEnd - (mFrame - mEnd);
+ mRate = -mRate;
+ }
+ if (mFrame < mStart) {
+ mFrame = mStart - (mFrame - mStart);
+ mRate = 0.0f;
+ mState |= (u8)1;
+ }
+ break;
+ case EMode_LOOP_REVERSE:
+ if (mFrame >= mEnd - 1.0f) {
+ mFrame = (mEnd - 1.0f) - (mFrame - (mEnd - 1.0f));
+ mRate = -mRate;
+ }
+ if (mFrame < mStart) {
+ mFrame = mStart - (mFrame - mStart);
+ mRate = -mRate;
+ mState |= (u8)2;
+ }
+ break;
+ }
+}
+
+J3DAnmTransform::J3DAnmTransform(s16 frameMax, f32* pScaleData, s16* pRotData, f32* pTransData)
+ : J3DAnmBase(frameMax) {
+ mScaleData = pScaleData;
+ mRotData = pRotData;
+ mTransData = pTransData;
+ field_0x18 = 0;
+ field_0x1a = 0;
+ field_0x1c = 0;
+ field_0x1e = 0;
+}
+
+void J3DAnmTransformFull::getTransform(u16 jointNo, J3DTransformInfo* pTransform) const {
+ J3D_ASSERT_RANGE(317, jointNo >= 0 && jointNo < field_0x1e);
+ J3D_ASSERT_NULLPTR(318, pTransform != NULL);
+
+ u16 idx = jointNo * 3;
+ J3DAnmTransformFullTable* entryX = &mAnmTable[idx];
+ J3DAnmTransformFullTable* entryY = &mAnmTable[idx + 1];
+ J3DAnmTransformFullTable* entryZ = &mAnmTable[idx + 2];
+
+ if (mFrame < 0.0f) {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset];
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset];
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset];
+
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset];
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset];
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset];
+
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset];
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset];
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset];
+ } else {
+ u32 frame_max;
+ u32 frame = (int)(mFrame + 0.5f);
+
+ frame_max = entryX->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + frame];
+ }
+
+ frame_max = entryX->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset + frame];
+ }
+
+ frame_max = entryX->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + frame];
+ }
+
+ frame_max = entryY->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + frame];
+ }
+
+ frame_max = entryY->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset + frame];
+ }
+
+ frame_max = entryY->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + frame];
+ }
+
+ frame_max = entryZ->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + frame];
+ }
+
+ frame_max = entryZ->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset + frame];
+ }
+
+ frame_max = entryZ->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + frame];
+ }
+ }
+}
+
+void J3DAnmTransformFullWithLerp::getTransform(u16 jointNo, J3DTransformInfo* pTransform) const {
+ J3D_ASSERT_RANGE(421, jointNo >= 0 && jointNo < field_0x1e);
+ J3D_ASSERT_NULLPTR(422, pTransform != NULL);
+
+ u16 idx = jointNo * 3;
+ J3DAnmTransformFullTable* entryX = &mAnmTable[idx];
+ J3DAnmTransformFullTable* entryY = &mAnmTable[idx + 1];
+ J3DAnmTransformFullTable* entryZ = &mAnmTable[idx + 2];
+
+ if (mFrame < 0.0f) {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset];
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset];
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset];
+
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset];
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset];
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset];
+
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset];
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset];
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset];
+ } else {
+ u32 frame_max;
+ int frame = (int)mFrame;
+
+ if (frame == mFrame) {
+ frame_max = entryX->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + frame];
+ }
+
+ frame_max = entryX->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset + frame];
+ }
+
+ frame_max = entryX->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + frame];
+ }
+
+ frame_max = entryY->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + frame];
+ }
+
+ frame_max = entryY->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset + frame];
+ }
+
+ frame_max = entryY->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + frame];
+ }
+
+ frame_max = entryZ->mScaleMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + frame];
+ }
+
+ frame_max = entryZ->mRotationMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset + (frame_max - 1)];
+ } else {
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset + frame];
+ }
+
+ frame_max = entryZ->mTranslateMaxFrame;
+ if (frame >= frame_max) {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + frame];
+ }
+ } else {
+ f32 rate = mFrame - frame;
+ f32 var_f30 = 1.0f - rate;
+
+ u32 next_frame = frame + 1;
+
+ frame_max = entryX->mScaleMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.x = mScaleData[entryX->mScaleOffset + frame]
+ + rate * (mScaleData[entryX->mScaleOffset + next_frame]
+ - mScaleData[entryX->mScaleOffset + frame]);
+ }
+
+ frame_max = entryX->mRotationMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mRotation.x = mRotData[entryX->mRotationOffset + (frame_max - 1)];
+ } else {
+ u32 rot1 = (u16)mRotData[entryX->mRotationOffset + frame];
+ u32 rot2 = (u16)mRotData[entryX->mRotationOffset + next_frame];
+ int delta = rot2 - rot1;
+ if (delta > 0x8000) {
+ rot1 += 0x10000;
+ delta -= 0x10000;
+ } else if (-delta > 0x8000) {
+ delta += 0x10000;
+ }
+ pTransform->mRotation.x = (u32)((f32)rot1 + rate * (f32)delta);
+ }
+
+ frame_max = entryX->mTranslateMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateOffset + frame]
+ + rate * (mTransData[entryX->mTranslateOffset + next_frame]
+ - mTransData[entryX->mTranslateOffset + frame]);
+ }
+
+ frame_max = entryY->mScaleMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.y = mScaleData[entryY->mScaleOffset + frame]
+ + rate * (mScaleData[entryY->mScaleOffset + next_frame]
+ - mScaleData[entryY->mScaleOffset + frame]);
+ }
+
+ frame_max = entryY->mRotationMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mRotation.y = mRotData[entryY->mRotationOffset + (frame_max - 1)];
+ } else {
+ u32 rot1 = (u16)mRotData[entryY->mRotationOffset + frame];
+ u32 rot2 = (u16)mRotData[entryY->mRotationOffset + next_frame];
+ int delta = rot2 - rot1;
+ if (delta > 0x8000) {
+ rot1 += 0x10000;
+ delta -= 0x10000;
+ } else if (-delta > 0x8000) {
+ delta += 0x10000;
+ }
+ pTransform->mRotation.y = (u32)((f32)rot1 + rate * (f32)delta);
+ }
+
+ frame_max = entryY->mTranslateMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateOffset + frame]
+ + rate * (mTransData[entryY->mTranslateOffset + next_frame]
+ - mTransData[entryY->mTranslateOffset + frame]);
+ }
+
+ frame_max = entryZ->mScaleMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + (frame_max - 1)];
+ } else {
+ pTransform->mScale.z = mScaleData[entryZ->mScaleOffset + frame]
+ + rate * (mScaleData[entryZ->mScaleOffset + next_frame]
+ - mScaleData[entryZ->mScaleOffset + frame]);
+ }
+
+ frame_max = entryZ->mRotationMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mRotation.z = mRotData[entryZ->mRotationOffset + (frame_max - 1)];
+ } else {
+ u32 rot1 = (u16)mRotData[entryZ->mRotationOffset + frame];
+ u32 rot2 = (u16)mRotData[entryZ->mRotationOffset + next_frame];
+ int delta = rot2 - rot1;
+ if (delta > 0x8000) {
+ rot1 += 0x10000;
+ delta -= 0x10000;
+ } else if (-delta > 0x8000) {
+ delta += 0x10000;
+ }
+ pTransform->mRotation.z = (u32)((f32)rot1 + rate * (f32)delta);
+ }
+
+ frame_max = entryZ->mTranslateMaxFrame;
+ if (next_frame >= frame_max) {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + (frame_max - 1)];
+ } else {
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateOffset + frame]
+ + rate * (mTransData[entryZ->mTranslateOffset + next_frame]
+ - mTransData[entryZ->mTranslateOffset + frame]);
+ }
+ }
+ }
+}
+
+inline f32 J3DHermiteInterpolation(f32 p1, f32 const* p2, f32 const* p3, f32 const* p4,
+ f32 const* p5, f32 const* p6, f32 const* p7) {
+ return JMAHermiteInterpolation(p1, *p2, *p3, *p4, *p5, *p6, *p7);
+}
+
+inline f32 J3DHermiteInterpolation(__REGISTER f32 pp1, __REGISTER s16 const* pp2,
+ __REGISTER s16 const* pp3, __REGISTER s16 const* pp4,
+ __REGISTER s16 const* pp5, __REGISTER s16 const* pp6,
+ __REGISTER s16 const* pp7) {
+#ifdef __MWERKS__
+ register f32 p1 = pp1;
+ register f32 ff8;
+ register f32 ff7;
+ register f32 ff6;
+ register f32 ff5;
+ register f32 ff4;
+ register f32 ff3;
+ register f32 ff2;
+ register f32 ff0;
+ register f32 fout;
+ register s16 const* p2 = pp2;
+ register s16 const* p3 = pp3;
+ register s16 const* p4 = pp4;
+ register s16 const* p5 = pp5;
+ register s16 const* p6 = pp6;
+ register s16 const* p7 = pp7;
+ // clang-format off
+ asm {
+ psq_l ff2, 0(p2), 0x1, 5
+ psq_l ff0, 0(p5), 0x1, 5
+ psq_l ff7, 0(p3), 0x1, 5
+ fsubs ff5, ff0, ff2
+ psq_l ff6, 0(p6), 0x1, 5
+ fsubs ff3, p1, ff2
+ psq_l ff0, 0(p7), 0x1, 5
+ fsubs ff4, ff6, ff7
+ fdivs ff3, ff3, ff5
+ psq_l fout, 0(p4), 0x1, 5
+ fmadds ff0, ff0, ff5, ff7
+ fmuls ff2, ff3, ff3
+ fnmsubs ff4, ff5, fout, ff4
+ fsubs ff0, ff0, ff6
+ fsubs ff0, ff0, ff4
+ fmuls ff0, ff2, ff0
+ fmadds fout, ff5, fout, ff0
+ fmadds fout, fout, ff3, ff7
+ fmadds fout, ff4, ff2, fout
+ fsubs fout, fout, ff0
+ }
+ // clang-format on
+ return fout;
+#endif
+}
+
+template<typename T>
+f32 J3DGetKeyFrameInterpolation(f32 frame, J3DAnmKeyTableBase* pKeyTable, T* pData) {
+ J3D_ASSERT_NULLPTR(740, pData != NULL);
+
+ if (frame < pData[0]) {
+ return pData[1];
+ }
+
+ if (pKeyTable->mType == 0) {
+ if (pData[(pKeyTable->mMaxFrame - 1) * 3] <= frame) {
+ return pData[(pKeyTable->mMaxFrame - 1) * 3 + 1];
+ }
+
+ u32 uVar7 = pKeyTable->mMaxFrame;
+ while (uVar7 > 1) {
+ u32 uVar2 = uVar7 >> 1;
+ u32 tmp = uVar2 * 3;
+ if (frame >= pData[tmp]) {
+ pData += tmp;
+ uVar7 = uVar7 - uVar2;
+ } else {
+ uVar7 = uVar2;
+ }
+ }
+
+ f32 interpolated = J3DHermiteInterpolation(frame, &pData[0], &pData[1], &pData[2], &pData[3], &pData[4], &pData[5]);
+ return interpolated;
+ } else {
+ if (pData[(pKeyTable->mMaxFrame - 1) * 4] <= frame) {
+ return pData[(pKeyTable->mMaxFrame - 1) * 4 + 1];
+ }
+
+ u32 var_r27 = pKeyTable->mMaxFrame;
+ while (var_r27 > 1) {
+ u32 var_r25 = var_r27 >> 1;
+ u32 var_r23 = var_r25 * 4;
+ if (frame >= pData[var_r23]) {
+ pData += var_r23;
+ var_r27 = var_r27 - var_r25;
+ } else {
+ var_r27 = var_r25;
+ }
+ }
+
+ f32 interpolated = J3DHermiteInterpolation(frame, &pData[0], &pData[1], &pData[3], &pData[4], &pData[5], &pData[6]);
+ return interpolated;
+ }
+}
+
+void J3DAnmTransformKey::calcTransform(f32 frame, u16 jointNo, J3DTransformInfo* pTransform) const {
+ J3D_ASSERT_RANGE(829, jointNo >= 0 && jointNo < field_0x1e);
+ J3D_ASSERT_NULLPTR(830, pTransform != NULL);
+
+ u16 idx = jointNo * 3;
+ J3DAnmTransformKeyTable* entryX = &mAnmTable[idx];
+ J3DAnmTransformKeyTable* entryY = &mAnmTable[idx + 1];
+ J3DAnmTransformKeyTable* entryZ = &mAnmTable[idx + 2];
+
+ switch (entryX->mScaleInfo.mMaxFrame) {
+ case 0:
+ pTransform->mScale.x = 1.0f;
+ break;
+ case 1:
+ pTransform->mScale.x = mScaleData[entryX->mScaleInfo.mOffset];
+ break;
+ default:
+ pTransform->mScale.x = J3DGetKeyFrameInterpolation(frame, &entryX->mScaleInfo,
+ &mScaleData[entryX->mScaleInfo.mOffset]);
+ }
+
+ switch (entryY->mScaleInfo.mMaxFrame) {
+ case 0:
+ pTransform->mScale.y = 1.0f;
+ break;
+ case 1:
+ pTransform->mScale.y = mScaleData[entryY->mScaleInfo.mOffset];
+ break;
+ default:
+ pTransform->mScale.y = J3DGetKeyFrameInterpolation(frame, &entryY->mScaleInfo,
+ &mScaleData[entryY->mScaleInfo.mOffset]);
+ }
+
+ switch (entryZ->mScaleInfo.mMaxFrame) {
+ case 0:
+ pTransform->mScale.z = 1.0f;
+ break;
+ case 1:
+ pTransform->mScale.z = mScaleData[entryZ->mScaleInfo.mOffset];
+ break;
+ default:
+ pTransform->mScale.z = J3DGetKeyFrameInterpolation(frame, &entryZ->mScaleInfo,
+ &mScaleData[entryZ->mScaleInfo.mOffset]);
+ }
+
+ switch (entryX->mRotationInfo.mMaxFrame) {
+ case 0:
+ pTransform->mRotation.x = 0;
+ break;
+ case 1:
+ pTransform->mRotation.x = mRotData[entryX->mRotationInfo.mOffset] << mDecShift;
+ break;
+ default:
+ pTransform->mRotation.x = (int)J3DGetKeyFrameInterpolation(frame, &entryX->mRotationInfo,
+ &mRotData[entryX->mRotationInfo.mOffset]) << mDecShift;
+ }
+
+ switch (entryY->mRotationInfo.mMaxFrame) {
+ case 0:
+ pTransform->mRotation.y = 0;
+ break;
+ case 1:
+ pTransform->mRotation.y = mRotData[entryY->mRotationInfo.mOffset] << mDecShift;
+ break;
+ default:
+ pTransform->mRotation.y = (int)J3DGetKeyFrameInterpolation(frame, &entryY->mRotationInfo,
+ &mRotData[entryY->mRotationInfo.mOffset]) << mDecShift;
+ }
+
+ switch (entryZ->mRotationInfo.mMaxFrame) {
+ case 0:
+ pTransform->mRotation.z = 0;
+ break;
+ case 1:
+ pTransform->mRotation.z = mRotData[entryZ->mRotationInfo.mOffset] << mDecShift;
+ break;
+ default:
+ pTransform->mRotation.z = (int)J3DGetKeyFrameInterpolation(frame, &entryZ->mRotationInfo,
+ &mRotData[entryZ->mRotationInfo.mOffset]) << mDecShift;
+ }
+
+ switch (entryX->mTranslateInfo.mMaxFrame) {
+ case 0:
+ pTransform->mTranslate.x = 0.0f;
+ break;
+ case 1:
+ pTransform->mTranslate.x = mTransData[entryX->mTranslateInfo.mOffset];
+ break;
+ default:
+ pTransform->mTranslate.x = J3DGetKeyFrameInterpolation(frame, &entryX->mTranslateInfo,
+ &mTransData[entryX->mTranslateInfo.mOffset]);
+ }
+
+ switch (entryY->mTranslateInfo.mMaxFrame) {
+ case 0:
+ pTransform->mTranslate.y = 0.0f;
+ break;
+ case 1:
+ pTransform->mTranslate.y = mTransData[entryY->mTranslateInfo.mOffset];
+ break;
+ default:
+ pTransform->mTranslate.y = J3DGetKeyFrameInterpolation(frame, &entryY->mTranslateInfo,
+ &mTransData[entryY->mTranslateInfo.mOffset]);
+ }
+
+ switch (entryZ->mTranslateInfo.mMaxFrame) {
+ case 0:
+ pTransform->mTranslate.z = 0.0f;
+ break;
+ case 1:
+ pTransform->mTranslate.z = mTransData[entryZ->mTranslateInfo.mOffset];
+ break;
+ default:
+ pTransform->mTranslate.z = J3DGetKeyFrameInterpolation(frame, &entryZ->mTranslateInfo,
+ &mTransData[entryZ->mTranslateInfo.mOffset]);
+ }
+}
+
+J3DAnmTextureSRTKey::J3DAnmTextureSRTKey() {
+ mDecShift = 0;
+ mTrackNum = mScaleNum = mRotNum = mTransNum = 0;
+ mAnmTable = NULL;
+ mScaleData = mTransData = NULL;
+ mRotData = NULL;
+ field_0x4a = field_0x44 = field_0x46 = field_0x48 = 0;
+ field_0x58 = NULL;
+ field_0x4c = field_0x54 = NULL;
+ field_0x50 = NULL;
+ mTexMtxCalcType = 0;
+}
+
+void J3DAnmTextureSRTKey::calcTransform(f32 frame, u16 jointNo, J3DTextureSRTInfo* pTexSRTInfo) const {
+ J3D_ASSERT_RANGE(992, jointNo >= 0 && jointNo < mTrackNum);
+ J3D_ASSERT_NULLPTR(993, pTexSRTInfo != NULL);
+
+ u16 idx = jointNo * 3;
+ J3DAnmTransformKeyTable* entryX = &mAnmTable[idx];
+ J3DAnmTransformKeyTable* entryY = &mAnmTable[idx + 1];
+ J3DAnmTransformKeyTable* entryRot = &mAnmTable[idx + 2];
+
+ switch (entryX->mScaleInfo.mMaxFrame) {
+ case 0:
+ pTexSRTInfo->mScaleX = 1.0f;
+ break;
+ case 1:
+ pTexSRTInfo->mScaleX = mScaleData[entryX->mScaleInfo.mOffset];
+ break;
+ default:
+ pTexSRTInfo->mScaleX = J3DGetKeyFrameInterpolation(frame, &entryX->mScaleInfo,
+ &mScaleData[entryX->mScaleInfo.mOffset]);
+ }
+
+ switch (entryY->mScaleInfo.mMaxFrame) {
+ case 0:
+ pTexSRTInfo->mScaleY = 1.0f;
+ break;
+ case 1:
+ pTexSRTInfo->mScaleY = mScaleData[entryY->mScaleInfo.mOffset];
+ break;
+ default:
+ pTexSRTInfo->mScaleY = J3DGetKeyFrameInterpolation(frame, &entryY->mScaleInfo,
+ &mScaleData[entryY->mScaleInfo.mOffset]);
+ }
+
+ switch (entryRot->mRotationInfo.mMaxFrame) {
+ case 0:
+ pTexSRTInfo->mRotation = 0;
+ break;
+ case 1:
+ pTexSRTInfo->mRotation = mRotData[entryRot->mRotationInfo.mOffset] << mDecShift;
+ break;
+ default:
+ pTexSRTInfo->mRotation = (int)J3DGetKeyFrameInterpolation(frame, &entryRot->mRotationInfo,
+ &mRotData[entryRot->mRotationInfo.mOffset]) << mDecShift;
+ }
+
+ switch (entryX->mTranslateInfo.mMaxFrame) {
+ case 0:
+ pTexSRTInfo->mTranslationX = 0.0f;
+ break;
+ case 1:
+ pTexSRTInfo->mTranslationX = mTransData[entryX->mTranslateInfo.mOffset];
+ break;
+ default:
+ pTexSRTInfo->mTranslationX = J3DGetKeyFrameInterpolation(frame, &entryX->mTranslateInfo,
+ &mTransData[entryX->mTranslateInfo.mOffset]);
+ }
+
+ switch (entryY->mTranslateInfo.mMaxFrame) {
+ case 0:
+ pTexSRTInfo->mTranslationY = 0.0f;
+ break;
+ case 1:
+ pTexSRTInfo->mTranslationY = mTransData[entryY->mTranslateInfo.mOffset];
+ break;
+ default:
+ pTexSRTInfo->mTranslationY = J3DGetKeyFrameInterpolation(frame, &entryY->mTranslateInfo,
+ &mTransData[entryY->mTranslateInfo.mOffset]);
+ }
+}
+
+f32 J3DAnmClusterFull::getWeight(u16 index) const {
+ int maxFrame = mAnmTable[index].mMaxFrame;
+ int frame = (int)(mFrame + 0.5f);
+
+ if (mFrame < 0.0f) {
+ return mWeight[mAnmTable[index].mOffset];
+ } else if (frame >= (u16)maxFrame) {
+ return mWeight[mAnmTable[index].mOffset + ((u16)maxFrame - 1)];
+ } else {
+ return mWeight[mAnmTable[index].mOffset + frame];
+ }
+}
+
+f32 J3DAnmClusterKey::getWeight(u16 index) const {
+ int maxFrame = (u16)mAnmTable[index].mWeightTable.mMaxFrame;
+ switch (maxFrame) {
+ case 0:
+ return 1.0f;
+ case 1:
+ return mWeight[mAnmTable[index].mWeightTable.mOffset];
+ default:
+ return J3DGetKeyFrameInterpolation(mFrame, &mAnmTable[index].mWeightTable,
+ &mWeight[mAnmTable[index].mWeightTable.mOffset]);
+ }
+}
+
+J3DAnmVtxColor::J3DAnmVtxColor() {
+ for (int i = 0; i < 2; i++) {
+ mAnmTableNum[i] = 0;
+ }
+ for (int i = 0; i < 2; i++) {
+ mAnmVtxColorIndexData[i] = NULL;
+ }
+}
+
+J3DAnmVtxColorFull::J3DAnmVtxColorFull() {
+ for (int i = 0; i < 2; i++) {
+ mpTable[i] = NULL;
+ }
+}
+
+void J3DAnmVtxColorFull::getColor(u8 tableNo, u16 index, GXColor* pColor) const {
+ J3D_ASSERT_NULLPTR(1254, pColor != NULL);
+ J3DAnmColorFullTable* entry = &mpTable[tableNo][index];
+
+ if (mFrame < 0.0f) {
+ pColor->r = mColorR[entry->mROffset];
+ pColor->g = mColorG[entry->mGOffset];
+ pColor->b = mColorB[entry->mBOffset];
+ pColor->a = mColorA[entry->mAOffset];
+ } else {
+ int frame = (int)(mFrame + 0.5f);
+ u16 maxFrame;
+
+ maxFrame = entry->mRMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->r = mColorR[entry->mROffset + (maxFrame - 1)];
+ } else {
+ pColor->r = mColorR[entry->mROffset + frame];
+ }
+
+ maxFrame = entry->mGMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->g = mColorG[entry->mGOffset + (maxFrame - 1)];
+ } else {
+ pColor->g = mColorG[entry->mGOffset + frame];
+ }
+
+ maxFrame = entry->mBMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->b = mColorB[entry->mBOffset + (maxFrame - 1)];
+ } else {
+ pColor->b = mColorB[entry->mBOffset + frame];
+ }
+
+ maxFrame = entry->mAMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->a = mColorA[entry->mAOffset + (maxFrame - 1)];
+ } else {
+ pColor->a = mColorA[entry->mAOffset + frame];
+ }
+ }
+}
+
+J3DAnmVtxColorKey::J3DAnmVtxColorKey() {
+ for (int i = 0; i < 2; i++) {
+ mpTable[i] = 0;
+ }
+}
+
+void J3DAnmVtxColorKey::getColor(u8 tableNo, u16 index, GXColor* pColor) const {
+ J3D_ASSERT_NULLPTR(1338, pColor != NULL);
+ J3DAnmColorKeyTable* entry = &mpTable[tableNo][index];
+
+ f32 col;
+ switch (entry->mRInfo.mMaxFrame) {
+ case 0:
+ pColor->r = 0;
+ break;
+ case 1:
+ pColor->r = mColorR[entry->mRInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mRInfo,
+ &mColorR[entry->mRInfo.mOffset]);
+ if (col <= 0.0f) {
+ pColor->r = 0;
+ } else if (col <= 255.0f) {
+ OSf32tou8(&col, &pColor->r);
+ } else {
+ pColor->r = 255;
+ }
+ }
+
+ switch (entry->mGInfo.mMaxFrame) {
+ case 0:
+ pColor->g = 0;
+ break;
+ case 1:
+ pColor->g = mColorG[entry->mGInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mGInfo,
+ &mColorG[entry->mGInfo.mOffset]);
+ if (col <= 0.0f) {
+ pColor->g = 0;
+ } else if (col <= 255.0f) {
+ OSf32tou8(&col, &pColor->g);
+ } else {
+ pColor->g = 255;
+ }
+ }
+
+ switch (entry->mBInfo.mMaxFrame) {
+ case 0:
+ pColor->b = 0;
+ break;
+ case 1:
+ pColor->b = mColorB[entry->mBInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mBInfo,
+ &mColorB[entry->mBInfo.mOffset]);
+ if (col <= 0.0f) {
+ pColor->b = 0;
+ } else if (col <= 255.0f) {
+ OSf32tou8(&col, &pColor->b);
+ } else {
+ pColor->b = 255;
+ }
+ }
+
+ switch (entry->mAInfo.mMaxFrame) {
+ case 0:
+ pColor->a = 0;
+ break;
+ case 1:
+ pColor->a = mColorA[entry->mAInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mAInfo,
+ &mColorA[entry->mAInfo.mOffset]);
+ if (col <= 0.0f) {
+ pColor->a = 0;
+ } else if (col <= 255.0f) {
+ OSf32tou8(&col, &pColor->a);
+ } else {
+ pColor->a = 255;
+ }
+ }
+}
+
+J3DAnmColor::J3DAnmColor() : field_0xc(0), field_0xe(0), field_0x10(0),
+ field_0x12(0), mUpdateMaterialNum(0), mUpdateMaterialID(NULL) {}
+
+
+void J3DAnmColor::searchUpdateMaterialID(J3DMaterialTable* pMatTable) {
+ for (u16 i = 0; i < mUpdateMaterialNum; i++) {
+ int index = pMatTable->getMaterialName()->getIndex(mUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mUpdateMaterialID[i] = index;
+ } else {
+ mUpdateMaterialID[i] = 0xffff;
+ }
+ }
+}
+
+J3DAnmColorFull::J3DAnmColorFull() {
+ mColorR = NULL;
+ mColorG = NULL;
+ mColorB = NULL;
+ mColorA = NULL;
+ mAnmTable = NULL;
+}
+
+void J3DAnmColorFull::getColor(u16 index, GXColor* pColor) const {
+ J3D_ASSERT_RANGE(1537, index >= 0 && index < mUpdateMaterialNum);
+ J3D_ASSERT_NULLPTR(1538, pColor != NULL);
+ J3DAnmColorFullTable* entry = &mAnmTable[index];
+
+ if (mFrame < 0.0f) {
+ pColor->r = mColorR[entry->mROffset];
+ pColor->g = mColorG[entry->mGOffset];
+ pColor->b = mColorB[entry->mBOffset];
+ pColor->a = mColorA[entry->mAOffset];
+ } else {
+ int frame = (int)(mFrame + 0.5f);
+ u16 maxFrame;
+
+ maxFrame = entry->mRMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->r = mColorR[entry->mROffset + (maxFrame - 1)];
+ } else {
+ pColor->r = mColorR[entry->mROffset + frame];
+ }
+
+ maxFrame = entry->mGMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->g = mColorG[entry->mGOffset + (maxFrame - 1)];
+ } else {
+ pColor->g = mColorG[entry->mGOffset + frame];
+ }
+
+ maxFrame = entry->mBMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->b = mColorB[entry->mBOffset + (maxFrame - 1)];
+ } else {
+ pColor->b = mColorB[entry->mBOffset + frame];
+ }
+
+ maxFrame = entry->mAMaxFrame;
+ if (frame >= maxFrame) {
+ pColor->a = mColorA[entry->mAOffset + (maxFrame - 1)];
+ } else {
+ pColor->a = mColorA[entry->mAOffset + frame];
+ }
+ }
+}
+
+J3DAnmColorKey::J3DAnmColorKey() {
+ mColorR = NULL;
+ mColorG = NULL;
+ mColorB = NULL;
+ mColorA = NULL;
+ mAnmTable = NULL;
+}
+
+void J3DAnmColorKey::getColor(u16 index, GXColor* pColor) const {
+ J3D_ASSERT_RANGE(1614, index >= 0 && index < mUpdateMaterialNum);
+ J3D_ASSERT_NULLPTR(1615, pColor != NULL);
+ J3DAnmColorKeyTable* entry = &mAnmTable[index];
+
+ f32 col;
+ switch (entry->mRInfo.mMaxFrame) {
+ case 0:
+ pColor->r = 0;
+ break;
+ case 1:
+ pColor->r = mColorR[entry->mRInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mRInfo,
+ &mColorR[entry->mRInfo.mOffset]);
+ if (col < 0.0f) {
+ pColor->r = 0;
+ } else if (col > 255.0f) {
+ pColor->r = 255;
+ } else {
+ OSf32tou8(&col, &pColor->r);
+ }
+ }
+
+ switch (entry->mGInfo.mMaxFrame) {
+ case 0:
+ pColor->g = 0;
+ break;
+ case 1:
+ pColor->g = mColorG[entry->mGInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mGInfo,
+ &mColorG[entry->mGInfo.mOffset]);
+ if (col < 0.0f) {
+ pColor->g = 0;
+ } else if (col > 255.0f) {
+ pColor->g = 255;
+ } else {
+ OSf32tou8(&col, &pColor->g);
+ }
+ }
+
+ switch (entry->mBInfo.mMaxFrame) {
+ case 0:
+ pColor->b = 0;
+ break;
+ case 1:
+ pColor->b = mColorB[entry->mBInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mBInfo,
+ &mColorB[entry->mBInfo.mOffset]);
+ if (col < 0.0f) {
+ pColor->b = 0;
+ } else if (col > 255.0f) {
+ pColor->b = 255;
+ } else {
+ OSf32tou8(&col, &pColor->b);
+ }
+ }
+
+ switch (entry->mAInfo.mMaxFrame) {
+ case 0:
+ pColor->a = 0;
+ break;
+ case 1:
+ pColor->a = mColorA[entry->mAInfo.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mAInfo,
+ &mColorA[entry->mAInfo.mOffset]);
+ if (col < 0.0f) {
+ pColor->a = 0;
+ } else if (col > 255.0f) {
+ pColor->a = 255;
+ } else {
+ OSf32tou8(&col, &pColor->a);
+ }
+ }
+}
+
+J3DAnmTevRegKey::J3DAnmTevRegKey() {
+ mCRegUpdateMaterialNum = mKRegUpdateMaterialNum = 0;
+
+ mCRegDataCountR =
+ mCRegDataCountG =
+ mCRegDataCountB =
+ mCRegDataCountA = 0;
+
+ mKRegDataCountR =
+ mKRegDataCountG =
+ mKRegDataCountB =
+ mKRegDataCountA = 0;
+
+ mCRegUpdateMaterialID = mKRegUpdateMaterialID = NULL;
+
+ mAnmCRegDataR =
+ mAnmCRegDataG =
+ mAnmCRegDataB =
+ mAnmCRegDataA = NULL;
+
+ mAnmKRegDataR =
+ mAnmKRegDataG =
+ mAnmKRegDataB =
+ mAnmKRegDataA = NULL;
+}
+
+
+J3DAnmTexPattern::J3DAnmTexPattern() : mTextureIndex(NULL), mAnmTable(NULL),
+ field_0x14(0), mUpdateMaterialNum(0), mUpdateMaterialID(NULL) {}
+
+void J3DAnmTexPattern::getTexNo(u16 index, u16* pTexNo) const {
+ u32 maxFrame = mAnmTable[index].mMaxFrame;
+ J3D_ASSERT_RANGE(1743, index >= 0 && index < mUpdateMaterialNum);
+ J3D_ASSERT_NULLPTR(1744, pTexNo != NULL);
+
+ if (mFrame < 0.0f) {
+ *pTexNo = mTextureIndex[mAnmTable[index].mOffset];
+ } else if (mFrame >= (u16)maxFrame) {
+ *pTexNo = mTextureIndex[mAnmTable[index].mOffset + ((u16)maxFrame - 1)];
+ } else {
+ *pTexNo = mTextureIndex[mAnmTable[index].mOffset + (int)mFrame];
+ }
+}
+
+void J3DAnmTexPattern::searchUpdateMaterialID(J3DMaterialTable* pMatTable) {
+ J3D_ASSERT_NULLPTR(1790, pMatTable != NULL);
+
+ for (u16 i = 0; i < mUpdateMaterialNum; i++) {
+ s32 index = pMatTable->getMaterialName()->getIndex(mUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mUpdateMaterialID[i] = index;
+ } else {
+ mUpdateMaterialID[i] = -1;
+ }
+ }
+}
+
+void J3DAnmTexPattern::searchUpdateMaterialID(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(1813, pModelData != NULL);
+ searchUpdateMaterialID(&pModelData->getMaterialTable());
+}
+
+void J3DAnmTextureSRTKey::searchUpdateMaterialID(J3DMaterialTable* pMatTable) {
+ J3D_ASSERT_NULLPTR(1832, pMatTable != NULL);
+
+ for (u16 i = 0; i < getUpdateMaterialNum(); i++) {
+ s32 index = pMatTable->getMaterialName()->getIndex(mUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mUpdateMaterialID[i] = index;
+ } else {
+ mUpdateMaterialID[i] = -1;
+ }
+ }
+
+ for (u16 i = 0; i < getPostUpdateMaterialNum(); i++) {
+ s32 index = pMatTable->getMaterialName()->getIndex(mPostUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mPostUpdateMaterialID[i] = index;
+ } else {
+ mPostUpdateMaterialID[i] = -1;
+ }
+ }
+}
+
+void J3DAnmTextureSRTKey::searchUpdateMaterialID(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(1871, pModelData != NULL);
+ searchUpdateMaterialID(&pModelData->getMaterialTable());
+}
+
+void J3DAnmTevRegKey::getTevColorReg(u16 index, GXColorS10* pColor) const {
+ J3D_ASSERT_RANGE(1887, index >= 0 && index < mCRegUpdateMaterialNum);
+ J3D_ASSERT_NULLPTR(1888, pColor != NULL);
+ J3DAnmCRegKeyTable* entry = &mAnmCRegKeyTable[index];
+
+ f32 col;
+ switch (entry->mRTable.mMaxFrame) {
+ case 0:
+ pColor->r = 0;
+ break;
+ case 1:
+ pColor->r = mAnmCRegDataR[entry->mRTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mRTable,
+ &mAnmCRegDataR[entry->mRTable.mOffset]);
+ if (col < -0x400) {
+ pColor->r = -0x400;
+ } else if (col > 0x3FF) {
+ pColor->r = 0x3FF;
+ } else {
+ OSf32tos16(&col, &pColor->r);
+ }
+ }
+
+ switch (entry->mGTable.mMaxFrame) {
+ case 0:
+ pColor->g = 0;
+ break;
+ case 1:
+ pColor->g = mAnmCRegDataG[entry->mGTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mGTable,
+ &mAnmCRegDataG[entry->mGTable.mOffset]);
+ if (col < -0x400) {
+ pColor->g = -0x400;
+ } else if (col > 0x3FF) {
+ pColor->g = 0x3FF;
+ } else {
+ OSf32tos16(&col, &pColor->g);
+ }
+ }
+
+ switch (entry->mBTable.mMaxFrame) {
+ case 0:
+ pColor->b = 0;
+ break;
+ case 1:
+ pColor->b = mAnmCRegDataB[entry->mBTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mBTable,
+ &mAnmCRegDataB[entry->mBTable.mOffset]);
+ if (col < -0x400) {
+ pColor->b = -0x400;
+ } else if (col > 0x3FF) {
+ pColor->b = 0x3FF;
+ } else {
+ OSf32tos16(&col, &pColor->b);
+ }
+ }
+
+ switch (entry->mATable.mMaxFrame) {
+ case 0:
+ pColor->a = 0;
+ break;
+ case 1:
+ pColor->a = mAnmCRegDataA[entry->mATable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mATable,
+ &mAnmCRegDataA[entry->mATable.mOffset]);
+ if (col < -0x400) {
+ pColor->a = -0x400;
+ } else if (col > 0x3FF) {
+ pColor->a = 0x3FF;
+ } else {
+ OSf32tos16(&col, &pColor->a);
+ }
+ }
+}
+
+void J3DAnmTevRegKey::getTevKonstReg(u16 index, GXColor* pColor) const {
+ J3D_ASSERT_RANGE(1989, index >= 0 && index < mKRegUpdateMaterialNum);
+ J3D_ASSERT_NULLPTR(1990, pColor != NULL);
+ J3DAnmKRegKeyTable* entry = &mAnmKRegKeyTable[index];
+
+ f32 col;
+ switch (entry->mRTable.mMaxFrame) {
+ case 0:
+ pColor->r = 0;
+ break;
+ case 1:
+ pColor->r = mAnmKRegDataR[entry->mRTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mRTable,
+ &mAnmKRegDataR[entry->mRTable.mOffset]);
+ if (col < 0) {
+ pColor->r = 0;
+ } else if (col > 0xFF) {
+ pColor->r = 0xFF;
+ } else {
+ OSf32tou8(&col, &pColor->r);
+ }
+ }
+
+ switch (entry->mGTable.mMaxFrame) {
+ case 0:
+ pColor->g = 0;
+ break;
+ case 1:
+ pColor->g = mAnmKRegDataG[entry->mGTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mGTable,
+ &mAnmKRegDataG[entry->mGTable.mOffset]);
+ if (col < 0) {
+ pColor->g = 0;
+ } else if (col > 0xFF) {
+ pColor->g = 0xFF;
+ } else {
+ OSf32tou8(&col, &pColor->g);
+ }
+ }
+
+ switch (entry->mBTable.mMaxFrame) {
+ case 0:
+ pColor->b = 0;
+ break;
+ case 1:
+ pColor->b = mAnmKRegDataB[entry->mBTable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mBTable,
+ &mAnmKRegDataB[entry->mBTable.mOffset]);
+ if (col < 0) {
+ pColor->b = 0;
+ } else if (col > 0xFF) {
+ pColor->b = 0xFF;
+ } else {
+ OSf32tou8(&col, &pColor->b);
+ }
+ }
+
+ switch (entry->mATable.mMaxFrame) {
+ case 0:
+ pColor->a = 0;
+ break;
+ case 1:
+ pColor->a = mAnmKRegDataA[entry->mATable.mOffset];
+ break;
+ default:
+ col = J3DGetKeyFrameInterpolation(mFrame, &entry->mATable,
+ &mAnmKRegDataA[entry->mATable.mOffset]);
+ if (col < 0) {
+ pColor->a = 0;
+ } else if (col > 0xFF) {
+ pColor->a = 0xFF;
+ } else {
+ OSf32tou8(&col, &pColor->a);
+ }
+ }
+}
+
+void J3DAnmTevRegKey::searchUpdateMaterialID(J3DMaterialTable* pMatTable) {
+ J3D_ASSERT_NULLPTR(2083, pMatTable != NULL);
+
+ for (u16 i = 0; i < mCRegUpdateMaterialNum; i++) {
+ s32 index = pMatTable->getMaterialName()->getIndex(mCRegUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mCRegUpdateMaterialID[i] = index;
+ } else {
+ mCRegUpdateMaterialID[i] = -1;
+ }
+ }
+
+ for (u16 i = 0; i < mKRegUpdateMaterialNum; i++) {
+ s32 index = pMatTable->getMaterialName()->getIndex(mKRegUpdateMaterialName.getName(i));
+ if (index != -1) {
+ mKRegUpdateMaterialID[i] = index;
+ } else {
+ mKRegUpdateMaterialID[i] = -1;
+ }
+ }
+}
+
+void J3DAnmTevRegKey::searchUpdateMaterialID(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(2119, pModelData != NULL);
+ searchUpdateMaterialID(&pModelData->getMaterialTable());
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
new file mode 100644
index 0000000000..d5bd1977a9
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
@@ -0,0 +1,269 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DCluster.h"
+#include "JSystem/J3DGraphAnimator/J3DAnimation.h"
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/JMath/JMATrigonometric.h"
+#include <base/PPCArch.h>
+
+J3DDeformData::J3DDeformData() {
+ mClusterNum = 0;
+ mClusterKeyNum = 0;
+ mClusterVertexNum = 0;
+ mClusterPointer = NULL;
+ mClusterKeyPointer = NULL;
+ mClusterVertex = NULL;
+ mVtxPosNum = 0;
+ mVtxNrmNum = 0;
+ mVtxPos = NULL;
+ mVtxNrm = NULL;
+ mClusterName = NULL;
+ mClusterKeyName = NULL;
+}
+
+void J3DDeformData::offAllFlag(u32 i_flag) {
+ for (u16 i = 0; i < mClusterNum; i++) {
+ mClusterPointer[i].getDeformer()->offFlag(i_flag);
+ }
+}
+
+void J3DDeformData::deform(J3DModel* model) {
+ J3D_ASSERT_NULLPTR(110, model);
+
+ deform(model->getVertexBuffer());
+}
+
+void J3DDeformData::deform(J3DVertexBuffer* buffer) {
+ J3D_ASSERT_NULLPTR(141, buffer);
+
+ buffer->swapVtxPosArrayPointer();
+ buffer->swapVtxNrmArrayPointer();
+
+ for (u16 i = 0; i < mClusterNum; i++) {
+ mClusterPointer[i].getDeformer()->deform(buffer, i);
+ }
+
+ DCStoreRangeNoSync(buffer->getVtxPosArrayPointer(0),
+ buffer->getVertexData()->getVtxNum() * sizeof(Vec));
+ DCStoreRangeNoSync(buffer->getVtxNrmArrayPointer(0),
+ buffer->getVertexData()->getNrmNum() * sizeof(Vec));
+ PPCSync();
+
+ buffer->setCurrentVtxPos(buffer->getVtxPosArrayPointer(0));
+ buffer->setCurrentVtxNrm(buffer->getVtxNrmArrayPointer(0));
+}
+
+void J3DDeformData::setAnm(J3DAnmCluster* anm) {
+ for (u16 i = 0; i < mClusterNum; i++) {
+ mClusterPointer[i].getDeformer()->setAnmCluster(anm);
+ }
+}
+
+J3DDeformer::J3DDeformer(J3DDeformData* data) {
+ mDeformData = data;
+ mAnmCluster = NULL;
+ field_0x8 = NULL;
+ field_0xc = NULL;
+ mFlags = 3;
+}
+
+void J3DDeformer::deform(J3DVertexBuffer* buffer, u16 param_1) {
+ J3D_ASSERT_NULLPTR(222, buffer);
+
+ u16 var_r31 = 0;
+ if (mAnmCluster != NULL) {
+ for (u16 i = 0; i < param_1; i++) {
+ var_r31 += mDeformData->getClusterPointer(i)->mKeyNum;
+ }
+
+ u16 num = mDeformData->getClusterPointer(param_1)->mKeyNum;
+ for (u16 i = 0; i < num; i++) {
+ field_0x8[i] = mAnmCluster->getWeight(var_r31++);
+ }
+
+ deform(buffer, param_1, field_0x8);
+ }
+}
+
+void J3DDeformer::deform_VtxPosF32(J3DVertexBuffer* i_buffer, J3DCluster* i_cluster,
+ J3DClusterKey* i_key, f32* i_weights) {
+ J3DClusterKey* key;
+ int posNum = i_cluster->mPosNum;
+ int keyNum = i_cluster->mKeyNum;
+ f32* vtxPosArray = (f32*)i_buffer->getVtxPosArrayPointer(0);
+ f32* deformVtxPos = mDeformData->getVtxPos();
+ u16* iVar9 = i_cluster->field_0x18;
+
+ for (int i = 0; i < posNum; i++) {
+ int index = iVar9[i] * 3;
+ vtxPosArray[index] = 0.0f;
+ vtxPosArray[index + 1] = 0.0f;
+ vtxPosArray[index + 2] = 0.0f;
+ }
+
+ f32 local_58[2] = {1.0f, -1.0f};
+
+ for (u16 i = 0; i < posNum; i++) {
+ int index = i_cluster->field_0x18[i] * 3;
+ for (u16 j = 0; j < keyNum; j++) {
+ int uVar8;
+ int uVar7;
+ key = &i_key[j];
+ uVar8 = uVar7 = ((u16*)key->field_0x4)[i];
+ uVar7 &= ~0xE000;
+ uVar7 *= 3;
+ f32 deform0 = deformVtxPos[uVar7];
+ f32 deform1 = deformVtxPos[uVar7 + 1];
+ f32 deform2 = deformVtxPos[uVar7 + 2];
+ deform0 *= local_58[((uVar8 & 0x8000) >> 0xF)];
+ deform1 *= local_58[((uVar8 & 0x4000) >> 0xE)];
+ deform2 *= local_58[((uVar8 & 0x2000) >> 0xD)];
+ vtxPosArray[index] += deform0 * i_weights[j];
+ vtxPosArray[index + 1] += deform1 * i_weights[j];
+ vtxPosArray[index + 2] += deform2 * i_weights[j];
+ }
+ }
+}
+
+// NONMATCHING one missing mr
+void J3DDeformer::deform_VtxNrmF32(J3DVertexBuffer* i_buffer, J3DCluster* i_cluster,
+ J3DClusterKey* i_key, f32* i_weights) {
+ f32* vtxNrmArray = (f32*)i_buffer->getVtxNrmArrayPointer(0);
+ f32* deformVtxNrm = mDeformData->getVtxNrm();
+ f32* iVar13 = field_0xc;
+ u16 keyNum = i_cluster->mKeyNum;
+ int uVar2 = i_cluster->field_0x16;
+
+ for (u16 i = 0; i < i_cluster->field_0x14; i++) {
+ int index = i * 3;
+ iVar13[index] = 0.0f;
+ iVar13[index + 1] = 0.0f;
+ iVar13[index + 2] = 0.0f;
+ for (u16 j = 0; j < keyNum; j++) {
+ J3DClusterKey* key = &i_key[j];
+ int uVar3 = ((u16*)key->field_0x8)[i];
+ int uVar4 = uVar3;
+ uVar3 &= ~0xE000;
+ uVar3 *= 3;
+ Vec deform0;
+ if (uVar4 & 0x8000) {
+ deform0.x = -deformVtxNrm[uVar3];
+ } else {
+ deform0.x = deformVtxNrm[uVar3];
+ }
+ if (uVar4 & 0x4000) {
+ deform0.y = -deformVtxNrm[uVar3 + 1];
+ } else {
+ deform0.y = deformVtxNrm[uVar3 + 1];
+ }
+ if (uVar4 & 0x2000) {
+ deform0.z = -deformVtxNrm[uVar3 + 2];
+ } else {
+ deform0.z = deformVtxNrm[uVar3 + 2];
+ }
+ iVar13[index] += deform0.x * i_weights[j];
+ iVar13[index + 1] += deform0.y * i_weights[j];
+ iVar13[index + 2] += deform0.z * i_weights[j];
+ }
+ normalize(&iVar13[index]);
+ }
+
+ for (u16 i = 0; i < uVar2; i++) {
+ J3DClusterVertex* clusterVtx = &i_cluster->mClusterVertex[i];
+ Vec vec;
+ vec.x = 0.0f;
+ vec.y = 0.0f;
+ vec.z = 0.0f;
+ f32 scale = 1.0f / clusterVtx->mNum;
+ for (u16 j = 0; j < clusterVtx->mNum; j++) {
+ int index = clusterVtx->field_0x4[j] * 3;
+ vec.x += scale * iVar13[index];
+ vec.y += scale * iVar13[index + 1];
+ vec.z += scale * iVar13[index + 2];
+ }
+ normalize((f32*)&vec);
+
+ for (u16 j = 0; j < clusterVtx->mNum; j++) {
+ u16 tmp = clusterVtx->field_0x8[j];
+ if (tmp == 0xffff) {
+ continue;
+ }
+ int index = tmp * 3;
+ u16 iVar4 = clusterVtx->field_0x4[j];
+ int index2 = iVar4 * 3;
+
+ f32 dot = vec.x * iVar13[index2] + vec.y * iVar13[index2 + 1]
+ + vec.z * iVar13[index2 + 2];
+ f32 angle;
+ if (dot >= 1.0f) {
+ angle = 0.0f;
+ } else if (dot > -1.0f) {
+ angle = JMath::acosDegree(dot);
+ } else {
+ angle = 180.0f;
+ }
+
+ if (angle <= i_cluster->mMinAngle) {
+ vtxNrmArray[index] = vec.x;
+ vtxNrmArray[index + 1] = vec.y;
+ vtxNrmArray[index + 2] = vec.z;
+ } else if (angle > i_cluster->mMaxAngle) {
+ vtxNrmArray[index] = iVar13[iVar4 * 3];
+ vtxNrmArray[index + 1] = iVar13[iVar4 * 3 + 1];
+ vtxNrmArray[index + 2] = iVar13[iVar4 * 3 + 2];
+ } else {
+ f32 weights[2];
+ weights[0] = (angle - i_cluster->mMinAngle)
+ / (i_cluster->mMaxAngle - i_cluster->mMinAngle);
+ weights[1] = 1.0f - weights[0];
+ vtxNrmArray[index] = weights[0] * iVar13[index2] + weights[1] * vec.x;
+ vtxNrmArray[index + 1] = weights[0] * iVar13[index2 + 1] + weights[1] * vec.y;
+ vtxNrmArray[index + 2] = weights[0] * iVar13[index2 + 2] + weights[1] * vec.z;
+ }
+ }
+ }
+}
+
+void J3DDeformer::deform(J3DVertexBuffer* i_buffer, u16 param_1, f32* i_weights) {
+ J3D_ASSERT_NULLPTR(505, i_buffer != NULL);
+
+ if (checkFlag(2)) {
+ JUT_ASSERT_MSG(512, i_buffer->getVertexData()->getVtxPosType() == 4, "Error : Invalid Verex Format");
+ if (i_buffer->getVertexData()->getVtxPosType() == 4) {
+ J3DCluster* cluster = mDeformData->getClusterPointer(param_1);
+ u16 offset = 0;
+ J3DClusterKey* clusterKey = NULL;
+
+ for (u16 i = 0; i < param_1; i++) {
+ offset += mDeformData->getClusterPointer(i)->mKeyNum + 1;
+ }
+
+ clusterKey = mDeformData->getClusterKeyPointer(offset);
+
+ int var_r23 = cluster->mKeyNum;
+ normalizeWeight(var_r23, i_weights);
+ deform_VtxPosF32(i_buffer, cluster, clusterKey, i_weights);
+
+ if (checkFlag(1) && cluster->mFlags != 0 && i_buffer->getVertexData()->getVtxNrmType() == 4)
+ {
+ deform_VtxNrmF32(i_buffer, cluster, clusterKey, i_weights);
+ }
+ }
+ }
+}
+
+static void dummy(J3DDeformData* data) {
+ data->getClusterNum();
+}
+
+void J3DDeformer::normalizeWeight(int i_keyNum, f32* i_weights) {
+ f32 totalWeight = 0.0f;
+ for (u16 i = 0; i < i_keyNum; i++) {
+ totalWeight += i_weights[i];
+ }
+
+ f32 scale = 1.0f / totalWeight;
+ for (u16 i = 0; i < i_keyNum; i++) {
+ i_weights[i] *= scale;
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
new file mode 100644
index 0000000000..4091a3b7a1
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
@@ -0,0 +1,243 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/J3DGraphBase/J3DDrawBuffer.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+#include "JSystem/JMath/JMath.h"
+#include "m_Do/m_Do_mtx.h"
+
+void J3DMtxCalcJ3DSysInitBasic::init(Vec const& scale, Mtx const& mtx) {
+ J3DSys::mCurrentS = scale;
+ Vec init = {1.0f, 1.0f, 1.0f};
+ J3DSys::mParentS = init;
+ JMAMTXApplyScale(mtx, J3DSys::mCurrentMtx, scale.x, scale.y, scale.z);
+}
+
+void J3DMtxCalcJ3DSysInitMaya::init(Vec const& scale, Mtx const& mtx) {
+ Vec init = {1.0f, 1.0f, 1.0f};
+ J3DSys::mParentS = init;
+ J3DSys::mCurrentS = scale;
+ JMAMTXApplyScale(mtx, J3DSys::mCurrentMtx, scale.x, scale.y, scale.z);
+}
+
+J3DMtxBuffer* J3DMtxCalc::mMtxBuffer;
+
+J3DJoint* J3DMtxCalc::mJoint;
+
+void J3DMtxCalcCalcTransformBasic::calcTransform(J3DTransformInfo const& transInfo) {
+ J3DJoint* joint = J3DMtxCalc::getJoint();
+ J3DMtxBuffer* mtxBuf = J3DMtxCalc::getMtxBuffer();
+ u16 jntNo = joint->getJntNo();
+
+ MtxP anmMtx = mtxBuf->getAnmMtx(jntNo);
+
+ J3DSys::mCurrentS.x *= transInfo.mScale.x;
+ J3DSys::mCurrentS.y *= transInfo.mScale.y;
+ J3DSys::mCurrentS.z *= transInfo.mScale.z;
+ J3DGetTranslateRotateMtx(transInfo, anmMtx);
+
+ if (!checkScaleOne(J3DSys::mCurrentS)) {
+ mtxBuf->setScaleFlag(jntNo, 0);
+ JMAMTXApplyScale(anmMtx, anmMtx, transInfo.mScale.x, transInfo.mScale.y,
+ transInfo.mScale.z);
+ } else {
+ mtxBuf->setScaleFlag(jntNo, 1);
+ }
+
+ MTXConcat(J3DSys::mCurrentMtx, anmMtx, J3DSys::mCurrentMtx);
+ MTXCopy(J3DSys::mCurrentMtx, anmMtx);
+}
+
+void J3DMtxCalcCalcTransformSoftimage::calcTransform(J3DTransformInfo const& transInfo) {
+ J3DJoint* joint = J3DMtxCalc::getJoint();
+ J3DMtxBuffer* mtxBuf = J3DMtxCalc::getMtxBuffer();
+ u16 jntNo = joint->getJntNo();
+
+ MtxP anmMtx = mtxBuf->getAnmMtx(jntNo);
+
+ J3DGetTranslateRotateMtx(transInfo.mRotation.x, transInfo.mRotation.y, transInfo.mRotation.z,
+ transInfo.mTranslate.x * J3DSys::mCurrentS.x,
+ transInfo.mTranslate.y * J3DSys::mCurrentS.y,
+ transInfo.mTranslate.z * J3DSys::mCurrentS.z, anmMtx);
+ MTXConcat(J3DSys::mCurrentMtx, anmMtx, J3DSys::mCurrentMtx);
+
+ J3DSys::mCurrentS.x *= transInfo.mScale.x;
+ J3DSys::mCurrentS.y *= transInfo.mScale.y;
+ J3DSys::mCurrentS.z *= transInfo.mScale.z;
+
+ if (!checkScaleOne(J3DSys::mCurrentS)) {
+ mtxBuf->setScaleFlag(jntNo, 0);
+ JMAMTXApplyScale(J3DSys::mCurrentMtx, anmMtx, J3DSys::mCurrentS.x, J3DSys::mCurrentS.y,
+ J3DSys::mCurrentS.z);
+ anmMtx[0][3] = J3DSys::mCurrentMtx[0][3];
+ anmMtx[1][3] = J3DSys::mCurrentMtx[1][3];
+ anmMtx[2][3] = J3DSys::mCurrentMtx[2][3];
+ } else {
+ mtxBuf->setScaleFlag(jntNo, 1);
+ MTXCopy(J3DSys::mCurrentMtx, anmMtx);
+ }
+}
+
+void J3DMtxCalcCalcTransformMaya::calcTransform(J3DTransformInfo const& transInfo) {
+ J3DJoint* joint = J3DMtxCalc::getJoint();
+ J3DMtxBuffer* mtxBuf = J3DMtxCalc::getMtxBuffer();
+
+ u16 jntNo = joint->getJntNo();
+
+ MtxP anmMtx = mtxBuf->getAnmMtx(jntNo);
+
+ J3DGetTranslateRotateMtx(transInfo, anmMtx);
+
+ if (transInfo.mScale.x == 1.0f && transInfo.mScale.y == 1.0f && transInfo.mScale.z == 1.0f) {
+ mtxBuf->setScaleFlag(jntNo, 1);
+ } else {
+ mtxBuf->setScaleFlag(jntNo, 0);
+ JMAMTXApplyScale(anmMtx, anmMtx, transInfo.mScale.x, transInfo.mScale.y,
+ transInfo.mScale.z);
+ }
+
+ u8 scaleCompensate = joint->getScaleCompensate();
+ if (scaleCompensate == 1) {
+ Vec inv;
+ inv.x = JMath::fastReciprocal(J3DSys::mParentS.x);
+ inv.y = JMath::fastReciprocal(J3DSys::mParentS.y);
+ inv.z = JMath::fastReciprocal(J3DSys::mParentS.z);
+
+ anmMtx[0][0] *= inv.x;
+ anmMtx[0][1] *= inv.x;
+ anmMtx[0][2] *= inv.x;
+ anmMtx[1][0] *= inv.y;
+ anmMtx[1][1] *= inv.y;
+ anmMtx[1][2] *= inv.y;
+ anmMtx[2][0] *= inv.z;
+ anmMtx[2][1] *= inv.z;
+ anmMtx[2][2] *= inv.z;
+ }
+
+ MTXConcat(J3DSys::mCurrentMtx, anmMtx, J3DSys::mCurrentMtx);
+ MTXCopy(J3DSys::mCurrentMtx, anmMtx);
+
+ J3DSys::mParentS.x = transInfo.mScale.x;
+ J3DSys::mParentS.y = transInfo.mScale.y;
+ J3DSys::mParentS.z = transInfo.mScale.z;
+}
+
+void J3DJoint::appendChild(J3DJoint* pChild) {
+ if (mChild == NULL) {
+ mChild = pChild;
+ return;
+ }
+ J3DJoint* curChild = mChild;
+ while (curChild->getYounger() != NULL) {
+ curChild = curChild->getYounger();
+ }
+ curChild->setYounger(pChild);
+}
+
+J3DJoint::J3DJoint() {
+ mCallBackUserData = NULL;
+ mCallBack = NULL;
+ field_0x8 = NULL;
+ mChild = NULL;
+ mYounger = NULL;
+ mJntNo = 0;
+ mKind = 1;
+ mScaleCompensate = false;
+ J3DTransformInfo* r30 = &mTransformInfo;
+ void* r29 = __memcpy(r30, &j3dDefaultTransformInfo, sizeof(J3DTransformInfo));
+ mBoundingSphereRadius = 0.0f;
+ mMtxCalc = NULL;
+ mMesh = NULL;
+
+ Vec init = {0.0f, 0.0f, 0.0f};
+ mMin = init;
+ Vec init2 = {0.0f, 0.0f, 0.0f};
+ mMax = init2;
+}
+
+void J3DJoint::entryIn() {
+ MtxP anmMtx = j3dSys.getModel()->getAnmMtx(mJntNo);
+ j3dSys.getDrawBuffer(0)->setZMtx(anmMtx);
+ j3dSys.getDrawBuffer(1)->setZMtx(anmMtx);
+ for (J3DMaterial* mesh = mMesh; mesh != NULL;) {
+ if (mesh->getShape()->checkFlag(J3DShpFlag_Visible)) {
+ mesh = mesh->getNext();
+ } else {
+ J3DMatPacket* matPacket = j3dSys.getModel()->getMatPacket(mesh->getIndex());
+ J3DShapePacket* shapePacket =
+ j3dSys.getModel()->getShapePacket(mesh->getShape()->getIndex());
+ if (!matPacket->isLocked()) {
+ if (mesh->getMaterialAnm()) {
+ mesh->getMaterialAnm()->calc(mesh);
+ }
+ mesh->calc(anmMtx);
+ }
+ mesh->setCurrentMtx();
+ matPacket->setMaterialAnmID(mesh->getMaterialAnm());
+ matPacket->setShapePacket(shapePacket);
+ bool isDrawModeOpaTexEdge = mesh->isDrawModeOpaTexEdge() == FALSE;
+ u8 r24 = matPacket->entry(j3dSys.getDrawBuffer(isDrawModeOpaTexEdge));
+ if (r24) {
+ j3dSys.setMatPacket(matPacket);
+ J3DDrawBuffer::entryNum++;
+ mesh->makeDisplayList();
+ }
+ mesh = mesh->getNext();
+ }
+ }
+}
+
+J3DMtxCalc* J3DJoint::mCurrentMtxCalc;
+
+void J3DJoint::recursiveCalc() {
+ J3DMtxCalc* prevMtxCalc = NULL;
+ Mtx prevCurrentMtx;
+ MTXCopy(J3DSys::mCurrentMtx, prevCurrentMtx);
+ Vec current, parent;
+ current = J3DSys::mCurrentS;
+ parent = J3DSys::mParentS;
+ if (getMtxCalc() != NULL) {
+ prevMtxCalc = getCurrentMtxCalc();
+ J3DMtxCalc* piVar2 = this->getMtxCalc();
+ setCurrentMtxCalc(piVar2);
+ J3DMtxCalc::setJoint(this);
+#if DEBUG
+ J3DMtxCalc::setMtxBuffer(J3DMtxCalc::getMtxBuffer());
+#endif
+ piVar2->calc();
+ } else {
+ if (getCurrentMtxCalc() != NULL) {
+ J3DMtxCalc* uVar6 = getCurrentMtxCalc();
+ J3DMtxCalc::setJoint(this);
+ uVar6->calc();
+ }
+ }
+
+ J3DJointCallBack jointCallback = getCallBack();
+ if (jointCallback != NULL) {
+ (*jointCallback)(this, 0);
+ }
+
+ J3DJoint* joint = getChild();
+ if (joint != NULL) {
+ joint->recursiveCalc();
+ }
+ MTXCopy(prevCurrentMtx, J3DSys::mCurrentMtx);
+
+ J3DSys::mCurrentS = current;
+ J3DSys::mParentS = parent;
+
+ if (prevMtxCalc != NULL) {
+ setCurrentMtxCalc(prevMtxCalc);
+ }
+ if (jointCallback != NULL) {
+ (*jointCallback)(this, 1);
+ }
+
+ joint = getYounger();
+ if (joint != NULL) {
+ joint->recursiveCalc();
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
new file mode 100644
index 0000000000..f6b54ff587
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
@@ -0,0 +1,116 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphAnimator/J3DJointTree.h"
+#include "JSystem/J3DGraphAnimator/J3DMaterialAttach.h"
+#include "JSystem/J3DGraphAnimator/J3DShapeTable.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+
+enum {
+ kTypeEnd = 0x00,
+ kTypeBeginChild = 0x01,
+ kTypeEndChild = 0x02,
+ kTypeJoint = 0x10,
+ kTypeMaterial = 0x11,
+ kTypeShape = 0x12,
+};
+
+J3DJointTree::J3DJointTree()
+ : mHierarchy(NULL), mFlags(0), mModelDataType(0), mRootNode(NULL), mBasicMtxCalc(NULL),
+ mJointNodePointer(NULL), mJointNum(0), mWEvlpMtxNum(0), mWEvlpMixMtxNum(0),
+ mWEvlpMixMtxIndex(0), mWEvlpMixWeight(0), mInvJointMtx(NULL), mWEvlpImportantMtxIdx(0),
+ field_0x40(0), mJointName(NULL) {}
+
+void J3DJointTree::makeHierarchy(J3DJoint* pJoint, const J3DModelHierarchy** pHierarchy,
+ J3DMaterialTable* pMaterialTable, J3DShapeTable* pShapeTable) {
+ J3D_ASSERT_NULLPTR(95, pHierarchy != NULL);
+ J3DJoint* curJoint = pJoint;
+
+ while (true) {
+ J3DJoint* newJoint = NULL;
+ J3DMaterial* newMaterial = NULL;
+ J3DShape* newShape = NULL;
+
+ switch ((*pHierarchy)->mType) {
+ case kTypeBeginChild:
+ (*pHierarchy)++;
+ makeHierarchy(curJoint, pHierarchy, pMaterialTable, pShapeTable);
+ break;
+ case kTypeEndChild:
+ (*pHierarchy)++;
+ return;
+ case kTypeEnd:
+ return;
+ case kTypeJoint:
+ newJoint = mJointNodePointer[((*pHierarchy)++)->mValue];
+ break;
+ case kTypeMaterial:
+ newMaterial = pMaterialTable->getMaterialNodePointer(((*pHierarchy)++)->mValue);
+ break;
+ case kTypeShape:
+ newShape = pShapeTable->getShapeNodePointer(((*pHierarchy)++)->mValue);
+ break;
+ }
+
+ if (newJoint != NULL) {
+ curJoint = newJoint;
+ if (pJoint == NULL)
+ mRootNode = newJoint;
+ else
+ pJoint->appendChild(newJoint);
+ } else if (newMaterial != NULL && pJoint->getType() == 'NJNT') {
+ pJoint->addMesh(newMaterial);
+ newMaterial->setJoint(pJoint);
+ } else if (newShape != NULL && pJoint->getType() == 'NJNT') {
+ J3DMaterial* newMaterial = pJoint->getMesh();
+ newMaterial->addShape(newShape);
+ newShape->setMaterial(newMaterial);
+ }
+ }
+}
+
+void J3DJointTree::findImportantMtxIndex() {
+ s32 wEvlpMtxNum = getWEvlpMtxNum();
+ u32 tableIdx = 0;
+ u16 drawFullWgtMtxNum = getDrawFullWgtMtxNum();
+ u16* wEvlpMixIndex = getWEvlpMixMtxIndex();
+ f32* wEvlpMixWeight = getWEvlpMixWeight();
+ u16* wEvlpImportantMtxIdx = getWEvlpImportantMtxIndex();
+
+ // Rigid matrices are easy.
+ for (u16 i = 0; i < drawFullWgtMtxNum; i++)
+ wEvlpImportantMtxIdx[i] = getDrawMtxIndex(i);
+
+ // For envelope matrices, we need to find the matrix with the most contribution.
+ for (s32 i = 0; i < wEvlpMtxNum; i++) {
+ s32 mixNum = getWEvlpMixMtxNum(i);
+ u16 bestIdx = 0;
+ f32 bestWeight = -0.1f;
+
+ for (s32 j = 0; j < mixNum; j++, tableIdx++) {
+ if (bestWeight < wEvlpMixWeight[tableIdx]) {
+ bestWeight = wEvlpMixWeight[tableIdx];
+ bestIdx = wEvlpMixIndex[tableIdx];
+ }
+ }
+
+ wEvlpImportantMtxIdx[i + getDrawFullWgtMtxNum()] = bestIdx;
+ }
+}
+
+void J3DJointTree::calc(J3DMtxBuffer* pMtxBuffer, Vec const& scale, f32 const (&mtx)[3][4]) {
+ J3D_ASSERT_NULLPTR(217, pMtxBuffer != NULL);
+ getBasicMtxCalc()->init(scale, mtx);
+ getBasicMtxCalc()->setMtxBuffer(pMtxBuffer);
+
+ J3DJoint* root = getRootNode();
+ if (root == NULL)
+ return;
+
+ root->setCurrentMtxCalc(getBasicMtxCalc());
+ root->recursiveCalc();
+}
+
+void J3DMtxCalc::setMtxBuffer(J3DMtxBuffer* mtxBuffer) {
+ J3DMtxCalc::mMtxBuffer = mtxBuffer;
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp
new file mode 100644
index 0000000000..f280a1583e
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp
@@ -0,0 +1,116 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+
+void J3DMaterialAnm::initialize() {
+ for (int i = 0; i < ARRAY_SIZE(mMatColorAnm); i++) {
+ mMatColorAnm[i].setAnmFlag(false);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mTexNoAnm); i++) {
+ mTexNoAnm[i].setAnmFlag(false);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mTevColorAnm); i++) {
+ mTevColorAnm[i].setAnmFlag(false);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mTevKColorAnm); i++) {
+ mTevKColorAnm[i].setAnmFlag(false);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mTexMtxAnm); i++) {
+ mTexMtxAnm[i].setAnmFlag(false);
+ }
+}
+
+void J3DMaterialAnm::calc(J3DMaterial* pMaterial) const {
+ J3D_ASSERT_NULLPTR(54, pMaterial != NULL);
+
+ for (u32 i = 0; i < ARRAY_SIZE(mMatColorAnm); i++) {
+ if (mMatColorAnm[i].getAnmFlag()) {
+ GXColor* color = pMaterial->mColorBlock->getMatColor(i);
+ mMatColorAnm[i].calc(color);
+ }
+ }
+
+ u16 tmp;
+ for (u32 i = 0; i < ARRAY_SIZE(mTexNoAnm); i++) {
+ if (mTexNoAnm[i].getAnmFlag()) {
+ mTexNoAnm[i].calc(&tmp);
+ pMaterial->mTevBlock->setTexNo(i, tmp);
+ }
+ }
+
+ for (u32 i = 0; i < 3; i++) {
+ if (mTevColorAnm[i].getAnmFlag()) {
+ GXColorS10* color = pMaterial->mTevBlock->getTevColor(i);
+ mTevColorAnm[i].calc(color);
+ }
+ }
+
+ for (u32 i = 0; i < ARRAY_SIZE(mTevKColorAnm); i++) {
+ if (mTevKColorAnm[i].getAnmFlag()) {
+ GXColor* color = pMaterial->mTevBlock->getTevKColor(i);
+ mTevKColorAnm[i].calc(color);
+ }
+ }
+
+ for (u32 i = 0; i < ARRAY_SIZE(mTexMtxAnm); i++) {
+ if (mTexMtxAnm[i].getAnmFlag()) {
+ J3DTextureSRTInfo* pSRT = &pMaterial->mTexGenBlock->getTexMtx(i)->getTexMtxInfo().mSRT;
+ mTexMtxAnm[i].calc(pSRT);
+ }
+ }
+}
+
+void J3DMaterialAnm::setMatColorAnm(int idx, J3DMatColorAnm* pMatColorAnm) {
+ J3D_ASSERT_RANGE(106, idx >= 0 && idx < 2);
+
+ if (pMatColorAnm == NULL) {
+ mMatColorAnm[idx].setAnmFlag(false);
+ } else {
+ mMatColorAnm[idx] = *pMatColorAnm;
+ }
+}
+
+void J3DMaterialAnm::setTexMtxAnm(int idx, J3DTexMtxAnm* pTexMtxAnm) {
+ J3D_ASSERT_RANGE(117, idx >= 0 && idx < 8);
+
+ if (pTexMtxAnm == NULL) {
+ mTexMtxAnm[idx].setAnmFlag(false);
+ } else {
+ mTexMtxAnm[idx] = *pTexMtxAnm;
+ }
+}
+
+void J3DMaterialAnm::setTexNoAnm(int idx, J3DTexNoAnm* pTexNoAnm) {
+ J3D_ASSERT_RANGE(128, idx >= 0 && idx < 8);
+
+ if (pTexNoAnm == NULL) {
+ mTexNoAnm[idx].setAnmFlag(false);
+ } else {
+ mTexNoAnm[idx] = *pTexNoAnm;
+ }
+}
+
+void J3DMaterialAnm::setTevColorAnm(int idx, J3DTevColorAnm* pTevColorAnm) {
+ J3D_ASSERT_RANGE(139, idx >= 0 && idx < 4);
+
+ if (pTevColorAnm == NULL) {
+ mTevColorAnm[idx].setAnmFlag(false);
+ } else {
+ mTevColorAnm[idx] = *pTevColorAnm;
+ }
+}
+
+void J3DMaterialAnm::setTevKColorAnm(int idx, J3DTevKColorAnm* pTevKColorAnm) {
+ J3D_ASSERT_RANGE(150, idx >= 0 && idx < 4);
+
+ if (pTevKColorAnm == NULL) {
+ mTevKColorAnm[idx].setAnmFlag(false);
+ } else {
+ mTevKColorAnm[idx] = *pTevKColorAnm;
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
new file mode 100644
index 0000000000..ee148288a1
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
@@ -0,0 +1,303 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DMaterialAttach.h"
+#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+#include "JSystem/JUtility/JUTAssert.h"
+
+void J3DMaterialTable::clear() {
+ mMaterialNum = 0;
+ mUniqueMatNum = 0;
+ mMaterialNodePointer = NULL;
+ mMaterialName = NULL;
+ field_0x10 = 0;
+ mTexture = NULL;
+ mTextureName = NULL;
+ field_0x1c = 0;
+}
+
+J3DMaterialTable::J3DMaterialTable() {
+ mMaterialNum = 0;
+ mUniqueMatNum = 0;
+ mMaterialNodePointer = NULL;
+ mMaterialName = NULL;
+ field_0x10 = 0;
+ mTexture = NULL;
+ mTextureName = NULL;
+ field_0x1c = 0;
+}
+
+J3DMaterialTable::~J3DMaterialTable() {}
+
+int J3DMaterialTable::removeMatColorAnimator(J3DAnmColor* pAnmColor) {
+ J3D_ASSERT_NULLPTR(208, pAnmColor != NULL);
+ int ret = false;
+
+ u16 updateMatNum = pAnmColor->getUpdateMaterialNum();
+ for (u16 i = 0; i < updateMatNum; i++) {
+ if (pAnmColor->isValidUpdateMaterialID(i)) {
+ u16 matNo = pAnmColor->getUpdateMaterialID(i);
+ J3DMaterialAnm* materialAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ if (materialAnm == NULL) {
+ ret = true;
+ } else {
+ materialAnm->setMatColorAnm(0, NULL);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int J3DMaterialTable::removeTexNoAnimator(J3DAnmTexPattern* pAnmTexPattern) {
+ J3D_ASSERT_NULLPTR(242, pAnmTexPattern != NULL);
+ int ret = 0;
+
+ u16 materialNum = pAnmTexPattern->getUpdateMaterialNum();
+ J3DAnmTexPatternFullTable* anm_table = (J3DAnmTexPatternFullTable*)pAnmTexPattern->getAnmTable();
+
+ for (u16 i = 0; i < materialNum; i++) {
+ if (pAnmTexPattern->isValidUpdateMaterialID(i)) {
+ u16 matNo = pAnmTexPattern->getUpdateMaterialID(i);
+ J3DMaterialAnm* pMatAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ u8 texNo = anm_table[i].mTexNo;
+ if (pMatAnm == NULL)
+ ret = 1;
+ else
+ pMatAnm->setTexNoAnm(texNo, NULL);
+ }
+ }
+
+ return ret;
+}
+
+int J3DMaterialTable::removeTexMtxAnimator(J3DAnmTextureSRTKey* pAnmTexSRTKey) {
+ J3D_ASSERT_NULLPTR(278, pAnmTexSRTKey != NULL);
+ s32 ret = 0;
+
+ u16 materialNum = pAnmTexSRTKey->getUpdateMaterialNum();
+ u16 postUpdateMaterialNum[1];
+ postUpdateMaterialNum[0] = pAnmTexSRTKey->getPostUpdateMaterialNum();
+
+ for (u16 i = 0; i < materialNum; i++) {
+ if (pAnmTexSRTKey->isValidUpdateMaterialID(i)) {
+ u16 matNo = pAnmTexSRTKey->getUpdateMaterialID(i);
+ J3DMaterial* pMaterial = getMaterialNodePointer(matNo);
+ J3DMaterialAnm* pMatAnm = pMaterial->getMaterialAnm();
+ u8 texMtxID = pAnmTexSRTKey->getUpdateTexMtxID(i);
+ if (pMatAnm == NULL) {
+ ret = 1;
+ } else if (texMtxID != 0xFF) {
+ pMatAnm->setTexMtxAnm(texMtxID, NULL);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int J3DMaterialTable::removeTevRegAnimator(J3DAnmTevRegKey* pAnmTevRegKey) {
+ J3D_ASSERT_NULLPTR(320, pAnmTevRegKey != NULL);
+ s32 ret = 0;
+
+ u16 cRegMaterialNum = pAnmTevRegKey->getCRegUpdateMaterialNum();
+ u16 kRegMaterialNum = pAnmTevRegKey->getKRegUpdateMaterialNum();
+
+ for (u16 i = 0; i < cRegMaterialNum; i++) {
+ if (pAnmTevRegKey->isValidCRegUpdateMaterialID(i)) {
+ const u16 spC = pAnmTevRegKey->getCRegUpdateMaterialID(i);
+ J3DMaterialAnm* pMatAnm = getMaterialNodePointer(spC)->getMaterialAnm();
+ const J3DAnmCRegKeyTable* table = pAnmTevRegKey->getAnmCRegKeyTable();
+ const u8 colorId = table[i].mColorId;
+ if (pMatAnm == NULL)
+ ret = 1;
+ else
+ pMatAnm->setTevColorAnm(colorId, NULL);
+ }
+ }
+
+ for (u16 i = 0; i < kRegMaterialNum; i++) {
+ if (pAnmTevRegKey->isValidKRegUpdateMaterialID(i)) {
+ const u16 spA = pAnmTevRegKey->getKRegUpdateMaterialID(i);
+ J3DMaterialAnm* pMatAnm = getMaterialNodePointer(spA)->getMaterialAnm();
+ const J3DAnmKRegKeyTable* table = pAnmTevRegKey->getAnmKRegKeyTable();
+ const u8 colorId = table[i].mColorId;
+ if (pMatAnm == NULL) {
+ ret = 1;
+ } else {
+ pMatAnm->setTevKColorAnm(colorId, NULL);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int J3DMaterialTable::createTexMtxForAnimator(J3DAnmTextureSRTKey* pTexSRTKey) {
+ J3D_ASSERT_NULLPTR(382, pTexSRTKey != NULL);
+ int rv = 0;
+
+ u16 materialNum = pTexSRTKey->getUpdateMaterialNum();
+ if (isLocked()) {
+ return 2;
+ }
+
+ for (u16 i = 0; i < materialNum; i++) {
+ if (pTexSRTKey->isValidUpdateMaterialID(i)) {
+ const u16 matNo = pTexSRTKey->getUpdateMaterialID(i);
+ J3DMaterial* material = getMaterialNodePointer(matNo);
+ u8 texMtx = pTexSRTKey->getUpdateTexMtxID(i);
+
+ J3DMaterialAnm* pMaterialAnm = material->getMaterialAnm();
+ if (pMaterialAnm == NULL) {
+ rv = 1;
+ } else {
+ if (texMtx != 0xff && material->getTexMtx(texMtx) == NULL) {
+ J3DTexMtx* mtx = new J3DTexMtx();
+ rv = 4;
+ material->setTexMtx(texMtx, mtx);
+ JUT_WARN(420, "matNo<%d> : texMtx%d nothing !\n", matNo, texMtx);
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+int J3DMaterialTable::entryMatColorAnimator(J3DAnmColor* pAnmColor) {
+ J3D_ASSERT_NULLPTR(450, pAnmColor != NULL);
+ int rv = 0;
+
+ u16 materialNum = pAnmColor->getUpdateMaterialNum();
+ if (isLocked()) {
+ return 2;
+ }
+
+ for (u16 i = 0; i < materialNum; i++) {
+ if (pAnmColor->isValidUpdateMaterialID(i)) {
+ const u16 matNo = pAnmColor->getUpdateMaterialID(i);
+ J3DMaterialAnm* materialAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ if (materialAnm == NULL) {
+ rv = 1;
+ } else {
+ J3DMatColorAnm matColorAnm(i, pAnmColor);
+ materialAnm->setMatColorAnm(0, &matColorAnm);
+ }
+ }
+ }
+
+ return rv;
+}
+
+int J3DMaterialTable::entryTexNoAnimator(J3DAnmTexPattern* pAnmTexPattern) {
+ J3D_ASSERT_NULLPTR(489, pAnmTexPattern != NULL);
+ int rv = 0;
+
+ u16 materialNum = pAnmTexPattern->getUpdateMaterialNum();
+ if (isLocked()) {
+ return 2;
+ }
+
+ for (u16 i = 0; i < materialNum; i++) {
+ if (pAnmTexPattern->isValidUpdateMaterialID(i)) {
+ const u16 matNo = pAnmTexPattern->getUpdateMaterialID(i);
+ J3DMaterialAnm* materialAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ const J3DAnmTexPatternFullTable* table = pAnmTexPattern->getAnmTable();
+ const u8 texNo = table[i].mTexNo;
+ if (materialAnm == NULL) {
+ rv = 1;
+ } else {
+ J3DTexNoAnm texNoAnm(i, pAnmTexPattern);
+ materialAnm->setTexNoAnm(texNo, &texNoAnm);
+ }
+ }
+ }
+
+ return rv;
+}
+
+int J3DMaterialTable::entryTexMtxAnimator(J3DAnmTextureSRTKey* pAnmTexSRTKey) {
+ J3D_ASSERT_NULLPTR(532, pAnmTexSRTKey != NULL);
+ int rv = 0;
+ u16 materialNum = pAnmTexSRTKey->getUpdateMaterialNum();
+
+ rv = createTexMtxForAnimator(pAnmTexSRTKey);
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (isLocked()) {
+ return 2;
+ }
+
+ for (u16 no = 0; no < materialNum; no++) {
+ if (pAnmTexSRTKey->isValidUpdateMaterialID(no)) {
+ const u16 matNo = pAnmTexSRTKey->getUpdateMaterialID(no);
+ J3DMaterial* material = getMaterialNodePointer(matNo);
+ J3DMaterialAnm* materialAnm = material->getMaterialAnm();
+ u8 texMtxID = pAnmTexSRTKey->getUpdateTexMtxID(no);
+ if (materialAnm == NULL) {
+ rv = 1;
+ } else {
+ if (texMtxID != 0xff) {
+ if (material->getTexCoord(texMtxID) != NULL) {
+ material->getTexCoord(texMtxID)->setTexGenMtx((u8)texMtxID * 3 + 30);
+ }
+ J3DTexMtxInfo& tmtxinfo = material->getTexMtx(texMtxID)->getTexMtxInfo();
+ tmtxinfo.mInfo = (tmtxinfo.mInfo & 0x3f) | (pAnmTexSRTKey->getTexMtxCalcType() << 7);
+ tmtxinfo.mCenter.x = pAnmTexSRTKey->getSRTCenter(no)->x;
+ tmtxinfo.mCenter.y = pAnmTexSRTKey->getSRTCenter(no)->y;
+ tmtxinfo.mCenter.z = pAnmTexSRTKey->getSRTCenter(no)->z;
+ J3DTexMtxAnm texMtxAnm(no, pAnmTexSRTKey);
+ materialAnm->setTexMtxAnm(texMtxID, &texMtxAnm);
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+int J3DMaterialTable::entryTevRegAnimator(J3DAnmTevRegKey* pAnmTevRegKey) {
+ J3D_ASSERT_NULLPTR(599, pAnmTevRegKey != NULL);
+ int rv = 0;
+
+ u16 cRegNum = pAnmTevRegKey->getCRegUpdateMaterialNum();
+ u16 kRegNum = pAnmTevRegKey->getKRegUpdateMaterialNum();
+ if (isLocked()) {
+ return 2;
+ }
+
+ for (u16 i = 0; i < cRegNum; i++) {
+ if (pAnmTevRegKey->isValidCRegUpdateMaterialID(i)) {
+ const u16 matNo = pAnmTevRegKey->getCRegUpdateMaterialID(i);
+ J3DMaterialAnm* materialAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ const J3DAnmCRegKeyTable* table = pAnmTevRegKey->getAnmCRegKeyTable();
+ u8 colorId = table[i].mColorId;
+ if (materialAnm == NULL) {
+ rv = 1;
+ } else {
+ J3DTevColorAnm tevColorAnm(i, pAnmTevRegKey);
+ materialAnm->setTevColorAnm(colorId, &tevColorAnm);
+ }
+ }
+ }
+
+ for (u16 i = 0; i < kRegNum; i++) {
+ if (pAnmTevRegKey->isValidKRegUpdateMaterialID(i)) {
+ const u16 matNo = pAnmTevRegKey->getKRegUpdateMaterialID(i);
+ J3DMaterialAnm* materialAnm = getMaterialNodePointer(matNo)->getMaterialAnm();
+ const J3DAnmKRegKeyTable* table = pAnmTevRegKey->getAnmKRegKeyTable();
+ const u8 colorId = table[i].mColorId;
+ if (materialAnm == NULL) {
+ rv = 1;
+ } else {
+ J3DTevKColorAnm tevKColorAnm(i, pAnmTevRegKey);
+ materialAnm->setTevKColorAnm(colorId, &tevKColorAnm);
+ }
+ }
+ }
+
+ return rv;
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp
new file mode 100644
index 0000000000..f423f1db2f
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp
@@ -0,0 +1,555 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
+#include "JSystem/J3DGraphAnimator/J3DShapeTable.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+#include "JSystem/J3DGraphBase/J3DShapeMtx.h"
+#include "JSystem/J3DGraphBase/J3DSys.h"
+
+#define J3D_ASSERTMSG(LINE, COND, MSG) JUT_ASSERT_MSG(LINE, (COND) != 0, MSG)
+#define J3D_WARN1(LINE, MSG, ARG1) JUT_WARN(LINE, MSG, ARG1)
+
+void J3DModel::initialize() {
+ mModelData = NULL;
+ mFlags = 0;
+ mDiffFlag = 0;
+ mCalcCallBack = NULL;
+ mUserArea = 0;
+
+ mBaseScale.x = 1.0f;
+ mBaseScale.y = 1.0f;
+ mBaseScale.z = 1.0f;
+
+ MTXIdentity(mBaseTransformMtx);
+ MTXIdentity(mInternalView);
+
+ mMtxBuffer = NULL;
+ mMatPacket = NULL;
+ mShapePacket = NULL;
+ mDeformData = NULL;
+ mSkinDeform = NULL;
+ mVtxColorCalc = NULL;
+ mUnkCalc1 = NULL;
+ mUnkCalc2 = NULL;
+}
+
+s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 mdlFlags, u32 mtxNum) {
+ J3D_ASSERTMSG(83, pModelData != NULL, "Error : null pointer.");
+ J3D_ASSERTMSG(84, mtxNum != 0, "Error : non-zero argument is specified 0.");
+ int ret = kJ3DError_Success;
+
+ mModelData = pModelData;
+ mMtxBuffer = new J3DMtxBuffer();
+
+ if (mMtxBuffer == NULL) {
+ return kJ3DError_Alloc;
+ }
+
+ ret = mMtxBuffer->create(pModelData, mtxNum);
+ if (ret != kJ3DError_Success) {
+ return ret;
+ }
+
+ ret = createShapePacket(pModelData);
+ if (ret != kJ3DError_Success) {
+ return ret;
+ }
+
+ ret = createMatPacket(pModelData, mdlFlags);
+ if (ret != kJ3DError_Success) {
+ return ret;
+ }
+
+ mVertexBuffer.setVertexData(&pModelData->getVertexData());
+ prepareShapePackets();
+
+ if (mdlFlags & J3DMdlFlag_Unk1) {
+ onFlag(J3DMdlFlag_Unk1);
+ }
+ if (mdlFlags & J3DMdlFlag_UseDefaultJ3D) {
+ onFlag(J3DMdlFlag_UseDefaultJ3D);
+ }
+ if (mdlFlags & J3DMdlFlag_EnableLOD) {
+ onFlag(J3DMdlFlag_EnableLOD);
+ }
+ if (mdlFlags & J3DMdlFlag_UseSharedDL) {
+ onFlag(J3DMdlFlag_UseSharedDL);
+ }
+ if (mdlFlags & J3DMdlFlag_UseSingleDL) {
+ onFlag(J3DMdlFlag_UseSingleDL);
+ }
+ if (mdlFlags & J3DMdlFlag_DifferedDLBuffer) {
+ onFlag(J3DMdlFlag_DifferedDLBuffer);
+ }
+ if (mdlFlags & J3DMdlFlag_SkinPosCpu) {
+ J3D_WARN1(149, "%s", "Don't forget to call J3DModel::setSkinDeform\n if you set J3DMdlFlag_SkinPosCpu.");
+ onFlag(J3DMdlFlag_SkinPosCpu);
+ }
+ if (mdlFlags & J3DMdlFlag_SkinNrmCpu) {
+ J3D_WARN1(154, "%s", "Don't forget to call J3DModel::setSkinDeform\n if you set J3DMdlFlag_SkinNrmCpu.");
+ onFlag(J3DMdlFlag_SkinNrmCpu);
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DModel::createShapePacket(J3DModelData* pModelData) {
+ J3D_ASSERTMSG(173, pModelData != NULL, "Error : null pointer.");
+
+ if (pModelData->getShapeNum() != 0) {
+ mShapePacket = new J3DShapePacket[pModelData->getShapeNum()];
+
+ if (mShapePacket == NULL) {
+ return kJ3DError_Alloc;
+ }
+
+ for (int i = 0; i < pModelData->getShapeNum(); i++) {
+ mShapePacket[i].setShape(pModelData->getShapeNodePointer(i));
+ mShapePacket[i].setModel(this);
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DModel::createMatPacket(J3DModelData* pModelData, u32 mdlFlags) {
+ J3D_ASSERTMSG(207, pModelData != NULL, "Error : null pointer.");
+ s32 ret = 0;
+
+ if (pModelData->getMaterialNum() != 0) {
+ mMatPacket = new J3DMatPacket[pModelData->getMaterialNum()];
+
+ if (mMatPacket == NULL) {
+ return kJ3DError_Alloc;
+ }
+ }
+
+ u16 matNum = pModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ J3DMaterial* materialNode = pModelData->getMaterialNodePointer(i);
+ J3DMatPacket* matPacket = mMatPacket + i;
+ J3DShapePacket* shapePacket = mShapePacket + materialNode->getShape()->getIndex();
+
+ matPacket->setMaterial(materialNode);
+ matPacket->setInitShapePacket(shapePacket);
+ matPacket->addShapePacket(shapePacket);
+ matPacket->setTexture(pModelData->getTexture());
+ matPacket->setMaterialID(materialNode->mDiffFlag);
+
+ if (pModelData->getModelDataType() == 1) {
+ matPacket->lock();
+ }
+
+ if (mdlFlags & J3DMdlFlag_DifferedDLBuffer) {
+ J3DDisplayListObj* dlobj = materialNode->getSharedDisplayListObj();
+ J3D_ASSERTMSG(253, dlobj != NULL, "Error : User need to call J3DModelData::newSharedDisplayList() before using DifferedDLBuffer.");
+ matPacket->setDisplayListObj(dlobj);
+ } else {
+ if (pModelData->getModelDataType() == 1) {
+ if (mdlFlags & J3DMdlFlag_UseSingleDL) {
+ J3DDisplayListObj* dlobj = materialNode->getSharedDisplayListObj();
+ matPacket->setDisplayListObj(dlobj);
+ } else {
+ J3DDisplayListObj* dlobj = materialNode->getSharedDisplayListObj();
+ ret = dlobj->single_To_Double();
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ matPacket->setDisplayListObj(dlobj);
+ }
+ } else if (mdlFlags & J3DMdlFlag_UseSharedDL) {
+ if (mdlFlags & J3DMdlFlag_UseSingleDL) {
+ ret = materialNode->newSingleSharedDisplayList(materialNode->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ J3DDisplayListObj* dlobj = materialNode->getSharedDisplayListObj();
+ matPacket->setDisplayListObj(dlobj);
+ } else {
+ ret = materialNode->newSharedDisplayList(materialNode->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ J3DDisplayListObj* dlobj = materialNode->getSharedDisplayListObj();
+ ret = dlobj->single_To_Double();
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ matPacket->setDisplayListObj(dlobj);
+ }
+ } else {
+ if (mdlFlags & J3DMdlFlag_UseSingleDL) {
+ ret = matPacket->newSingleDisplayList(materialNode->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+ } else {
+ ret = matPacket->newDisplayList(materialNode->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+ }
+ }
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DModel::newDifferedDisplayList(u32 diffFlags) {
+ mDiffFlag = diffFlags;
+
+ u16 shapeNum = getModelData()->getShapeNum();
+ for (u16 i = 0; i < shapeNum; i++) {
+ s32 ret = getShapePacket(i)->newDifferedDisplayList(diffFlags);
+ if (ret != kJ3DError_Success)
+ return ret;
+ }
+
+ return kJ3DError_Success;
+}
+
+void J3DModel::ptrToIndex() {
+ j3dSys.setModel(this);
+ j3dSys.setTexture(mModelData->getTexture());
+
+ u16 matNum = mModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ J3DMatPacket* matPacket = getMatPacket(i);
+
+ GDLObj dlobj;
+ GDInitGDLObj(&dlobj, matPacket->getDisplayList(0), matPacket->getDisplayListSize());
+ GDSetCurrent(&dlobj);
+
+ mModelData->getMaterialNodePointer(i)->getTevBlock()->ptrToIndex();
+
+ GDSetCurrent(NULL);
+ }
+}
+
+void J3DModel::lock() {
+ int matNum = mModelData->getMaterialNum();
+ for (int i = 0; i < matNum; i++) {
+ mMatPacket[i].lock();
+ }
+}
+
+void J3DModel::unlock() {
+ int matNum = mModelData->getMaterialNum();
+ for (int i = 0; i < matNum; i++) {
+ mMatPacket[i].unlock();
+ }
+}
+
+void J3DModel::makeDL() {
+ j3dSys.setModel(this);
+ j3dSys.setTexture(mModelData->getTexture());
+
+ u16 matNum = mModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ j3dSys.setMatPacket(&mMatPacket[i]);
+ mModelData->getMaterialNodePointer(i)->makeDisplayList();
+ }
+}
+
+void J3DModel::calcMaterial() {
+ j3dSys.setModel(this);
+
+ if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
+ j3dSys.onFlag(4);
+ } else {
+ j3dSys.offFlag(4);
+ }
+
+ if (checkFlag(J3DMdlFlag_SkinNrmCpu)) {
+ j3dSys.onFlag(8);
+ } else {
+ j3dSys.offFlag(8);
+ }
+
+ mModelData->syncJ3DSysFlags();
+ j3dSys.setTexture(mModelData->getTexture());
+
+ u16 matNum = mModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ j3dSys.setMatPacket(&mMatPacket[i]);
+
+ J3DMaterial* material = mModelData->getMaterialNodePointer(i);
+ if (material->getMaterialAnm() != NULL) {
+ material->getMaterialAnm()->calc(material);
+ }
+
+ material->calc(getAnmMtx(material->getJoint()->getJntNo()));
+ }
+}
+
+void J3DModel::calcDiffTexMtx() {
+ j3dSys.setModel(this);
+
+ u16 matNum = mModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ j3dSys.setMatPacket(&mMatPacket[i]);
+ J3DMaterial* materialNode = mModelData->getMaterialNodePointer(i);
+ materialNode->calcDiffTexMtx(getAnmMtx(materialNode->getJoint()->getJntNo()));
+ }
+
+ u16 shapeNum = getModelData()->getShapeNum();
+ for (u16 i = 0; i < shapeNum; i++) {
+ J3DShapePacket* shapePacket = getShapePacket(i);
+ J3DTexGenBlock* texGenBlock = mModelData->getShapeNodePointer(i)->getMaterial()->getTexGenBlock();
+
+ for (u16 j = 0; (int)j < 8; j++) {
+ J3DTexMtx* texMtxNode = texGenBlock->getTexMtx(j);
+ J3DTexMtxObj* texMtxObj = shapePacket->getTexMtxObj();
+ if (texMtxNode != NULL && texMtxObj != NULL) {
+ texMtxObj->setMtx(j, texMtxNode->getMtx());
+ }
+ }
+ }
+}
+
+void J3DModel::diff() {
+ u16 matNum = mModelData->getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ j3dSys.setMatPacket(&mMatPacket[i]);
+ mModelData->getMaterialNodePointer(i)->diff(mDiffFlag);
+ }
+}
+
+s32 J3DModel::setDeformData(J3DDeformData* p_deformData, u32 param_1) {
+ mDeformData = p_deformData;
+
+ if (p_deformData == NULL) {
+ return kJ3DError_Success;
+ }
+
+ s32 ret = mVertexBuffer.copyLocalVtxArray(param_1);
+ if (ret) {
+ return ret;
+ }
+
+ if (param_1 & 4) {
+ p_deformData->offAllFlag(1);
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DModel::setSkinDeform(J3DSkinDeform* p_skinDeform, u32 flags) {
+ mSkinDeform = p_skinDeform;
+
+ if (p_skinDeform == NULL) {
+ offFlag(J3DMdlFlag_SkinPosCpu);
+ offFlag(J3DMdlFlag_SkinNrmCpu);
+ return 5;
+ }
+
+ mSkinDeform->initMtxIndexArray(mModelData);
+
+ if (mModelData->checkFlag(0x100)) {
+ mSkinDeform->changeFastSkinDL(mModelData);
+ flags &= ~2;
+ flags &= ~4;
+ mSkinDeform->transformVtxPosNrm(mModelData);
+ mSkinDeform->initSkinInfo(mModelData);
+ }
+
+ s32 ret = kJ3DError_Success;
+ if ((~flags & 2)) {
+ ret = mVertexBuffer.allocTransformedVtxPosArray();
+ if (ret != kJ3DError_Success) {
+ offFlag(J3DMdlFlag_SkinPosCpu);
+ return ret;
+ }
+ onFlag(J3DMdlFlag_SkinPosCpu);
+ } else {
+ offFlag(J3DMdlFlag_SkinPosCpu);
+ }
+
+ if ((~flags & 4)) {
+ ret = mVertexBuffer.allocTransformedVtxNrmArray();
+ if (ret != kJ3DError_Success) {
+ offFlag(J3DMdlFlag_SkinNrmCpu);
+ return ret;
+ }
+ onFlag(J3DMdlFlag_SkinNrmCpu);
+ } else {
+ offFlag(J3DMdlFlag_SkinNrmCpu);
+ }
+
+ return ret;
+}
+
+void J3DModel::calcAnmMtx() {
+ j3dSys.setModel(this);
+
+ if (checkFlag(J3DMdlFlag_UseDefaultJ3D)) {
+ getModelData()->getJointTree().calc(mMtxBuffer, j3dDefaultScale, j3dDefaultMtx);
+ } else {
+ getModelData()->getJointTree().calc(mMtxBuffer, mBaseScale, mBaseTransformMtx);
+ }
+}
+
+void J3DModel::calcWeightEnvelopeMtx() {
+ if (getModelData()->getWEvlpMtxNum() != 0 && !checkFlag(J3DMdlFlag_EnableLOD)) {
+ if (!getModelData()->checkFlag(0x100)) {
+ mMtxBuffer->calcWeightEnvelopeMtx();
+ }
+ }
+}
+
+void J3DModel::update() {
+ calc();
+ entry();
+}
+
+void J3DModel::calc() {
+ j3dSys.setModel(this);
+
+ if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
+ j3dSys.onFlag(J3DSysFlag_SkinPosCpu);
+ } else {
+ j3dSys.offFlag(J3DSysFlag_SkinPosCpu);
+ }
+
+ if (checkFlag(J3DMdlFlag_SkinNrmCpu)) {
+ j3dSys.onFlag(J3DSysFlag_SkinNrmCpu);
+ } else {
+ j3dSys.offFlag(J3DSysFlag_SkinNrmCpu);
+ }
+
+ mModelData->syncJ3DSysFlags();
+ mVertexBuffer.frameInit();
+
+ if (mUnkCalc2 != NULL) {
+ mUnkCalc2->calc(mModelData);
+ }
+
+ if (mDeformData != NULL) {
+ mDeformData->deform(this);
+ }
+
+ if (mVtxColorCalc != NULL) {
+ mVtxColorCalc->calc(this);
+ }
+
+ if (mUnkCalc1 != NULL) {
+ mUnkCalc1->calc(this);
+ }
+
+ calcAnmMtx();
+ calcWeightEnvelopeMtx();
+
+ if (mSkinDeform != NULL) {
+ mSkinDeform->deform(this);
+ }
+
+ if (mCalcCallBack != NULL) {
+ mCalcCallBack(this, 0);
+ }
+}
+
+void J3DModel::entry() {
+ j3dSys.setModel(this);
+
+ if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
+ j3dSys.onFlag(J3DSysFlag_SkinPosCpu);
+ } else {
+ j3dSys.offFlag(J3DSysFlag_SkinPosCpu);
+ }
+
+ if (checkFlag(J3DMdlFlag_SkinNrmCpu)) {
+ j3dSys.onFlag(J3DSysFlag_SkinNrmCpu);
+ } else {
+ j3dSys.offFlag(J3DSysFlag_SkinNrmCpu);
+ }
+
+ mModelData->syncJ3DSysFlags();
+ j3dSys.setTexture(mModelData->getTexture());
+
+ for (u16 i = 0; i < mModelData->getJointNum(); i++) {
+ J3DJoint* joint = mModelData->getJointNodePointer(i);
+ if (joint->getMesh() != NULL) {
+ joint->entryIn();
+ }
+ }
+}
+
+void J3DModel::viewCalc() {
+ mMtxBuffer->swapDrawMtx();
+ mMtxBuffer->swapNrmMtx();
+
+ if (getModelData()->checkFlag(0x10)) {
+ if (getMtxCalcMode() == 2) {
+ J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
+ (MtxP)&mInternalView);
+ }
+ } else if (isCpuSkinningOn()) {
+ if (getMtxCalcMode() == 2) {
+ J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
+ (MtxP)&mInternalView);
+ }
+ } else if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
+ mMtxBuffer->calcDrawMtx(getMtxCalcMode(), mBaseScale, mBaseTransformMtx);
+ calcNrmMtx();
+ calcBumpMtx();
+ DCStoreRangeNoSync(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
+ DCStoreRange(getNrmMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx33));
+ } else if (checkFlag(J3DMdlFlag_SkinNrmCpu)) {
+ mMtxBuffer->calcDrawMtx(getMtxCalcMode(), mBaseScale, mBaseTransformMtx);
+ calcBBoardMtx();
+ DCStoreRange(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
+ } else {
+ mMtxBuffer->calcDrawMtx(getMtxCalcMode(), mBaseScale, mBaseTransformMtx);
+ calcNrmMtx();
+ calcBBoardMtx();
+ calcBumpMtx();
+ DCStoreRangeNoSync(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
+ DCStoreRange(getNrmMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx33));
+ }
+
+ prepareShapePackets();
+}
+
+void J3DModel::calcNrmMtx() {
+ mMtxBuffer->calcNrmMtx();
+}
+
+void J3DModel::calcBumpMtx() {
+ if (getModelData()->checkBumpFlag()) {
+ u32 bumpMtxIdx = 0;
+ u16 materialNum = getModelData()->getMaterialNum();
+
+ for (u16 i = 0; i < materialNum; i++) {
+ J3DMaterial* material = getModelData()->getMaterialNodePointer(i);
+ if (material->getNBTScale()->mbHasScale == TRUE) {
+ material->getShape()->calcNBTScale(*material->getNBTScale()->getScale(),
+ getNrmMtxPtr(), getBumpMtxPtr(bumpMtxIdx));
+ DCStoreRange(getBumpMtxPtr(bumpMtxIdx), mModelData->getDrawMtxNum() * sizeof(Mtx33));
+ bumpMtxIdx++;
+ }
+ }
+ }
+}
+
+void J3DModel::calcBBoardMtx() {
+ if (getModelData()->checkBBoardFlag()) {
+ mMtxBuffer->calcBBoardMtx();
+ }
+}
+
+void J3DModel::prepareShapePackets() {
+ u16 shapeNum = mModelData->getShapeNum();
+
+ for (u16 i = 0; i < shapeNum; i++) {
+ J3DShape* shapeNode = mModelData->getShapeNodePointer(i);
+ J3DShapePacket* shapePacket = &mShapePacket[i];
+ shapePacket->setMtxBuffer(mMtxBuffer);
+
+ if (getMtxCalcMode() == 2) {
+ shapePacket->setBaseMtxPtr(&mInternalView);
+ } else {
+ shapePacket->setBaseMtxPtr((Mtx*)j3dSys.getViewMtx());
+ }
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
new file mode 100644
index 0000000000..606882eb0a
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
@@ -0,0 +1,100 @@
+//
+// J3DModelData
+//
+
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DModelData.h"
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+
+void J3DModelData::clear() {
+ mpRawData = 0;
+ mFlags = 0;
+ mbHasBumpArray = 0;
+ mbHasBillboard = 0;
+}
+
+J3DModelData::J3DModelData() {
+ clear();
+}
+
+s32 J3DModelData::newSharedDisplayList(u32 mdlFlags) {
+ u16 matNum = getMaterialNum();
+
+ for (u16 i = 0; i < matNum; i++) {
+ s32 ret;
+ if (mdlFlags & J3DMdlFlag_UseSingleDL) {
+ ret = getMaterialNodePointer(i)->newSingleSharedDisplayList(getMaterialNodePointer(i)->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+ } else {
+ ret = getMaterialNodePointer(i)->newSharedDisplayList(getMaterialNodePointer(i)->countDLSize());
+ if (ret != kJ3DError_Success)
+ return ret;
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+void J3DModelData::indexToPtr() {
+ j3dSys.setTexture(getTexture());
+
+ static BOOL sInterruptFlag = OSDisableInterrupts();
+ OSDisableScheduler();
+
+ GDLObj gdl_obj;
+ u16 matNum = getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ J3DMaterial* matNode = getMaterialNodePointer(i);
+ J3DDisplayListObj* dl_obj = matNode->getSharedDisplayListObj();
+
+ GDInitGDLObj(&gdl_obj, dl_obj->getDisplayList(0), dl_obj->getDisplayListSize());
+ GDSetCurrent(&gdl_obj);
+ matNode->getTevBlock()->indexToPtr();
+ }
+
+ GDSetCurrent(NULL);
+ OSEnableScheduler();
+ OSRestoreInterrupts(sInterruptFlag);
+}
+
+void J3DModelData::makeSharedDL() {
+ j3dSys.setTexture(getTexture());
+
+ u16 matNum = getMaterialNum();
+ for (u16 i = 0; i < matNum; i++) {
+ getMaterialNodePointer(i)->makeSharedDisplayList();
+ }
+}
+
+void J3DModelData::simpleCalcMaterial(u16 idx, Mtx param_1) {
+ syncJ3DSysFlags();
+
+ J3DMaterial* mat;
+ J3DJoint* jointNode = getJointNodePointer(idx);
+ for (mat = jointNode->getMesh(); mat != NULL; mat = mat->getNext()) {
+ if (mat->getMaterialAnm() != NULL) {
+ mat->getMaterialAnm()->calc(mat);
+ }
+ mat->calc(param_1);
+ }
+}
+
+void J3DModelData::syncJ3DSysPointers() const {
+ j3dSys.setTexture(getTexture());
+ j3dSys.setVtxPos(getVtxPosArray());
+ j3dSys.setVtxNrm(getVtxNrmArray());
+ j3dSys.setVtxCol(getVtxColorArray(0));
+}
+
+void J3DModelData::syncJ3DSysFlags() const {
+ if (checkFlag(0x20)) {
+ j3dSys.onFlag(J3DSysFlag_PostTexMtx);
+ } else {
+ j3dSys.offFlag(J3DSysFlag_PostTexMtx);
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp
new file mode 100644
index 0000000000..a1e9ba0243
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp
@@ -0,0 +1,523 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphAnimator/J3DMtxBuffer.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
+#include "JSystem/JKernel/JKRHeap.h"
+
+Mtx J3DMtxBuffer::sNoUseDrawMtx;
+
+Mtx33 J3DMtxBuffer::sNoUseNrmMtx;
+
+Mtx* J3DMtxBuffer::sNoUseDrawMtxPtr = &J3DMtxBuffer::sNoUseDrawMtx;
+
+Mtx33* J3DMtxBuffer::sNoUseNrmMtxPtr = &J3DMtxBuffer::sNoUseNrmMtx;
+
+// force .sdata2 order
+f32 dummy1() {
+ return 1.0f;
+}
+
+f32 dummy0() {
+ return 0.0f;
+}
+
+void J3DMtxBuffer::initialize() {
+ mJointTree = NULL;
+ mpScaleFlagArr = NULL;
+ mpEvlpScaleFlagArr = NULL;
+ mpAnmMtx = NULL;
+ mpWeightEvlpMtx = NULL;
+ mpDrawMtxArr[0] = NULL;
+ mpDrawMtxArr[1] = NULL;
+ mpNrmMtxArr[0] = NULL;
+ mpNrmMtxArr[1] = NULL;
+ mpBumpMtxArr[0] = NULL;
+ mpBumpMtxArr[1] = NULL;
+ mMtxNum = 1;
+ mCurrentViewNo = 0;
+ mpUserAnmMtx = NULL;
+}
+
+enum {
+ J3DMdlDataFlag_ConcatView = 0x10,
+ J3DMdlDataFlag_NoAnimation = 0x100,
+};
+
+s32 J3DMtxBuffer::create(J3DModelData* pModelData, u32 mtxNum) {
+ J3D_ASSERT_NULLPTR(76, pModelData != NULL);
+ J3D_ASSERT_NONZEROARG(77, mtxNum != 0);
+
+ s32 ret = kJ3DError_Success;
+ mMtxNum = mtxNum;
+ mJointTree = &pModelData->getJointTree();
+
+ ret = createAnmMtx(pModelData);
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ ret = createWeightEnvelopeMtx(pModelData);
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ if (pModelData->checkFlag(J3DMdlDataFlag_NoAnimation)) {
+ setNoUseDrawMtx();
+ } else {
+ u32 loadType = getMdlDataFlag_MtxLoadType(pModelData->getFlag());
+ switch (loadType) {
+ case J3DMdlDataFlag_ConcatView:
+ ret = setNoUseDrawMtx();
+ break;
+ case 0:
+ default:
+ ret = createDoubleDrawMtx(pModelData, mtxNum);
+ break;
+ }
+ }
+
+ if (ret != kJ3DError_Success)
+ return ret;
+
+ if (pModelData->getFlag() & J3DMdlDataFlag_ConcatView) {
+ pModelData->setBumpFlag(0);
+ } else {
+ ret = createBumpMtxArray(pModelData, mtxNum);
+
+ if (ret != kJ3DError_Success)
+ return ret;
+ }
+
+ return ret;
+}
+
+J3DError J3DMtxBuffer::createAnmMtx(J3DModelData* pModelData) {
+ if (pModelData->getJointNum() != 0) {
+ mpScaleFlagArr = new u8[pModelData->getJointNum()];
+ mpAnmMtx = new Mtx[pModelData->getJointNum()];
+ mpUserAnmMtx = mpAnmMtx;
+ }
+
+ if (mpScaleFlagArr == NULL)
+ return kJ3DError_Alloc;
+
+ if (mpAnmMtx == NULL) {
+ return kJ3DError_Alloc;
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DMtxBuffer::createWeightEnvelopeMtx(J3DModelData* pModelData) {
+ if (pModelData->getWEvlpMtxNum() != 0) {
+ mpEvlpScaleFlagArr = new u8[pModelData->getWEvlpMtxNum()];
+ mpWeightEvlpMtx = new Mtx[pModelData->getWEvlpMtxNum()];
+ }
+
+ if (pModelData->getWEvlpMtxNum() != 0 && mpEvlpScaleFlagArr == NULL)
+ return kJ3DError_Alloc;
+ if (pModelData->getWEvlpMtxNum() != 0 && mpWeightEvlpMtx == NULL)
+ return kJ3DError_Alloc;
+
+ return kJ3DError_Success;
+}
+
+s32 J3DMtxBuffer::setNoUseDrawMtx() {
+ mpDrawMtxArr[0] = mpDrawMtxArr[1] = &sNoUseDrawMtxPtr;
+ mpNrmMtxArr[0] = mpNrmMtxArr[1] = &sNoUseNrmMtxPtr;
+ mpBumpMtxArr[0] = mpBumpMtxArr[1] = NULL;
+ return kJ3DError_Success;
+}
+
+s32 J3DMtxBuffer::createDoubleDrawMtx(J3DModelData* pModelData, u32 mtxNum) {
+ if (mtxNum != 0) {
+ for (s32 i = 0; i < 2; i++) {
+ mpDrawMtxArr[i] = new Mtx*[mtxNum];
+ mpNrmMtxArr[i] = new Mtx33*[mtxNum];
+ mpBumpMtxArr[i] = NULL;
+ }
+ }
+
+ if (mtxNum != 0) {
+ for (s32 i = 0; i < 2; i++) {
+ if (mpDrawMtxArr[i] == NULL)
+ return kJ3DError_Alloc;
+ if (mpNrmMtxArr[i] == NULL)
+ return kJ3DError_Alloc;
+ }
+ }
+
+ for (s32 i = 0; i < 2; i++) {
+ for (u32 j = 0; j < mtxNum; j++) {
+ if (pModelData->getDrawMtxNum() != 0) {
+ mpDrawMtxArr[i][j] = new (0x20) Mtx[pModelData->getDrawMtxNum()];
+ mpNrmMtxArr[i][j] = new (0x20) Mtx33[pModelData->getDrawMtxNum()];
+ }
+ }
+ }
+
+ for (s32 i = 0; i < 2; i++) {
+ for (u32 j = 0; j < mtxNum; j++) {
+ if (pModelData->getDrawMtxNum() != 0) {
+ if (mpDrawMtxArr[i][j] == NULL)
+ return kJ3DError_Alloc;
+ if (mpNrmMtxArr[i][j] == NULL)
+ return kJ3DError_Alloc;
+ }
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+s32 J3DMtxBuffer::createBumpMtxArray(J3DModelData* i_modelData, u32 mtxNum) {
+ J3D_ASSERT_NULLPTR(295, i_modelData != NULL);
+
+ if (i_modelData->getModelDataType() == 0) {
+ u16 bumpMtxNum = 0;
+ u16 materialCount = 0;
+ u16 materialNum = i_modelData->getMaterialNum();
+ for (u16 j = 0; j < materialNum; j++) {
+ J3DMaterial* material = i_modelData->getMaterialNodePointer(j);
+ if (material->getNBTScale()->mbHasScale == true) {
+ bumpMtxNum += material->getShape()->countBumpMtxNum();
+ materialCount++;
+ }
+ }
+
+ if (bumpMtxNum != 0 && mtxNum != 0) {
+ for (int i = 0; i < 2; i++) {
+ mpBumpMtxArr[i] = new Mtx33**[(u16)materialCount];
+ if (mpBumpMtxArr[i] == NULL) {
+ return kJ3DError_Alloc;
+ }
+ }
+ }
+
+ for (int i = 0; i < 2; i++) {
+ u32 offset = 0;
+ u16 materialNum = i_modelData->getMaterialNum();
+ for (u16 j = 0; j < materialNum; j++) {
+ J3DMaterial* material = i_modelData->getMaterialNodePointer(j);
+ if (material->getNBTScale()->mbHasScale == true) {
+ mpBumpMtxArr[i][offset] = new Mtx33*[mtxNum];
+ if (mpBumpMtxArr[i][offset] == NULL) {
+ return kJ3DError_Alloc;
+ }
+ material->getShape()->setBumpMtxOffset(offset);
+ offset++;
+ }
+ }
+ }
+
+ for (int i = 0; i < 2; i++) {
+ u32 offset = 0;
+ u16 materialNum = i_modelData->getMaterialNum();
+ for (u16 j = 0; j < materialNum; j++) {
+ J3DMaterial* material = i_modelData->getMaterialNodePointer((u16)j);
+ if (material->getNBTScale()->mbHasScale == true) {
+ for (int k = 0; k < mtxNum; k++) {
+ mpBumpMtxArr[i][offset][k] = new (0x20) Mtx33[i_modelData->getDrawMtxNum()];
+ if (mpBumpMtxArr[i][offset][k] == NULL) {
+ return kJ3DError_Alloc;
+ }
+ }
+ offset++;
+ }
+ }
+ }
+
+ if (materialCount != 0) {
+ i_modelData->setBumpFlag(1);
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+static f32 J3DUnit01[] = { 0.0f, 1.0f };
+
+void J3DMtxBuffer::calcWeightEnvelopeMtx() {
+ __REGISTER MtxP weightAnmMtx;
+ __REGISTER Mtx* worldMtx;
+ __REGISTER Mtx* invMtx;
+ __REGISTER f32 weight;
+ int idx;
+ int j;
+ int mixNum;
+ int i;
+ int max;
+ u16* indices;
+ f32* weights;
+ u8* pScale;
+
+ #if DEBUG || !__MWERKS__
+ __REGISTER Mtx mtx;
+ #else
+ __REGISTER f32 var_f1;
+ __REGISTER f32 var_f2;
+ __REGISTER f32 var_f3;
+ __REGISTER f32 var_f4;
+ __REGISTER f32 var_f5;
+ __REGISTER f32 var_f6;
+ __REGISTER f32 var_f7;
+ __REGISTER f32 var_f8;
+ __REGISTER f32 var_f9;
+ __REGISTER f32 var_f10;
+ __REGISTER f32 var_f11;
+ __REGISTER f32 var_f12;
+ __REGISTER f32 var_f13;
+ __REGISTER f32 var_f31;
+ __REGISTER f32 var_f30;
+ __REGISTER f32 var_f29;
+ __REGISTER f32 var_f28;
+ __REGISTER f32 var_f27;
+ __REGISTER f32* var_r7 = J3DUnit01;
+ #endif
+
+ i = -1;
+ max = mJointTree->getWEvlpMtxNum();
+ indices = mJointTree->getWEvlpMixMtxIndex() - 1;
+ weights = mJointTree->getWEvlpMixWeight() - 1;
+
+ #if !DEBUG && __MWERKS__
+ asm {
+ psq_l var_f27, 0x0(var_r7), 0, 0 /* qr0 */
+ ps_merge00 var_f10, var_f27, var_f27
+ ps_merge00 var_f12, var_f27, var_f27
+ ps_merge00 var_f31, var_f27, var_f27
+ }
+ #endif
+
+ while (++i < max) {
+ pScale = &mpEvlpScaleFlagArr[i];
+ *pScale = 1;
+ weightAnmMtx = mpWeightEvlpMtx[i];
+
+ #if DEBUG || !__MWERKS__
+ weightAnmMtx[0][0] = weightAnmMtx[0][1] = weightAnmMtx[0][2] = weightAnmMtx[0][3] =
+ weightAnmMtx[1][0] = weightAnmMtx[1][1] = weightAnmMtx[1][2] = weightAnmMtx[1][3] =
+ weightAnmMtx[2][0] = weightAnmMtx[2][1] = weightAnmMtx[2][2] = weightAnmMtx[2][3] = 0.0f;
+ #else
+ asm {
+ ps_merge00 var_f9, var_f27, var_f27
+ ps_merge00 var_f11, var_f27, var_f27
+ ps_merge00 var_f13, var_f27, var_f27
+ }
+ #endif
+
+ j = 0;
+ mixNum = mJointTree->getWEvlpMixMtxNum(i);
+ do {
+ idx = *++indices;
+ worldMtx = &mpAnmMtx[idx];
+ invMtx = &mJointTree->getInvJointMtx((u16)idx);
+
+ #if DEBUG || !__MWERKS__
+ MTXConcat(*worldMtx, *invMtx, mtx);
+ #else
+ // Fakematch? Doesn't match if worldMtx and invMtx are used directly.
+ __REGISTER void* var_r5 = worldMtx;
+ __REGISTER void* var_r6 = invMtx;
+ asm {
+ psq_l var_f2, 0x0(var_r6), 0, 0 /* qr0 */
+ psq_l var_f1, 0x0(var_r5), 0, 0 /* qr0 */
+ psq_l var_f3, 0x10(var_r5), 0, 0 /* qr0 */
+ psq_l var_f5, 0x20(var_r5), 0, 0 /* qr0 */
+ ps_muls0 var_f8, var_f2, var_f1
+ psq_l var_f6, 0x10(var_r6), 0, 0 /* qr0 */
+ ps_muls0 var_f30, var_f2, var_f3
+ ps_muls0 var_f29, var_f2, var_f5
+ psq_l var_f7, 0x20(var_r6), 0, 0 /* qr0 */
+ ps_madds1 var_f8, var_f6, var_f1, var_f8
+ psq_l var_f2, 0x8(var_r5), 0, 0 /* qr0 */
+ ps_madds1 var_f30, var_f6, var_f3, var_f30
+ psq_l var_f4, 0x18(var_r5), 0, 0 /* qr0 */
+ ps_madds1 var_f29, var_f6, var_f5, var_f29
+ psq_l var_f6, 0x28(var_r5), 0, 0 /* qr0 */
+ ps_madds0 var_f8, var_f7, var_f2, var_f8
+ }
+ #endif
+
+ weight = *++weights;
+
+ #if DEBUG || !__MWERKS__
+ weightAnmMtx[0][0] += mtx[0][0] * weight;
+ weightAnmMtx[0][1] += mtx[0][1] * weight;
+ weightAnmMtx[0][2] += mtx[0][2] * weight;
+ weightAnmMtx[0][3] += mtx[0][3] * weight;
+ weightAnmMtx[1][0] += mtx[1][0] * weight;
+ weightAnmMtx[1][1] += mtx[1][1] * weight;
+ weightAnmMtx[1][2] += mtx[1][2] * weight;
+ weightAnmMtx[1][3] += mtx[1][3] * weight;
+ weightAnmMtx[2][0] += mtx[2][0] * weight;
+ weightAnmMtx[2][1] += mtx[2][1] * weight;
+ weightAnmMtx[2][2] += mtx[2][2] * weight;
+ weightAnmMtx[2][3] += mtx[2][3] * weight;
+ #else
+ asm {
+ ps_madds0 var_f30, var_f7, var_f4, var_f30
+ ps_madds0 var_f29, var_f7, var_f6, var_f29
+ psq_l var_f7, 0x8(var_r6), 0, 0 /* qr0 */
+ ps_madds0 var_f9, var_f8, weight, var_f9
+ ps_madds0 var_f11, var_f30, weight, var_f11
+ ps_madds0 var_f13, var_f29, weight, var_f13
+ psq_l var_f8, 0x18(var_r6), 0, 0 /* qr0 */
+ ps_muls0 var_f30, var_f7, var_f1
+ ps_muls0 var_f29, var_f7, var_f3
+ ps_muls0 var_f28, var_f7, var_f5
+ psq_l var_f7, 0x28(var_r6), 0, 0 /* qr0 */
+ psq_st var_f9, 0x0(weightAnmMtx), 0, 0 /* qr0 */
+ ps_madds1 var_f30, var_f8, var_f1, var_f30
+ ps_madds1 var_f29, var_f8, var_f3, var_f29
+ ps_madds1 var_f28, var_f8, var_f5, var_f28
+ ps_madds0 var_f30, var_f7, var_f2, var_f30
+ ps_madds0 var_f29, var_f7, var_f4, var_f29
+ ps_madds0 var_f28, var_f7, var_f6, var_f28
+ psq_st var_f11, 0x10(weightAnmMtx), 0, 0 /* qr0 */
+ psq_st var_f13, 0x20(weightAnmMtx), 0, 0 /* qr0 */
+ ps_madd var_f30, var_f27, var_f2, var_f30
+ ps_madd var_f29, var_f27, var_f4, var_f29
+ ps_madd var_f28, var_f27, var_f6, var_f28
+ ps_madds0 var_f10, var_f30, weight, var_f10
+ ps_madds0 var_f12, var_f29, weight, var_f12
+ ps_madds0 var_f31, var_f28, weight, var_f31
+ }
+ #endif
+
+ *pScale &= mpScaleFlagArr[idx];
+ } while (++j < mixNum);
+
+ #if !DEBUG && __MWERKS__
+ asm {
+ psq_st var_f10, 0x8(weightAnmMtx), 0, 0 /* qr0 */
+ ps_merge00 var_f10, var_f27, var_f27
+ psq_st var_f12, 0x18(weightAnmMtx), 0, 0 /* qr0 */
+ ps_merge00 var_f12, var_f27, var_f27
+ psq_st var_f31, 0x28(weightAnmMtx), 0, 0 /* qr0 */
+ ps_merge00 var_f31, var_f27, var_f27
+ }
+ #endif
+ }
+}
+
+void J3DMtxBuffer::calcDrawMtx(u32 mdlFlag, Vec const& param_1, Mtx const& param_2) {
+ Mtx* sp24, *sp20;
+ int sp1C = 0;
+ sp20 = mpAnmMtx;
+ sp24 = mpWeightEvlpMtx;
+
+ MtxP viewMtx;
+ Mtx viewBaseMtx;
+ u16 fullWgtNum; // r25
+ u16 local_68;
+ u16 local_6a;
+ u16 local_6c;
+
+ switch (mdlFlag) {
+ case 0:
+ viewMtx = j3dSys.getViewMtx();
+ fullWgtNum = mJointTree->getDrawFullWgtMtxNum();
+ for (u16 i = 0; i < fullWgtNum; i++) {
+ MTXConcat(viewMtx, getAnmMtx(mJointTree->getDrawMtxIndex(i)), *getDrawMtx(i));
+ }
+ if (mJointTree->getDrawMtxNum() > fullWgtNum) {
+ J3DPSMtxArrayConcat(viewMtx, *mpWeightEvlpMtx, *getDrawMtx(fullWgtNum),
+ mJointTree->getWEvlpMtxNum());
+ }
+ return;
+ case 1:
+ local_68 = mJointTree->getDrawFullWgtMtxNum();
+ for (u16 i = 0; i < local_68; i++) {
+ MTXCopy(getAnmMtx(mJointTree->getDrawMtxIndex(i)), *getDrawMtx(i));
+ }
+ local_6a = mJointTree->getDrawFullWgtMtxNum();
+ for (u16 i = 0; i < local_6a; i++) {
+ MTXCopy(getWeightAnmMtx(i), *getDrawMtx(mJointTree->getDrawFullWgtMtxNum() + i));
+ }
+ break;
+ case 2:
+ J3DCalcViewBaseMtx(j3dSys.getViewMtx(), param_1, param_2, viewBaseMtx);
+ local_6c = mJointTree->getDrawFullWgtMtxNum();
+ for (u16 i = 0; i < local_6c; i++) {
+ MTXConcat(viewBaseMtx, getAnmMtx(mJointTree->getDrawMtxIndex(i)), *getDrawMtx(i));
+ }
+ if (mJointTree->getDrawMtxNum() > mJointTree->getDrawFullWgtMtxNum()) {
+ J3DPSMtxArrayConcat(viewBaseMtx, *mpWeightEvlpMtx,
+ *getDrawMtx(mJointTree->getDrawFullWgtMtxNum()),
+ mJointTree->getWEvlpMtxNum());
+ }
+ return;
+ default:
+ JUT_ASSERT_MSG(778, 0, "Error : model flag is invalid.")
+ }
+}
+
+void J3DMtxBuffer::calcNrmMtx() {
+ u16 drawMtxNum = mJointTree->getDrawMtxNum();
+ for (u16 i = 0; i < drawMtxNum; i++) {
+ if (mJointTree->getDrawMtxFlag(i) == 0) {
+ if (getScaleFlag(mJointTree->getDrawMtxIndex(i)) == 1) {
+ setNrmMtx(i, *getDrawMtx(i));
+ } else {
+ J3DPSCalcInverseTranspose(*getDrawMtx(i), *getNrmMtx(i));
+ }
+ } else {
+ if (getEnvScaleFlag(mJointTree->getDrawMtxIndex(i)) == 1) {
+ setNrmMtx(i, *getDrawMtx(i));
+ } else {
+ J3DPSCalcInverseTranspose(*getDrawMtx(i), *getNrmMtx(i));
+ }
+ }
+ }
+}
+
+void J3DMtxBuffer::calcBBoardMtx() {
+ u16 drawMtxNum = mJointTree->getDrawMtxNum();
+ for (u16 i = 0; i < drawMtxNum; i++) {
+ if (mJointTree->getDrawMtxFlag(i) == 0) {
+ u16 index = mJointTree->getDrawMtxIndex(i);
+ if (mJointTree->getJointNodePointer(index)->getMtxType() == 1) {
+ MtxP drawMtx = *getDrawMtx(i);
+ J3DCalcBBoardMtx(drawMtx);
+
+ Mtx33* nrmMtx = getNrmMtx(i);
+ (*nrmMtx)[0][0] = 1.0f / drawMtx[0][0];
+ (*nrmMtx)[0][1] = 0.0f;
+ (*nrmMtx)[0][2] = 0.0f;
+ (*nrmMtx)[1][0] = 0.0f;
+ (*nrmMtx)[1][1] = 1.0f / drawMtx[1][1];
+ (*nrmMtx)[1][2] = 0.0f;
+ (*nrmMtx)[2][0] = 0.0f;
+ (*nrmMtx)[2][1] = 0.0f;
+ (*nrmMtx)[2][2] = 1.0f / drawMtx[2][2];
+ } else if (mJointTree->getJointNodePointer(index)->getMtxType() == 2) {
+ MtxP drawMtx = *getDrawMtx(i);
+ J3DCalcYBBoardMtx(drawMtx);
+ Mtx33* nrmMtx = getNrmMtx(i);
+ J3DPSCalcInverseTranspose(drawMtx, *nrmMtx);
+ }
+ }
+ }
+}
+
+void J3DCalcViewBaseMtx(Mtx view, Vec const& scale, const Mtx& base, Mtx dst) {
+ Mtx m;
+
+ m[0][0] = base[0][0] * scale.x;
+ m[0][1] = base[0][1] * scale.y;
+ m[0][2] = base[0][2] * scale.z;
+ m[0][3] = base[0][3];
+
+ m[1][0] = base[1][0] * scale.x;
+ m[1][1] = base[1][1] * scale.y;
+ m[1][2] = base[1][2] * scale.z;
+ m[1][3] = base[1][3];
+
+ m[2][0] = base[2][0] * scale.x;
+ m[2][1] = base[2][1] * scale.y;
+ m[2][2] = base[2][2] * scale.z;
+ m[2][3] = base[2][3];
+
+ MTXConcat(view, m, dst);
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
new file mode 100644
index 0000000000..04430c32f7
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
@@ -0,0 +1,40 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DShapeTable.h"
+#include "JSystem/J3DGraphBase/J3DShape.h"
+
+void J3DShapeTable::hide() {
+ u16 shapeNum = mShapeNum;
+ for (u16 i = 0; i < shapeNum; i++) {
+ mShapeNodePointer[i]->onFlag(1);
+ }
+}
+
+void J3DShapeTable::show() {
+ u16 shapeNum = mShapeNum;
+ for (u16 i = 0; i < shapeNum; i++) {
+ mShapeNodePointer[i]->offFlag(1);
+ }
+}
+
+void J3DShapeTable::initShapeNodes(J3DDrawMtxData* pMtxData, J3DVertexData* pVtxData) {
+ u16 shapeNum = mShapeNum;
+ for (u16 i = 0; i < shapeNum; i++) {
+ J3DShape* shapeNode = mShapeNodePointer[i];
+
+ shapeNode->setDrawMtxDataPointer(pMtxData);
+ shapeNode->setVertexDataPointer(pVtxData);
+ shapeNode->makeVcdVatCmd();
+ }
+}
+
+void J3DShapeTable::sortVcdVatCmd() {
+ u16 shapeNum = mShapeNum;
+ for (u16 next = 0; next < shapeNum; next++) {
+ for (u16 prev = 0; prev < next; prev++) {
+ if (mShapeNodePointer[next]->isSameVcdVatCmd(mShapeNodePointer[prev])) {
+ mShapeNodePointer[next]->setVcdVatCmd(mShapeNodePointer[prev]->getVcdVatCmd());
+ }
+ }
+ }
+}
diff --git a/libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp b/libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp
new file mode 100644
index 0000000000..f27b56cd1a
--- /dev/null
+++ b/libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp
@@ -0,0 +1,698 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DGraphAnimator/J3DSkinDeform.h"
+#include "JSystem/J3DGraphAnimator/J3DAnimation.h"
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/JKernel/JKRHeap.h"
+#include <cstring>
+
+J3DSkinNList::J3DSkinNList() {
+ field_0x0 = NULL;
+ field_0x4 = NULL;
+ field_0x8 = NULL;
+ field_0xc = NULL;
+ field_0x10 = 0;
+ field_0x12 = 0;
+}
+
+static void J3DPSWeightMTXMultVec(f32 (*param_0)[4], f32 param_1, Vec* param_2, Vec* param_3) {
+ f32 f4 = param_0[0][3] + param_0[0][0] * param_2->x;
+ f32 f5 = param_0[1][3] + param_0[1][0] * param_2->x;
+ f32 f3 = param_0[2][3] + param_0[2][0] * param_2->x;
+ f4 += param_0[0][1] * param_2->y;
+ f5 += param_0[1][1] * param_2->y;
+ f3 += param_0[2][1] * param_2->y;
+ f4 += param_0[0][2] * param_2->z;
+ f5 += param_0[1][2] * param_2->z;
+ f3 += param_0[2][2] * param_2->z;
+ param_3->x += f4 * param_1;
+ param_3->y += f5 * param_1;
+ param_3->z += f3 * param_1;
+}
+
+static void J3DPSWeightMTXMultVecSR(f32 (*param_0)[4], f32 param_1, Vec* param_2,
+ Vec* param_3) {
+ f32 f4 = param_0[0][0] * param_2->x;
+ f32 f5 = param_0[1][0] * param_2->x;
+ f32 f3 = param_0[2][0] * param_2->x;
+ f4 += param_0[0][1] * param_2->y;
+ f5 += param_0[1][1] * param_2->y;
+ f3 += param_0[2][1] * param_2->y;
+ f4 += param_0[0][2] * param_2->z;
+ f5 += param_0[1][2] * param_2->z;
+ f3 += param_0[2][2] * param_2->z;
+ param_3->x += f4 * param_1;
+ param_3->y += f5 * param_1;
+ param_3->z += f3 * param_1;
+}
+
+void J3DSkinNList::calcSkin_VtxPosF32(f32 (*param_0)[4], void* param_1, void* param_2) {
+ int r29 = field_0x10;
+ for (int i = 0; i < r29; i++) {
+ Vec* pVec1 = (Vec*)param_1 + field_0x0[i];
+ Vec* pVec2 = (Vec*)param_2 + field_0x0[i];
+ f32 weight = field_0x8[i];
+ J3DPSWeightMTXMultVec(param_0, weight, pVec1, pVec2);
+ }
+}
+
+void J3DSkinNList::calcSkin_VtxNrmF32(f32 (*param_0)[4], void* param_1, void* param_2) {
+ int r29 = field_0x12;
+ for (int i = 0; i < r29; i++) {
+ Vec* pVec1 = (Vec*)param_1 + field_0x4[i];
+ Vec* pVec2 = (Vec*)param_2 + field_0x4[i];
+ f32 weight = field_0xc[i];
+ J3DPSWeightMTXMultVecSR(param_0, weight, pVec1, pVec2);
+ }
+}
+
+J3DSkinDeform::J3DSkinDeform() {
+ mPosData = NULL;
+ mNrmData = NULL;
+ mPosMtx = NULL;
+ mNrmMtx = NULL;
+ mFlags = 3;
+ field_0x18 = 1;
+ field_0x19 = 0;
+ field_0x1c = 0;
+ field_0x20 = 0;
+ mSkinNList = NULL;
+}
+
+u16* J3DSkinDeform::sWorkArea_WEvlpMixMtx[1024];
+
+f32* J3DSkinDeform::sWorkArea_WEvlpMixWeight[1024];
+
+void J3DSkinDeform::initSkinInfo(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(322, pModelData != NULL);
+
+ int vtxNum = pModelData->getVtxNum();
+ int wevlpMtxNum = pModelData->getWEvlpMtxNum();
+ u16* wevlpMtxIndex = pModelData->getWEvlpMixMtxIndex();
+ f32* wevlpMixWeights = pModelData->getWEvlpMixWeight();
+ int currentOffset = 0;
+
+ for (int i = 0; i < wevlpMtxNum; i++) {
+ sWorkArea_WEvlpMixMtx[i] = wevlpMtxIndex + currentOffset;
+ sWorkArea_WEvlpMixWeight[i] = wevlpMixWeights + currentOffset;
+ currentOffset += pModelData->getWEvlpMixMtxNum(i);
+ }
+
+ if (pModelData->getJointNum() != 0) {
+ mSkinNList = new J3DSkinNList[pModelData->getJointNum()];
+ }
+
+ for (int i = 0; i < pModelData->getVtxNum(); i++) {
+ u16 uVar8 = mPosData[i];
+ if (uVar8 != 0xffff) {
+ if (!pModelData->getDrawMtxFlag(uVar8)) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ mSkinNList[drawMtxIndex].field_0x10++;
+ } else {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int wevlpMtxNum = pModelData->getWEvlpMixMtxNum(drawMtxIndex);
+ u16* indices = sWorkArea_WEvlpMixMtx[drawMtxIndex];
+ for (int j = 0; j < wevlpMtxNum; j++) {
+ mSkinNList[indices[j]].field_0x10++;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < pModelData->getNrmNum(); i++) {
+ u16 uVar8 = mNrmData[i];
+ if (uVar8 != 0xffff) {
+ if (!pModelData->getDrawMtxFlag(uVar8)) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ mSkinNList[drawMtxIndex].field_0x12++;
+ } else {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int wevlpMtxNum = pModelData->getWEvlpMixMtxNum(drawMtxIndex);
+ u16* indices = sWorkArea_WEvlpMixMtx[drawMtxIndex];
+ for (int j = 0; j < wevlpMtxNum; j++) {
+ mSkinNList[indices[j]].field_0x12++;
+ }
+ }
+ }
+ }
+
+ for (u16 i = 0; i < pModelData->getJointNum(); i++) {
+ if (mSkinNList[i].field_0x10) {
+ mSkinNList[i].field_0x0 = new u16[mSkinNList[i].field_0x10];
+ mSkinNList[i].field_0x8 = new f32[mSkinNList[i].field_0x10];
+ mSkinNList[i].field_0x10 = 0;
+ }
+ if (mSkinNList[i].field_0x12) {
+ mSkinNList[i].field_0x4 = new u16[mSkinNList[i].field_0x12];
+ mSkinNList[i].field_0xc = new f32[mSkinNList[i].field_0x12];
+ mSkinNList[i].field_0x12 = 0;
+ }
+ }
+
+ for (int i = 0; i < pModelData->getVtxNum(); i++) {
+ u16 uVar8 = mPosData[i];
+ if (uVar8 != 0xffff) {
+ if (!pModelData->getDrawMtxFlag(uVar8)) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int uVar9 = mSkinNList[drawMtxIndex].field_0x10++;
+ mSkinNList[drawMtxIndex].field_0x0[uVar9] = i;
+ mSkinNList[drawMtxIndex].field_0x8[uVar9] = 1.0f;
+ } else {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int wevlpMtxNum = pModelData->getWEvlpMixMtxNum(drawMtxIndex);
+ u16* indices = sWorkArea_WEvlpMixMtx[drawMtxIndex];
+ f32* weights = sWorkArea_WEvlpMixWeight[drawMtxIndex];
+ for (int j = 0; j < wevlpMtxNum; j++) {
+ int uVar9 = mSkinNList[indices[j]].field_0x10++;
+ mSkinNList[indices[j]].field_0x0[uVar9] = i;
+ mSkinNList[indices[j]].field_0x8[uVar9] = weights[j];
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < pModelData->getNrmNum(); i++) {
+ u16 uVar8 = mNrmData[i];
+ if (uVar8 != 0xffff) {
+ if (!pModelData->getDrawMtxFlag(uVar8)) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int uVar9 = mSkinNList[drawMtxIndex].field_0x12++;
+ mSkinNList[drawMtxIndex].field_0x4[uVar9] = i;
+ mSkinNList[drawMtxIndex].field_0xc[uVar9] = 1.0f;
+ } else {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(uVar8);
+ int wevlpMtxNum = pModelData->getWEvlpMixMtxNum(drawMtxIndex);
+ u16* indices = sWorkArea_WEvlpMixMtx[drawMtxIndex];
+ f32* weights = sWorkArea_WEvlpMixWeight[drawMtxIndex];
+ for (int j = 0; j < wevlpMtxNum; j++) {
+ int uVar9 = mSkinNList[indices[j]].field_0x12++;
+ mSkinNList[indices[j]].field_0x4[uVar9] = i;
+ mSkinNList[indices[j]].field_0xc[uVar9] = weights[j];
+ }
+ }
+ }
+ }
+}
+
+u16 J3DSkinDeform::sWorkArea_MtxReg[1024];
+
+int J3DSkinDeform::initMtxIndexArray(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(507, pModelData != NULL);
+ if (mPosData != NULL && mNrmData != NULL) {
+ return kJ3DError_Success;
+ }
+
+ mPosData = new u16[pModelData->getVtxNum()];
+ if (mPosData == NULL) {
+ return kJ3DError_Alloc;
+ }
+
+ for (int i = 0; i < pModelData->getVtxNum(); i++) {
+ mPosData[i] = 0xffff;
+ }
+
+ if (pModelData->getNrmNum()) {
+ mNrmData = new u16[pModelData->getNrmNum()];
+ if (mNrmData == NULL) {
+ return kJ3DError_Alloc;
+ }
+ for (int i = 0; i < pModelData->getNrmNum(); i++) {
+ mNrmData[i] = 0;
+ }
+ } else {
+ mNrmData = NULL;
+ }
+
+ mPosMtx = new Mtx[pModelData->getJointNum()];
+ mNrmMtx = new (32) Mtx33[pModelData->getDrawMtxNum()];
+ if (mPosMtx == NULL) {
+ return kJ3DError_Alloc;
+ }
+ if (mNrmMtx == NULL) {
+ return kJ3DError_Alloc;
+ }
+
+ for (u16 i = 0; i < pModelData->getShapeNum(); i++) {
+ u32 kSize[4] = {0, 1, 1, 2};
+ int pnmtx_num = -1;
+ int vtx_num = -1;
+ int nrm_num = -1;
+ int tex_num = -1;
+ int r23 = 0;
+ for (GXVtxDescList* vtxDesc = pModelData->getShapeNodePointer(i)->getVtxDesc(); vtxDesc->attr != 0xff; vtxDesc++) {
+ switch (vtxDesc->attr) {
+ case GX_VA_PNMTXIDX:
+ pnmtx_num = r23;
+ break;
+ case GX_VA_POS:
+ vtx_num = r23;
+ if (vtxDesc->type != GX_INDEX16) {
+ OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n");
+ return 6;
+ }
+ break;
+ case GX_VA_NRM:
+ nrm_num = r23;
+ if (vtxDesc->type != GX_INDEX16) {
+ OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n");
+ return 6;
+ }
+ break;
+ case GX_VA_TEX0:
+ tex_num = r23;
+ if (vtxDesc->type != GX_INDEX16) {
+ OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n");
+ return 6;
+ }
+ break;
+ }
+ r23 += kSize[(int)vtxDesc->type];
+ }
+
+ for (u16 j = 0; j < (u16)pModelData->getShapeNodePointer(i)->getMtxGroupNum(); j++) {
+ J3DShapeMtx* pShapeMtx = pModelData->getShapeNodePointer(i)->getShapeMtx(j);
+ u8* pDList = pModelData->getShapeNodePointer(i)->getShapeDraw(j)->getDisplayList();
+ u8* pDListPos = pDList;
+ int uVar13;
+ for (;
+ (intptr_t)pDListPos - (intptr_t)pDList < pModelData->getShapeNodePointer(i)->getShapeDraw(j)->getDisplayListSize();
+ pDListPos += r23 * uVar13
+ //TODO: This loop's logic has drastically different codegen between GCN and Shield
+ // in a way that so far can't be pinned down as just compiler differences. This
+ // may have been refactored in the J3D version used for Shield, but note that
+ // it's very possible that this is a fakematch and there's some other way of
+ // expressing it that matches for both versions.
+#if PLATFORM_GCN
+ , pDListPos += 3
+#endif
+ )
+ {
+ u8 command = *pDListPos;
+#if !PLATFORM_GCN
+ pDListPos++;
+#endif
+ if (command != GX_TRIANGLEFAN && command != GX_TRIANGLESTRIP) {
+ break;
+ }
+
+#if PLATFORM_GCN
+ uVar13 = *(u16*)(pDListPos + 1);
+#else
+ uVar13 = *(u16*)pDListPos;
+ pDListPos += 2;
+#endif
+ for (int local_60 = 0; local_60 < uVar13; local_60++) {
+#if PLATFORM_GCN
+ u8* iVar5 = ((u8*)(pDListPos + 3) + r23 * local_60);
+#else
+ u8* iVar5 = ((u8*)pDListPos + r23 * local_60);
+#endif
+ u8 bVar3 = *(u8*)(iVar5 + pnmtx_num) / 3U;
+ u16 vtx_idx = *(u16*)(iVar5 + vtx_num);
+ u16 nrm_idx = *(u16*)(iVar5 + nrm_num);
+ u16 uVar3 = *(u16*)(iVar5 + tex_num);
+ u16 local_76 = pShapeMtx->getUseMtxIndex(bVar3);
+ if (local_76 == 0xffff) {
+ local_76 = sWorkArea_MtxReg[bVar3];
+ } else if (pnmtx_num != -1) {
+ sWorkArea_MtxReg[bVar3] = local_76;
+ }
+
+ J3D_ASSERT_RANGE(673, local_76 < pModelData->getDrawMtxNum());
+ J3D_ASSERT_RANGE(674, vtx_idx < pModelData->getVtxNum());
+ mPosData[vtx_idx] = local_76;
+
+ if (nrm_num != -1) {
+ J3D_ASSERT_RANGE(680, nrm_idx < pModelData->getNrmNum());
+ mNrmData[nrm_idx] = local_76;
+ }
+ }
+ }
+
+ if (nrm_num == -1) {
+ pModelData->getShapeNodePointer(i)->onFlag(J3DShpFlag_EnableLod);
+ pModelData->getShapeNodePointer(i)->offFlag(J3DShpFlag_SkinNrmCpu);
+ }
+ }
+ }
+
+ for (int i = 0; i < pModelData->getVtxNum(); i++) {
+ if (mPosData[i] == 0xffff) {
+ field_0x18 = 0x0;
+ mPosData[i] = 0;
+ OS_REPORT("Error : Invalid Positon Data Exists!.");
+ OS_REPORT("Error : Invalid Positon Index = %d\n", i);
+ }
+ }
+
+ return kJ3DError_Success;
+}
+
+void J3DSkinDeform::changeFastSkinDL(J3DModelData* pModelData) {
+ J3D_ASSERT_NULLPTR(740, pModelData != NULL);
+ for (u16 i = 0; i < pModelData->getShapeNum(); i++) {
+ u32 kSize[4] = {0,1,1,2};
+ int pnmtxIdxOffs = -1;
+ int vtxSize = 0;
+
+ J3DShape* pShapeNode = pModelData->getShapeNodePointer(i);
+ for (GXVtxDescList* vtxDesc = pShapeNode->getVtxDesc(); vtxDesc->attr != GX_VA_NULL; vtxDesc++) {
+ if (vtxDesc->attr == GX_VA_PNMTXIDX) {
+ pnmtxIdxOffs = vtxSize;
+ }
+ vtxSize += kSize[vtxDesc->type];
+ }
+
+ if (pnmtxIdxOffs != -1) {
+ for (u16 j = 0; j < (u16)pShapeNode->getMtxGroupNum(); j++) {
+ u8* displayListStart = pShapeNode->getShapeDraw(j)->getDisplayList();
+ u8* dl = displayListStart;
+ u8* dst = displayListStart;
+ while ((dl - displayListStart) < pShapeNode->getShapeDraw(j)->getDisplayListSize()) {
+ u8 cmd = *dl;
+ dl++;
+ *dst++ = cmd;
+
+ if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
+ break;
+
+ int vtxCount = *(u16*)dl;
+ dl += 2;
+ *(u16*)dst = vtxCount;
+ dst += 2;
+
+ for (int k = 0; k < vtxCount; k++) {
+ u8* src = &dl[vtxSize * k];
+ memcpy(dst, src + 1, (int)(vtxSize - 1)); // The -1 is to remove GX_VA_PNMTXIDX
+ dst += (int)(vtxSize - 1);
+ }
+ dl = (u8*)dl + vtxSize * vtxCount;
+ }
+
+ int dlistSize = ((intptr_t)dst - (intptr_t)displayListStart + 0x1f) & ~0x1f;
+ while ((intptr_t)dst - (intptr_t)displayListStart < pShapeNode->getShapeDraw(j)->getDisplayListSize()) {
+ *dst++ = 0;
+ }
+
+ pShapeNode->getShapeDraw(j)->setDisplayListSize(dlistSize);
+ DCStoreRange(displayListStart, pShapeNode->getShapeDraw(j)->getDisplayListSize());
+ }
+ }
+ }
+
+ for (u16 i = 0; i < pModelData->getShapeNum(); i++) {
+ J3DShape* shape = pModelData->getShapeNodePointer(i);
+ GXVtxDescList* desc = shape->getVtxDesc();
+ GXVtxDescList* descDst = desc;
+ for (; desc->attr != GX_VA_NULL; desc++) {
+ if (desc->attr != GX_VA_PNMTXIDX) {
+ descDst->attr = desc->attr;
+ descDst->type = desc->type;
+ descDst++;
+ }
+ }
+ descDst->attr = GX_VA_NULL;
+ descDst->type = GX_NONE;
+ shape->makeVcdVatCmd();
+ }
+}
+
+void J3DSkinDeform::calcNrmMtx(J3DMtxBuffer* pMtxBuffer) {
+ J3DJointTree* jointTree = pMtxBuffer->getJointTree();
+ u16 drawMtxNum = jointTree->getDrawMtxNum();
+ for (u16 i = 0; i < drawMtxNum; i++) {
+ if (jointTree->getDrawMtxFlag(i) == 0) {
+ if (pMtxBuffer->getScaleFlag(jointTree->getDrawMtxIndex(i)) == 1) {
+ setNrmMtx(i, pMtxBuffer->getAnmMtx(jointTree->getDrawMtxIndex(i)));
+ } else {
+ J3DPSCalcInverseTranspose(pMtxBuffer->getAnmMtx(jointTree->getDrawMtxIndex(i)), getNrmMtx(i));
+ }
+ } else {
+ if (pMtxBuffer->getEnvScaleFlag(jointTree->getDrawMtxIndex(i)) == 1) {
+ setNrmMtx(i, pMtxBuffer->getWeightAnmMtx(jointTree->getDrawMtxIndex(i)));
+ } else {
+ J3DPSCalcInverseTranspose(pMtxBuffer->getWeightAnmMtx(jointTree->getDrawMtxIndex(i)), getNrmMtx(i));
+ }
+ }
+ }
+}
+
+void J3DSkinDeform::transformVtxPosNrm(J3DModelData* pModelData) {
+ if (pModelData->getWEvlpMtxNum() != 0 && field_0x19 == 0) {
+ int vtmNum = pModelData->getVtxNum();
+ int nrmNum = pModelData->getNrmNum();
+
+ for (int i = 0; i < vtmNum; i++) {
+ u16 posIndex = mPosData[i];
+ if (pModelData->getDrawMtxFlag(posIndex) == 0) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(posIndex);
+ Vec* pos = ((Vec*)pModelData->getVtxPosArray()) + i;
+ Mtx invMtx;
+ MTXInverse(pModelData->getInvJointMtx(drawMtxIndex), invMtx);
+ MTXMultVec(invMtx, pos, pos);
+ }
+ }
+
+ for (int i = 0; i < nrmNum; i++) {
+ u16 nrmIndex = mNrmData[i];
+ if (pModelData->getDrawMtxFlag(nrmIndex) == 0) {
+ u16 drawMtxIndex = pModelData->getDrawMtxIndex(nrmIndex);
+ Vec* nrm = ((Vec*)pModelData->getVtxNrmArray()) + i;
+ Mtx invMtx;
+ MTXInverse(pModelData->getInvJointMtx(drawMtxIndex), invMtx);
+ MTXMultVecSR(invMtx, nrm, nrm);
+ }
+ }
+
+ field_0x19 = 1;
+ }
+}
+
+void J3DSkinDeform::calcAnmInvJointMtx(J3DMtxBuffer* pMtxBuffer) {
+ J3D_ASSERT_NULLPTR(978, pMtxBuffer != NULL);
+
+ if (pMtxBuffer->getJointTree()->getWEvlpMtxNum() != 0) {
+ int jointNum = pMtxBuffer->getJointTree()->getJointNum();
+ Mtx* anmMtx = (Mtx*)pMtxBuffer->getAnmMtx(0);
+ Mtx* invJointMtx = &pMtxBuffer->getJointTree()->getInvJointMtx(0);
+ Mtx* posMtx = mPosMtx;
+ for (int i = 0; i < jointNum; i++) {
+ MTXConcat(anmMtx[i], invJointMtx[i], posMtx[i]);
+ }
+ }
+}
+
+void J3DSkinDeform::deformFastVtxPos_F32(J3DVertexBuffer* pVtxBuffer, J3DMtxBuffer* pMtxBuffer) const {
+ pVtxBuffer->swapTransformedVtxPos();
+ J3DJointTree* jointTree = pMtxBuffer->getJointTree();
+ u32 vtxNum = pVtxBuffer->getVertexData()->getVtxNum();
+ int sp14 = jointTree->getDrawMtxNum();
+ void* currentVtxPos = pVtxBuffer->getCurrentVtxPos();
+ void* transformedVtxPos = pVtxBuffer->getTransformedVtxPos(0);
+
+ J3DFillZero32B(transformedVtxPos, OSRoundUp32B(vtxNum * sizeof(Vec)));
+
+ if (jointTree->getWEvlpMtxNum() != 0) {
+ u16 jointNum = jointTree->getJointNum();
+ for (u16 i = 0; i < jointNum; i++) {
+ J3DSkinNList* skinList = mSkinNList + i;
+ skinList->calcSkin_VtxPosF32(mPosMtx[i], currentVtxPos, transformedVtxPos);
+ }
+ } else {
+ u16 jointNum = jointTree->getJointNum();
+ for (u16 i = 0; i < jointNum; i++) {
+ J3DSkinNList* skinList = mSkinNList + i;
+ skinList->calcSkin_VtxPosF32(pMtxBuffer->getAnmMtx(i), currentVtxPos, transformedVtxPos);
+ }
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxPos(0), pVtxBuffer->getVertexData()->getVtxNum() * sizeof(Vec));
+ pVtxBuffer->setCurrentVtxPos(transformedVtxPos);
+}
+
+void J3DSkinDeform::deformFastVtxNrm_F32(J3DVertexBuffer* pVtxBuffer, J3DMtxBuffer* pMtxBuffer) const {
+ pVtxBuffer->swapTransformedVtxNrm();
+ J3DJointTree* jointTree = pMtxBuffer->getJointTree();
+ int nrmNum = pVtxBuffer->getVertexData()->getNrmNum();
+ int sp18 = jointTree->getDrawMtxNum();
+ void* currentVtxNrm = pVtxBuffer->getCurrentVtxNrm();
+ void* transformedVtxNrm = pVtxBuffer->getTransformedVtxNrm(0);
+
+ for (int i = 0; i < nrmNum; i++) {
+ ((f32*)transformedVtxNrm)[(i * 3) + 0] = 0.0f;
+ ((f32*)transformedVtxNrm)[(i * 3) + 1] = 0.0f;
+ ((f32*)transformedVtxNrm)[(i * 3) + 2] = 0.0f;
+ }
+
+ if (jointTree->getWEvlpMtxNum() != 0) {
+ u16 jointNum = jointTree->getJointNum();
+ for (u16 i = 0; i < jointNum; i++) {
+ J3DSkinNList* skinList = mSkinNList + i;
+ skinList->calcSkin_VtxNrmF32(mPosMtx[i], currentVtxNrm, transformedVtxNrm);
+ }
+ } else {
+ u16 jointNum = jointTree->getJointNum();
+ for (u16 i = 0; i < jointNum; i++) {
+ J3DSkinNList* skinList = mSkinNList + i;
+ skinList->calcSkin_VtxNrmF32(pMtxBuffer->getAnmMtx(i), currentVtxNrm, transformedVtxNrm);
+ }
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxNrm(0), pVtxBuffer->getVertexData()->getNrmNum() * sizeof(Vec));
+ pVtxBuffer->setCurrentVtxNrm(transformedVtxNrm);
+}
+
+void J3DSkinDeform::deformVtxPos_F32(J3DVertexBuffer* pVtxBuffer, J3DMtxBuffer* pMtxBuffer) const {
+ Mtx* anmMtx = NULL;
+ Mtx* anmMtxs[2];
+ anmMtxs[0] = (Mtx*)pMtxBuffer->getAnmMtx(0);
+ anmMtxs[1] = (Mtx*)pMtxBuffer->getWeightAnmMtx(0);
+ pVtxBuffer->swapTransformedVtxPos();
+
+ J3DJointTree* jointTree = pMtxBuffer->getJointTree();
+ int vtxNum = pVtxBuffer->getVertexData()->getVtxNum();
+ int sp8 = jointTree->getDrawMtxNum();
+ void* currentVtxPos = (void*)pVtxBuffer->getCurrentVtxPos();
+ void* transformedVtxPos = (void*)pVtxBuffer->getTransformedVtxPos(0);
+
+ for (int i = 0; i < vtxNum; i++) {
+ anmMtx = anmMtxs[jointTree->getDrawMtxFlag(mPosData[i])];
+ J3DPSMulMtxVec(anmMtx[jointTree->getDrawMtxIndex(mPosData[i])], (Vec*)(((f32*)currentVtxPos) + (i * 3)), (Vec*)(((f32*)transformedVtxPos) + (i * 3)));
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxPos(0), pVtxBuffer->getVertexData()->getVtxNum() * sizeof(Vec));
+ pVtxBuffer->setCurrentVtxPos(transformedVtxPos);
+}
+
+void J3DSkinDeform::deformVtxPos_S16(J3DVertexBuffer* pVtxBuffer, J3DMtxBuffer* pMtxBuffer) const {
+ Mtx* anmMtx = NULL;
+ Mtx* anmMtxs[2];
+ anmMtxs[0] = (Mtx*)pMtxBuffer->getAnmMtx(0);
+ anmMtxs[1] = (Mtx*)pMtxBuffer->getWeightAnmMtx(0);
+ int vtxPosFrac = pVtxBuffer->getVertexData()->getVtxPosFrac();
+ J3DGQRSetup7(vtxPosFrac, 7, vtxPosFrac, 7);
+ pVtxBuffer->swapTransformedVtxPos();
+
+ J3DJointTree* jointTree = pMtxBuffer->getJointTree();
+ int vtxNum = pVtxBuffer->getVertexData()->getVtxNum();
+ int sp8 = jointTree->getDrawMtxNum();
+ void* currentVtxPos = (void*)pVtxBuffer->getCurrentVtxPos();
+ void* transformedVtxPos = (void*)pVtxBuffer->getTransformedVtxPos(0);
+
+ for (int i = 0; i < vtxNum; i++) {
+ anmMtx = anmMtxs[jointTree->getDrawMtxFlag(mPosData[i])];
+ J3DPSMulMtxVec(anmMtx[jointTree->getDrawMtxIndex(mPosData[i])], (S16Vec*)(((s16*)currentVtxPos) + (i * 3)), (S16Vec*)(((s16*)transformedVtxPos) + (i * 3)));
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxPos(0), pVtxBuffer->getVertexData()->getVtxNum() * sizeof(S16Vec));
+ pVtxBuffer->setCurrentVtxPos(transformedVtxPos);
+}
+
+void J3DSkinDeform::deformVtxNrm_F32(J3DVertexBuffer* pVtxBuffer) const {
+ pVtxBuffer->swapTransformedVtxNrm();
+ int nrmNum = pVtxBuffer->getVertexData()->getNrmNum();
+ void* currentVtxNrm = (void*)pVtxBuffer->getCurrentVtxNrm();
+ void* transformedVtxNrm = (void*)pVtxBuffer->getTransformedVtxNrm(0);
+
+ for (int i = 0; i < nrmNum; i++) {
+ J3DPSMulMtxVec(mNrmMtx[mNrmData[i]], (Vec*)((u8*)currentVtxNrm + i * 3 * 4), (Vec*)((u8*)transformedVtxNrm + i * 3 * 4));
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxNrm(0), pVtxBuffer->getVertexData()->getNrmNum() * sizeof(Vec));
+ pVtxBuffer->setCurrentVtxNrm(transformedVtxNrm);
+}
+
+void J3DSkinDeform::deformVtxNrm_S16(J3DVertexBuffer* pVtxBuffer) const {
+ int vtxNrmFrac = pVtxBuffer->getVertexData()->getVtxNrmFrac();
+ J3DGQRSetup7(vtxNrmFrac, 7, vtxNrmFrac, 7);
+ pVtxBuffer->swapTransformedVtxNrm();
+
+ int nrmNum = pVtxBuffer->getVertexData()->getNrmNum();
+ void* currentVtxNrm = (void*)pVtxBuffer->getCurrentVtxNrm();
+ void* transformedVtxNrm = (void*)pVtxBuffer->getTransformedVtxNrm(0);
+
+ for (int i = 0; i < nrmNum; i++) {
+ J3DPSMulMtxVec(mNrmMtx[mNrmData[i]], (S16Vec*)(((s16*)currentVtxNrm) + (i * 3)), (S16Vec*)(((s16*)transformedVtxNrm) + (i * 3)));
+ }
+
+ DCStoreRange(pVtxBuffer->getTransformedVtxNrm(0), pVtxBuffer->getVertexData()->getNrmNum() * sizeof(S16Vec));
+ pVtxBuffer->setCurrentVtxNrm(transformedVtxNrm);
+}
+
+void J3DSkinDeform::deform(J3DModel* pModel) {
+ J3D_ASSERT_NULLPTR(1270, pModel != NULL);
+
+ if (pModel->checkFlag(J3DMdlFlag_SkinPosCpu)) {
+ onFlag(2);
+ } else {
+ offFlag(2);
+ }
+
+ if (pModel->checkFlag(J3DMdlFlag_SkinNrmCpu)) {
+ onFlag(1);
+ } else {
+ offFlag(1);
+ }
+
+ deform(pModel->getVertexBuffer(), pModel->getMtxBuffer());
+}
+
+void J3DSkinDeform::deform(J3DVertexBuffer* pVtxBuffer, J3DMtxBuffer* pMtxBuffer) {
+ J3D_ASSERT_NULLPTR(1299, pVtxBuffer != NULL);
+ J3D_ASSERT_NULLPTR(1300, pMtxBuffer != NULL);
+
+ if (pMtxBuffer->getJointTree()->checkFlag(0x100)) {
+ calcAnmInvJointMtx(pMtxBuffer);
+ }
+
+ if (checkFlag(2) != 0) {
+ if (pMtxBuffer->getJointTree()->checkFlag(0x100)) {
+ deformFastVtxPos_F32(pVtxBuffer, pMtxBuffer);
+ } else {
+ if (pVtxBuffer->getVertexData()->getVtxPosType() == 4) {
+ deformVtxPos_F32(pVtxBuffer, pMtxBuffer);
+ } else {
+ deformVtxPos_S16(pVtxBuffer, pMtxBuffer);
+ }
+ }
+ }
+
+ if (checkFlag(1)) {
+ if (pMtxBuffer->getJointTree()->checkFlag(0x100)) {
+ deformFastVtxNrm_F32(pVtxBuffer, pMtxBuffer);
+ } else {
+ calcNrmMtx(pMtxBuffer);
+ if (pVtxBuffer->getVertexData()->getVtxNrmType() == 4) {
+ deformVtxNrm_F32(pVtxBuffer);
+ } else {
+ deformVtxNrm_S16(pVtxBuffer);
+ }
+ }
+ }
+}
+
+void J3DVtxColorCalc::calc(J3DModel* pModel) {
+ J3D_ASSERT_NULLPTR(1351, pModel != NULL);
+ calc(pModel->getVertexBuffer());
+}
+
+void J3DVtxColorCalc::calc(J3DVertexBuffer* buffer) {
+ J3D_ASSERT_NULLPTR(1366, buffer != NULL);
+ if (checkFlag(1) && mpVtxColor) {
+ buffer->swapVtxColArrayPointer();
+ u16 anmTableNum = mpVtxColor->getAnmTableNum(0);
+ GXColor* colorArray = buffer->getVtxColArrayPointer(0);
+ for (u32 i = 0; i < anmTableNum; i++) {
+ GXColor color;
+ mpVtxColor->getColor(0, i, &color);
+ J3DAnmVtxColorIndexData* r28 = mpVtxColor->getAnmVtxColorIndexData(0, i);
+ for (u32 j = 0; j < r28->mNum; j++) {
+ colorArray[((u16*)r28->mpData)[j]] = color;
+ }
+ }
+ DCStoreRange(colorArray, buffer->getVertexData()->getColNum() * 4);
+ buffer->setCurrentVtxCol(colorArray);
+ }
+}
+
+J3DSkinDeform::~J3DSkinDeform() {}