//
// Generated by dtk
// Translation Unit: J3DModel.cpp
//

#include "JSystem/JSystem.h" // IWYU pragma: keep

#include "JSystem/J3DGraphAnimator/J3DModel.h"
#include "JSystem/J3DGraphAnimator/J3DJoint.h"
#include "JSystem/J3DGraphAnimator/J3DMaterialAnm.h"
#include "JSystem/J3DGraphBase/J3DSys.h"
#include "JSystem/JKernel/JKRHeap.h"
#include "dolphin/os/OSCache.h"

Mtx J3DModel::sNoUseDrawMtx;
Mtx33 J3DModel::sNoUseNrmMtx;
Mtx* J3DModel::sNoUseDrawMtxPtr = &J3DModel::sNoUseDrawMtx;
Mtx33* J3DModel::sNoUseNrmMtxPtr = &J3DModel::sNoUseNrmMtx;

/* 802ED564-802ED5AC       .text __ct__8J3DModelFv */
J3DModel::J3DModel() {
    initialize();
}

/* 802ED5AC-802ED610       .text __dt__8J3DModelFv */
J3DModel::~J3DModel() {
}

/* 802ED610-802ED6C4       .text initialize__8J3DModelFv */
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(mViewBaseMtx);

    mpScaleFlagArr = NULL;
    mpEvlpScaleFlagArr = NULL;
    mpNodeMtx = NULL;
    mpWeightEnvMtx = NULL;
    mpDrawMtxBuf[0] = NULL;
    mpDrawMtxBuf[1] = NULL;
    mpNrmMtxBuf[0] = NULL;
    mpNrmMtxBuf[1] = NULL;
    mpBumpMtxArr[0] = NULL;
    mpBumpMtxArr[1] = NULL;
    mMtxBufferFlag = 1;
    mCurrentViewNo = 0;
    mpMatPacket = NULL;
    mpShapePacket = NULL;
    mpDeformData = NULL;
    mpSkinDeform = NULL;
    field_0xc4 = NULL;
    field_0xc8 = NULL;
    mpVisibilityManager = NULL;
}

static inline u32 getMdlDataFlag_MtxLoadType(u32 flag) {
    return flag & 0xF0;
}

/* 802ED6C4-802ED8D8       .text entryModelData__8J3DModelFP12J3DModelDataUlUl */
s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 modelFlag, u32 mtxBufferFlag) {
    s32 ret = J3DErrType_Success;

    mModelData = pModelData;
    mMtxBufferFlag = mtxBufferFlag;

    if (pModelData->getJointNum() != 0) {
        mpScaleFlagArr = new u8[pModelData->getJointNum()];
        if (pModelData->getWEvlpMtxNum() != 0)
            mpEvlpScaleFlagArr = new u8[pModelData->getWEvlpMtxNum()];
        mpNodeMtx = new Mtx[pModelData->getJointNum()];
    }

    if (pModelData->getWEvlpMtxNum() != 0) {
        mpWeightEnvMtx = new Mtx[pModelData->getWEvlpMtxNum()];
    }

    if (mpScaleFlagArr == NULL)
        return J3DErrType_OutOfMemory;

    if (pModelData->getWEvlpMtxNum() != 0 && mpEvlpScaleFlagArr == NULL)
        return J3DErrType_OutOfMemory;

    if (mpNodeMtx == NULL)
        return J3DErrType_OutOfMemory;

    if (pModelData->getWEvlpMtxNum() != 0 && mpWeightEnvMtx == NULL)
        return J3DErrType_OutOfMemory;

    if (pModelData->checkFlag(J3DMdlDataFlag_NoAnimation)) {
        setNoUseDrawMtx();
    } else {
        switch (getMdlDataFlag_MtxLoadType(pModelData->getFlag())) {
        case J3DMdlDataFlag_NoUseDrawMtx:
            ret = setNoUseDrawMtx();
            break;
        case J3DMdlDataFlag_ConcatView:
            ret = createSingleDrawMtx(pModelData);
            break;
        case 0:
        default:
            ret = createDoubleDrawMtx(pModelData, mtxBufferFlag);
            break;
        }
    }

    if (ret != J3DErrType_Success)
        return ret;

    ret = createShapePacket(pModelData);
    if (ret != J3DErrType_Success)
        return ret;

    ret = createMatPacket(pModelData, modelFlag);
    if (ret != J3DErrType_Success)
        return ret;

    if (pModelData->checkFlag(J3DMdlDataFlag_ConcatView)) {
        mModelData->setBumpFlag(0);
    } else {
        ret = createBumpMtxArray(pModelData, mtxBufferFlag);
        if (ret != J3DErrType_Success)
            return ret;
    }

    mVertexBuffer.setVertexData(&pModelData->getVertexData());
    prepareShapePackets();
    ret = J3DErrType_Success;

    return ret;
}

