mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 01:59:19 +02:00
Store model position in the v7 node marker for O(1) ring skipping
The camera-ring visual load replays the twin once per distance ring, and each pass had to read every node's header + X Y Z tokens (~8 tokens through the cParser pipeline) just to decide whether the node is in the current ring -- expensive when a scenery has a million flora instances. Bump the twin format to v7: a visual model node's marker now carries its local position (3 f32), captured at bake time from the node's first three numbers. The reader hands the position out (scenery_binary_reader::node_position), and the deserializer ring-tests a model and skips it in O(1) over the marker span, straight from the dispatch loop, without deserialize_node decoding any of its tokens. deserialize_model uses the same marker position for its own ring test so the two decisions agree exactly (a node near a ring boundary can't be dropped by both adjacent rings). Shapes/older twins have no marker position and fall back to the token-based test. The per-frame visual budget is factored into VISUAL_BUDGET_MS. Verified: td.scn rebakes to v7, no duplicates, no unexpected tokens, completes ~1s. tomaszewo (1M+ flora) stays memory-bounded with no duplicates; full streaming is still paced by walking every node per ring (the remaining cost is the replay pipeline itself, which a spatial section index would address). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -319,7 +319,7 @@ void cParser::bakeFinishNode()
|
||||
// flush a node still open at end-of-file or one whose type was unrecognized
|
||||
if (m_bakenode_active && m_writer)
|
||||
{
|
||||
m_writer->end_node(m_bakenode_visual);
|
||||
m_writer->end_node(m_bakenode_visual, m_bakenode_haspos, m_bakenode_pos[0], m_bakenode_pos[1], m_bakenode_pos[2]);
|
||||
}
|
||||
m_bakenode_active = false;
|
||||
}
|
||||
@@ -774,6 +774,7 @@ void cParser::readToken(std::string &out, bool ToLower, const char *Break)
|
||||
m_bakenode_active = true;
|
||||
m_bakenode_count = 0;
|
||||
m_bakenode_visual = false;
|
||||
m_bakenode_haspos = false;
|
||||
m_bakenode_end.clear();
|
||||
}
|
||||
else if (m_bakenode_active && m_bakenode_end.empty() && (lowered == "node"))
|
||||
@@ -785,6 +786,7 @@ void cParser::readToken(std::string &out, bool ToLower, const char *Break)
|
||||
m_bakenode_active = true;
|
||||
m_bakenode_count = 0;
|
||||
m_bakenode_visual = false;
|
||||
m_bakenode_haspos = false;
|
||||
m_bakenode_end.clear();
|
||||
}
|
||||
|
||||
@@ -807,11 +809,18 @@ void cParser::readToken(std::string &out, bool ToLower, const char *Break)
|
||||
{
|
||||
// 5th node entry is the type token (node, range_max, range_min, name, type)
|
||||
classifyNodeType(lowered, m_bakenode_visual, m_bakenode_end);
|
||||
// a model node's entries 6,7,8 are its local X Y Z -- record them in the
|
||||
// marker so the camera-ring load can skip the node without reading its body
|
||||
m_bakenode_haspos = (lowered == "model");
|
||||
}
|
||||
else if (m_bakenode_haspos && (m_bakenode_count >= 6) && (m_bakenode_count <= 8))
|
||||
{
|
||||
m_bakenode_pos[m_bakenode_count - 6] = value;
|
||||
}
|
||||
else if ((false == m_bakenode_end.empty()) && (lowered == m_bakenode_end))
|
||||
{
|
||||
// terminator captured: close the node
|
||||
m_writer->end_node(m_bakenode_visual);
|
||||
m_writer->end_node(m_bakenode_visual, m_bakenode_haspos, m_bakenode_pos[0], m_bakenode_pos[1], m_bakenode_pos[2]);
|
||||
m_bakenode_active = false;
|
||||
}
|
||||
}
|
||||
@@ -903,6 +912,13 @@ bool cParser::skipReplayNode()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cParser::currentNodePosition(double &X, double &Y, double &Z)
|
||||
{
|
||||
// delegate to the deepest active include child (it serves the current node), like skip
|
||||
if (mIncludeParser) { return mIncludeParser->currentNodePosition(X, Y, Z); }
|
||||
return (m_replay && m_reader && m_reader->node_position(X, Y, Z));
|
||||
}
|
||||
|
||||
std::vector<std::string> cParser::readParameters(cParser &Input)
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user