#include "nw4r/g3d.h" // IWYU pragma: export namespace nw4r { namespace g3d { NW4R_G3D_RTTI_DEF(ScnMdl); /****************************************************************************** * * CopiedMatAccess * ******************************************************************************/ ResTexObj ScnMdl::CopiedMatAccess::GetResTexObj(bool markDirty) { if (mpScnMdl != NULL && mTexObj.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_TEXOBJ); } return mTexObj; } return ResTexObj(NULL); } ResTexSrt ScnMdl::CopiedMatAccess::GetResTexSrt(bool markDirty) { if (mpScnMdl != NULL && mTexSrt.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_TEXSRT); } return mTexSrt; } return ResTexSrt(NULL); } ResMatChan ScnMdl::CopiedMatAccess::GetResMatChan(bool markDirty) { if (mpScnMdl != NULL && mChan.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_MATCHAN); } return mChan; } return ResMatChan(NULL); } ResGenMode ScnMdl::CopiedMatAccess::GetResGenMode(bool markDirty) { if (mpScnMdl != NULL && mGenMode.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_GENMODE); } return mGenMode; } return ResGenMode(NULL); } ResMatMisc ScnMdl::CopiedMatAccess::GetResMatMisc(bool markDirty) { if (mpScnMdl != NULL && mMatMisc.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_MATMISC); } return mMatMisc; } return ResMatMisc(NULL); } ResMatPix ScnMdl::CopiedMatAccess::GetResMatPix(bool markDirty) { if (mpScnMdl != NULL && mPix.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_MATPIX); } return mPix; } return ResMatPix(NULL); } ResMatTevColor ScnMdl::CopiedMatAccess::GetResMatTevColor(bool markDirty) { if (mpScnMdl != NULL && mTevColor.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_MATTEVCOLOR); } return mTevColor; } return ResMatTevColor(NULL); } ResTev ScnMdl::CopiedMatAccess::GetResTev(bool markDirty) { if (mpScnMdl != NULL && mTev.IsValid()) { if (markDirty) { mpScnMdl->MatBufferDirty(mMatID, ScnMdl::BUFOPTION_TEV); } return mTev; } return ResTev(NULL); } ResTexObj ScnMdl::CopiedMatAccess::GetResTexObjEx() { if (mpScnMdl != NULL) { if (mTexObj.IsValid()) { return mTexObj; } return mpScnMdl->GetResMdl().GetResMat(mMatID).GetResTexObj(); } return ResTexObj(NULL); } ResTexSrt ScnMdl::CopiedMatAccess::GetResTexSrtEx() { if (mpScnMdl != NULL) { if (mTexSrt.IsValid()) { return mTexSrt; } return mpScnMdl->GetResMdl().GetResMat(mMatID).GetResTexSrt(); } return ResTexSrt(NULL); } ResMatChan ScnMdl::CopiedMatAccess::GetResMatChanEx() { if (mpScnMdl != NULL) { if (mChan.IsValid()) { return mChan; } return mpScnMdl->GetResMdl().GetResMat(mMatID).GetResMatChan(); } return ResMatChan(NULL); } ScnMdl::CopiedMatAccess::CopiedMatAccess(ScnMdl *pScnMdl, u32 id) : mTexObj(NULL), mTlutObj(NULL), mTexSrt(NULL), mChan(NULL), mGenMode(NULL), mMatMisc(NULL), mPix(NULL), mTevColor(NULL), mIndMtxAndScale(NULL), mTexCoordGen(NULL), mTev(NULL) { if (pScnMdl != NULL && pScnMdl->GetResMdl().GetResMat(id).IsValid()) { mpScnMdl = pScnMdl; mMatID = id; DrawResMdlReplacement &rReplacement = pScnMdl->mReplacement; if (rReplacement.texObjDataArray != NULL) { mTexObj = ResTexObj(&rReplacement.texObjDataArray[id]); } else { mTexObj = ResTexObj(NULL); } if (rReplacement.tlutObjDataArray != NULL) { mTlutObj = ResTlutObj(&rReplacement.tlutObjDataArray[id]); } else { mTlutObj = ResTlutObj(NULL); } if (rReplacement.texSrtDataArray != NULL) { mTexSrt = ResTexSrt(&rReplacement.texSrtDataArray[id]); } else { mTexSrt = ResTexSrt(NULL); } if (rReplacement.chanDataArray != NULL) { mChan = ResMatChan(&rReplacement.chanDataArray[id]); } else { mChan = ResMatChan(NULL); } if (rReplacement.genModeDataArray != NULL) { mGenMode = ResGenMode(&rReplacement.genModeDataArray[id]); } else { mGenMode = ResGenMode(NULL); } if (rReplacement.matMiscDataArray != NULL) { mMatMisc = ResMatMisc(&rReplacement.matMiscDataArray[id]); } else { mMatMisc = ResMatMisc(NULL); } if (rReplacement.pixDLArray != NULL) { mPix = ResMatPix(&rReplacement.pixDLArray[id]); } else { mPix = ResMatPix(NULL); } if (rReplacement.tevColorDLArray != NULL) { mTevColor = ResMatTevColor(&rReplacement.tevColorDLArray[id]); } else { mTevColor = ResMatTevColor(NULL); } if (rReplacement.indMtxAndScaleDLArray != NULL) { mIndMtxAndScale = ResMatIndMtxAndScale(&rReplacement.indMtxAndScaleDLArray[id]); } else { mIndMtxAndScale = ResMatIndMtxAndScale(NULL); } if (rReplacement.texCoordGenDLArray != NULL) { mTexCoordGen = ResMatTexCoordGen(&rReplacement.texCoordGenDLArray[id]); } else { mTexCoordGen = ResMatTexCoordGen(NULL); } if (rReplacement.tevDataArray != NULL) { mTev = ResTev(&rReplacement.tevDataArray[id]); } else { mTev = ResTev(NULL); } } else { mpScnMdl = NULL; mMatID = id; mTexObj = ResTexObj(NULL); mTlutObj = ResTlutObj(NULL); mTexSrt = ResTexSrt(NULL); mChan = ResMatChan(NULL); mGenMode = ResGenMode(NULL); mMatMisc = ResMatMisc(NULL); mPix = ResMatPix(NULL); mTevColor = ResMatTevColor(NULL); mIndMtxAndScale = ResMatIndMtxAndScale(NULL); mTexCoordGen = ResMatTexCoordGen(NULL); mTev = ResTev(NULL); } } /****************************************************************************** * * CopiedVisAccess * ******************************************************************************/ bool ScnMdl::CopiedVisAccess::IsVisible() const { if (mpScnMdl != NULL) { if (mpVis != NULL) { return *mpVis != 0; } return mpScnMdl->GetResMdl().GetResNode(mNodeID).IsVisible(); } return false; } bool ScnMdl::CopiedVisAccess::SetVisibility(bool visible) { if (mpScnMdl != NULL && mpVis != NULL) { if (visible) { if (*mpVis == 0) { mpScnMdl->VisBufferDirty(); *mpVis = 1; } } else if (*mpVis != 0) { mpScnMdl->VisBufferDirty(); *mpVis = 0; } return true; } return false; } bool ScnMdl::CopiedVisAccess::SetVisibilityEx(bool visible) { if (mpScnMdl != NULL) { if (mpVis != NULL) { if (visible && *mpVis == 0 || !visible && *mpVis != 0) { mpScnMdl->VisBufferDirty(); } *mpVis = visible; } else { mpScnMdl->GetResMdl().GetResNode(mNodeID).SetVisibility(visible); } return true; } return false; } ScnMdl::CopiedVisAccess::CopiedVisAccess(ScnMdl *pScnMdl, u32 id) { if (pScnMdl != NULL && pScnMdl->GetResMdl().GetResNode(id).IsValid()) { mpScnMdl = pScnMdl; mNodeID = id; if (pScnMdl->mReplacement.visArray != NULL) { mpVis = &pScnMdl->mReplacement.visArray[id]; } else { mpVis = NULL; } } else { mpScnMdl = NULL; mNodeID = id; mpVis = NULL; } } /****************************************************************************** * * CopiedVtxAccess * ******************************************************************************/ ResVtxPos ScnMdl::CopiedVtxAccess::GetResVtxPos(u32 id) { ResVtxPos res = GetPos(id); // goto signifies inline... Dwarf doesnt have info if (mpScnMdl != NULL && res == mpScnMdl->GetResMdl().GetResVtxPos(id)) { return ResVtxPos(NULL); } return res; } ResVtxNrm ScnMdl::CopiedVtxAccess::GetResVtxNrm(u32 id) { ResVtxNrm res = GetNrm(id); // goto signifies inline... Dwarf doesnt have info if (mpScnMdl != NULL && res == mpScnMdl->GetResMdl().GetResVtxNrm(id)) { return ResVtxNrm(NULL); } return res; } /****************************************************************************** * * ScnMdl * ******************************************************************************/ ScnMdl *ScnMdl::Construct(MEMAllocator *pAllocator, u32 *pSize, ResMdl mdl, u32 bufferOption, int numView) { if (!mdl.IsValid()) { return NULL; } if (numView == 0) { numView = 1; } else if (numView > VIEW_MAX) { numView = VIEW_MAX; } ScnMdl *pScnMdl = NULL; u32 worldMtxNum = mdl.GetResMdlInfo().GetNumPosNrmMtx(); u32 viewMtxNum = mdl.GetResMdlInfo().GetNumViewMtx(); u32 matNum = mdl.GetResMatNumEntries(); u32 nodeNum = mdl.GetResNodeNumEntries(); u32 scnMdlSize = sizeof(ScnMdl); u32 worldMtxArraySize = worldMtxNum * sizeof(math::MTX34); u32 worldMtxAttribArraySize = worldMtxNum * sizeof(u32); u32 viewPosMtxArrayUnitSize = viewMtxNum * sizeof(math::MTX34); u32 viewPosMtxArraySize = numView * align32(viewPosMtxArrayUnitSize); u32 viewNrmMtxArrayUnitSize = viewMtxNum * sizeof(math::MTX33); u32 viewNrmMtxArraySize = mdl.GetResMdlInfo().ref().need_nrm_mtx_array ? numView * align32(viewNrmMtxArrayUnitSize) : 0; u32 viewTexMtxArrayUnitSize = viewPosMtxArrayUnitSize; // TODO: Fakematch u32 viewTexMtxArraySize = mdl.ref().info.need_tex_mtx_array ? numView * align32(viewTexMtxArrayUnitSize) : 0; u32 matBufferDirtyFlagSize = matNum * sizeof(u32); // clang-format off u32 resTexObjSize = (bufferOption & BUFOPTION_TEXOBJ) ? matNum * sizeof(ResTexObjData) : 0; u32 resTlutObjSize = (bufferOption & BUFOPTION_TLUTOBJ) ? matNum * sizeof(ResTlutObjData) : 0; u32 resTexSrtSize = (bufferOption & BUFOPTION_TEXSRT) ? matNum * sizeof(ResTexSrtData) : 0; u32 resChanSize = (bufferOption & BUFOPTION_MATCHAN) ? matNum * sizeof(ResChanData) : 0; u32 resGenModeSize = (bufferOption & BUFOPTION_GENMODE) ? matNum * sizeof(ResGenModeData) : 0; u32 resMatMiscSize = (bufferOption & BUFOPTION_MATMISC) ? matNum * sizeof(ResMatMiscData) : 0; u32 visSize = (bufferOption & BUFOPTION_VIS) ? nodeNum * sizeof(u8) : 0; u32 resPixSize = (bufferOption & BUFOPTION_MATPIX) ? matNum * sizeof(ResPixDL) : 0; u32 resTevColorSize = (bufferOption & BUFOPTION_MATTEVCOLOR) ? matNum * sizeof(ResTevColorDL) : 0; u32 resIndMtxAndScaleSize = (bufferOption & BUFOPTION_MATINDMTXSCALE) ? matNum * sizeof(ResIndMtxAndScaleDL) : 0; u32 resTexCoordGenSize = (bufferOption & BUFOPTION_MATTEXCOORDGEN) ? matNum * sizeof(ResTexCoordGenDL) : 0; u32 resTevSize = (bufferOption & BUFOPTION_TEV) ? matNum * sizeof(ResTevData) : 0; // clang-format on u32 vtxPosTableSize = 0; u32 vtxPosBufferSize = 0; if (bufferOption & BUFOPTION_VTXPOS) { u32 vtxPosNum = mdl.GetResVtxPosNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); vtxPosTableSize = vtxPosNum * sizeof(ResVtxPosData *); for (u32 i = 0; i < vtxPosNum; i++) { u32 j; ResVtxPos pos = mdl.GetResVtxPos(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (pos.ptr() == shp.GetResVtxPos().ptr()) { break; } } if (j != shpNum) { vtxPosBufferSize += align32(pos.GetSize()); } } } u32 vtxNrmTableSize = 0; u32 vtxNrmBufferSize = 0; if (bufferOption & BUFOPTION_VTXNRM) { u32 vtxNrmNum = mdl.GetResVtxNrmNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); vtxNrmTableSize = vtxNrmNum * sizeof(ResVtxNrmData *); for (u32 i = 0; i < vtxNrmNum; i++) { u32 j; ResVtxNrm nrm = mdl.GetResVtxNrm(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (nrm.ptr() == shp.GetResVtxNrm().ptr()) { break; } } if (j != shpNum) { vtxNrmBufferSize += align32(nrm.GetSize()); } } } u32 vtxClrTableSize = 0; u32 vtxClrBufferSize = 0; if (bufferOption & BUFOPTION_VTXCLR) { u32 vtxClrNum = mdl.GetResVtxClrNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); vtxClrTableSize = vtxClrNum * sizeof(ResVtxClrData *); for (u32 i = 0; i < vtxClrNum; i++) { u32 j; ResVtxClr clr = mdl.GetResVtxClr(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (clr.ptr() == shp.GetResVtxClr(0).ptr() || clr.ptr() == shp.GetResVtxClr(1).ptr()) { break; } } if (j != shpNum) { vtxClrBufferSize += align32(clr.GetSize()); } } } // clang-format off u32 worldMtxArrayOfs = align32(scnMdlSize); u32 worldMtxAttribArrayOfs = align32(worldMtxArrayOfs + worldMtxArraySize); u32 viewPosMtxArrayOfs = align32(worldMtxAttribArrayOfs + worldMtxAttribArraySize); u32 viewNrmMtxArrayOfs = align32(viewPosMtxArrayOfs + viewPosMtxArraySize); u32 viewTexMtxArrayOfs = align32(viewNrmMtxArrayOfs + viewNrmMtxArraySize); u32 matBufferDirtyFlagOfs = align4(viewTexMtxArrayOfs + viewTexMtxArraySize); u32 resTexObjOfs = align32(matBufferDirtyFlagOfs + matBufferDirtyFlagSize); u32 resTlutObjOfs = align4(resTexObjOfs + resTexObjSize); u32 resTexSrtOfs = align4(resTlutObjOfs + resTlutObjSize); u32 resChanOfs = align4(resTexSrtOfs + resTexSrtSize); u32 resGenModeOfs = align4(resChanOfs + resChanSize); u32 resMatMiscOfs = align4(resGenModeOfs + resGenModeSize); u32 visOfs = align4(resMatMiscOfs + resMatMiscSize); u32 resPixOfs = align32(visOfs + visSize); u32 resTevColorOfs = align32(resPixOfs + resPixSize); u32 resIndMtxAndScaleOfs = align32(resTevColorOfs + resTevColorSize); u32 resTexCoordGenOfs = align32(resIndMtxAndScaleOfs + resIndMtxAndScaleSize); u32 resTevOfs = align32(resTexCoordGenOfs + resTexCoordGenSize); // clang-format on u32 vtxPosTableOfs = align32(resTevOfs + resTevSize); u32 vtxNrmTableOfs = vtxPosTableOfs + vtxPosTableSize; u32 vtxClrTableOfs = vtxNrmTableOfs + vtxNrmTableSize; u32 vtxPosBufferOfs = align32(vtxClrTableOfs + vtxClrTableSize); u32 vtxNrmBufferOfs = align32(vtxPosBufferOfs + vtxPosBufferSize); u32 vtxClrBufferOfs = align32(vtxNrmBufferOfs + vtxNrmBufferSize); u32 size = align32(vtxClrBufferOfs + vtxClrBufferSize); if (pSize != NULL) { *pSize = size; } if (pAllocator != NULL) { u8 *pBuffer = reinterpret_cast(Alloc(pAllocator, size)); if (pBuffer == NULL) { return NULL; } DrawResMdlReplacement replacement; replacement.flag = 0; if (!(bufferOption & BUFOPTION_0x1000000)) { replacement.flag |= 1; } // clang-format off replacement.visArray = visSize != 0 ? reinterpret_cast(pBuffer + visOfs) : NULL; replacement.texObjDataArray = resTexObjSize != 0 ? reinterpret_cast(pBuffer + resTexObjOfs) : NULL; replacement.tlutObjDataArray = resTlutObjSize != 0 ? reinterpret_cast(pBuffer + resTlutObjOfs) : NULL; replacement.texSrtDataArray = resTexSrtSize != 0 ? reinterpret_cast(pBuffer + resTexSrtOfs) : NULL; replacement.chanDataArray = resChanSize != 0 ? reinterpret_cast(pBuffer + resChanOfs) : NULL; replacement.genModeDataArray = resGenModeSize != 0 ? reinterpret_cast(pBuffer + resGenModeOfs) : NULL; replacement.matMiscDataArray = resMatMiscSize != 0 ? reinterpret_cast(pBuffer + resMatMiscOfs) : NULL; replacement.pixDLArray = resPixSize != 0 ? reinterpret_cast(pBuffer + resPixOfs) : NULL; replacement.tevColorDLArray = resTevColorSize != 0 ? reinterpret_cast(pBuffer + resTevColorOfs) : NULL; replacement.indMtxAndScaleDLArray = resIndMtxAndScaleSize != 0 ? reinterpret_cast(pBuffer + resIndMtxAndScaleOfs) : NULL; replacement.texCoordGenDLArray = resTexCoordGenSize != 0 ? reinterpret_cast(pBuffer + resTexCoordGenOfs) : NULL; replacement.tevDataArray = resTevSize != 0 ? reinterpret_cast(pBuffer + resTevOfs) : NULL; replacement.vtxPosTable = vtxPosTableSize != 0 ? reinterpret_cast(pBuffer + vtxPosTableOfs) : NULL; replacement.vtxNrmTable = vtxNrmTableSize != 0 ? reinterpret_cast(pBuffer + vtxNrmTableOfs) : NULL; replacement.vtxClrTable = vtxClrTableSize != 0 ? reinterpret_cast(pBuffer + vtxClrTableOfs) : NULL; // clang-format on if (replacement.vtxPosTable != NULL) { u32 vtxPosNum = mdl.GetResVtxPosNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); u32 ofs = vtxPosBufferOfs; for (u32 i = 0; i < vtxPosNum; i++) { u32 j; ResVtxPos pos = mdl.GetResVtxPos(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (pos.ptr() == shp.GetResVtxPos().ptr()) { break; } } if (j != shpNum) { replacement.vtxPosTable[i] = reinterpret_cast(pBuffer + ofs); ofs += align32(pos.GetSize()); pos.CopyTo(replacement.vtxPosTable[i]); } else { replacement.vtxPosTable[i] = pos.ptr(); } } } if (replacement.vtxNrmTable != NULL) { u32 vtxNrmNum = mdl.GetResVtxNrmNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); u32 ofs = vtxNrmBufferOfs; for (u32 i = 0; i < vtxNrmNum; i++) { u32 j; ResVtxNrm nrm = mdl.GetResVtxNrm(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (nrm.ptr() == shp.GetResVtxNrm().ptr()) { break; } } if (j != shpNum) { replacement.vtxNrmTable[i] = reinterpret_cast(pBuffer + ofs); ofs += align32(nrm.GetSize()); nrm.CopyTo(replacement.vtxNrmTable[i]); } else { replacement.vtxNrmTable[i] = nrm.ptr(); } } } if (replacement.vtxClrTable != NULL) { u32 vtxClrNum = mdl.GetResVtxClrNumEntries(); u32 shpNum = mdl.GetResShpNumEntries(); u32 ofs = vtxClrBufferOfs; for (u32 i = 0; i < vtxClrNum; i++) { u32 j; ResVtxClr clr = mdl.GetResVtxClr(i); for (j = 0; j < shpNum; j++) { ResShp shp = mdl.GetResShp(j); if (clr.ptr() == shp.GetResVtxClr(0).ptr() || clr.ptr() == shp.GetResVtxClr(1).ptr()) { break; } } if (j != shpNum) { replacement.vtxClrTable[i] = reinterpret_cast(pBuffer + ofs); ofs += align32(clr.GetSize()); clr.CopyTo(replacement.vtxClrTable[i]); } else { replacement.vtxClrTable[i] = clr.ptr(); } } } u32 replacementFlag = 0; if (bufferOption & BUFOPTION_0x1000000) { replacementFlag |= 1; } // clang-format off pScnMdl = new (pBuffer) ScnMdl( pAllocator, mdl, reinterpret_cast(pBuffer + worldMtxArrayOfs), reinterpret_cast(pBuffer + worldMtxAttribArrayOfs), reinterpret_cast(pBuffer + viewPosMtxArrayOfs), viewNrmMtxArraySize != 0 ? reinterpret_cast(pBuffer + viewNrmMtxArrayOfs) : NULL, viewTexMtxArraySize != 0 ? reinterpret_cast(pBuffer + viewTexMtxArrayOfs) : NULL, numView, viewMtxNum, &replacement, reinterpret_cast(pBuffer + matBufferDirtyFlagOfs), replacementFlag); // clang-format off pScnMdl->InitBuffer(); } return pScnMdl; } void ScnMdl::ScnMdl_G3DPROC_CALC_WORLD(u32 param, const math::MTX34* pParent) { ScnMdlSmpl_CalcPosture(param, pParent); if (IsVisBufferRefreshNeeded() && IsVisBufferDirty()) { CleanVisBuffer(); } if (GetAnmObjVis() != NULL) { if (mReplacement.visArray != NULL) { ApplyVisAnmResult(mReplacement.visArray, GetResMdl(), GetAnmObjVis()); VisBufferDirty(); } else { ApplyVisAnmResult(GetResMdl(), GetAnmObjVis()); } } CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param, const_cast(pParent)); } void ScnMdl::ScnMdl_G3DPROC_CALC_MAT(u32 param, void* pInfo) { CheckCallback_CALC_MAT(CALLBACK_TIMING_A, param, pInfo); ResMdl mdl = GetResMdl(); u32 matNum = mdl.GetResMatNumEntries(); for (u32 i = 0; i < matNum; i++) { ResMat mat = mdl.GetResMat(i); if (IsMatBufferDirty(i, BUFOPTION_TEXOBJ)) { CleanMatBuffer(i, BUFOPTION_TEXOBJ); } if (IsMatBufferDirty(i, BUFOPTION_TLUTOBJ)) { CleanMatBuffer(i, BUFOPTION_TLUTOBJ); } if (IsMatBufferDirty(i, BUFOPTION_MATINDMTXSCALE)) { CleanMatBuffer(i, BUFOPTION_MATINDMTXSCALE); } if (IsMatBufferDirty(i, BUFOPTION_TEXSRT)) { CleanMatBuffer(i, BUFOPTION_TEXSRT); } if (IsMatBufferDirty(i, BUFOPTION_MATCHAN)) { CleanMatBuffer(i, BUFOPTION_MATCHAN); } if (IsMatBufferDirty(i, BUFOPTION_MATTEVCOLOR)) { CleanMatBuffer(i, BUFOPTION_MATTEVCOLOR); } if (IsMatBufferDirty(i, BUFOPTION_GENMODE)) { CleanMatBuffer(i, BUFOPTION_GENMODE); } if (IsMatBufferDirty(i, BUFOPTION_MATMISC)) { CleanMatBuffer(i, BUFOPTION_MATMISC); } if (IsMatBufferDirty(i, BUFOPTION_MATPIX)) { CleanMatBuffer(i, BUFOPTION_MATPIX); } if (IsMatBufferDirty(i, BUFOPTION_MATTEXCOORDGEN)) { CleanMatBuffer(i, BUFOPTION_MATTEXCOORDGEN); } if (IsMatBufferDirty(i, BUFOPTION_TEV)) { CleanMatBuffer(i, BUFOPTION_TEV); } if (GetAnmObjTexPat() != NULL && GetAnmObjTexPat()->TestExistence(i)) { TexPatAnmResult resultBuf; const TexPatAnmResult* pResult = GetAnmObjTexPat()->GetResult(&resultBuf, i); ResTexObj texObj = mReplacement.texObjDataArray != NULL ? ResTexObj(&mReplacement.texObjDataArray[i]) : mat.GetResTexObj(); ResTlutObj tlutObj = mReplacement.tlutObjDataArray != NULL ? ResTlutObj(&mReplacement.tlutObjDataArray[i]) : mat.GetResTlutObj(); ApplyTexPatAnmResult(texObj, tlutObj, pResult); texObj.EndEdit(); tlutObj.EndEdit(); MatBufferDirty(i, BUFOPTION_TEXOBJ | BUFOPTION_TLUTOBJ); } if (GetAnmObjTexSrt() != NULL && GetAnmObjTexSrt()->TestExistence(i)) { TexSrtAnmResult resultBuf; const TexSrtAnmResult* pResult = GetAnmObjTexSrt()->GetResult(&resultBuf, i); ResTexSrt srt = mReplacement.texSrtDataArray != NULL ? ResTexSrt(&mReplacement.texSrtDataArray[i]) : mat.GetResTexSrt(); ResMatIndMtxAndScale ind = mReplacement.indMtxAndScaleDLArray != NULL ? ResMatIndMtxAndScale( &mReplacement.indMtxAndScaleDLArray[i]) : mat.GetResMatIndMtxAndScale(); ApplyTexSrtAnmResult(srt, ind, pResult); ind.EndEdit(); srt.EndEdit(); MatBufferDirty(i, BUFOPTION_TEXSRT | BUFOPTION_MATINDMTXSCALE); } if (GetAnmObjMatClr() != NULL && GetAnmObjMatClr()->TestExistence(i)) { ClrAnmResult resultBuf; ResMatTevColor tevColor = mReplacement.tevColorDLArray != NULL ? ResMatTevColor(&mReplacement.tevColorDLArray[i]) : mat.GetResMatTevColor(); ResMatChan chan = mReplacement.chanDataArray != NULL ? ResMatChan(&mReplacement.chanDataArray[i]) : mat.GetResMatChan(); const ClrAnmResult* pResult = GetAnmObjMatClr()->GetResult(&resultBuf, i); ApplyClrAnmResult(chan, tevColor, pResult); chan.EndEdit(); tevColor.EndEdit(); MatBufferDirty(i, BUFOPTION_MATTEVCOLOR | BUFOPTION_MATCHAN); } } CheckCallback_CALC_MAT(CALLBACK_TIMING_C, param, pInfo); } void ScnMdl::ScnMdl_G3DPROC_DRAW_OPA(u32 param, void* pInfo) { CheckCallback_DRAW_OPA(CALLBACK_TIMING_A, param, pInfo); u32 drawMode = pInfo != NULL ? *static_cast(pInfo) : GetDrawMode(); DrawResMdlDirectly(GetResMdl(), GetViewPosMtxArray(), GetViewNrmMtxArray(), GetViewTexMtxArray(), GetByteCodeDrawOpa(), NULL, &mReplacement, drawMode); CheckCallback_DRAW_OPA(CALLBACK_TIMING_C, param, pInfo); } void ScnMdl::ScnMdl_G3DPROC_DRAW_XLU(u32 param, void* pInfo) { CheckCallback_DRAW_XLU(CALLBACK_TIMING_A, param, pInfo); u32 drawMode = pInfo != NULL ? *static_cast(pInfo) : GetDrawMode(); DrawResMdlDirectly(GetResMdl(), GetViewPosMtxArray(), GetViewNrmMtxArray(), GetViewTexMtxArray(), NULL, GetByteCodeDrawXlu(), &mReplacement, drawMode); CheckCallback_DRAW_XLU(CALLBACK_TIMING_C, param, pInfo); } void ScnMdl::ScnMdl_G3DPROC_CALC_VTX(u32 param, void* pInfo) { #pragma unused(param) #pragma unused(pInfo) if (GetAnmObjShp() == NULL) { return; } CalcVtx(GetResMdl(), GetAnmObjShp(), mReplacement.vtxPosTable, mReplacement.vtxNrmTable, mReplacement.vtxClrTable); } void ScnMdl::G3dProc(u32 task, u32 param, void* pInfo) { if (IsG3dProcDisabled(task)) { return; } switch (task) { case G3DPROC_GATHER_SCNOBJ: { ScnMdlSmpl_G3DPROC_GATHER_SCNOBJ(param, static_cast(pInfo)); break; } case G3DPROC_CALC_WORLD: { ScnMdl_G3DPROC_CALC_WORLD(param, static_cast(pInfo)); break; } case G3DPROC_CALC_MAT: { ScnMdl_G3DPROC_CALC_MAT(param, pInfo); break; } case G3DPROC_CALC_VIEW: { ScnMdlSmpl_G3DPROC_CALC_VIEW(param, static_cast(pInfo)); break; } case G3DPROC_DRAW_OPA: { ScnMdl_G3DPROC_DRAW_OPA(param, pInfo); break; } case G3DPROC_DRAW_XLU: { ScnMdl_G3DPROC_DRAW_XLU(param, pInfo); break; } case G3DPROC_UPDATEFRAME: { ScnMdlSmpl_G3DPROC_UPDATEFRAME(param, pInfo); if (mpAnmObjShp != NULL) { mpAnmObjShp->UpdateFrame(); } break; } case G3DPROC_CHILD_DETACHED: { RemoveAnmObj(static_cast(pInfo)); break; } case G3DPROC_CALC_VTX: { ScnMdl_G3DPROC_CALC_VTX(param, pInfo); break; } default: { DefG3dProcScnLeaf(task, param, pInfo); break; } } } bool ScnMdl::SetScnObjOption(u32 option, u32 value) { switch (option) { case OPTION_VISBUFFER_REFRESH_NEEDED: { if (value) { mFlagVisBuffer &= ~VISBUFFER_NOT_REFRESH_NEEDED; } else { mFlagVisBuffer |= VISBUFFER_NOT_REFRESH_NEEDED; } break; } default: { return ScnMdlSimple::SetScnObjOption(option, value); } } return true; } bool ScnMdl::GetScnObjOption(u32 option, u32* pValue) const { if (pValue == NULL) { return false; } switch (option) { case OPTION_VISBUFFER_REFRESH_NEEDED: { *pValue = !(mFlagVisBuffer & VISBUFFER_NOT_REFRESH_NEEDED); break; } default: { return ScnMdlSimple::GetScnObjOption(option, pValue); } } return true; } void ScnMdl::InitBuffer() { ResMdl mdl = GetResMdl(); u32 matNum = mdl.GetResMatNumEntries(); u32 nodeNum = mdl.GetResNodeNumEntries(); u32 i; if (mReplacement.visArray != NULL) { for (i = 0; i < nodeNum; i++) { if (mdl.GetResNode(i).IsVisible()) { mReplacement.visArray[i] = true; } else { mReplacement.visArray[i] = false; } } } for (i = 0; i < matNum; i++) { ResMat mat = mdl.GetResMat(i); mpMatBufferDirtyFlag[i] = 0; if (mReplacement.texObjDataArray != NULL) { mat.GetResTexObj() .CopyTo(&mReplacement.texObjDataArray[i]) .EndEdit(); } if (mReplacement.tlutObjDataArray != NULL) { mat.GetResTlutObj() .CopyTo(&mReplacement.tlutObjDataArray[i]) .EndEdit(); } if (mReplacement.texSrtDataArray != NULL) { mat.GetResTexSrt() .CopyTo(&mReplacement.texSrtDataArray[i]) .EndEdit(); } if (mReplacement.chanDataArray != NULL) { mat.GetResMatChan() .CopyTo(&mReplacement.chanDataArray[i]) .EndEdit(); } if (mReplacement.genModeDataArray != NULL) { mat.GetResGenMode() .CopyTo(&mReplacement.genModeDataArray[i]) .EndEdit(); } if (mReplacement.matMiscDataArray != NULL) { mat.GetResMatMisc() .CopyTo(&mReplacement.matMiscDataArray[i]) .EndEdit(); } if (mReplacement.pixDLArray != NULL) { mat.GetResMatPix().CopyTo(&mReplacement.pixDLArray[i]).EndEdit(); } if (mReplacement.tevColorDLArray != NULL) { mat.GetResMatTevColor() .CopyTo(&mReplacement.tevColorDLArray[i]) .EndEdit(); } if (mReplacement.indMtxAndScaleDLArray != NULL) { mat.GetResMatIndMtxAndScale() .CopyTo(&mReplacement.indMtxAndScaleDLArray[i]) .EndEdit(); } if (mReplacement.texCoordGenDLArray != NULL) { mat.GetResMatTexCoordGen() .CopyTo(&mReplacement.texCoordGenDLArray[i]) .EndEdit(); } if (mReplacement.tevDataArray != NULL) { mat.GetResTev().CopyTo(&mReplacement.tevDataArray[i]).EndEdit(); } } } void ScnMdl::CleanMatBuffer(u32 idx, u32 option) { ResMat mat = GetResMdl().GetResMat(idx); if ((option & BUFOPTION_TEXOBJ) && mReplacement.texObjDataArray != NULL) { mat.GetResTexObj().CopyTo(&mReplacement.texObjDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_TLUTOBJ) && mReplacement.tlutObjDataArray != NULL) { mat.GetResTlutObj().CopyTo(&mReplacement.tlutObjDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_TEXSRT) && mReplacement.texSrtDataArray != NULL) { mat.GetResTexSrt().CopyTo(&mReplacement.texSrtDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_MATCHAN) && mReplacement.chanDataArray != NULL) { mat.GetResMatChan().CopyTo(&mReplacement.chanDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_GENMODE) && mReplacement.genModeDataArray != NULL) { mat.GetResGenMode().CopyTo(&mReplacement.genModeDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_MATMISC) && mReplacement.matMiscDataArray != NULL) { mat.GetResMatMisc().CopyTo(&mReplacement.matMiscDataArray[idx]).EndEdit(); } if ((option & BUFOPTION_MATPIX) && mReplacement.pixDLArray != NULL) { mat.GetResMatPix().CopyTo(&mReplacement.pixDLArray[idx]).EndEdit(); } if ((option & BUFOPTION_MATTEVCOLOR) && mReplacement.tevColorDLArray != NULL) { mat.GetResMatTevColor() .CopyTo(&mReplacement.tevColorDLArray[idx]) .EndEdit(); } if ((option & BUFOPTION_MATINDMTXSCALE) && mReplacement.indMtxAndScaleDLArray != NULL) { mat.GetResMatIndMtxAndScale() .CopyTo(&mReplacement.indMtxAndScaleDLArray[idx]) .EndEdit(); } if ((option & BUFOPTION_MATTEXCOORDGEN) && mReplacement.texCoordGenDLArray != NULL) { mat.GetResMatTexCoordGen() .CopyTo(&mReplacement.texCoordGenDLArray[idx]) .EndEdit(); } if ((option & BUFOPTION_TEV) && mReplacement.tevDataArray != NULL) { mat.GetResTev().CopyTo(&mReplacement.tevDataArray[idx]).EndEdit(); } mpMatBufferDirtyFlag[idx] = mpMatBufferDirtyFlag[idx] & ~option; } void ScnMdl::CleanVisBuffer() { ResMdl mdl = GetResMdl(); u32 nodeNum = mdl.GetResNodeNumEntries(); if (mReplacement.visArray != NULL) { for (u32 i = 0; i < nodeNum; i++) { if (mdl.GetResNode(i).IsVisible()) { mReplacement.visArray[i] = true; } else { mReplacement.visArray[i] = false; } } } mFlagVisBuffer &= ~VISBUFFER_DIRTY; } bool ScnMdl::SetAnmObj(AnmObj* pObj, AnmObjType type) { if (pObj != NULL && pObj->GetParent() == NULL) { if (type == ANMOBJTYPE_SHP || type == ANMOBJTYPE_NOT_SPECIFIED) { AnmObjShp* pShp = DynamicCast(pObj); if (pShp != NULL) { if (!pShp->IsBound()) { return false; } if (mpAnmObjShp != NULL) { RemoveAnmObj(mpAnmObjShp); } mpAnmObjShp = pShp; pShp->G3dProc(G3DPROC_ATTACH_PARENT, 0, this); mReplacement.flag &= ~1; return true; } else { if (type == ANMOBJTYPE_NOT_SPECIFIED) { return ScnMdlSimple::SetAnmObj(pObj, type); } return false; } } else { return ScnMdlSimple::SetAnmObj(pObj, type); } } return false; } bool ScnMdl::RemoveAnmObj(AnmObj* pObj) { if (pObj == NULL) { return NULL; } if (pObj == mpAnmObjShp) { mpAnmObjShp->G3dProc(G3DPROC_DETACH_PARENT, 0, this); mpAnmObjShp = NULL; if (!(mReplacementFlag & 1)) { mReplacement.flag |= 1; return true; } if (mReplacement.vtxPosTable != NULL) { u32 vtxPosNum = GetResMdl().GetResVtxPosNumEntries(); for (u32 i = 0; i < vtxPosNum; i++) { ResVtxPos pos = GetResMdl().GetResVtxPos(i); if (pos.ptr() != mReplacement.vtxPosTable[i]) { pos.CopyTo(mReplacement.vtxPosTable[i]); } } } if (mReplacement.vtxNrmTable != NULL) { u32 vtxNrmNum = GetResMdl().GetResVtxNrmNumEntries(); for (u32 i = 0; i < vtxNrmNum; i++) { ResVtxNrm nrm = GetResMdl().GetResVtxNrm(i); if (nrm.ptr() != mReplacement.vtxNrmTable[i]) { nrm.CopyTo(mReplacement.vtxNrmTable[i]); } } } if (mReplacement.vtxClrTable != NULL) { u32 vtxClrNum = GetResMdl().GetResVtxClrNumEntries(); for (u32 i = 0; i < vtxClrNum; i++) { ResVtxClr clr = GetResMdl().GetResVtxClr(i); if (clr.ptr() != mReplacement.vtxClrTable[i]) { clr.CopyTo(mReplacement.vtxClrTable[i]); } } } return true; } return ScnMdlSimple::RemoveAnmObj(pObj); } AnmObj* ScnMdl::RemoveAnmObj(AnmObjType type) { if (type == ANMOBJTYPE_SHP) { AnmObj* pOld = mpAnmObjShp; RemoveAnmObj(mpAnmObjShp); return pOld; } return ScnMdlSimple::RemoveAnmObj(type); } AnmObj* ScnMdl::GetAnmObj(AnmObjType type) { if (type == ANMOBJTYPE_SHP) { return mpAnmObjShp; } return ScnMdlSimple::GetAnmObj(type); } const AnmObj* ScnMdl::GetAnmObj(AnmObjType type) const { if (type == ANMOBJTYPE_SHP) { return mpAnmObjShp; } return ScnMdlSimple::GetAnmObj(type); } ScnMdl::ScnMdl(MEMAllocator* pAllocator, ResMdl mdl, math::MTX34* pWorldMtxArray, u32* pWorldMtxAttribArray, math::MTX34* pViewPosMtxArray, math::MTX33* pViewNrmMtxArray, math::MTX34* pViewTexMtxArray, int numView, int numViewMtx, DrawResMdlReplacement* pReplacement, u32* pMatBufferDirtyFlag, u32 replacementFlag) : ScnMdlSimple(pAllocator, mdl, pWorldMtxArray, pWorldMtxAttribArray, pViewPosMtxArray, pViewNrmMtxArray, pViewTexMtxArray, numView, numViewMtx), mpAnmObjShp(NULL), mFlagVisBuffer(NULL), mpMatBufferDirtyFlag(pMatBufferDirtyFlag), mReplacement(*pReplacement), mReplacementFlag(replacementFlag) {} ScnMdl::~ScnMdl() { if (mpAnmObjShp != NULL) { RemoveAnmObj(mpAnmObjShp); } } } // namespace g3d } // namespace nw4r