mirror of https://github.com/AxioDL/metaforce.git
More CCubeModel/CCubeMaterial
This commit is contained in:
parent
832eb180bd
commit
586268c66f
|
@ -0,0 +1,429 @@
|
||||||
|
#include "Graphics/CCubeMaterial.hpp"
|
||||||
|
|
||||||
|
#include "GameGlobalObjects.hpp"
|
||||||
|
#include "Graphics/CCubeModel.hpp"
|
||||||
|
#include "Graphics/CCubeRenderer.hpp"
|
||||||
|
#include "Graphics/CCubeSurface.hpp"
|
||||||
|
#include "Graphics/CModel.hpp"
|
||||||
|
|
||||||
|
namespace metaforce {
|
||||||
|
static u32 sReflectionType = 0;
|
||||||
|
static u32 sLastMaterialUnique = UINT32_MAX;
|
||||||
|
static const u8* sLastMaterialCached = nullptr;
|
||||||
|
static const CCubeModel* sLastModelCached = nullptr;
|
||||||
|
static const CCubeModel* sRenderingModel = nullptr;
|
||||||
|
static float sReflectionAlpha = 0.f;
|
||||||
|
|
||||||
|
void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& surface, CCubeModel& model) {
|
||||||
|
if (sLastMaterialCached == x0_data) {
|
||||||
|
if (sReflectionType == 1) {
|
||||||
|
if (sLastModelCached == sRenderingModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (sReflectionType != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CCubeModel::sRenderModelBlack) {
|
||||||
|
SetCurrentBlack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sRenderingModel = &model;
|
||||||
|
sLastMaterialCached = x0_data;
|
||||||
|
|
||||||
|
u32 numIndStages = 0;
|
||||||
|
const auto matFlags = GetFlags();
|
||||||
|
const u8* materialDataCur = x0_data;
|
||||||
|
|
||||||
|
const bool reflection = bool(
|
||||||
|
matFlags & (Flags(CCubeMaterialFlagBits::fSamusReflection) | CCubeMaterialFlagBits::fSamusReflectionSurfaceEye));
|
||||||
|
if (reflection) {
|
||||||
|
if (!(matFlags & CCubeMaterialFlagBits::fSamusReflectionSurfaceEye)) {
|
||||||
|
EnsureViewDepStateCached(nullptr);
|
||||||
|
} else {
|
||||||
|
EnsureViewDepStateCached(&surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 texCount = SBig(*reinterpret_cast<const u32*>(materialDataCur + 4));
|
||||||
|
if ((flags.x2_flags & 4) != 0) { // render without texture lock
|
||||||
|
materialDataCur += (2 + texCount) * 4;
|
||||||
|
} else {
|
||||||
|
materialDataCur += 8;
|
||||||
|
for (u32 i = 0; i < texCount; ++i) {
|
||||||
|
u32 texIdx = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
sRenderingModel->GetTexture(texIdx)->Load(i, CTexture::EClampMode::One);
|
||||||
|
materialDataCur += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto groupIdx = SBig(*reinterpret_cast<const u32*>(materialDataCur + 4));
|
||||||
|
if (sLastMaterialUnique != UINT32_MAX && sLastMaterialUnique == groupIdx && sReflectionType == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sLastMaterialUnique = groupIdx;
|
||||||
|
|
||||||
|
CCubeMaterialVatFlags vatFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
// SetVtxDescv_Compressed(vatFlags);
|
||||||
|
materialDataCur += 8;
|
||||||
|
|
||||||
|
bool packedLightMaps = matFlags.IsSet(CCubeMaterialFlagBits::fLightmapUvArray);
|
||||||
|
if (packedLightMaps != CCubeModel::sUsingPackedLightmaps) {
|
||||||
|
model.SetUsingPackedLightmaps(packedLightMaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 finalKColorCount = 0;
|
||||||
|
if (matFlags & CCubeMaterialFlagBits::fKonstValues) {
|
||||||
|
u32 konstCount = *reinterpret_cast<const u32*>(materialDataCur);
|
||||||
|
finalKColorCount = konstCount;
|
||||||
|
materialDataCur += 4;
|
||||||
|
for (u32 i = 0; i < konstCount; ++i) {
|
||||||
|
u32 kColor = *reinterpret_cast<const u32*>(materialDataCur);
|
||||||
|
materialDataCur += 4;
|
||||||
|
// TODO set KColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 blendFactors = *reinterpret_cast<const u32*>(materialDataCur);
|
||||||
|
materialDataCur += 4;
|
||||||
|
if (g_Renderer->IsInAreaDraw()) {
|
||||||
|
// TODO blackout fog, additive blend
|
||||||
|
} else {
|
||||||
|
SetupBlendMode(blendFactors, flags, matFlags.IsSet(CCubeMaterialFlagBits::fAlphaTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool indTex = matFlags.IsSet(CCubeMaterialFlagBits::fSamusReflectionIndirectTexture);
|
||||||
|
u32 indTexSlot = 0;
|
||||||
|
if (indTex) {
|
||||||
|
indTexSlot = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
materialDataCur += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleDepth(flags.x2_flags, matFlags);
|
||||||
|
|
||||||
|
u32 chanCount = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
materialDataCur += 4;
|
||||||
|
u32 firstChan = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
materialDataCur += 4 * chanCount;
|
||||||
|
u32 finalNumColorChans = HandleColorChannels(chanCount, firstChan);
|
||||||
|
|
||||||
|
u32 firstTev = 0;
|
||||||
|
if (CCubeModel::sRenderModelShadow)
|
||||||
|
firstTev = 2;
|
||||||
|
|
||||||
|
u32 matTevCount = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||||
|
materialDataCur += 4;
|
||||||
|
u32 finalTevCount = matTevCount;
|
||||||
|
|
||||||
|
const u32* texMapTexCoordFlags = reinterpret_cast<const u32*>(materialDataCur + matTevCount * 20);
|
||||||
|
const u32* tcgs = reinterpret_cast<const u32*>(texMapTexCoordFlags + matTevCount);
|
||||||
|
bool usesTevReg2 = false;
|
||||||
|
|
||||||
|
u32 finalCCFlags = 0;
|
||||||
|
u32 finalACFlags = 0;
|
||||||
|
|
||||||
|
if (g_Renderer->IsThermalVisorActive()) {
|
||||||
|
finalTevCount = firstTev + 1;
|
||||||
|
u32 ccFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 8));
|
||||||
|
finalCCFlags = ccFlags;
|
||||||
|
u32 outputReg = ccFlags >> 9 & 0x3;
|
||||||
|
if (outputReg == 1) { // TevReg0
|
||||||
|
materialDataCur += 20;
|
||||||
|
texMapTexCoordFlags += 1;
|
||||||
|
finalCCFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 8));
|
||||||
|
// Set TevReg0 = 0xc0c0c0c0
|
||||||
|
}
|
||||||
|
finalACFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 12));
|
||||||
|
HandleTev(firstTev, materialDataCur, texMapTexCoordFlags, CCubeModel::sRenderModelShadow);
|
||||||
|
usesTevReg2 = false;
|
||||||
|
} else {
|
||||||
|
finalTevCount = firstTev + matTevCount;
|
||||||
|
for (u32 i = firstTev; i < finalTevCount; ++i) {
|
||||||
|
HandleTev(i, materialDataCur, texMapTexCoordFlags, CCubeModel::sRenderModelShadow && i == firstTev);
|
||||||
|
u32 ccFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 8));
|
||||||
|
finalCCFlags = ccFlags;
|
||||||
|
finalACFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 12));
|
||||||
|
u32 outputReg = ccFlags >> 9 & 0x3;
|
||||||
|
if (outputReg == 3) { // TevReg2
|
||||||
|
usesTevReg2 = true;
|
||||||
|
}
|
||||||
|
materialDataCur += 20;
|
||||||
|
texMapTexCoordFlags += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 tcgCount = 0;
|
||||||
|
if (g_Renderer->IsThermalVisorActive()) {
|
||||||
|
u32 fullTcgCount = SBig(*tcgs);
|
||||||
|
tcgCount = std::min(fullTcgCount, 2u);
|
||||||
|
for (u32 i = 0; i < tcgCount; ++i) {
|
||||||
|
// TODO set TCG
|
||||||
|
}
|
||||||
|
tcgs += fullTcgCount + 1;
|
||||||
|
} else {
|
||||||
|
tcgCount = SBig(*tcgs);
|
||||||
|
for (u32 i = 0; i < tcgCount; ++i) {
|
||||||
|
// TODO set TCG
|
||||||
|
}
|
||||||
|
tcgs += tcgCount + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32* uvAnim = tcgs;
|
||||||
|
u32 animCount = uvAnim[1];
|
||||||
|
uvAnim += 2;
|
||||||
|
u32 texMtx = 30;
|
||||||
|
u32 pttTexMtx = 64;
|
||||||
|
for (u32 i = 0; i < animCount; ++i) {
|
||||||
|
u32 size = HandleAnimatedUV(uvAnim, texMtx, pttTexMtx);
|
||||||
|
if (size == 0)
|
||||||
|
break;
|
||||||
|
uvAnim += size;
|
||||||
|
texMtx += 3;
|
||||||
|
pttTexMtx += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.x0_blendMode != 0) {
|
||||||
|
HandleTransparency(finalTevCount, finalKColorCount, flags, blendFactors, finalCCFlags, finalACFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reflection) {
|
||||||
|
if (sReflectionAlpha > 0.f) {
|
||||||
|
u32 additionalTevs = 0;
|
||||||
|
if (indTex) {
|
||||||
|
additionalTevs = HandleReflection(usesTevReg2, indTexSlot, 0, finalTevCount, texCount, tcgCount,
|
||||||
|
finalKColorCount, finalCCFlags, finalACFlags);
|
||||||
|
numIndStages = 1;
|
||||||
|
tcgCount += 2;
|
||||||
|
} else {
|
||||||
|
additionalTevs = HandleReflection(usesTevReg2, 255, 0, finalTevCount, texCount, tcgCount, finalKColorCount,
|
||||||
|
finalCCFlags, finalACFlags);
|
||||||
|
tcgCount += 1;
|
||||||
|
}
|
||||||
|
texCount += 1;
|
||||||
|
finalTevCount += additionalTevs;
|
||||||
|
finalKColorCount += 1;
|
||||||
|
} else if (((finalCCFlags >> 9) & 0x3) != 0) {
|
||||||
|
DoPassthru(finalTevCount);
|
||||||
|
finalTevCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CCubeModel::sRenderModelShadow) {
|
||||||
|
DoModelShadow(texCount, tcgCount);
|
||||||
|
tcgCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNumIndStages(numIndStages);
|
||||||
|
// SetNumTevStages(finalTevCount);
|
||||||
|
// SetNumTexGens(tcgCount);
|
||||||
|
// SetNumColorChans(finalNumColorChans);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::SetCurrentBlack() {
|
||||||
|
auto flags = GetFlags();
|
||||||
|
auto vatFlags = GetVatFlags();
|
||||||
|
|
||||||
|
if (flags.IsSet(CCubeMaterialFlagBits::fDepthSorting) || flags.IsSet(CCubeMaterialFlagBits::fAlphaTest)) {
|
||||||
|
// set fog mode 0x21
|
||||||
|
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, ERglBlendFactor::Zero, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||||
|
} else {
|
||||||
|
// set fog mode 5
|
||||||
|
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::Zero, ERglLogicOp::Clear);
|
||||||
|
}
|
||||||
|
// set vtx desc flags
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::SetupBlendMode(u32 blendFactors, const CModelFlags& flags, bool alphaTest) {
|
||||||
|
auto newSrcFactor = static_cast<ERglBlendFactor>(blendFactors & 0xffff);
|
||||||
|
auto newDstFactor = static_cast<ERglBlendFactor>(blendFactors >> 16 & 0xffff);
|
||||||
|
if (alphaTest) {
|
||||||
|
// discard fragments with alpha < 0.25
|
||||||
|
aurora::gfx::set_alpha_discard(true);
|
||||||
|
newSrcFactor = ERglBlendFactor::One;
|
||||||
|
newDstFactor = ERglBlendFactor::Zero;
|
||||||
|
} else {
|
||||||
|
aurora::gfx::set_alpha_discard(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.x0_blendMode > 4 && newSrcFactor == ERglBlendFactor::One) {
|
||||||
|
newSrcFactor = ERglBlendFactor::SrcAlpha;
|
||||||
|
if (newDstFactor == ERglBlendFactor::Zero) {
|
||||||
|
newDstFactor = flags.x0_blendMode > 6 ? ERglBlendFactor::One : ERglBlendFactor::InvSrcAlpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO set fog color zero if dst blend zero
|
||||||
|
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, newSrcFactor, newDstFactor, ERglLogicOp::Clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::HandleDepth(u16 modelFlags, CCubeMaterialFlags matFlags) {
|
||||||
|
ERglEnum func = ERglEnum::Never;
|
||||||
|
if ((modelFlags & 0x1) == 0) {
|
||||||
|
func = ERglEnum::Always;
|
||||||
|
} else if ((modelFlags & 0x8) != 0) {
|
||||||
|
func = (modelFlags & 0x10) != 0 ? ERglEnum::Greater : ERglEnum::GEqual;
|
||||||
|
} else {
|
||||||
|
func = (modelFlags & 0x10) != 0 ? ERglEnum::Less : ERglEnum::LEqual;
|
||||||
|
}
|
||||||
|
bool depthWrite = (modelFlags & 0x2) != 0 && matFlags & CCubeMaterialFlagBits::fDepthWrite;
|
||||||
|
aurora::gfx::set_depth_mode(func, depthWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::ResetCachedMaterials() {
|
||||||
|
KillCachedViewDepState();
|
||||||
|
sLastMaterialUnique = UINT32_MAX;
|
||||||
|
sRenderingModel = nullptr;
|
||||||
|
sLastMaterialCached = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::KillCachedViewDepState() { sLastModelCached = nullptr; }
|
||||||
|
|
||||||
|
void CCubeMaterial::EnsureViewDepStateCached(const CCubeSurface* surface) {
|
||||||
|
// TODO
|
||||||
|
if ((surface != nullptr || sLastModelCached != sRenderingModel) && sRenderingModel != nullptr) {
|
||||||
|
sLastModelCached = sRenderingModel;
|
||||||
|
if (surface == nullptr) {
|
||||||
|
sReflectionType = 1;
|
||||||
|
} else {
|
||||||
|
sReflectionType = 2;
|
||||||
|
}
|
||||||
|
if (g_Renderer->IsReflectionDirty()) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_Renderer->SetReflectionDirty(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) {
|
||||||
|
if (CCubeModel::sRenderModelShadow) {
|
||||||
|
if (chanCount != 0) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return chanCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::HandleTev(u32 tevCur, const u8* materialDataCur, const u32* texMapTexCoordFlags,
|
||||||
|
bool shadowMapsEnabled) {
|
||||||
|
u32 colorArgs = shadowMapsEnabled ? 0x7a04f : SBig(*materialDataCur);
|
||||||
|
// CGX::SetStandardDirectTev_Compressed
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, u32 texMtx, u32 pttTexMtx) {
|
||||||
|
u32 type = SBig(*uvAnim);
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
case 1:
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
case 2:
|
||||||
|
// TODO
|
||||||
|
return 5;
|
||||||
|
case 3:
|
||||||
|
// TODO
|
||||||
|
return 3;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
// TODO
|
||||||
|
return 5;
|
||||||
|
case 6:
|
||||||
|
// TODO
|
||||||
|
return 1;
|
||||||
|
case 7:
|
||||||
|
// TODO
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount, const CModelFlags& modelFlags,
|
||||||
|
u32 blendFactors, u32& finalCCFlags, u32& finalACFlags) {
|
||||||
|
if (modelFlags.x0_blendMode == 2) {
|
||||||
|
u16 dstFactor = blendFactors >> 16 & 0xffff;
|
||||||
|
if (dstFactor == 1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (modelFlags.x0_blendMode == 3) {
|
||||||
|
// Stage outputting splatted KAlpha as color to reg0
|
||||||
|
// GXSetTevColorIn(finalTevCount, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_KONST);
|
||||||
|
// GXSetTevAlphaIn(finalTevCount, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
|
||||||
|
// GXSetTevColorOp(finalTevCount, 0, 0, 0, 1, 1); // ColorReg0
|
||||||
|
// GXSetTevKColorSel(finalTevCount, finalKColorCount+28);
|
||||||
|
// GXSetTevAlphaOp(finalTevCount, 0, 0, 0, 1, 0); // AlphaRegPrev
|
||||||
|
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||||
|
// GXSetTevDirect(finalTevCount);
|
||||||
|
// Stage interpolating from splatted KAlpha using KColor
|
||||||
|
// GXSetTevColorIn(finalTevCount + 1, TEVCOLORARG_CPREV, TEVCOLORARG_C0, TEVCOLORARG_KONST, TEVCOLORARG_ZERO);
|
||||||
|
// GXSetTevAlphaIn(finalTevCount + 1, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
|
||||||
|
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
|
||||||
|
// SetStandardTevColorAlphaOp(finalTevCount + 1);
|
||||||
|
// GXSetTevDirect(finalTevCount + 1);
|
||||||
|
// GXSetTevOrder(finalTevCount + 1, 255, 255, 255);
|
||||||
|
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
|
||||||
|
finalKColorCount += 1;
|
||||||
|
finalTevCount += 2;
|
||||||
|
} else {
|
||||||
|
// Mul KAlpha
|
||||||
|
u32 tevAlpha = 0x000380C7; // TEVALPHAARG_ZERO, TEVALPHAARG_KONST, TEVALPHAARG_APREV, TEVALPHAARG_ZERO
|
||||||
|
if (modelFlags.x0_blendMode == 8) {
|
||||||
|
// Set KAlpha
|
||||||
|
tevAlpha = 0x00031CE7; // TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_KONST
|
||||||
|
}
|
||||||
|
// Mul KColor
|
||||||
|
u32 tevColor = 0x000781CF; // TEVCOLORARG_ZERO, TEVCOLORARG_KONST, TEVCOLORARG_CPREV, TEVCOLORARG_ZERO
|
||||||
|
if (modelFlags.x0_blendMode == 2) {
|
||||||
|
// Add KColor
|
||||||
|
tevColor = 0x0007018F; // TEVCOLORARG_ZERO, TEVCOLORARG_ONE, TEVCOLORARG_CPREV, TEVCOLORARG_KONST
|
||||||
|
}
|
||||||
|
// GXSetTevColorIn(finalTevCount)
|
||||||
|
// GXSetTevAlphaIn(finalTevCount)
|
||||||
|
// SetStandardTevColorAlphaOp(finalTevCount);
|
||||||
|
finalCCFlags = 0x100; // Just clamp, output prev reg
|
||||||
|
finalACFlags = 0x100;
|
||||||
|
// GXSetTevDirect(finalTevCount);
|
||||||
|
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||||
|
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
|
||||||
|
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
|
||||||
|
// GXSetTevKAlphaSel(finalTevCount, finalKColorCount+28);
|
||||||
|
finalTevCount += 1;
|
||||||
|
finalKColorCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CCubeMaterial::HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount,
|
||||||
|
u32 tcgCount, u32 finalKColorCount, u32& finalCCFlags, u32& finalACFlags) {
|
||||||
|
u32 out = 0;
|
||||||
|
if (usesTevReg2) {
|
||||||
|
// GX_CC_C2
|
||||||
|
out = 1;
|
||||||
|
} else {
|
||||||
|
// GX_CC_KONST
|
||||||
|
}
|
||||||
|
// set reflection kcolor
|
||||||
|
// tex = g_Renderer->GetRealReflection
|
||||||
|
// tex.Load(texCount, 0)
|
||||||
|
|
||||||
|
finalACFlags = 0;
|
||||||
|
finalCCFlags = 0;
|
||||||
|
return out + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::DoPassthru(u32 finalTevCount) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeMaterial::DoModelShadow(u32 texCount, u32 tcgCount) {
|
||||||
|
// CCubeModel::sShadowTexture->Load(texCount, CTexture::EClampMode::One);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
} // namespace metaforce
|
|
@ -9,23 +9,118 @@
|
||||||
#include "IObjectStore.hpp"
|
#include "IObjectStore.hpp"
|
||||||
|
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
enum class EStateFlags {
|
class CCubeModel;
|
||||||
Unused1 = 1 << 0,
|
class CCubeSurface;
|
||||||
Unused2 = 1 << 1,
|
struct CModelFlags;
|
||||||
Unused3 = 1 << 2,
|
|
||||||
KonstEnabled = 1 << 3,
|
template <typename BitType>
|
||||||
DepthSorting = 1 << 4,
|
class Flags {
|
||||||
AlphaTest = 1 << 5,
|
public:
|
||||||
Reflection = 1 << 6,
|
using MaskType = typename std::underlying_type<BitType>::type;
|
||||||
DepthWrite = 1 << 7,
|
|
||||||
ReflectionSurfaceEye = 1 << 8,
|
// constructors
|
||||||
OccluderMesh = 1 << 9,
|
constexpr Flags() noexcept : m_mask(0) {}
|
||||||
ReflectionIndirectTexture = 1 << 10,
|
|
||||||
LightMap = 1 << 11,
|
constexpr Flags(BitType bit) noexcept : m_mask(static_cast<MaskType>(bit)) {}
|
||||||
Unused4 = 1 << 12,
|
|
||||||
LightmapUVArray = 1 << 13,
|
constexpr Flags(Flags<BitType> const& rhs) noexcept : m_mask(rhs.m_mask) {}
|
||||||
|
|
||||||
|
constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr bool IsSet(Flags<BitType> const bit) const noexcept { return bool(*this & bit); }
|
||||||
|
|
||||||
|
// relational operators
|
||||||
|
auto operator<=>(Flags<BitType> const&) const noexcept = default;
|
||||||
|
|
||||||
|
// logical operator
|
||||||
|
constexpr bool operator!() const noexcept { return !m_mask; }
|
||||||
|
|
||||||
|
// bitwise operators
|
||||||
|
constexpr Flags<BitType> operator&(Flags<BitType> const& rhs) const noexcept {
|
||||||
|
return Flags<BitType>(m_mask & rhs.m_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags<BitType> operator|(Flags<BitType> const& rhs) const noexcept {
|
||||||
|
return Flags<BitType>(m_mask | rhs.m_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags<BitType> operator^(Flags<BitType> const& rhs) const noexcept {
|
||||||
|
return Flags<BitType>(m_mask ^ rhs.m_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignment operators
|
||||||
|
constexpr Flags<BitType>& operator=(Flags<BitType> const& rhs) noexcept {
|
||||||
|
m_mask = rhs.m_mask;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags<BitType>& operator|=(Flags<BitType> const& rhs) noexcept {
|
||||||
|
m_mask |= rhs.m_mask;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags<BitType>& operator&=(Flags<BitType> const& rhs) noexcept {
|
||||||
|
m_mask &= rhs.m_mask;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags<BitType>& operator^=(Flags<BitType> const& rhs) noexcept {
|
||||||
|
m_mask ^= rhs.m_mask;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast operators
|
||||||
|
explicit constexpr operator bool() const noexcept { return m_mask != 0; }
|
||||||
|
|
||||||
|
explicit constexpr operator MaskType() const noexcept { return m_mask; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MaskType m_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CCubeMaterialFlagBits : u32 {
|
||||||
|
fKonstValues = 0x8,
|
||||||
|
fDepthSorting = 0x10,
|
||||||
|
fAlphaTest = 0x20,
|
||||||
|
fSamusReflection = 0x40,
|
||||||
|
fDepthWrite = 0x80,
|
||||||
|
fSamusReflectionSurfaceEye = 0x100,
|
||||||
|
fShadowOccluderMesh = 0x200,
|
||||||
|
fSamusReflectionIndirectTexture = 0x400,
|
||||||
|
fLightmap = 0x800,
|
||||||
|
fLightmapUvArray = 0x2000,
|
||||||
|
fTextureSlotMask = 0xffff0000
|
||||||
|
};
|
||||||
|
using CCubeMaterialFlags = Flags<CCubeMaterialFlagBits>;
|
||||||
|
|
||||||
|
enum class CCubeMaterialVatAttribute : u32 {
|
||||||
|
Position = 0,
|
||||||
|
Normal = 2,
|
||||||
|
Color0 = 4,
|
||||||
|
Color1 = 8,
|
||||||
|
Tex0 = 10,
|
||||||
|
Tex1 = 12,
|
||||||
|
Tex2 = 14,
|
||||||
|
Tex3 = 16,
|
||||||
|
Tex4 = 18,
|
||||||
|
Tex5 = 20,
|
||||||
|
Tex6 = 22,
|
||||||
|
};
|
||||||
|
enum class CCubeMaterialVatAttributeType : u32 { None = 0, Direct = 1, Index8 = 2, Index16 = 3 };
|
||||||
|
class CCubeMaterialVatFlags {
|
||||||
|
u32 m_flags = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr CCubeMaterialVatFlags() noexcept = default;
|
||||||
|
constexpr CCubeMaterialVatFlags(u32 flags) noexcept : m_flags(flags){};
|
||||||
|
[[nodiscard]] CCubeMaterialVatAttributeType GetAttributeType(CCubeMaterialVatAttribute attribute) const noexcept {
|
||||||
|
return CCubeMaterialVatAttributeType((m_flags >> u32(attribute)) & 0x3);
|
||||||
|
}
|
||||||
|
void SetAttributeType(CCubeMaterialVatAttribute attribute, CCubeMaterialVatAttributeType type) noexcept {
|
||||||
|
m_flags &= ~(u32(0x3) << u32(attribute));
|
||||||
|
m_flags |= u32(type) << u32(attribute);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ENABLE_BITWISE_ENUM(EStateFlags);
|
|
||||||
|
|
||||||
class CCubeMaterial {
|
class CCubeMaterial {
|
||||||
const u8* x0_data;
|
const u8* x0_data;
|
||||||
|
@ -33,24 +128,44 @@ class CCubeMaterial {
|
||||||
public:
|
public:
|
||||||
explicit CCubeMaterial(const u8* data) : x0_data(data) {}
|
explicit CCubeMaterial(const u8* data) : x0_data(data) {}
|
||||||
|
|
||||||
void SetCurrent(CModelFlags flags, const CCubeSurface& surface, const CCubeModel& model);
|
void SetCurrent(const CModelFlags& flags, const CCubeSurface& surface, CCubeModel& model);
|
||||||
|
|
||||||
[[nodiscard]] u32 GetCompressedBlend() {
|
[[nodiscard]] u32 GetCompressedBlend() {
|
||||||
const u32* ptr = reinterpret_cast<const u32*>(x0_data[(GetTextureCount() * 4) + 16]);
|
const u32* ptr = reinterpret_cast<const u32*>(x0_data + (GetTextureCount() * 4) + 16);
|
||||||
if (IsFlagSet(EStateFlags::KonstEnabled)) {
|
if (GetFlags() & CCubeMaterialFlagBits::fKonstValues) {
|
||||||
ptr += SBig(*ptr) + 1;
|
ptr += SBig(*ptr) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SBig(*ptr);
|
return SBig(*ptr);
|
||||||
}
|
}
|
||||||
[[nodiscard]] EStateFlags GetFlags() const { return EStateFlags(SBig(*reinterpret_cast<const u32*>(x0_data))); }
|
[[nodiscard]] CCubeMaterialFlags GetFlags() const {
|
||||||
[[nodiscard]] bool IsFlagSet(EStateFlags flag) const { return True(GetFlags() & flag); }
|
return CCubeMaterialFlags(SBig(*reinterpret_cast<const u32*>(x0_data)));
|
||||||
|
}
|
||||||
|
[[nodiscard]] CCubeMaterialVatFlags GetVatFlags() const {
|
||||||
|
return SBig(*reinterpret_cast<const u32*>(x0_data + 8 + (GetTextureCount() * 4)));
|
||||||
|
}
|
||||||
[[nodiscard]] u32 GetUsedTextureSlots() const { return static_cast<u32>(GetFlags()) >> 16; }
|
[[nodiscard]] u32 GetUsedTextureSlots() const { return static_cast<u32>(GetFlags()) >> 16; }
|
||||||
[[nodiscard]] u32 GetTextureCount() const { return SBig(*reinterpret_cast<const u32*>(&x0_data[4])); }
|
[[nodiscard]] u32 GetTextureCount() const { return SBig(*reinterpret_cast<const u32*>(x0_data + 4)); }
|
||||||
[[nodiscard]] u32 GetVertexDesc() const {
|
[[nodiscard]] u32 GetVertexDesc() const {
|
||||||
return SBig(*reinterpret_cast<const u32*>(&x0_data[(GetTextureCount() * 4) + 8]));
|
return SBig(*reinterpret_cast<const u32*>(&x0_data + (GetTextureCount() * 4) + 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ResetCachedMaterials();
|
static void ResetCachedMaterials();
|
||||||
|
static void EnsureViewDepStateCached(const CCubeSurface* surface);
|
||||||
|
static void KillCachedViewDepState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetCurrentBlack();
|
||||||
|
|
||||||
|
static void SetupBlendMode(u32 blendFactors, const CModelFlags& flags, bool alphaTest);
|
||||||
|
static void HandleDepth(u16 modelFlags, CCubeMaterialFlags matFlags);
|
||||||
|
static u32 HandleColorChannels(u32 chanCount, u32 firstChan);
|
||||||
|
static void HandleTev(u32 tevCur, const u8* materialDataCur, const u32* texMapTexCoordFlags, bool shadowMapsEnabled);
|
||||||
|
static u32 HandleAnimatedUV(const u32* uvAnim, u32 texMtx, u32 pttTexMtx);
|
||||||
|
static void HandleTransparency(u32& finalTevCount, u32& finalKColorCount, const CModelFlags& modelFlags,
|
||||||
|
u32 blendFactors, u32& finalCCFlags, u32& finalACFlags);
|
||||||
|
static u32 HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount, u32 tcgCount,
|
||||||
|
u32 finalKColorCount, u32& finalCCFlags, u32& finalACFlags);
|
||||||
|
static void DoPassthru(u32 finalTevCount);
|
||||||
|
static void DoModelShadow(u32 texCount, u32 tcgCount);
|
||||||
};
|
};
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -4,8 +4,22 @@
|
||||||
#include "Graphics/CCubeMaterial.hpp"
|
#include "Graphics/CCubeMaterial.hpp"
|
||||||
#include "Graphics/CCubeSurface.hpp"
|
#include "Graphics/CCubeSurface.hpp"
|
||||||
#include "Graphics/CGraphics.hpp"
|
#include "Graphics/CGraphics.hpp"
|
||||||
|
#include "Graphics/CModel.hpp"
|
||||||
|
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
|
bool CCubeModel::sRenderModelBlack = false;
|
||||||
|
bool CCubeModel::sRenderModelShadow = false;
|
||||||
|
bool CCubeModel::sUsingPackedLightmaps = false;
|
||||||
|
const CTexture* CCubeModel::sShadowTexture = nullptr;
|
||||||
|
|
||||||
|
static bool sDrawingOccluders = false;
|
||||||
|
static bool sDrawingWireframe = false;
|
||||||
|
|
||||||
|
static zeus::CTransform sTextureProjectionTransform;
|
||||||
|
static u8 sChannel0DisableLightMask = 0;
|
||||||
|
static u8 sChannel1EnableLightMask = 0;
|
||||||
|
|
||||||
|
static zeus::CVector3f sPlayerPosition;
|
||||||
|
|
||||||
CCubeModel::CCubeModel(std::vector<CCubeSurface>* surfaces, std::vector<TCachedToken<CTexture>>* textures,
|
CCubeModel::CCubeModel(std::vector<CCubeSurface>* surfaces, std::vector<TCachedToken<CTexture>>* textures,
|
||||||
u8* materialData, std::vector<zeus::CVector3f>* positions, std::vector<zeus::CColor>* colors,
|
u8* materialData, std::vector<zeus::CVector3f>* positions, std::vector<zeus::CColor>* colors,
|
||||||
|
@ -24,7 +38,8 @@ CCubeModel::CCubeModel(std::vector<CCubeSurface>* surfaces, std::vector<TCachedT
|
||||||
|
|
||||||
for (u32 i = x0_modelInstance.Surfaces()->size(); i > 0; --i) {
|
for (u32 i = x0_modelInstance.Surfaces()->size(); i > 0; --i) {
|
||||||
auto& surf = (*x0_modelInstance.Surfaces())[i - 1];
|
auto& surf = (*x0_modelInstance.Surfaces())[i - 1];
|
||||||
if (!GetMaterialByIndex(surf.GetMaterialIndex()).IsFlagSet(EStateFlags::DepthSorting)) {
|
const auto matFlags = GetMaterialByIndex(surf.GetMaterialIndex()).GetFlags();
|
||||||
|
if (!matFlags.IsSet(CCubeMaterialFlagBits::fDepthSorting)) {
|
||||||
surf.SetNextSurface(x38_firstUnsortedSurf);
|
surf.SetNextSurface(x38_firstUnsortedSurf);
|
||||||
x38_firstUnsortedSurf = &surf;
|
x38_firstUnsortedSurf = &surf;
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,4 +112,196 @@ void CCubeModel::MakeTexturesFromMats(const u8* ptr, std::vector<TCachedToken<CT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCubeModel::Draw(const CModelFlags& flags) {
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
SetArraysCurrent();
|
||||||
|
DrawSurfaces(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags) {
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
SetSkinningArraysCurrent(positions, normals);
|
||||||
|
DrawSurfaces(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawAlpha(const CModelFlags& flags) {
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
SetArraysCurrent();
|
||||||
|
DrawAlphaSurfaces(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawAlphaSurfaces(const CModelFlags& flags) {
|
||||||
|
if (sDrawingWireframe) {
|
||||||
|
const auto* surface = x3c_firstSortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurfaceWireframe(*surface);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
} else if (TryLockTextures()) {
|
||||||
|
const auto* surface = x3c_firstSortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurface(*surface, flags);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces) {
|
||||||
|
if (positions == nullptr) {
|
||||||
|
SetArraysCurrent();
|
||||||
|
} else {
|
||||||
|
SetSkinningArraysCurrent(positions, normals);
|
||||||
|
}
|
||||||
|
if (surfaces != ESurfaceSelection::Sorted) {
|
||||||
|
const auto* surface = x38_firstUnsortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
const auto mat = GetMaterialByIndex(surface->GetMaterialIndex());
|
||||||
|
// TODO draw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (surfaces != ESurfaceSelection::Unsorted) {
|
||||||
|
const auto* surface = x3c_firstSortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
const auto mat = GetMaterialByIndex(surface->GetMaterialIndex());
|
||||||
|
// TODO draw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces) {
|
||||||
|
// TODO bunch of CGX stuff, what is it doing?
|
||||||
|
DrawFlat(positions, normals, surfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawNormal(const CModelFlags& flags) {
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
SetArraysCurrent();
|
||||||
|
DrawNormalSurfaces(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawNormalSurfaces(const CModelFlags& flags) {
|
||||||
|
if (sDrawingWireframe) {
|
||||||
|
const auto* surface = x38_firstUnsortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurfaceWireframe(*surface);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
} else if (TryLockTextures()) {
|
||||||
|
const auto* surface = x38_firstUnsortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurface(*surface, flags);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawSurface(const CCubeSurface& surface, const CModelFlags& flags) {
|
||||||
|
auto mat = GetMaterialByIndex(surface.GetMaterialIndex());
|
||||||
|
if (!mat.GetFlags().IsSet(CCubeMaterialFlagBits::fShadowOccluderMesh) || sDrawingOccluders) {
|
||||||
|
mat.SetCurrent(flags, surface, *this);
|
||||||
|
// TODO draw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawSurfaces(const CModelFlags& flags) {
|
||||||
|
if (sDrawingWireframe) {
|
||||||
|
const auto* surface = x38_firstUnsortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurfaceWireframe(*surface);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
surface = x3c_firstSortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurfaceWireframe(*surface);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
} else if (TryLockTextures()) {
|
||||||
|
const auto* surface = x38_firstUnsortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurface(*surface, flags);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
surface = x3c_firstSortedSurf;
|
||||||
|
while (surface != nullptr) {
|
||||||
|
DrawSurface(*surface, flags);
|
||||||
|
surface = surface->GetNextSurface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DrawSurfaceWireframe(const CCubeSurface& surface) {
|
||||||
|
auto mat = GetMaterialByIndex(surface.GetMaterialIndex());
|
||||||
|
// TODO convert vertices to line strips and draw
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
|
||||||
|
u8 chan1EnableLightMask) {
|
||||||
|
sRenderModelShadow = true;
|
||||||
|
sShadowTexture = &shadowTex;
|
||||||
|
sTextureProjectionTransform = textureProjXf;
|
||||||
|
sChannel0DisableLightMask = chan0DisableMask;
|
||||||
|
sChannel1EnableLightMask = chan1EnableLightMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::DisableShadowMaps() { sRenderModelShadow = false; }
|
||||||
|
|
||||||
|
void CCubeModel::SetArraysCurrent() {
|
||||||
|
if (x0_modelInstance.GetVertexPointer() != nullptr) {
|
||||||
|
// TODO set vertices active
|
||||||
|
}
|
||||||
|
if (x0_modelInstance.GetNormalPointer() != nullptr) {
|
||||||
|
// TODO set normals active
|
||||||
|
}
|
||||||
|
SetStaticArraysCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::SetDrawingOccluders(bool v) { sDrawingOccluders = v; }
|
||||||
|
|
||||||
|
void CCubeModel::SetModelWireframe(bool v) { sDrawingWireframe = v; }
|
||||||
|
|
||||||
|
void CCubeModel::SetNewPlayerPositionAndTime(const zeus::CVector3f& pos, const CStopwatch& time) {
|
||||||
|
sPlayerPosition = pos;
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
// TODO time
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::SetRenderModelBlack(bool v) {
|
||||||
|
sRenderModelBlack = v;
|
||||||
|
// TODO another value is set here, but always 0?
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals) {
|
||||||
|
// TODO activate vertices, normals & colors
|
||||||
|
SetStaticArraysCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::SetStaticArraysCurrent() {
|
||||||
|
// TODO activate colors
|
||||||
|
const auto* packedTexCoords = x0_modelInstance.GetPackedTCPointer();
|
||||||
|
const auto* texCoords = x0_modelInstance.GetTCPointer();
|
||||||
|
if (packedTexCoords == nullptr) {
|
||||||
|
sUsingPackedLightmaps = false;
|
||||||
|
}
|
||||||
|
if (sUsingPackedLightmaps) {
|
||||||
|
// TODO activate packed TCs for texture 0
|
||||||
|
} else if (texCoords != nullptr) {
|
||||||
|
// TODO activate TCs for texture 0
|
||||||
|
}
|
||||||
|
if (texCoords != nullptr) {
|
||||||
|
for (int i = 1; i < 8; ++i) {
|
||||||
|
// TODO activate TCs for textures 1-7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CCubeMaterial::KillCachedViewDepState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCubeModel::SetUsingPackedLightmaps(bool v) {
|
||||||
|
sUsingPackedLightmaps = v;
|
||||||
|
if (v) {
|
||||||
|
// TODO activate packed TCs for texture 0
|
||||||
|
} else {
|
||||||
|
// TODO activate TCs for texture 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -17,6 +17,7 @@ struct CModelFlags;
|
||||||
enum class ESurfaceSelection {
|
enum class ESurfaceSelection {
|
||||||
Unsorted,
|
Unsorted,
|
||||||
Sorted,
|
Sorted,
|
||||||
|
All,
|
||||||
};
|
};
|
||||||
|
|
||||||
// These parameters were originally float*
|
// These parameters were originally float*
|
||||||
|
@ -81,36 +82,41 @@ public:
|
||||||
bool TryLockTextures();
|
bool TryLockTextures();
|
||||||
void UnlockTextures();
|
void UnlockTextures();
|
||||||
void RemapMaterialData(u8* data, std::vector<TCachedToken<CTexture>>& textures);
|
void RemapMaterialData(u8* data, std::vector<TCachedToken<CTexture>>& textures);
|
||||||
void Draw(CModelFlags flags);
|
void Draw(const CModelFlags& flags);
|
||||||
void DrawAlpha(CModelFlags flags);
|
void DrawAlpha(const CModelFlags& flags);
|
||||||
void DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
void DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
||||||
void DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
void DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
||||||
void DrawNormal(CModelFlags flags);
|
void DrawNormal(const CModelFlags& flags);
|
||||||
void DrawSurface(const CCubeSurface& surface, CModelFlags flags);
|
void DrawSurface(const CCubeSurface& surface, const CModelFlags& flags);
|
||||||
void DrawSurfaceWireframe(const CCubeSurface& surface);
|
void DrawSurfaceWireframe(const CCubeSurface& surface);
|
||||||
void SetArraysCurrent();
|
void SetArraysCurrent();
|
||||||
|
void SetUsingPackedLightmaps(bool v);
|
||||||
|
|
||||||
TVectorRef GetPositions() const { return x0_modelInstance.GetVertexPointer(); }
|
[[nodiscard]] TVectorRef GetPositions() const { return x0_modelInstance.GetVertexPointer(); }
|
||||||
TVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); }
|
[[nodiscard]] TVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); }
|
||||||
|
[[nodiscard]] TCachedToken<CTexture>& GetTexture(u32 idx) const { return x1c_textures->at(idx); }
|
||||||
|
|
||||||
static void EnableShadowMaps(CTexture shadowTex, zeus::CTransform textureProjXf, u8 chan0DisableMask,
|
static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
|
||||||
u8 chan1EnableLightMask);
|
u8 chan1EnableLightMask);
|
||||||
static void DisableShadowMaps();
|
static void DisableShadowMaps();
|
||||||
static void MakeTexturesFromMats(const u8* ptr, std::vector<TCachedToken<CTexture>>& texture, IObjectStore* store,
|
static void MakeTexturesFromMats(const u8* ptr, std::vector<TCachedToken<CTexture>>& texture, IObjectStore* store,
|
||||||
bool b1);
|
bool b1);
|
||||||
static void KillCachedViewDepState();
|
|
||||||
static void SetDrawingOccluders(bool v);
|
static void SetDrawingOccluders(bool v);
|
||||||
static void SetModelWireframe();
|
static void SetModelWireframe(bool v);
|
||||||
static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos, const CStopwatch& time);
|
static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos, const CStopwatch& time);
|
||||||
static void SetRenderModelBlack(bool v);
|
static void SetRenderModelBlack(bool v);
|
||||||
|
|
||||||
|
static bool sRenderModelBlack;
|
||||||
|
static bool sUsingPackedLightmaps;
|
||||||
|
static bool sRenderModelShadow;
|
||||||
|
static const CTexture* sShadowTexture;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Draw(TVectorRef positions, TVectorRef normals, CModelFlags flags);
|
void Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags);
|
||||||
void DrawAlphaSurfaces(CModelFlags flags);
|
void DrawAlphaSurfaces(const CModelFlags& flags);
|
||||||
void DrawNormalSurfaces(CModelFlags flags);
|
void DrawNormalSurfaces(const CModelFlags& flags);
|
||||||
void DrawSurfaces(CModelFlags flags);
|
void DrawSurfaces(const CModelFlags& flags);
|
||||||
void SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals);
|
void SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals);
|
||||||
void SetStaticArraysCurrent();
|
void SetStaticArraysCurrent();
|
||||||
void SetUsingPackedLightmaps(bool v);
|
|
||||||
};
|
};
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -206,5 +206,11 @@ public:
|
||||||
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb);
|
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb);
|
||||||
void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb,
|
void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb,
|
||||||
float alpha);
|
float alpha);
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
[[nodiscard]] bool IsInAreaDraw() const { return x318_30_inAreaDraw; }
|
||||||
|
[[nodiscard]] bool IsReflectionDirty() const { return x318_24_refectionDirty; }
|
||||||
|
void SetReflectionDirty(bool v) { x318_24_refectionDirty = v; }
|
||||||
|
[[nodiscard]] bool IsThermalVisorActive() const { return x318_29_thermalVisor; }
|
||||||
};
|
};
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -27,8 +27,13 @@ class CCubeSurface {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CCubeSurface(const u8* ptr, u32 len); // Metaforce addition for extracting surface data
|
explicit CCubeSurface(const u8* ptr, u32 len); // Metaforce addition for extracting surface data
|
||||||
|
|
||||||
// bool IsValid() const;
|
// bool IsValid() const;
|
||||||
|
[[nodiscard]] CCubeModel* GetParent() { return x14_parent; }
|
||||||
|
[[nodiscard]] const CCubeModel* GetParent() const { return x14_parent; }
|
||||||
void SetParent(CCubeModel* parent) { x14_parent = parent; }
|
void SetParent(CCubeModel* parent) { x14_parent = parent; }
|
||||||
|
[[nodiscard]] CCubeSurface* GetNextSurface() { return x18_nextSurface; }
|
||||||
|
[[nodiscard]] const CCubeSurface* GetNextSurface() const { return x18_nextSurface; }
|
||||||
void SetNextSurface(CCubeSurface* next) { x18_nextSurface = next; }
|
void SetNextSurface(CCubeSurface* next) { x18_nextSurface = next; }
|
||||||
[[nodiscard]] u32 GetMaterialIndex() const { return xc_materialIndex; }
|
[[nodiscard]] u32 GetMaterialIndex() const { return xc_materialIndex; }
|
||||||
[[nodiscard]] u32 GetDisplayListSize() const { return x10_displayListSize & 0x7fffffff; }
|
[[nodiscard]] u32 GetDisplayListSize() const { return x10_displayListSize & 0x7fffffff; }
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Runtime/RetroTypes.hpp"
|
|
||||||
#include "Graphics/CCubeModel.hpp"
|
#include "Graphics/CCubeModel.hpp"
|
||||||
|
#include "Runtime/RetroTypes.hpp"
|
||||||
|
|
||||||
#include <zeus/CAABox.hpp>
|
#include <zeus/CAABox.hpp>
|
||||||
#include <zeus/CTransform.hpp>
|
#include <zeus/CTransform.hpp>
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
#include "CToken.hpp"
|
#include "CToken.hpp"
|
||||||
#include "GCNTypes.hpp"
|
#include "GCNTypes.hpp"
|
||||||
|
#include "Graphics/CCubeModel.hpp"
|
||||||
#include "Graphics/CTexture.hpp"
|
#include "Graphics/CTexture.hpp"
|
||||||
#include "IObjectStore.hpp"
|
#include "IObjectStore.hpp"
|
||||||
#include "Graphics/CCubeModel.hpp"
|
|
||||||
|
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
class CCubeSurface;
|
class CCubeSurface;
|
||||||
|
|
|
@ -142,7 +142,10 @@ enum class ZComp : uint8_t {
|
||||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept;
|
void set_cull_mode(metaforce::ERglCullMode mode) noexcept;
|
||||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||||
metaforce::ERglLogicOp op) noexcept;
|
metaforce::ERglLogicOp op) noexcept;
|
||||||
void set_depth_mode(bool test, metaforce::ERglEnum func, bool update);
|
void set_depth_mode(metaforce::ERglEnum func, bool update);
|
||||||
|
|
||||||
|
// Model state
|
||||||
|
void set_alpha_discard(bool v);
|
||||||
|
|
||||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept;
|
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept;
|
||||||
void update_projection(const zeus::CMatrix4f& proj) noexcept;
|
void update_projection(const zeus::CMatrix4f& proj) noexcept;
|
||||||
|
|
Loading…
Reference in New Issue