#include "nw4r/g3d.h" // IWYU pragma: export namespace nw4r { namespace g3d { NW4R_G3D_RTTI_DEF(ScnRfl); void ScnRfl::SetLightSetIdx(int idx) { if (idx < 0 || idx > G3DState::NUM_LIGHT_SET - 1) { mIdxLightSet = -1; return; } mIdxLightSet = idx; } void ScnRfl::SetFogIdx(int idx) { // @bug G3DState only allows 32 fog entries if (idx < 0 || idx > 127) { mIdxFog = -1; return; } mIdxFog = idx; } bool ScnRfl::SetExpression(RFLExpression expression) { if (IsCharModelReady()) { RFLSetExpression(&mCharModel, expression); return true; } return false; } bool ScnRfl::GetExpression(RFLExpression *pExpression) { if (pExpression != NULL && IsCharModelReady()) { *pExpression = RFLGetExpression(&mCharModel); return true; } return false; } bool ScnRfl::SetupCharModel(RFLDataSource src, u16 index, RFLMiddleDB *pMiddleDB) { ReleaseCharModel(); mRFLErrCode = RFLInitCharModel(&mCharModel, src, pMiddleDB, index, mpNglBuffer, mResolution, mExpressionFlag); if (mRFLErrCode != RFLErrcode_Success) { return false; } mCharModelReady = TRUE; return true; } void ScnRfl::ReleaseCharModel() { if (IsCharModelReady()) { mCharModelReady = FALSE; } } ScnRfl * ScnRfl::Construct(MEMAllocator *pAllocator, u32 *pSize, RFLResolution resolution, u32 exprFlags, u32 userDataSize) { ScnRfl *pScnRfl = NULL; u32 scnRflSize = sizeof(ScnRfl); u32 nglSize = RFLGetModelBufferSize(resolution, exprFlags); u32 userOffset = align4(scnRflSize); u32 nglOffset = align32(userOffset + userDataSize); u32 size = align32(nglOffset + nglSize); if (pSize != NULL) { *pSize = size; } if (pAllocator != NULL) { u8 *pBuffer = reinterpret_cast(Alloc(pAllocator, size)); if (pBuffer == NULL) { return NULL; } // clang-format off pScnRfl = new (pBuffer) ScnRfl( pAllocator, pBuffer + nglOffset, userDataSize != 0 ? pBuffer + userOffset : NULL, resolution, exprFlags); // clang-format on } return pScnRfl; } void ScnRfl::G3dProc(u32 task, u32 param, void *pInfo) { if (IsG3dProcDisabled(task)) { return; } switch (task) { case G3DPROC_GATHER_SCNOBJ: { IScnObjGather *pCollection = static_cast(pInfo); pCollection->Add(this, true, true); break; } case G3DPROC_CALC_WORLD: { CheckCallback_CALC_WORLD(CALLBACK_TIMING_A, param, pInfo); CalcWorldMtx(static_cast(pInfo), ¶m); CheckCallback_CALC_WORLD(CALLBACK_TIMING_B, param, pInfo); CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param, pInfo); break; } case G3DPROC_CALC_VIEW: { CheckCallback_CALC_VIEW(CALLBACK_TIMING_A, param, pInfo); CalcViewMtx(static_cast(pInfo)); CheckCallback_CALC_VIEW(CALLBACK_TIMING_B, param, pInfo); math::MTX34 viewMtx; GetMtx(MTX_VIEW, &viewMtx); RFLSetMtx(&mCharModel, viewMtx); CheckCallback_CALC_VIEW(CALLBACK_TIMING_C, param, pInfo); break; } case G3DPROC_DRAW_OPA: { if (!IsCharModelReady()) { break; } if (mpDrawProc == NULL) { LoadDrawSetting(); RFLDrawOpa(&mCharModel); } else { CallDrawProc(true); } break; } case G3DPROC_DRAW_XLU: { if (!IsCharModelReady()) { break; } if (mpDrawProc == NULL) { LoadDrawSetting(); RFLDrawXlu(&mCharModel); } else { CallDrawProc(false); } break; } default: { DefG3dProcScnLeaf(task, param, pInfo); break; } } } void ScnRfl::CallDrawProc(bool opa) { G3DState::LoadFog(GetFogIdx()); u32 diffMask, specMask; AmbLightObj lobj; G3DState::LoadLightSet(GetLightSetIdx(), &diffMask, &specMask, &lobj); GXColor ambColor; ambColor.r = 0.5f + (lobj.r * mAmbientColor.r) * (1.0f / 255.0f); ambColor.g = 0.5f + (lobj.g * mAmbientColor.g) * (1.0f / 255.0f); ambColor.b = 0.5f + (lobj.b * mAmbientColor.b) * (1.0f / 255.0f); ambColor.a = 0.5f + (lobj.a * mAmbientColor.a) * (1.0f / 255.0f); G3DState::Invalidate(G3DState::INVALIDATE_ALL & ~(G3DState::INVALIDATE_FOG | G3DState::INVALIDATE_LIGHT)); mpDrawProc(this, &mCharModel, diffMask, specMask, ambColor, opa); } void ScnRfl::LoadDrawSetting() { RFLDrawSetting setting; G3DState::LoadFog(GetFogIdx()); u32 diffMask, specMask; AmbLightObj lobj; G3DState::LoadLightSet(GetLightSetIdx(), &diffMask, &specMask, &lobj); setting.lightEnable = GetLightSetIdx() >= 0 ? TRUE : FALSE; setting.lightMask = static_cast(diffMask); setting.diffuse = GetDiffuseFunc(); setting.attn = GetAttnFunc(); setting.compLoc = GXGetZCompLoc(); setting.ambColor.r = 0.5f + ((lobj.r * mAmbientColor.r) * (1.0f / 255.0f)); setting.ambColor.g = 0.5f + ((lobj.g * mAmbientColor.g) * (1.0f / 255.0f)); setting.ambColor.b = 0.5f + ((lobj.b * mAmbientColor.b) * (1.0f / 255.0f)); setting.ambColor.a = 0.5f + ((lobj.a * mAmbientColor.a) * (1.0f / 255.0f)); G3DState::Invalidate(G3DState::INVALIDATE_ALL & ~(G3DState::INVALIDATE_FOG | G3DState::INVALIDATE_LIGHT)); RFLLoadDrawSetting(&setting); } ScnRfl::ScnRfl(MEMAllocator *pAllocator, void *pNglBuffer, void *pUserData, RFLResolution resolution, u32 exprFlag) : ScnLeaf(pAllocator), mResolution(resolution), mExpressionFlag(exprFlag), mIdxLightSet(-1), mIdxFog(-1), mZCompLoc(TRUE), mCharModelReady(FALSE), mDiffuseFn(GX_DF_CLAMP), mAttnFn(GX_AF_SPOT), mpNglBuffer(pNglBuffer), mRFLErrCode(RFLErrcode_Success), mpDrawProc(NULL), mpUserData(pUserData) { mAmbientColor.r = mAmbientColor.g = mAmbientColor.b = 64; mAmbientColor.a = 255; } } // namespace g3d } // namespace nw4r