telemetry: emit track geometry (DriveGraph nodes) in RaceStarted
Walk the main driveline graph at race start and populate TrackGeometry with center, left/right edge, width, and distance_from_start for each DriveNode quad. Includes bounding box and start position/heading for 2D minimap rendering.
This commit is contained in:
@@ -19,9 +19,12 @@
|
|||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "tracks/track_sector.hpp"
|
#include "tracks/track_sector.hpp"
|
||||||
#include "tracks/check_manager.hpp"
|
#include "tracks/check_manager.hpp"
|
||||||
|
#include "tracks/drive_graph.hpp"
|
||||||
|
#include "tracks/drive_node.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
#include "utils/string_utils.hpp"
|
#include "utils/string_utils.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <random>
|
#include <random>
|
||||||
@@ -176,6 +179,106 @@ void TelemetryEmitter::onRaceStarted()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Track geometry (for 2D minimap / replay) ---
|
||||||
|
DriveGraph* graph = DriveGraph::get();
|
||||||
|
if (graph != nullptr && graph->getNumNodes() > 0)
|
||||||
|
{
|
||||||
|
auto* geom = ev->mutable_track_geometry();
|
||||||
|
|
||||||
|
float min_x = 1e9f, min_y = 1e9f, min_z = 1e9f;
|
||||||
|
float max_x = -1e9f, max_y = -1e9f, max_z = -1e9f;
|
||||||
|
|
||||||
|
// Walk the main driveline loop following successor 0.
|
||||||
|
unsigned int num_nodes = graph->getNumNodes();
|
||||||
|
unsigned int current = 0;
|
||||||
|
unsigned int visited = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const DriveNode* dn = graph->getNode(current);
|
||||||
|
if (dn == nullptr) break;
|
||||||
|
|
||||||
|
auto* node = geom->add_nodes();
|
||||||
|
|
||||||
|
// Center
|
||||||
|
const Vec3& center = dn->getCenter();
|
||||||
|
auto* c = node->mutable_center();
|
||||||
|
c->set_x(center.x());
|
||||||
|
c->set_y(center.y());
|
||||||
|
c->set_z(center.z());
|
||||||
|
|
||||||
|
// Width
|
||||||
|
node->set_width(dn->getPathWidth());
|
||||||
|
|
||||||
|
// Distance from start
|
||||||
|
node->set_distance_from_start(dn->getDistanceFromStart());
|
||||||
|
|
||||||
|
// Left and right edge points from Quad corners.
|
||||||
|
// Quad layout: [0]=lower-right, [1]=lower-left, [2]=upper-left, [3]=upper-right
|
||||||
|
const Vec3& lr = (*dn)[0];
|
||||||
|
const Vec3& ll = (*dn)[1];
|
||||||
|
const Vec3& ul = (*dn)[2];
|
||||||
|
const Vec3& ur = (*dn)[3];
|
||||||
|
|
||||||
|
// Left edge = midpoint of lower-left and upper-left
|
||||||
|
auto* left = node->mutable_left_edge();
|
||||||
|
left->set_x((ll.x() + ul.x()) * 0.5f);
|
||||||
|
left->set_y((ll.y() + ul.y()) * 0.5f);
|
||||||
|
left->set_z((ll.z() + ul.z()) * 0.5f);
|
||||||
|
|
||||||
|
// Right edge = midpoint of lower-right and upper-right
|
||||||
|
auto* right = node->mutable_right_edge();
|
||||||
|
right->set_x((lr.x() + ur.x()) * 0.5f);
|
||||||
|
right->set_y((lr.y() + ur.y()) * 0.5f);
|
||||||
|
right->set_z((lr.z() + ur.z()) * 0.5f);
|
||||||
|
|
||||||
|
// Update bounding box
|
||||||
|
min_x = std::min(min_x, center.x());
|
||||||
|
min_y = std::min(min_y, center.y());
|
||||||
|
min_z = std::min(min_z, center.z());
|
||||||
|
max_x = std::max(max_x, center.x());
|
||||||
|
max_y = std::max(max_y, center.y());
|
||||||
|
max_z = std::max(max_z, center.z());
|
||||||
|
|
||||||
|
// Follow successor 0 (main driveline)
|
||||||
|
if (dn->getNumberOfSuccessors() > 0)
|
||||||
|
current = dn->getSuccessor(0);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
visited++;
|
||||||
|
} while (current != 0 && visited < num_nodes);
|
||||||
|
|
||||||
|
// Bounding box
|
||||||
|
auto* bmin = geom->mutable_bbox_min();
|
||||||
|
bmin->set_x(min_x);
|
||||||
|
bmin->set_y(min_y);
|
||||||
|
bmin->set_z(min_z);
|
||||||
|
auto* bmax = geom->mutable_bbox_max();
|
||||||
|
bmax->set_x(max_x);
|
||||||
|
bmax->set_y(max_y);
|
||||||
|
bmax->set_z(max_z);
|
||||||
|
|
||||||
|
// Start position + heading
|
||||||
|
const DriveNode* start_node = graph->getNode(0);
|
||||||
|
if (start_node != nullptr)
|
||||||
|
{
|
||||||
|
auto* sp = geom->mutable_start_position();
|
||||||
|
sp->set_x(start_node->getCenter().x());
|
||||||
|
sp->set_y(start_node->getCenter().y());
|
||||||
|
sp->set_z(start_node->getCenter().z());
|
||||||
|
|
||||||
|
// Heading from node 0 toward its successor
|
||||||
|
if (start_node->getNumberOfSuccessors() > 0)
|
||||||
|
{
|
||||||
|
geom->set_start_heading(
|
||||||
|
start_node->getAngleToSuccessor(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Telemetry", "Track geometry: %u nodes, bbox=(%.0f,%.0f)-(%.0f,%.0f)",
|
||||||
|
visited, min_x, min_z, max_x, max_z);
|
||||||
|
}
|
||||||
|
|
||||||
sendFrame(frame);
|
sendFrame(frame);
|
||||||
Log::info("Telemetry", "Race started: game_id=%s track=%s karts=%d",
|
Log::info("Telemetry", "Race started: game_id=%s track=%s karts=%d",
|
||||||
m_game_id.c_str(), rm->getTrackName().c_str(), num_karts);
|
m_game_id.c_str(), rm->getTrackName().c_str(), num_karts);
|
||||||
|
|||||||
Reference in New Issue
Block a user