// // Generated by dtk // Translation Unit: J3DCluster.cpp // #include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/J3DGraphAnimator/J3DCluster.h" #include "JSystem/J3DGraphAnimator/J3DModel.h" #include "JSystem/J3DGraphAnimator/J3DSkinDeform.h" #include "JSystem/J3DGraphAnimator/J3DAnimation.h" #include "JSystem/JKernel/JKRHeap.h" #include "JSystem/J3DAssert.h" #include "dolphin/os/OS.h" #include "string.h" #include "stdint.h" /* 802F37C4-802F37E4 .text clear__13J3DDeformDataFv */ void J3DDeformData::clear() { mClusterNum = 0; mClusterPointer = NULL; mClusterKeyNum = 0; mClusterKeyPointer = NULL; mClusterName = NULL; mClusterKeyName = NULL; } /* 802F37E4-802F3814 .text __ct__13J3DDeformDataFv */ J3DDeformData::J3DDeformData() { clear(); } /* 802F3814-802F3838 .text deform__13J3DDeformDataFP8J3DModel */ void J3DDeformData::deform(J3DModel* model) { deform(model->getVertexBuffer()); } /* 802F3838-802F3900 .text deform__13J3DDeformDataFP15J3DVertexBuffer */ void J3DDeformData::deform(J3DVertexBuffer* vtx) { vtx->swapVtxPosArrayPointer(); vtx->swapVtxNrmArrayPointer(); for (u16 i = 0; i < mClusterNum; i++) mClusterPointer[i].getDeformer()->deform(vtx, i); DCStoreRange(vtx->getVtxPosArrayPointer(0), vtx->getVertexData()->getVtxNum() * 12); DCStoreRange(vtx->getVtxNrmArrayPointer(0), vtx->getVertexData()->getNrmNum() * 12); vtx->setCurrentVtxPos(vtx->getVtxPosArrayPointer(0)); vtx->setCurrentVtxNrm(vtx->getVtxNrmArrayPointer(0)); } /* 802F3900-802F3920 .text clear__11J3DDeformerFv */ void J3DDeformer::clear() { mDeformData = NULL; mAnmCluster = NULL; mWeightList = NULL; field_0x0c = NULL; mFlags = 3; } /* 802F3920-802F3A08 .text deform__11J3DDeformerFP15J3DVertexBufferUs */ void J3DDeformer::deform(J3DVertexBuffer* vtx, u16 idx) { u16 keyIdx = 0; if (mAnmCluster) { for (u16 i = 0; i < idx; i++) keyIdx += mDeformData->getClusterPointer(i)->mKeyNum; for (u16 i = 0; i < mDeformData->getClusterPointer(idx)->mKeyNum; i++) mWeightList[i] = mAnmCluster->getWeight(keyIdx++); deform(vtx, idx, mWeightList); } } /* 802F3A08-802F3FA8 .text deform__11J3DDeformerFP15J3DVertexBufferUsPf */ void J3DDeformer::deform(J3DVertexBuffer* vtx, u16 idx, f32* weightList) { /* Nonmatching */ if (checkFlag(2) && vtx->getVertexData()->getVtxPosType() == GX_F32) { J3DCluster* cluster = mDeformData->getClusterPointer(idx); int posNum = cluster->mPosNum; int keyNum = cluster->mKeyNum; u16 keyStart = 0; for (u16 i = 0; i < idx; i++) keyStart += mDeformData->getClusterPointer(i)->mKeyNum + 1; J3DClusterKey* key = mDeformData->getClusterKeyPointer(keyStart); normalizeWeight(keyNum, weightList); f32* vtxPosDst = (f32*)vtx->getVtxPosArrayPointer(0); f32* vtxPosSrc = (f32*)mDeformData->getVtxPos(); for (int i = 0; i < posNum; i++) { f32* vtx = &vtxPosDst[cluster->mPosDstIdx[i] * 3]; vtx[0] = 0.0f; vtx[1] = 0.0f; vtx[2] = 0.0f; } f32 sign[2] = { 1.0f, -1.0f }; for (u16 i = 0; i < posNum; i++) { for (u16 j = 0; j < keyNum; j++) { u16 flag = (u16)key[j].mPosFlag[i]; f32* src = &vtxPosSrc[(flag & 0x1FFF) * 3]; f32* dst = &vtxPosDst[cluster->mPosDstIdx[i] * 3]; dst[0] += weightList[j] * src[0] * sign[(flag >> 15) & 1]; dst[1] += weightList[j] * src[1] * sign[(flag >> 14) & 1]; dst[2] += weightList[j] * src[2] * sign[(flag >> 13) & 1]; } } if (checkFlag(1) && cluster->mFlags != 0 && vtx->getVertexData()->getVtxNrmType() == GX_F32) { f32* vtxNrmDst = (f32*)vtx->getVtxNrmArrayPointer(0); f32* vtxNrmSrc = mDeformData->getVtxNrm(); f32* nrmBuf = field_0x0c; for (u16 i = 0; i < cluster->mNrmNum; i++) { f32* dst = &nrmBuf[i * 3]; dst[0] = 0.0f; dst[1] = 0.0f; dst[2] = 0.0f; for (u16 j = 0; j < cluster->mKeyNum; j++) { u16 flag = key[j].mNrmFlag[i]; f32* src = &vtxNrmSrc[(flag & 0x1FFF) * 3]; f32 srcX = src[0]; f32 srcY = src[1]; f32 srcZ = src[2]; if (flag & 0x8000) srcX = -srcX; if (flag & 0x4000) srcY = -srcY; if (flag & 0x2000) srcZ = -srcZ; dst[0] += srcX * weightList[j]; dst[1] += srcY * weightList[j]; dst[2] += srcZ * weightList[j]; } normalize(dst); } for (u16 i = 0; i < cluster->mClusterVertexNum; i++) { J3DClusterVertex* vertex = &cluster->mClusterVertex[i]; f32 pos[3]; pos[0] = 0.0f; pos[1] = 0.0f; pos[2] = 0.0f; f32 weight = 1.0f / (float)vertex->mNum; for (u16 j = 0; j < vertex->mNum; j++) { f32* src = &nrmBuf[vertex->mSrcIdx[j] * 3]; pos[0] += weight * src[0]; pos[1] += weight * src[1]; pos[2] += weight * src[2]; } normalize(pos); for (u16 j = 0; j < vertex->mNum; j++) { u16 srcIdx = vertex->mSrcIdx[j]; u16 dstIdx = vertex->mDstIdx[j]; if (dstIdx == 0xFFFF) continue; f32* src = &nrmBuf[srcIdx * 3]; f32 dot = pos[0]*src[0] + pos[1]*src[1] + pos[2]*src[2]; f32 angle; if (dot >= 1.0f) { angle = 0.0f; } else if (dot > -1.0f) { angle = acos(dot); angle = (angle * 180.0f) / 3.1415f; } else { angle = 180.0f; } if (angle <= cluster->mMinAngle) { vtxNrmDst[dstIdx * 3 + 0] = pos[0]; vtxNrmDst[dstIdx * 3 + 1] = pos[1]; vtxNrmDst[dstIdx * 3 + 2] = pos[2]; } else if (angle > cluster->mMaxAngle) { vtxNrmDst[dstIdx * 3 + 0] = src[0]; vtxNrmDst[dstIdx * 3 + 1] = src[1]; vtxNrmDst[dstIdx * 3 + 2] = src[2]; } else { f32 weight = (angle - cluster->mMinAngle) / (cluster->mMaxAngle - cluster->mMinAngle); f32 inv = 1.0f - weight; vtxNrmDst[dstIdx * 3 + 0] = inv * pos[0] + weight * src[0]; vtxNrmDst[dstIdx * 3 + 1] = inv * pos[1] + weight * src[1]; vtxNrmDst[dstIdx * 3 + 2] = inv * pos[2] + weight * src[2]; } } } } } } /* 802F3FA8-802F4064 .text normalize__11J3DDeformerFPf */ void J3DDeformer::normalize(f32* vec) { f32 inv = 1.0f / std::sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); vec[0] *= inv; vec[1] *= inv; vec[2] *= inv; } /* 802F4064-802F40C0 .text normalizeWeight__11J3DDeformerFiPf */ void J3DDeformer::normalizeWeight(int count, f32* weight) { f32 sum = 0.0f; for (u16 i = 0; i < count; i++) sum += weight[i]; sum = 1.0f / sum; for (u16 i = 0; i < count; i++) weight[i] *= sum; } /* 802F40C0-802F40F0 .text __ct__13J3DSkinDeformFv */ J3DSkinDeform::J3DSkinDeform() { mPosUseMtx = NULL; mNrmUseMtx = NULL; mNrmMtx = NULL; mFlags = 3; field_0x14 = 1; } /* 802F40F0-802F44E8 .text initMtxIndexArray__13J3DSkinDeformFP12J3DModelData */ int J3DSkinDeform::initMtxIndexArray(J3DModelData* modelData) { if (mPosUseMtx != NULL && mNrmUseMtx != NULL) return J3DErrType_Success; mPosUseMtx = new u16[modelData->getVtxNum()]; if (mPosUseMtx == NULL) return J3DErrType_OutOfMemory; for (u32 i = 0; i < modelData->getVtxNum(); i++) mPosUseMtx[i] = 0xFFFF; if (modelData->getNrmNum() != 0) { mNrmUseMtx = new u16[modelData->getNrmNum()]; if (mNrmUseMtx == NULL) return J3DErrType_OutOfMemory; for (u32 i = 0; i < modelData->getNrmNum(); i++) mNrmUseMtx[i] = 0; } else { mNrmUseMtx = NULL; } mNrmMtx = new(0x20) Mtx33[modelData->getDrawMtxNum()]; if (mNrmMtx == NULL) return J3DErrType_OutOfMemory; for (u16 i = 0; i < modelData->getShapeNum(); i++) { int size[4] = { 0, 1, 1, 2 }; int pnmtxIdxOffs = -1; int posOffs = -1; int nrmOffs = -1; int vtxSize = 0; for (GXVtxDescList* desc = modelData->getShapeNodePointer(i)->getVtxDesc(); desc->attr != GX_VA_NULL; desc++) { switch (desc->attr) { case GX_VA_PNMTXIDX: pnmtxIdxOffs = vtxSize; break; case GX_VA_POS: posOffs = vtxSize; if (desc->type != GX_INDEX16) { OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n"); #if VERSION == VERSION_DEMO return; // !@bug: No return value #endif } break; case GX_VA_NRM: nrmOffs = vtxSize; if (desc->type != GX_INDEX16) { OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n"); #if VERSION == VERSION_DEMO return; // !@bug: No return value #endif } break; case GX_VA_TEX0: #if VERSION > VERSION_DEMO if (desc->type != GX_INDEX16) { OSReport(" Invlid Data : CPU Pipeline process GX_INDEX16 Data Only\n"); } #endif break; default: break; } vtxSize += size[desc->type]; } for (u16 j = 0; j < modelData->getShapeNodePointer(i)->getMtxGroupNum(); j++) { J3DShapeMtx* shapeMtx = modelData->getShapeNodePointer(i)->getShapeMtx(j); u8* displayListStart = modelData->getShapeNodePointer(i)->getShapeDraw(j)->getDisplayList(); for (u8* dl = displayListStart; (dl - displayListStart) < modelData->getShapeNodePointer(i)->getShapeDraw(j)->getDisplayListSize(); ) { u8 cmd = *dl; dl++; if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP) break; int vtxCount = *(u16*)dl; dl += 2; u16 useMtxIdxBuf[10]; for (int k = 0; k < vtxCount; k++) { u8* src = &dl[vtxSize * k]; u8 pnmtxIdx = (u32)*(u8*)&src[pnmtxIdxOffs] / 3; u16 posIdx = *(u16*)&src[posOffs]; u16 nrmIdx = *(u16*)&src[nrmOffs]; u16 useMtxIdx = shapeMtx->getUseMtxIndex(pnmtxIdx); if (useMtxIdx == 0xFFFF) { useMtxIdx = useMtxIdxBuf[pnmtxIdx]; } else if (pnmtxIdxOffs != -1) { useMtxIdxBuf[pnmtxIdx] = useMtxIdx; } mPosUseMtx[posIdx] = useMtxIdx; if (nrmOffs != -1) mNrmUseMtx[nrmIdx] = useMtxIdx; } dl = (u8*)dl + vtxSize * vtxCount; } if (nrmOffs == -1) { modelData->getShapeNodePointer(i)->onFlag(J3DShpFlag_EnableLod); modelData->getShapeNodePointer(i)->offFlag(J3DShpFlag_SkinNrmCpu); } } } for (u32 i = 0; i < modelData->getVtxNum(); i++) { if (mPosUseMtx[i] == 0xFFFF) { field_0x14 = 0; mPosUseMtx[i] = 0; } } return J3DErrType_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(); } } /* 802F4734-802F4850 .text calcNrmMtx__13J3DSkinDeformFP8J3DModel */ void J3DSkinDeform::calcNrmMtx(J3DModel* model) { J3DModelData* modelData = model->getModelData(); for (u16 i = 0; i < modelData->getDrawMtxNum(); i++) { if (modelData->getDrawMtxFlag(i) == 0) { if (model->getScaleFlag(modelData->getDrawMtxIndex(i)) == 1) { J3DPSMtx33CopyFrom34(model->getAnmMtx(modelData->getDrawMtxIndex(i)), mNrmMtx[i]); } else { J3DPSCalcInverseTranspose(model->getAnmMtx(modelData->getDrawMtxIndex(i)), mNrmMtx[i]); } } else { if (model->getEnvScaleFlag(modelData->getDrawMtxIndex(i)) == 1) { J3DPSMtx33CopyFrom34(model->getWeightAnmMtx(modelData->getDrawMtxIndex(i)), mNrmMtx[i]); } else { J3DPSCalcInverseTranspose(model->getWeightAnmMtx(modelData->getDrawMtxIndex(i)), mNrmMtx[i]); } } } } /* 802F4850-802F4974 .text deformVtxPos_F32__13J3DSkinDeformCFP8J3DModel */ void J3DSkinDeform::deformVtxPos_F32(J3DModel* model) const { Mtx* mtxArr[2]; mtxArr[0] = (Mtx*)model->getAnmMtx(0); mtxArr[1] = (Mtx*)model->getWeightAnmMtx(0); model->getVertexBuffer()->swapTransformedVtxPos(); int vtxNum = model->getModelData()->getVtxNum(); Vec* curVtxPos = (Vec*)model->getCurrentVtxPos(); Vec* transformedVtxPos = (Vec*)model->getVertexBuffer()->getTransformedVtxPos(0); for (int i = 0; i < vtxNum; i++) { Mtx* mtx = mtxArr[model->getModelData()->getDrawMtxFlag(mPosUseMtx[i])]; J3DPSMulMtxVec(mtx[model->getModelData()->getDrawMtxIndex(mPosUseMtx[i])], &curVtxPos[i], &transformedVtxPos[i]); } DCStoreRange(model->getVertexBuffer()->getTransformedVtxPos(0), model->getModelData()->getVtxNum() * sizeof(Vec)); model->setCurrentVtxPos(transformedVtxPos); } /* 802F4974-802F4AB4 .text deformVtxPos_S16__13J3DSkinDeformCFP8J3DModel */ void J3DSkinDeform::deformVtxPos_S16(J3DModel* model) const { Mtx* mtxArr[2]; mtxArr[0] = (Mtx*)model->getAnmMtx(0); mtxArr[1] = (Mtx*)model->getWeightAnmMtx(0); J3DGQRSetup7(model->getModelData()->getVertexData().getVtxPosFrac(), 7, model->getModelData()->getVertexData().getVtxPosFrac(), 7); model->getVertexBuffer()->swapTransformedVtxPos(); int vtxNum = model->getModelData()->getVtxNum(); S16Vec* curVtxPos = (S16Vec*)model->getCurrentVtxPos(); S16Vec* transformedVtxPos = (S16Vec*)model->getVertexBuffer()->getTransformedVtxPos(0); for (int i = 0; i < vtxNum; i++) { Mtx* mtx = mtxArr[model->getModelData()->getDrawMtxFlag(mPosUseMtx[i])]; J3DPSMulMtxVec(mtx[model->getModelData()->getDrawMtxIndex(mPosUseMtx[i])], &curVtxPos[i], &transformedVtxPos[i]); } DCStoreRange(model->getVertexBuffer()->getTransformedVtxPos(0), model->getModelData()->getVtxNum() * sizeof(SVec)); model->setCurrentVtxPos(transformedVtxPos); } /* 802F4AB4-802F4BB8 .text deformVtxNrm_F32__13J3DSkinDeformCFP8J3DModel */ void J3DSkinDeform::deformVtxNrm_F32(J3DModel* model) const { model->getVertexBuffer()->swapTransformedVtxNrm(); int vtxNum = model->getModelData()->getNrmNum(); Vec* curVtxNrm = (Vec*)model->getCurrentVtxNrm(); Vec* transformedVtxNrm = (Vec*)model->getVertexBuffer()->getTransformedVtxNrm(0); for (int i = 0; i < vtxNum; i++) { J3DPSMulMtxVec(mNrmMtx[mNrmUseMtx[i]], &curVtxNrm[i], &transformedVtxNrm[i]); } DCStoreRange(model->getVertexBuffer()->getTransformedVtxNrm(0), model->getModelData()->getNrmNum() * sizeof(Vec)); model->setCurrentVtxNrm(transformedVtxNrm); } /* 802F4BB8-802F4CD8 .text deformVtxNrm_S16__13J3DSkinDeformCFP8J3DModel */ void J3DSkinDeform::deformVtxNrm_S16(J3DModel* model) const { J3DGQRSetup7(model->getModelData()->getVertexData().getVtxNrmFrac(), 7, model->getModelData()->getVertexData().getVtxNrmFrac(), 7); model->getVertexBuffer()->swapTransformedVtxNrm(); int vtxNum = model->getModelData()->getNrmNum(); S16Vec* curVtxNrm = (S16Vec*)model->getCurrentVtxNrm(); S16Vec* transformedVtxNrm = (S16Vec*)model->getVertexBuffer()->getTransformedVtxNrm(0); for (int i = 0; i < vtxNum; i++) { J3DPSMulMtxVec(mNrmMtx[mNrmUseMtx[i]], &curVtxNrm[i], &transformedVtxNrm[i]); } DCStoreRange(model->getVertexBuffer()->getTransformedVtxNrm(0), model->getModelData()->getNrmNum() * sizeof(SVec)); model->setCurrentVtxNrm(transformedVtxNrm); } /* 802F4CD8-802F4D78 .text deform__13J3DSkinDeformFP8J3DModel */ void J3DSkinDeform::deform(J3DModel* model) { if (model->checkFlag(J3DMdlFlag_SkinPosCpu)) { if (model->getModelData()->getVertexData().getVtxPosType() == GX_F32) deformVtxPos_F32(model); else deformVtxPos_S16(model); } if (model->checkFlag(J3DMdlFlag_SkinNrmCpu)) { calcNrmMtx(model); if (model->getModelData()->getVertexData().getVtxNrmType() == GX_F32) deformVtxNrm_F32(model); else deformVtxNrm_S16(model); } }