mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 22:05: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()
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,7 @@ public:
|
||||||
Clip currentClipStatus;
|
Clip currentClipStatus;
|
||||||
float currentModelScale;
|
float currentModelScale;
|
||||||
float currentModelAlpha;
|
float currentModelAlpha;
|
||||||
|
bool currentDisableCulling;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -253,6 +254,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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue