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

View file

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

View file

@ -559,11 +559,12 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
-------- -------- -------- -----x-- Valid color table -------- -------- -------- -----x-- Valid color table
-------- -------- -------- ------xx Node type(0 = viewport, 1 = root node, 2 = culling node) -------- -------- -------- ------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 0x01: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx-- Model scale (float32) last 2 bits are control words
-------- -------- -------- ------x- Disable culling -------- -------- -------- ------x- Disable culling
-------- -------- -------- -------x Valid model scale -------- -------- -------- -------x Valid model scale
0x02 : -------- -------- x------- -------- Texture replace 0x02 : -------- -------- x------- -------- Texture replace
-------- -------- -x------ -------- Switch bank -------- -------- -x------ -------- Switch bank
-------- -------- --xxxxxx x------- X offset -------- -------- --xxxxxx x------- X offset
@ -595,7 +596,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
{ {
enum class NodeType { undefined = -1, viewport = 0, rootNode = 1, cullingNode = 2 }; enum class NodeType { undefined = -1, viewport = 0, rootNode = 1, cullingNode = 2 };
const UINT32 *node, *lodTable; const UINT32 *node, *lodPtr;
UINT32 matrixOffset, child1Ptr, sibling2Ptr; UINT32 matrixOffset, child1Ptr, sibling2Ptr;
BBox bbox; BBox bbox;
UINT16 uCullRadius; UINT16 uCullRadius;
@ -645,10 +646,11 @@ void CNew3D::DescendCullingNode(UINT32 addr)
if (!m_offset) { // Step 1.5+ if (!m_offset) { // Step 1.5+
float modelScale = Util::Uint32AsFloat(node[1]); if (node[0x01] & 1)
if (modelScale > std::numeric_limits<float>::min()) { m_nodeAttribs.currentModelScale = Util::Uint32AsFloat(node[0x01] & ~3); // mask out control bits
m_nodeAttribs.currentModelScale = modelScale;
} if (node[0x01] & 2)
m_nodeAttribs.currentDisableCulling = true;
// apply texture offsets, else retain current ones // apply texture offsets, else retain current ones
if ((node[0x02] & 0x8000)) { 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 // Apply matrix and translation
m_modelMat.PushMatrix(); 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 // Descend down first link
if ((node[0x00] & 0x08)) // 4-element LOD table 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)) { if ((node[0x03 - m_offset] & 0x20000000)) {
DescendCullingNode(lodTable[0] & 0xFFFFFF); DescendCullingNode(lodPtr[modelLOD] & 0xFFFFFF);
} }
else { else {
DrawModel(lodTable[0] & 0xFFFFFF); //TODO DrawModel(lodPtr[modelLOD] & 0xFFFFFF);
} }
} }
} }

View file

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