/* 802ED8D8-802ED904       .text setNoUseDrawMtx__8J3DModelFv */
s32 J3DModel::setNoUseDrawMtx() {
    mpDrawMtxBuf[1] = &sNoUseDrawMtxPtr;
    mpDrawMtxBuf[0] = &sNoUseDrawMtxPtr;
    mpNrmMtxBuf[1] = &sNoUseNrmMtxPtr;
    mpNrmMtxBuf[0] = &sNoUseNrmMtxPtr;
    mpBumpMtxArr[1] = NULL;
    mpBumpMtxArr[0] = NULL;
    return J3DErrType_Success;
}

/* 802ED904-802EDA14       .text createSingleDrawMtx__8J3DModelFP12J3DModelData */
s32 J3DModel::createSingleDrawMtx(J3DModelData* pModelData) {
    mpDrawMtxBuf[0] = new Mtx*[1];
    mpDrawMtxBuf[1] = mpDrawMtxBuf[0];
    mpNrmMtxBuf[0] = new Mtx33*[1];
    mpNrmMtxBuf[1] = mpNrmMtxBuf[0];
    mpBumpMtxArr[0] = NULL;
    mpBumpMtxArr[1] = NULL;

    if (mpDrawMtxBuf[0] == NULL)
        return J3DErrType_OutOfMemory;
    if (mpNrmMtxBuf[0] == NULL)
        return J3DErrType_OutOfMemory;

    if (pModelData->getDrawMtxNum() != 0) {
        mpDrawMtxBuf[0][0] = new (0x20) Mtx[pModelData->getDrawMtxNum()];
        mpDrawMtxBuf[1][0] = mpDrawMtxBuf[0][0];
        mpNrmMtxBuf[0][0] = new (0x20) Mtx33[1];
        mpNrmMtxBuf[1][0] = mpNrmMtxBuf[0][0];
    }

    if (pModelData->getDrawMtxNum() != 0 && mpDrawMtxBuf[0][0] == NULL)
        return J3DErrType_OutOfMemory;

    return J3DErrType_Success;
}

/* 802EDA14-802EDBC0       .text createDoubleDrawMtx__8J3DModelFP12J3DModelDataUl */
s32 J3DModel::createDoubleDrawMtx(J3DModelData* pModelData, u32 num) {
    if (num != 0) {
        for (s32 i = 0; i < 2; i++) {
            mpDrawMtxBuf[i] = new Mtx*[num];
            mpNrmMtxBuf[i] = new Mtx33*[num];
            mpBumpMtxArr[i] = NULL;
        }
    }

    if (num != 0) {
        for (u32 i = 0; i < 2; i++) {
            if (mpDrawMtxBuf[i] == NULL)
                return J3DErrType_OutOfMemory;
            if (mpNrmMtxBuf[i] == NULL)
                return J3DErrType_OutOfMemory;
        }
    }

    for (s32 i = 0; i < 2; i++) {
        for (u32 j = 0; j < num; j++) {
            if (pModelData->getDrawMtxNum() != 0) {
                mpDrawMtxBuf[i][j] = new (0x20) Mtx[pModelData->getDrawMtxNum()];
                mpNrmMtxBuf[i][j] = new (0x20) Mtx33[pModelData->getDrawMtxNum()];
            }
        }
    }

    for (s32 i = 0; i < 2; i++) {
        for (u32 j = 0; j < num; j++) {
            if (pModelData->getDrawMtxNum() != 0) {
                if (mpDrawMtxBuf[i][j] == NULL)
                    return J3DErrType_OutOfMemory;
                if (mpNrmMtxBuf[i][j] == NULL)
                    return J3DErrType_OutOfMemory;
            }
        }
    }

    return J3DErrType_Success;
}

