Merge pull request #101 from gm-matthew/lod-and-blending

Add LOD switching and blending out culling nodes
This commit is contained in:
dukeeeey 2023-11-03 19:56:17 +00:00 committed by GitHub
commit 628eeebbc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 39 deletions

View file

@ -4,12 +4,13 @@ namespace New3D {
NodeAttributes::NodeAttributes()
{
currentTexOffsetX = 0;
currentTexOffsetY = 0;
currentPage = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
currentModelAlpha = 1.0;
currentTexOffsetX = 0;
currentTexOffsetY = 0;
currentPage = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
currentModelAlpha = 1.0;
currentDisableCulling = false;
}
bool NodeAttributes::Push()
@ -23,12 +24,13 @@ bool NodeAttributes::Push()
return false;
}
na.page = currentPage;
na.texOffsetX = currentTexOffsetX;
na.texOffsetY = currentTexOffsetY;
na.clip = currentClipStatus;
na.modelScale = currentModelScale;
na.modelAlpha = currentModelAlpha;
na.page = currentPage;
na.texOffsetX = currentTexOffsetX;
na.texOffsetY = currentTexOffsetY;
na.clip = currentClipStatus;
na.modelScale = currentModelScale;
na.modelAlpha = currentModelAlpha;
na.disableCulling = currentDisableCulling;
m_vecAttribs.emplace_back(na);
@ -43,12 +45,13 @@ bool NodeAttributes::Pop()
auto &last = m_vecAttribs.back();
currentPage = last.page;
currentTexOffsetX = last.texOffsetX;
currentTexOffsetY = last.texOffsetY;
currentClipStatus = last.clip;
currentModelScale = last.modelScale;
currentModelAlpha = last.modelAlpha;
currentPage = last.page;
currentTexOffsetX = last.texOffsetX;
currentTexOffsetY = last.texOffsetY;
currentClipStatus = last.clip;
currentModelScale = last.modelScale;
currentModelAlpha = last.modelAlpha;
currentDisableCulling = last.disableCulling;
m_vecAttribs.pop_back();
@ -62,12 +65,13 @@ bool NodeAttributes::StackLimit()
void NodeAttributes::Reset()
{
currentPage = 0;
currentTexOffsetX = 0;
currentTexOffsetY = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
currentModelAlpha = 1.0f;
currentPage = 0;
currentTexOffsetX = 0;
currentTexOffsetY = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
currentModelAlpha = 1.0f;
currentDisableCulling = false;
m_vecAttribs.clear();
}

View file

@ -243,6 +243,7 @@ public:
Clip currentClipStatus;
float currentModelScale;
float currentModelAlpha;
bool currentDisableCulling;
private:
@ -254,6 +255,7 @@ private:
Clip clip;
float modelScale;
float modelAlpha; // from culling node
bool disableCulling;
};
std::vector<NodeAttribs> m_vecAttribs;
};

View file

@ -559,11 +559,12 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
-------- -------- -------- -----x-- Valid color table
-------- -------- -------- ------xx Node type(0 = viewport, 1 = root node, 2 = culling node)
0x01, 0x02 only present on Step 2 +
0x01, 0x02 only present on Step 1.5+
0x01: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx-- Model scale (float32) last 2 bits are control words
-------- -------- -------- ------x- Disable culling
-------- -------- -------- -------x Valid model scale
0x02 : -------- -------- x------- -------- Texture replace
-------- -------- -x------ -------- Switch bank
-------- -------- --xxxxxx x------- X offset
@ -595,7 +596,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
{
enum class NodeType { undefined = -1, viewport = 0, rootNode = 1, cullingNode = 2 };
const UINT32 *node, *lodTable;
const UINT32 *node, *lodPtr;
UINT32 matrixOffset, child1Ptr, sibling2Ptr;
BBox bbox;
UINT16 uCullRadius;
@ -645,10 +646,11 @@ void CNew3D::DescendCullingNode(UINT32 addr)
if (!m_offset) { // Step 1.5+
float modelScale = Util::Uint32AsFloat(node[1]);
if (modelScale > std::numeric_limits<float>::min()) {
m_nodeAttribs.currentModelScale = modelScale;
}
if (node[0x01] & 1)
m_nodeAttribs.currentModelScale = Util::Uint32AsFloat(node[0x01] & ~3); // mask out control bits
if (node[0x01] & 2)
m_nodeAttribs.currentDisableCulling = true;
// apply texture offsets, else retain current ones
if ((node[0x02] & 0x8000)) {
@ -660,8 +662,6 @@ void CNew3D::DescendCullingNode(UINT32 addr)
}
}
m_nodeAttribs.currentModelAlpha = 1; // TODO fade out if required
// Apply matrix and translation
m_modelMat.PushMatrix();
@ -705,19 +705,42 @@ void CNew3D::DescendCullingNode(UINT32 addr)
}
}
if (m_nodeAttribs.currentClipStatus != Clip::OUTSIDE && fCullRadius > R3DFloat::Pro16BitFltMin) {
float LODscale = fBlendRadius * m_nodeAttribs.currentModelScale / std::abs(m_modelMat.currentMatrix[14]);
LODFeatureType lodTableEntry = m_LODBlendTable->table[lodTablePointer];
if (m_nodeAttribs.currentDisableCulling)
{
m_nodeAttribs.currentModelAlpha = 1.0f;
}
else
{
float nodeAlpha = lodTableEntry.lod[3].blendFactor * (LODscale - lodTableEntry.lod[3].deleteSize);
nodeAlpha = std::clamp(nodeAlpha, 0.0f, 1.0f);
m_nodeAttribs.currentModelAlpha *= nodeAlpha; // alpha of each node multiples by the alpha of its parent
}
if (m_nodeAttribs.currentClipStatus != Clip::OUTSIDE && m_nodeAttribs.currentModelAlpha > 0.0f) {
// Descend down first link
if ((node[0x00] & 0x08)) // 4-element LOD table
{
lodTable = TranslateCullingAddress(child1Ptr);
lodPtr = TranslateCullingAddress(child1Ptr);
if (NULL != lodTable) {
// determine which LOD to use; we do not currently blend between LODs
int modelLOD;
for (modelLOD = 0; modelLOD < 3; modelLOD++)
{
if (LODscale >= lodTableEntry.lod[modelLOD].deleteSize)
break;
}
if (NULL != lodPtr) {
if ((node[0x03 - m_offset] & 0x20000000)) {
DescendCullingNode(lodTable[0] & 0xFFFFFF);
DescendCullingNode(lodPtr[modelLOD] & 0xFFFFFF);
}
else {
DrawModel(lodTable[0] & 0xFFFFFF); //TODO
DrawModel(lodPtr[modelLOD] & 0xFFFFFF);
}
}
}

View file

@ -3,8 +3,8 @@
struct LOD
{
float startRange; // possibly specified as angles also, yeah who knows >_<
float deleteRange;
float deleteSize;
float blendFactor;
};
struct LODFeatureType