diff options
| author | Luke Street <luke@street.dev> | 2026-03-01 15:35:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-01 14:35:36 -0800 |
| commit | 9649319ec4926457ef85e6094f8207474c977c2d (patch) | |
| tree | 1c5cd4c7cc4c1aee03f28921213da47f2775444d /libs/JSystem/src/J3DGraphAnimator | |
| parent | 6e149819e13b1f70ecbf8a4c66b030c17ffed2bb (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.cpp | 1420 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp | 269 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp | 243 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp | 116 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DMaterialAnm.cpp | 116 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp | 303 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DModel.cpp | 555 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp | 100 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DMtxBuffer.cpp | 523 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp | 40 | ||||
| -rw-r--r-- | libs/JSystem/src/J3DGraphAnimator/J3DSkinDeform.cpp | 698 |
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() {} |