/* 802EDBC0-802EDC8C       .text createShapePacket__8J3DModelFP12J3DModelData */
s32 J3DModel::createShapePacket(J3DModelData* pModelData) {
    if (pModelData->getShapeNum() != 0) {
        u16 shapeNum = pModelData->getShapeNum();

        mpShapePacket = new J3DShapePacket[shapeNum];
        if (mpShapePacket == NULL)
            return J3DErrType_OutOfMemory;

        for (int i = 0; i < pModelData->getShapeNum(); i++) {
            J3DShape* shapeNode = pModelData->getShapeNodePointer(i);
            mpShapePacket[i].setShape(shapeNode);
            mpShapePacket[i].setModel(this);
        }
    }

    return J3DErrType_Success;
}

/* 802EDC8C-802EDF60       .text createMatPacket__8J3DModelFP12J3DModelDataUl */
s32 J3DModel::createMatPacket(J3DModelData* pModelData, u32 flag) {
    if (pModelData->getMaterialNum() != 0) {
        mpMatPacket = new J3DMatPacket[pModelData->getMaterialNum()];

        if (mpMatPacket == NULL)
            return J3DErrType_OutOfMemory;
    }

    s32 ret;

    u32 singleDLFlag = flag & 0x40000;
    for (s32 i = 0; i < pModelData->getMaterialNum(); i++) {
        mpMatPacket[i].setMaterial(pModelData->getMaterialNodePointer(i));
        J3DShapePacket* shapePacket = getShapePacket(pModelData->getMaterialNodePointer(i)->getShape()->getIndex());
        mpMatPacket[i].setInitShapePacket(shapePacket);
        mpMatPacket[i].addShapePacket(shapePacket);
        mpMatPacket[i].setTexture(pModelData->getTexture());
        mpMatPacket[i].setMaterialID(pModelData->getMaterialNodePointer(i)->mDiffFlag);

        if (pModelData->getModelDataType() == 1)
            mpMatPacket[i].mFlags |= 0x01;

        if (!!(flag & 0x80000)) {
            mpMatPacket[i].mpDisplayListObj = pModelData->getMaterialNodePointer(i)->getSharedDisplayListObj();
        } else {
            if (pModelData->getModelDataType() == 1) {
                if (!!(flag & 0x40000)) {
                    mpMatPacket[i].mpDisplayListObj = pModelData->getMaterialNodePointer(i)->getSharedDisplayListObj();
                } else {
                    J3DDisplayListObj* sharedDL = pModelData->getMaterialNodePointer(i)->getSharedDisplayListObj();
                    ret = sharedDL->single_To_Double();
                    if (ret != J3DErrType_Success)
                        return ret;

                    mpMatPacket[i].mpDisplayListObj = sharedDL;
                }
            } else if (!!(flag & 0x20000)) {
                if (!!(flag & 0x40000)) {
                    ret = pModelData->getMaterialNodePointer(i)->newSingleSharedDisplayList(pModelData->getMaterialNodePointer(i)->countDLSize());
                    if (ret != J3DErrType_Success)
                        return ret;

                    mpMatPacket[i].mpDisplayListObj = pModelData->getMaterialNodePointer(i)->getSharedDisplayListObj();
                } else {
                    ret = pModelData->getMaterialNodePointer(i)->newSharedDisplayList(pModelData->getMaterialNodePointer(i)->countDLSize());
                    if (ret != J3DErrType_Success)
                        return ret;

                    J3DDisplayListObj* sharedDL = pModelData->getMaterialNodePointer(i)->getSharedDisplayListObj();
                    ret = sharedDL->single_To_Double();
                    if (ret != J3DErrType_Success)
                        return ret;

                    mpMatPacket[i].mpDisplayListObj = sharedDL;
                }
            } else {
                if (!!(flag & 0x40000)) {
                    u32 size = pModelData->getMaterialNodePointer(i)->countDLSize();
                    ret = mpMatPacket[i].newSingleDisplayList(size);
                    if (ret != J3DErrType_Success)
                        return ret;
                } else {
                    u32 size = pModelData->getMaterialNodePointer(i)->countDLSize();
                    ret = mpMatPacket[i].newDisplayList(size);
                    if (ret != J3DErrType_Success)
                        return ret;
                }
            }
        }
    }

    return J3DErrType_Success;
}

