mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
Add LOD switching and blending out culling nodes
We're not blending between LODs yet as we're not sure of the best way to implement it Also implementing control bits for disable culling and enable model scale (needed for ECA and Harley)
This commit is contained in:
parent
3a85bd9e25
commit
483dbdda2e
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@ public:
|
|||
Clip currentClipStatus;
|
||||
float currentModelScale;
|
||||
float currentModelAlpha;
|
||||
bool currentDisableCulling;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -253,6 +254,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