mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55:38 +00:00
Merge pull request #101 from gm-matthew/lod-and-blending
Add LOD switching and blending out culling nodes
This commit is contained in:
commit
628eeebbc3
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
struct LOD
|
||||
{
|
||||
float startRange; // possibly specified as angles also, yeah who knows >_<
|
||||
float deleteRange;
|
||||
float deleteSize;
|
||||
float blendFactor;
|
||||
};
|
||||
|
||||
struct LODFeatureType
|
||||
|
|
Loading…
Reference in a new issue