/* 802EDF60-802EE1D4       .text createBumpMtxArray__8J3DModelFP12J3DModelDataUl */
s32 J3DModel::createBumpMtxArray(J3DModelData* modelData, u32 bufferNum) {
    if (modelData->getModelDataType() == 0) {
        u32 bumpMtxNum = 0;
        u16 hasScaleNum = 0;
        for (s32 matIdx = 0; matIdx < modelData->getMaterialNum(); matIdx++) {
            J3DMaterial * pMaterial = getModelData()->getMaterialNodePointer(matIdx);
            if (pMaterial->getNBTScale()->mbHasScale == 1) {
                bumpMtxNum += pMaterial->getShape()->countBumpMtxNum();
                hasScaleNum++;
            }
        }

        if ((u16)bumpMtxNum != 0 && bufferNum != 0) {
            for (s32 i = 0; i < 2; i++) {
                mpBumpMtxArr[i] = new Mtx33**[hasScaleNum];
                if (mpBumpMtxArr[i] == NULL)
                    return J3DErrType_OutOfMemory;
            }
        }

        for (s32 i = 0; i < 2; i++) {
            u32 bumpMtxOffset = 0;
            for (s32 matIdx = 0; matIdx < modelData->getMaterialNum(); matIdx++) {
                J3DMaterial * pMaterial = getModelData()->getMaterialNodePointer(matIdx);
                if (pMaterial->getNBTScale()->mbHasScale == 1) {
                    mpBumpMtxArr[i][bumpMtxOffset] = new Mtx33*[bufferNum];
                    if (mpBumpMtxArr[i][bumpMtxOffset] == NULL)
                        return J3DErrType_OutOfMemory;
                    pMaterial->getShape()->setBumpMtxOffset(bumpMtxOffset);
                    bumpMtxOffset++;
                }
            }
        }

        for (s32 i = 0; i < 2; i++) {
            u32 bumpMtxOffset = 0;
            for (s32 matIdx = 0; matIdx < modelData->getMaterialNum(); matIdx++) {
                J3DMaterial * pMaterial = getModelData()->getMaterialNodePointer(matIdx);
                if (pMaterial->getNBTScale()->mbHasScale == 1) {
                    for (u32 j = 0; j < bufferNum; j++) {
                        mpBumpMtxArr[i][bumpMtxOffset][j] = new(0x20) Mtx33[modelData->getDrawMtxNum()];
                        if (mpBumpMtxArr[i][bumpMtxOffset][j] == NULL)
                            return J3DErrType_OutOfMemory;
                    }
                    bumpMtxOffset++;
                }
            }
        }

        if (hasScaleNum != 0)
            mModelData->setBumpFlag(1);
    }

    return J3DErrType_Success;
}

/* 802EE1D4-802EE254       .text newDifferedDisplayList__8J3DModelFUl */
s32 J3DModel::newDifferedDisplayList(u32 flag) {
    mDiffFlag = flag;
    for (u16 i = 0; i < getModelData()->getShapeNum(); i++) {
        s32 ret = getShapePacket(i)->newDifferedDisplayList(flag);
        if (ret != J3DErrType_Success)
            return ret;
    }
    return J3DErrType_Success;
}

/* 802EE254-802EE28C       .text lock__8J3DModelFv */
void J3DModel::lock() {
    u16 matNum = mModelData->getMaterialNum();

    for (int i = 0; i < matNum; i++) {
        mpMatPacket[i].lock();
    }
}

/* 802EE28C-802EE2C4       .text unlock__8J3DModelFv */
void J3DModel::unlock() {
    u16 matNum = mModelData->getMaterialNum();

    for (int i = 0; i < matNum; i++) {
        mpMatPacket[i].unlock();
    }
}

/* 802EE2C4-802EE42C       .text calcMaterial__8J3DModelFv */
void J3DModel::calcMaterial() {
    j3dSys.setModel(this);
    j3dSys.setTexture(mModelData->getTexture());

    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);
    }

    for (u16 i = 0; i < getModelData()->getMaterialNum(); i++) {
        j3dSys.setMatPacket(&mpMatPacket[i]);

        J3DMaterial* pMaterial = getModelData()->getMaterialNodePointer(i);
        if (pMaterial->getMaterialAnm() != NULL)
            pMaterial->getMaterialAnm()->calc(pMaterial);

        s32 jntNo = pMaterial->getJoint()->getJntNo();
        pMaterial->calc(getAnmMtx(jntNo));
    }
}

/* 802EE42C-802EE4BC       .text diff__8J3DModelFv */
void J3DModel::diff() {
    for (u16 i = 0; i < getModelData()->getMaterialNum(); i++) {
        j3dSys.setMatPacket(&mpMatPacket[i]);
        getModelData()->getMaterialNodePointer(i)->diff(mDiffFlag);
    }
}

