diff options
| author | robojumper <robojumper@gmail.com> | 2025-03-28 18:42:09 +0100 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2025-03-28 18:42:09 +0100 |
| commit | d35c4adeeffc0629f705518aedd9e8d4b4570364 (patch) | |
| tree | d005df9c3ec37e9bdb48824efc880b830a0a4c1b /src/egg/gfx/eggG3DUtility.cpp | |
| parent | 0766801142a25efcad59e98b77bca43b1c02bae0 (diff) | |
Running out of ideas for G3DUtility
Diffstat (limited to 'src/egg/gfx/eggG3DUtility.cpp')
| -rw-r--r-- | src/egg/gfx/eggG3DUtility.cpp | 378 |
1 files changed, 377 insertions, 1 deletions
diff --git a/src/egg/gfx/eggG3DUtility.cpp b/src/egg/gfx/eggG3DUtility.cpp index b8da6920..a61cefc6 100644 --- a/src/egg/gfx/eggG3DUtility.cpp +++ b/src/egg/gfx/eggG3DUtility.cpp @@ -1,3 +1,379 @@ #include "egg/gfx/eggG3DUtility.h" -namespace EGG {} // namespace EGG +#include "common.h" +#include "egg/core/eggHeap.h" +#include "nw4r/g3d/g3d_light.h" +#include "nw4r/g3d/g3d_state.h" +#include "nw4r/g3d/res/g3d_resanmamblight.h" +#include "nw4r/g3d/res/g3d_resanmlight.h" +#include "nw4r/g3d/res/g3d_resanmscn.h" +#include "nw4r/g3d/res/g3d_reslightset.h" +#include "nw4r/g3d/res/g3d_resmat.h" +#include "nw4r/g3d/res/g3d_resnode.h" +#include "nw4r/g3d/res/g3d_restev.h" +#include "nw4r/math/math_types.h" +#include "rvl/GX/GXTexture.h" +#include "rvl/GX/GXTypes.h" +#include "rvl/MTX/mtx.h" + +#include <cstring> + +namespace EGG { + +void G3DUtility::create(u32 size, Heap *pHeap) { + if (pHeap == nullptr) { + pHeap = Heap::getCurrentHeap(); + } + + if (size != 0) { + sBuf = operator new[](size, pHeap, 0x20); + sSize = size; + } else { + sBuf = nullptr; + sSize = 0; + } + + sOffset = 0; + + nw4r::g3d::G3DState::ScnDependentTexMtxFuncPtr pFunc; + u32 id = 5; + while (true) { + if (nw4r::g3d::G3DState::GetScnDependentTexMtxFunc(id, &pFunc, nullptr) && pFunc == defaultTexMtxFunc) { + break; + } + id++; + if (id >= 256) { + id = 5; + nw4r::g3d::G3DState::ScnDependentTexMtxFuncPtr pFunc2; + while (true) { + if (nw4r::g3d::G3DState::GetScnDependentTexMtxFunc(id, &pFunc2, nullptr) && + pFunc2 == nw4r::g3d::detail::ScnDependentMtxFunc::DefaultMapping) { + sId = id; + nw4r::g3d::G3DState::SetScnDependentTexMtxFunc( + id, defaultTexMtxFunc, nw4r::g3d::G3DState::SCNDEPENDENT_TEXMTX_FUNCTYPE_SRC_POS + ); + break; + } + id++; + if (id >= 256) { + break; + } + } + return; + } + } +} + +void G3DUtility::defaultTexMtxFunc(nw4r::math::MTX34 *pMtx, s8 camRef, s8 lightRef) { + const nw4r::math::MTX34 *mtxPtr = nw4r::g3d::G3DState::GetInvCameraMtxPtr(); + PSMTXCopy(mtxPtr->m, pMtx->m); +} + +bool G3DUtility::setUpLightSet(nw4r::g3d::LightSetting &lightSet, nw4r::g3d::ResAnmScn scn, int refNumber) { + if (!scn.IsValid()) { + return false; + } + + int end = scn.GetResLightSetMaxRefNumber() < lightSet.GetNumLightSet() ? scn.GetResLightSetMaxRefNumber() : + lightSet.GetNumLightSet(); + int start = 0; + if (refNumber >= 0) { + start = refNumber; + end = refNumber + 1; + } + + for (; start < end; start++) { + nw4r::g3d::LightSet set = lightSet.GetLightSet(start); + nw4r::g3d::ResLightSet resSet = scn.GetResLightSetByRefNumber(start); + + if (!set.IsValid()) { + return false; + } + + if (resSet.IsValid()) { + u32 counter = 7; + u32 j = 0; + u32 numLight = resSet.GetNumLight(); + if (numLight != 0) { + for (; j < numLight; j++) { + if (resSet.GetLightID(j) != 0xFFFF) { + nw4r::g3d::ResAnmLight anmLight = scn.GetResAnmLight(resSet.GetLightID(j)); + set.SelectLightObj(j, anmLight.GetRefNumber()); + if (anmLight.HasSpecularLight()) { + set.SelectLightObj(counter--, anmLight.GetSpecularLightIdx()); + } + } else { + set.SelectLightObj(j, -1); + } + } + } + + for (; numLight <= counter; numLight++) { + set.SelectLightObj(numLight, -1); + } + + if (resSet.HasAmbLight()) { + nw4r::g3d::ResAnmAmbLight anmAmbLight = scn.GetResAnmAmbLight(resSet.GetAmbLightID()); + set.SelectAmbLightObj(anmAmbLight.GetRefNumber()); + } else { + set.SelectAmbLightObj(-1); + } + } + } + + return true; +} + +inline bool searchInner( + const char *name, const char *candidate, bool exactMatch, G3DUtility::SearchResult *pResults, int i, int resultIdx, + int maxNumResults +) { + if (name != nullptr) { + bool found; + if (exactMatch) { + found = !std::strcmp(candidate, name); + } else { + found = std::strstr(candidate, name); + } + if (!found) { + goto err; + } + } + + if (resultIdx < maxNumResults) { + pResults[resultIdx].nodeIdx = i; + pResults[resultIdx].name = candidate; + } + return true; + +err: + return false; +} + +int G3DUtility::searchStringResNode( + nw4r::g3d::ResMdl mdl, const char *name, bool exactMatch, SearchResult *pResults, int maxNumResults +) { + u16 resultIdx = 0; + for (int i = 0; i < mdl.GetResNodeNumEntries(); i++) { + nw4r::g3d::ResNode nd = mdl.GetResNode(i); + const char *nodeName = nd.GetName(); + + if (searchInner(name, nodeName, exactMatch, pResults, i, resultIdx, maxNumResults)) { + resultIdx++; + } + } + + return resultIdx; +} + +int G3DUtility::searchStringResMat( + nw4r::g3d::ResMdl mdl, const char *name, bool exactMatch, SearchResult *pResults, int maxNumResults +) { + u16 resultIdx = 0; + for (int i = 0; i < mdl.GetResMatNumEntries(); i++) { + nw4r::g3d::ResMat mat = mdl.GetResMat(i); + const char *nodeName = mat.GetName(); + + if (searchInner(name, nodeName, exactMatch, pResults, i, resultIdx, maxNumResults)) { + resultIdx++; + } + } + + return resultIdx; +} + +int G3DUtility::searchStringResTexPlttInfo( + nw4r::g3d::ResMdl mdl, const char *name, bool exactMatch, SearchResult *pResults, int maxNumResults +) { + u16 resultIdx = 0; + for (u32 i = 0; i < mdl.GetResTexPlttInfoOffsetFromTexNameNumEntries(); i++) { + nw4r::g3d::ResTexPlttInfoOffset info = mdl.GetResTexPlttInfoOffsetFromTexName(i); + for (u16 j = 0; j < info.GetNumData(); j++) { + const char *nodeName = info.GetPllt(j).GetTexName(); + if (searchInner(name, nodeName, exactMatch, pResults, i, resultIdx, maxNumResults)) { + resultIdx++; + } + } + } + + return resultIdx; +} + +u16 G3DUtility::SetTexture( + nw4r::g3d::ResMat resMat, nw4r::g3d::ScnMdl::CopiedMatAccess *matAccess, const char *name, const GXTexObj *texObj, + bool copy, SetTextureResult *pResult, int maxNumResults, int param_8 +) { + if (!resMat.IsValid()) { + return 0; + } + + u16 resultIdx = 0; + for (u16 i = 0; i < resMat.GetNumResTexPlttInfo(); i++) { + nw4r::g3d::ResTexPlttInfo plltInfo = resMat.GetResTexPlttInfo(i); + const char *plltName = plltInfo.GetTexName(); + if (std::strcmp(name, plltName)) { + continue; + } + for (int j = 0; j < 2; j++) { + nw4r::g3d::ResTexObj resTexObj(nullptr); + if (j == 0) { + if ((matAccess == nullptr || param_8 == 1) || + (param_8 == 0 && !matAccess->GetResTexObj(false).IsValid())) { + resTexObj = resMat.GetResTexObj(); + } + } else if (matAccess != nullptr) { + resTexObj = param_8 == 0 ? matAccess->GetResTexObjEx() : matAccess->GetResTexObj(param_8 == 3); + } + + if (resTexObj.IsValid()) { + GXTexObj *obj = resTexObj.GetTexObj(plltInfo.ref().mapID); + if (copy) { + void *pImage; + u16 width; + u16 height; + GXTexFmt format; + GXTexWrapMode wrapS; + GXTexWrapMode wrapT; + u8 mipmap; + GXGetTexObjAll(obj, &pImage, &width, &height, &format, &wrapS, &wrapT, &mipmap); + + GXTexFilter minFilter; + GXTexFilter magFilter; + f32 minLOD; + f32 maxLOD; + f32 LODBias; + u8 biasClampEnable; + u8 edgeLODEnable; + GXAnisotropy anisotropy; + GXGetTexObjLODAll( + obj, &minFilter, &magFilter, &minLOD, &maxLOD, &LODBias, &biasClampEnable, &edgeLODEnable, + &anisotropy + ); + + *obj = *texObj; + GXInitTexObjFilter(obj, minFilter, magFilter); + GXInitTexObjWrapMode(obj, wrapS, wrapT); + } else { + *obj = *texObj; + } + } + } + + if (pResult != nullptr && resultIdx < maxNumResults) { + pResult[resultIdx].texCoordId = -1; + pResult[resultIdx].texMapId = -1; + + nw4r::g3d::ResTev resTev = resMat.GetResTev(); + for (u8 stage = 0; stage < resTev.GetNumTevStages(); stage++) { + GXTexCoordID coord; + GXTexMapID map; + if (resTev.GXGetTevOrder(static_cast<GXTevStageID>(stage), &coord, &map, nullptr) && + map == plltInfo.ref().mapID) { + pResult[resultIdx].texMapId = map; + pResult[resultIdx].texCoordId = coord; + } + } + } + resultIdx++; + } + + return resultIdx; +} + +int G3DUtility::ApplyLightMat(nw4r::g3d::ResMdl mdl, const char *prefix) { + GXTexCoordID matchingLayerCoords[8]; + + int prefixLen = std::strlen(prefix); + int result = 0; + + u32 i = 0; + u32 numMats = mdl.GetResMatNumEntries(); + if (numMats != 0) { + for (; i < numMats; i++) { + int numMatchingLayers = 0; + nw4r::g3d::ResMat mat = mdl.GetResMat(i); + if (mat.GetResGenMode().GXGetNumTexGens() >= mat.GetNumResTexPlttInfo()) { + for (u32 j = 0; j < mat.GetNumResTexPlttInfo(); j++) { + const char *texName = mat.GetResTexPlttInfo(j).GetTexName(); + bool prefixMatch = true; + int rem = prefixLen; + for (int i = 0; i < prefixLen; i++) { + if (prefix[i] != texName[i]) { + prefixMatch = false; + break; + } + } + if (prefixMatch) { + matchingLayerCoords[numMatchingLayers++] = static_cast<GXTexCoordID>(j); + } + } + + if (numMatchingLayers > 1) { + nw4r::g3d::ResGenMode genMode = mat.GetResGenMode(); + int numTexGens = genMode.GXGetNumTexGens(); + nw4r::g3d::ResMatTexCoordGen resMatTexCoordGen = mat.GetResMatTexCoordGen(); + nw4r::g3d::ResTexSrt resTexSrt = mat.GetResTexSrt(); + nw4r::g3d::ResTev resTev = mat.GetResTev(); + GXTexGenType texGenType; + GXTexGenSrc param; + GXBool normalize; + u32 postMtx; + resMatTexCoordGen.GXGetTexCoordGen2( + matchingLayerCoords[0], &texGenType, ¶m, &normalize, &postMtx + ); + numMatchingLayers--; + for (; numMatchingLayers > 0; numMatchingLayers--) { + GXTexCoordID idx = matchingLayerCoords[numMatchingLayers]; + if (idx == numTexGens - 1) { + u32 numStages = resTev.GetNumTevStages(); + for (u32 stage = 0; stage < numStages; stage++) { + GXTexCoordID coord; + GXTexMapID map; + GXChannelID channel; + if (resTev.GXGetTevOrder(static_cast<GXTevStageID>(stage), &coord, &map, &channel) && + coord == idx) { + resTev.GXSetTevOrder( + static_cast<GXTevStageID>(stage), + matchingLayerCoords[0], map, channel + ); + } + } + + int stage = 0; + int nInds = genMode.GXGetNumIndStages(); + for (; stage < nInds; stage++) { + GXTexCoordID coord; + GXTexMapID map; + if (resTev.GXGetIndTexOrder(static_cast<GXIndTexStageID>(stage), &coord, &map) && + coord == idx) { + resTev.GXSetIndTexOrder( + static_cast<GXIndTexStageID>(stage), + static_cast<GXTexCoordID>(matchingLayerCoords[0]), map + ); + } + } + resMatTexCoordGen.Disable(idx); + result++; + resTexSrt.Disable(idx); + numTexGens--; + } + } + resMatTexCoordGen.DCStore(false); + resTev.DCStore(false); + genMode.GXSetNumTexGens(numTexGens); + } + } + } + } + + return result; +} + +void *G3DUtility::BumpAlloc(u32 size, u32 align) { + u32 next = sOffset % align != 0 ? sOffset + (align - sOffset % align) : sOffset; + sOffset = next + size; + // REGSWAP + return reinterpret_cast<u8 *>(sBuf) + next; +} + +} // namespace EGG |
