mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 07:35:40 +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()
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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