/* 802EE4BC-802EE5D8       .text setSkinDeform__8J3DModelFP13J3DSkinDeformUl */
s32 J3DModel::setSkinDeform(J3DSkinDeform* pSkinDeform, u32 flags) {
    mpSkinDeform = pSkinDeform;

    s32 ret = J3DErrType_Success;

    if (pSkinDeform == NULL) {
        offFlag(J3DMdlFlag_SkinPosCpu);
        offFlag(J3DMdlFlag_SkinNrmCpu);
        return 5;
    } else {
        mpSkinDeform->initMtxIndexArray(mModelData);

        ret = mModelData->checkFlag(J3DMdlDataFlag_NoAnimation);
        if (ret != J3DErrType_Success) {
            mpSkinDeform->changeFastSkinDL(mModelData);
            flags &= ~2;
            flags &= ~4;
        }

        ret = 0;
        if ((~flags & 2)) {
            ret = mVertexBuffer.allocTransformedVtxPosArray();
            if (ret != J3DErrType_Success) {
                offFlag(J3DMdlFlag_SkinPosCpu);
                return ret;
            }
            onFlag(J3DMdlFlag_SkinPosCpu);
        } else {
            offFlag(J3DMdlFlag_SkinPosCpu);
        }

        if ((~flags & 4)) {
            ret = mVertexBuffer.allocTransformedVtxNrmArray();
            if (ret != J3DErrType_Success) {
                offFlag(J3DMdlFlag_SkinNrmCpu);
                return ret;
            }
            onFlag(J3DMdlFlag_SkinNrmCpu);
        } else {
            offFlag(J3DMdlFlag_SkinNrmCpu);
        }
    }

    return ret;
}

/* 802EE5D8-802EE67C       .text calcAnmMtx__8J3DModelFv */
void J3DModel::calcAnmMtx() {
    j3dSys.setModel(this);
    j3dSys.setCurrentMtxCalc(getModelData()->getBasicMtxCalc());

    if (checkFlag(J3DMdlFlag_Unk00002))
        j3dSys.getCurrentMtxCalc()->init(j3dDefaultScale, j3dDefaultMtx);
    else
        j3dSys.getCurrentMtxCalc()->init(mBaseScale, mBaseTransformMtx);

    getModelData()->getBasicMtxCalc()->recursiveCalc(getModelData()->getRootNode());
}

/* 802EE67C-802EE874       .text calcWeightEnvelopeMtx__8J3DModelFv */
void J3DModel::calcWeightEnvelopeMtx() {
    /* Nonmatching */
}

/* 802EE874-802EE8C0       .text update__8J3DModelFv */
void J3DModel::update() {
    calc();
    entry();
}

/* 802EE8C0-802EEA2C       .text calc__8J3DModelFv */
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);
    }

    mVertexBuffer.frameInit();

    if (mpVisibilityManager != NULL)
        mpVisibilityManager->setVisibility(getModelData());

    if (mpDeformData != NULL)
        mpDeformData->deform(this);

    if (field_0xc4 != NULL)
        field_0xc4->calc(this);

    if (field_0xc8 != NULL)
        field_0xc8->calc(this);

    calcAnmMtx();
    calcWeightEnvelopeMtx();

    if (mpSkinDeform != NULL)
        mpSkinDeform->deform(this);

    if (mCalcCallBack != NULL)
        mCalcCallBack(this, 0);
}

/* 802EEA2C-802EEB24       .text entry__8J3DModelFv */
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);
    }

    j3dSys.setTexture(getModelData()->getTexture());

    for (u16 i = 0; i < getModelData()->getJointNum(); i++) {
        J3DJoint* joint = getModelData()->getJointNodePointer(i);
        if (joint->getMesh() != NULL) {
            joint->entryIn();
        }
    }
}

/* 802EEB24-802EEBDC       .text calcViewBaseMtx__FPA4_fRC3VecRA3_A4_CfPA4_f */
void calcViewBaseMtx(MtxP viewMtx, const Vec& scale, const Mtx& baseMtx, MtxP dstMtx) {
    Mtx mtx;
    mtx[0][0] = baseMtx[0][0] * scale.x;
    mtx[0][1] = baseMtx[0][1] * scale.y;
    mtx[0][2] = baseMtx[0][2] * scale.z;
    mtx[0][3] = baseMtx[0][3];

    mtx[1][0] = baseMtx[1][0] * scale.x;
    mtx[1][1] = baseMtx[1][1] * scale.y;
    mtx[1][2] = baseMtx[1][2] * scale.z;
    mtx[1][3] = baseMtx[1][3];

    mtx[2][0] = baseMtx[2][0] * scale.x;
    mtx[2][1] = baseMtx[2][1] * scale.y;
    mtx[2][2] = baseMtx[2][2] * scale.z;
    mtx[2][3] = baseMtx[2][3];

    MTXConcat(viewMtx, mtx, dstMtx);
}

/* 802EEBDC-802EEE30       .text calcDrawMtx__8J3DModelFv */
void J3DModel::calcDrawMtx() {
    u16 i;
    switch (getMtxCalcMode()) {
    case 0: {
        MtxP viewMtx = j3dSys.getViewMtx();
        for (i = 0; i < mModelData->getDrawFullWgtMtxNum(); i++) {
            u16 drawMtxIdx = mModelData->getDrawMtxIndex(i);
            MTXConcat(viewMtx, getAnmMtx(drawMtxIdx), getDrawMtx(i));
        }
        if (mModelData->getDrawMtxNum() > mModelData->getDrawFullWgtMtxNum()) {
            J3DPSMtxArrayConcat(viewMtx, getWeightAnmMtx(0), getDrawMtx(mModelData->getDrawFullWgtMtxNum()), mModelData->getWEvlpMtxNum());
        }
        break;
    }
    case 1:
        for (i = 0; i < mModelData->getDrawFullWgtMtxNum(); i++) {
            MTXCopy(getAnmMtx(mModelData->getDrawMtxIndex(i)), getDrawMtx(i));
        }
        for (i = 0; i < mModelData->getWEvlpMtxNum(); i++) {
            MTXCopy(getWeightAnmMtx(i), getDrawMtx(mModelData->getDrawFullWgtMtxNum() + i));
        }
        break;
    case 2:
        calcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx, mViewBaseMtx);
        for (i = 0; i < mModelData->getDrawFullWgtMtxNum(); i++) {
            u16 drawMtxIdx = mModelData->getDrawMtxIndex(i);
            MTXConcat(mViewBaseMtx, getAnmMtx(drawMtxIdx), getDrawMtx(i));
        }
        if (mModelData->getDrawMtxNum() > mModelData->getDrawFullWgtMtxNum()) {
            J3DPSMtxArrayConcat(mViewBaseMtx, getWeightAnmMtx(0), getDrawMtx(mModelData->getDrawFullWgtMtxNum()), mModelData->getWEvlpMtxNum());
        }
        break;
    }
}

/* 802EEE30-802EF050       .text viewCalc__8J3DModelFv */
void J3DModel::viewCalc() {
    swapDrawMtx();
    swapNrmMtx();

    if (mModelData->checkFlag(J3DMdlDataFlag_NoUseDrawMtx)) {
        if (getMtxCalcMode() == 2)
            calcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx, (MtxP)&mViewBaseMtx);

        prepareShapePackets();
    } else if (isCpuSkinningOn()) {
        if (getMtxCalcMode() == 2)
            calcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx, (MtxP)&mViewBaseMtx);

        prepareShapePackets();
    } else {
        if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
            calcDrawMtx();
            calcNrmMtx();
            calcBumpMtx();
            DCStoreRange(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
            DCStoreRange(getNrmMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx33));
        } else if (checkFlag(J3DMdlFlag_SkinNrmCpu)) {
            calcDrawMtx();
            calcBBoard();
            DCStoreRange(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
        } else {
            calcDrawMtx();
            calcNrmMtx();
            calcBBoard();
            calcBumpMtx();
            DCStoreRange(getDrawMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx));
            DCStoreRange(getNrmMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx33));
        }

        prepareShapePackets();
    }
}

/* 802EF050-802EF1B8       .text calcNrmMtx__8J3DModelFv */
void J3DModel::calcNrmMtx() {
    if (getModelData()->checkFlag(J3DMdlDataFlag_ConcatView) == 0) {
        for (u16 i = 0; i < getModelData()->getDrawMtxNum(); i++) {
            if (getModelData()->getDrawMtxFlag(i) == 0) {
                if (getScaleFlag(getModelData()->getDrawMtxIndex(i)) == 1) {
                    setNrmMtx(i, getDrawMtx(i));
                } else
                    J3DPSCalcInverseTranspose(getDrawMtx(i), getNrmMtx(i));
            } else {
                if (getEnvScaleFlag(getModelData()->getDrawMtxIndex(i)) == 1) {
                    setNrmMtx(i, getDrawMtx(i));
                } else
                    J3DPSCalcInverseTranspose(getDrawMtx(i), getNrmMtx(i));
            }
        }
    }
}

