Impl raw reading, and some slash commands to test with scenes

This commit is contained in:
Aaron Kimbrell
2025-10-14 22:44:56 -05:00
parent fd6029ae10
commit 12fd9d0a21
10 changed files with 928 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
#include "WorldConfig.h"
#include "CDZoneTableTable.h"
#include <chrono>
#include <cmath>
#include "eObjectBits.h"
#include "CDZoneTableTable.h"
#include "AssetManager.h"
@@ -62,6 +63,9 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) {
m_pZone->Initalize();
// Build the scene graph after zone is loaded
BuildSceneGraph();
endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
LoadWorldConfig();
@@ -298,3 +302,109 @@ void dZoneManager::LoadWorldConfig() {
LOG_DEBUG("Loaded WorldConfig into memory");
}
LWOSCENEID dZoneManager::GetSceneIDFromPosition(const NiPoint3& position) const {
if (!m_pZone) return LWOSCENEID_INVALID;
const auto& terrainMesh = m_pZone->GetTerrainMesh();
// If mesh is empty, no scene data available
if (terrainMesh.vertices.empty() || terrainMesh.triangles.empty()) {
return LWOSCENEID_INVALID;
}
// Find the triangle containing this position (ignoring Y coordinate for scene lookup)
// We iterate through all triangles and find the one that contains the point in 2D (XZ plane)
for (size_t i = 0; i < terrainMesh.triangles.size(); i += 3) {
const auto& v0 = terrainMesh.vertices[terrainMesh.triangles[i]];
const auto& v1 = terrainMesh.vertices[terrainMesh.triangles[i + 1]];
const auto& v2 = terrainMesh.vertices[terrainMesh.triangles[i + 2]];
// Check if position is inside this triangle using 2D (XZ) coordinates
// Using barycentric coordinates / cross product method
const float x = position.x;
const float z = position.z;
const float x0 = v0.position.x;
const float z0 = v0.position.z;
const float x1 = v1.position.x;
const float z1 = v1.position.z;
const float x2 = v2.position.x;
const float z2 = v2.position.z;
// Calculate barycentric coordinates
const float denom = (z1 - z2) * (x0 - x2) + (x2 - x1) * (z0 - z2);
if (std::abs(denom) < 0.0001f) continue; // Degenerate triangle
const float a = ((z1 - z2) * (x - x2) + (x2 - x1) * (z - z2)) / denom;
const float b = ((z2 - z0) * (x - x2) + (x0 - x2) * (z - z2)) / denom;
const float c = 1.0f - a - b;
// Point is inside triangle if all barycentric coordinates are non-negative
if (a >= 0.0f && b >= 0.0f && c >= 0.0f) {
// Return the scene ID from the first vertex (all vertices in a triangle should have the same scene ID)
return LWOSCENEID(v0.sceneID);
}
}
// Position not found in any triangle
return LWOSCENEID_INVALID;
}
void dZoneManager::BuildSceneGraph() {
if (!m_pZone) return;
// Clear any existing adjacency list
m_SceneAdjacencyList.clear();
// Initialize adjacency list with all scenes
const auto& scenes = m_pZone->GetScenes();
for (const auto& [sceneID, sceneRef] : scenes) {
// Ensure every scene has an entry, even if it has no transitions
if (m_SceneAdjacencyList.find(sceneID) == m_SceneAdjacencyList.end()) {
m_SceneAdjacencyList[sceneID] = std::vector<LWOSCENEID>();
}
}
// Build adjacency list from scene transitions
const auto& transitions = m_pZone->GetSceneTransitions();
for (const auto& transition : transitions) {
// Each transition has multiple points, each pointing to a scene
// We need to determine which scenes this transition connects
// Group transition points by their scene IDs to find unique connections
std::set<LWOSCENEID> connectedScenes;
for (const auto& point : transition.points) {
if (point.sceneID != LWOSCENEID_INVALID) {
connectedScenes.insert(point.sceneID);
}
}
// Create bidirectional edges between all scenes in this transition
// (transitions typically connect two scenes, but can be more complex)
std::vector<LWOSCENEID> sceneList(connectedScenes.begin(), connectedScenes.end());
for (size_t i = 0; i < sceneList.size(); ++i) {
for (size_t j = 0; j < sceneList.size(); ++j) {
if (i != j) {
LWOSCENEID fromScene = sceneList[i];
LWOSCENEID toScene = sceneList[j];
// Add edge if it doesn't already exist
auto& adjacentScenes = m_SceneAdjacencyList[fromScene];
if (std::find(adjacentScenes.begin(), adjacentScenes.end(), toScene) == adjacentScenes.end()) {
adjacentScenes.push_back(toScene);
}
}
}
}
}
}
std::vector<LWOSCENEID> dZoneManager::GetAdjacentScenes(LWOSCENEID sceneID) const {
auto it = m_SceneAdjacencyList.find(sceneID);
if (it != m_SceneAdjacencyList.end()) {
return it->second;
}
return std::vector<LWOSCENEID>();
}