summaryrefslogtreecommitdiff
path: root/libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp')
-rw-r--r--libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp116
1 files changed, 116 insertions, 0 deletions
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;
+}