/* 802EF1B8-802EF2B0       .text calcBumpMtx__8J3DModelFv */
void J3DModel::calcBumpMtx() {
    if (getModelData()->checkBumpFlag() == 1) {
        s32 bumpMtxOffset = 0;
        for (s32 i = 0; i < getModelData()->getMaterialNum(); i++) {
            J3DMaterial * pMaterial = getModelData()->getMaterialNodePointer(i);
            if (pMaterial->getNBTScale()->mbHasScale == 1) {
                pMaterial->getShape()->calcNBTScale(*pMaterial->getNBTScale()->getScale(), getNrmMtxPtr(), getBumpMtxPtr(bumpMtxOffset));
                DCStoreRange(getBumpMtxPtr(bumpMtxOffset), getModelData()->getDrawMtxNum() * sizeof(Mtx33));
                bumpMtxOffset++;
            }
        }
    }
}

/* 802EF2B0-802EF414       .text calcBBoard__8J3DModelFv */
void J3DModel::calcBBoard() {
    if (getModelData()->checkBBoardFlag()) {
        for (u16 i = 0; i < getModelData()->getDrawMtxNum(); i++) {
            if (getModelData()->getDrawMtxFlag(i) != 0)
                continue;

            u8 mtxType = getModelData()->getJointNodePointer(getModelData()->getDrawMtxIndex(i))->getMtxType();
            if (mtxType == J3DJntMtxType_BBoard) {
                Mtx& 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 (mtxType == J3DJntMtxType_YBBoard) {
                Mtx& drawMtx = getDrawMtx(i);
                J3DCalcYBBoardMtx(drawMtx);
                Mtx33& nrmMtx = getNrmMtx(i);
                J3DPSCalcInverseTranspose(drawMtx, nrmMtx);
            }
        }
    }
}

/* 802EF414-802EF5D8       .text prepareShapePackets__8J3DModelFv */
void J3DModel::prepareShapePackets() {
    u16 shapeNum = getModelData()->getShapeNum();

    for (u16 i = 0; i < shapeNum; i++) {
        J3DShape *pShape = getModelData()->getShapeNodePointer(i);
        J3DShapePacket* pkt = getShapePacket(i);
        pkt->setScaleFlagArray(mpScaleFlagArr);
        pkt->setDrawMtx(mpDrawMtxBuf[1]);
        pkt->setNrmMtx(mpNrmMtxBuf[1]);
        pkt->setCurrentViewNoPtr(&mCurrentViewNo);
    }

    for (u16 i = 0; i < shapeNum; i++) {
        J3DShape *pShape = getModelData()->getShapeNodePointer(i);
        J3DShapePacket* pkt = getShapePacket(i);

        if (checkFlag(J3DMdlFlag_SkinPosCpu))
            pShape->onFlag(J3DShpFlag_SkinPosCpu);
        else
            pShape->offFlag(J3DShpFlag_SkinPosCpu);

        if (checkFlag(J3DMdlFlag_SkinNrmCpu) && !pShape->checkFlag(J3DShpFlag_EnableLod))
            pShape->onFlag(J3DShpFlag_SkinNrmCpu);
        else
            pShape->offFlag(J3DShpFlag_SkinNrmCpu);

        if (getMtxCalcMode() == 2)
            pkt->setBaseMtxPtr(&mViewBaseMtx);
        else
            pkt->setBaseMtxPtr(&j3dSys.mViewMtx);
    }

    if (getModelData()->checkBumpFlag() == 1) {
        for (s32 i = 0; i < getModelData()->getMaterialNum(); i++) {
            J3DMaterial* pMaterial = getModelData()->getMaterialNodePointer(i);
            if (pMaterial->getTexGenBlock()->getNBTScale()->mbHasScale == 1) {
                u16 shapeIdx = pMaterial->getShape()->getIndex();
                u32 bumpMtxOffs = pMaterial->getShape()->getBumpMtxOffset();
                mpShapePacket[shapeIdx].setNrmMtx(mpBumpMtxArr[1][bumpMtxOffs]);
            }
        }
    }
}
