mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-26 00:24:27 +00:00
refactor: deduplicate terrain grid lookup logic, remove unnecessary cast
Add IsValidForSceneLookup(), GetSceneIDAtGrid(), and GridToWorldPos() to Raw::Chunk. Use them in GenerateTerrainMesh, GetSceneIDFromPosition, SpawnScenePoints, and SpawnAllScenePoints instead of duplicated inline math. Remove unnecessary static_cast in LoadSceneTransitionInfo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2007,41 +2007,21 @@ namespace DEVGMCommands {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn at all sceneMap points in the current scene
|
|
||||||
uint32_t spawnedCount = 0;
|
uint32_t spawnedCount = 0;
|
||||||
|
|
||||||
for (const auto& chunk : raw.chunks) {
|
for (const auto& chunk : raw.chunks) {
|
||||||
if (chunk.sceneMap.empty() || chunk.colorMapResolution == 0 || chunk.heightMap.empty()
|
if (!chunk.IsValidForSceneLookup()) continue;
|
||||||
|| chunk.width <= 1 || chunk.height <= 1 || chunk.scaleFactor <= 0.0f) continue;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < chunk.width; ++i) {
|
for (uint32_t i = 0; i < chunk.width; ++i) {
|
||||||
for (uint32_t j = 0; j < chunk.height; ++j) {
|
for (uint32_t j = 0; j < chunk.height; ++j) {
|
||||||
const uint32_t heightIndex = chunk.width * i + j;
|
if (i * chunk.width + j >= chunk.heightMap.size()) continue;
|
||||||
if (heightIndex >= chunk.heightMap.size()) continue;
|
|
||||||
|
|
||||||
const float y = chunk.heightMap[heightIndex];
|
const uint8_t sceneID = chunk.GetSceneIDAtGrid(i, j);
|
||||||
|
if (sceneID != currentSceneID.GetSceneID()) continue;
|
||||||
|
|
||||||
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
|
|
||||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
|
||||||
|
|
||||||
uint8_t sceneID = 0;
|
|
||||||
if (sceneIndex < chunk.sceneMap.size()) {
|
|
||||||
sceneID = chunk.sceneMap[sceneIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sceneID == currentSceneID.GetSceneID()) {
|
|
||||||
const float worldX = (static_cast<float>(i) + (chunk.offsetX / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
const float worldY = y;
|
|
||||||
const float worldZ = (static_cast<float>(j) + (chunk.offsetZ / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
|
|
||||||
NiPoint3 spawnPos(worldX, worldY, worldZ);
|
|
||||||
EntityInfo info;
|
EntityInfo info;
|
||||||
info.lot = lot + currentSceneID.GetSceneID();
|
info.lot = lot + sceneID;
|
||||||
info.pos = spawnPos;
|
info.pos = chunk.GridToWorldPos(i, j);
|
||||||
info.rot = QuatUtils::IDENTITY;
|
info.rot = QuatUtils::IDENTITY;
|
||||||
info.spawner = nullptr;
|
info.spawner = nullptr;
|
||||||
info.spawnerID = entity->GetObjectID();
|
info.spawnerID = entity->GetObjectID();
|
||||||
@@ -2056,7 +2036,6 @@ namespace DEVGMCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (spawnedCount == 0) {
|
if (spawnedCount == 0) {
|
||||||
std::ostringstream feedback;
|
std::ostringstream feedback;
|
||||||
@@ -2092,43 +2071,22 @@ namespace DEVGMCommands {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn at all sceneMap points across all scenes
|
|
||||||
uint32_t spawnedCount = 0;
|
uint32_t spawnedCount = 0;
|
||||||
std::map<uint8_t, uint32_t> sceneSpawnCounts; // Track spawns per scene
|
std::map<uint8_t, uint32_t> sceneSpawnCounts;
|
||||||
|
|
||||||
for (const auto& chunk : raw.chunks) {
|
for (const auto& chunk : raw.chunks) {
|
||||||
if (chunk.sceneMap.empty() || chunk.colorMapResolution == 0 || chunk.heightMap.empty()
|
if (!chunk.IsValidForSceneLookup()) continue;
|
||||||
|| chunk.width <= 1 || chunk.height <= 1 || chunk.scaleFactor <= 0.0f) continue;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < chunk.width; ++i) {
|
for (uint32_t i = 0; i < chunk.width; ++i) {
|
||||||
for (uint32_t j = 0; j < chunk.height; ++j) {
|
for (uint32_t j = 0; j < chunk.height; ++j) {
|
||||||
const uint32_t heightIndex = chunk.width * i + j;
|
if (i * chunk.width + j >= chunk.heightMap.size()) continue;
|
||||||
if (heightIndex >= chunk.heightMap.size()) continue;
|
|
||||||
|
|
||||||
const float y = chunk.heightMap[heightIndex];
|
|
||||||
|
|
||||||
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
|
|
||||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
|
||||||
|
|
||||||
uint8_t sceneID = 0;
|
|
||||||
if (sceneIndex < chunk.sceneMap.size()) {
|
|
||||||
sceneID = chunk.sceneMap[sceneIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const uint8_t sceneID = chunk.GetSceneIDAtGrid(i, j);
|
||||||
if (sceneID == 0) continue;
|
if (sceneID == 0) continue;
|
||||||
|
|
||||||
const float worldX = (static_cast<float>(i) + (chunk.offsetX / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
const float worldY = y;
|
|
||||||
const float worldZ = (static_cast<float>(j) + (chunk.offsetZ / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
|
|
||||||
NiPoint3 spawnPos(worldX, worldY, worldZ);
|
|
||||||
EntityInfo info;
|
EntityInfo info;
|
||||||
info.lot = lot + sceneID;
|
info.lot = lot + sceneID;
|
||||||
info.pos = spawnPos;
|
info.pos = chunk.GridToWorldPos(i, j);
|
||||||
info.rot = QuatUtils::IDENTITY;
|
info.rot = QuatUtils::IDENTITY;
|
||||||
info.spawner = nullptr;
|
info.spawner = nullptr;
|
||||||
info.spawnerID = entity->GetObjectID();
|
info.spawnerID = entity->GetObjectID();
|
||||||
|
|||||||
@@ -14,6 +14,30 @@ constexpr uint32_t kMaxChunks = 1024;
|
|||||||
|
|
||||||
namespace Raw {
|
namespace Raw {
|
||||||
|
|
||||||
|
bool Chunk::IsValidForSceneLookup() const {
|
||||||
|
return !sceneMap.empty() && colorMapResolution > 0 && !heightMap.empty()
|
||||||
|
&& scaleFactor > 0.0f && width > 1 && height > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Chunk::GetSceneIDAtGrid(uint32_t i, uint32_t j) const {
|
||||||
|
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(width - 1)) * static_cast<float>(colorMapResolution - 1);
|
||||||
|
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(height - 1)) * static_cast<float>(colorMapResolution - 1);
|
||||||
|
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), colorMapResolution - 1);
|
||||||
|
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), colorMapResolution - 1);
|
||||||
|
const uint32_t sceneIndex = sceneI * colorMapResolution + sceneJ;
|
||||||
|
if (sceneIndex >= sceneMap.size()) return 0;
|
||||||
|
return sceneMap[sceneIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
NiPoint3 Chunk::GridToWorldPos(uint32_t i, uint32_t j) const {
|
||||||
|
const float y = (i * width + j < heightMap.size()) ? heightMap[i * width + j] : 0.0f;
|
||||||
|
return NiPoint3(
|
||||||
|
(static_cast<float>(i) + (offsetX / scaleFactor)) * scaleFactor,
|
||||||
|
y,
|
||||||
|
(static_cast<float>(j) + (offsetZ / scaleFactor)) * scaleFactor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read flair attributes from stream
|
* @brief Read flair attributes from stream
|
||||||
*/
|
*/
|
||||||
@@ -386,45 +410,14 @@ namespace Raw {
|
|||||||
uint32_t vertexOffset = 0;
|
uint32_t vertexOffset = 0;
|
||||||
|
|
||||||
for (const auto& chunk : raw.chunks) {
|
for (const auto& chunk : raw.chunks) {
|
||||||
// Skip chunks without scene maps or with invalid dimensions/scale
|
if (!chunk.IsValidForSceneLookup()) continue;
|
||||||
if (chunk.sceneMap.empty() || chunk.colorMapResolution == 0 || chunk.heightMap.empty()
|
|
||||||
|| chunk.scaleFactor <= 0.0f || chunk.width <= 1 || chunk.height <= 1) {
|
|
||||||
LOG("Skipping chunk %u (sceneMap: %zu, colorMapRes: %u, heightMap: %zu, scaleFactor: %f, width: %u, height: %u)",
|
|
||||||
chunk.id, chunk.sceneMap.size(), chunk.colorMapResolution, chunk.heightMap.size(),
|
|
||||||
chunk.scaleFactor, chunk.width, chunk.height);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("Processing chunk %u: width=%u, height=%u, colorMapRes=%u, sceneMapSize=%zu",
|
|
||||||
chunk.id, chunk.width, chunk.height, chunk.colorMapResolution, chunk.sceneMap.size());
|
|
||||||
|
|
||||||
// Generate vertices for this chunk
|
|
||||||
for (uint32_t i = 0; i < chunk.width; ++i) {
|
for (uint32_t i = 0; i < chunk.width; ++i) {
|
||||||
for (uint32_t j = 0; j < chunk.height; ++j) {
|
for (uint32_t j = 0; j < chunk.height; ++j) {
|
||||||
// Get height at this position
|
|
||||||
const uint32_t heightIndex = chunk.width * i + j;
|
const uint32_t heightIndex = chunk.width * i + j;
|
||||||
if (heightIndex >= chunk.heightMap.size()) continue;
|
if (heightIndex >= chunk.heightMap.size()) continue;
|
||||||
|
|
||||||
const float y = chunk.heightMap[heightIndex];
|
outMesh.vertices.emplace_back(chunk.GridToWorldPos(i, j), chunk.GetSceneIDAtGrid(i, j));
|
||||||
|
|
||||||
const float worldX = (static_cast<float>(i) + (chunk.offsetX / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
const float worldY = y;
|
|
||||||
const float worldZ = (static_cast<float>(j) + (chunk.offsetZ / chunk.scaleFactor)) * chunk.scaleFactor;
|
|
||||||
|
|
||||||
const NiPoint3 worldPos(worldX, worldY, worldZ);
|
|
||||||
|
|
||||||
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
|
||||||
|
|
||||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
|
||||||
|
|
||||||
uint8_t sceneID = 0;
|
|
||||||
if (sceneIndex < chunk.sceneMap.size()) {
|
|
||||||
sceneID = chunk.sceneMap[sceneIndex];
|
|
||||||
}
|
|
||||||
outMesh.vertices.emplace_back(worldPos, sceneID);
|
|
||||||
if (i > 0 && j > 0) {
|
if (i > 0 && j > 0) {
|
||||||
const uint32_t currentVert = vertexOffset + chunk.width * i + j;
|
const uint32_t currentVert = vertexOffset + chunk.width * i + j;
|
||||||
const uint32_t leftVert = currentVert - 1;
|
const uint32_t leftVert = currentVert - 1;
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ struct Chunk {
|
|||||||
std::vector<uint16_t> meshVertSize;
|
std::vector<uint16_t> meshVertSize;
|
||||||
std::vector<MeshTri> meshTri;
|
std::vector<MeshTri> meshTri;
|
||||||
|
|
||||||
|
bool IsValidForSceneLookup() const;
|
||||||
|
uint8_t GetSceneIDAtGrid(uint32_t i, uint32_t j) const;
|
||||||
|
NiPoint3 GridToWorldPos(uint32_t i, uint32_t j) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ SceneTransitionInfo Zone::LoadSceneTransitionInfo(std::istream& file) {
|
|||||||
uint32_t sceneID, layerID;
|
uint32_t sceneID, layerID;
|
||||||
BinaryIO::BinaryRead(file, sceneID);
|
BinaryIO::BinaryRead(file, sceneID);
|
||||||
BinaryIO::BinaryRead(file, layerID);
|
BinaryIO::BinaryRead(file, layerID);
|
||||||
info.sceneID = LWOSCENEID(static_cast<int32_t>(sceneID), layerID);
|
info.sceneID = LWOSCENEID(sceneID, layerID);
|
||||||
BinaryIO::BinaryRead(file, info.position);
|
BinaryIO::BinaryRead(file, info.position);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,37 +321,17 @@ LWOSCENEID dZoneManager::GetSceneIDFromPosition(const NiPoint3& position) const
|
|||||||
// Find the chunk containing this position
|
// Find the chunk containing this position
|
||||||
// Reverse the world position calculation from GenerateTerrainMesh
|
// Reverse the world position calculation from GenerateTerrainMesh
|
||||||
for (const auto& chunk : raw.chunks) {
|
for (const auto& chunk : raw.chunks) {
|
||||||
if (chunk.sceneMap.empty() || chunk.scaleFactor <= 0.0f || chunk.width <= 1 || chunk.height <= 1 || chunk.colorMapResolution == 0) continue;
|
if (!chunk.IsValidForSceneLookup()) continue;
|
||||||
|
|
||||||
// Reverse: worldX = (i + offsetX/scaleFactor) * scaleFactor
|
|
||||||
// Therefore: i = worldX/scaleFactor - offsetX/scaleFactor
|
|
||||||
const float heightI = posX / chunk.scaleFactor - (chunk.offsetX / chunk.scaleFactor);
|
const float heightI = posX / chunk.scaleFactor - (chunk.offsetX / chunk.scaleFactor);
|
||||||
const float heightJ = posZ / chunk.scaleFactor - (chunk.offsetZ / chunk.scaleFactor);
|
const float heightJ = posZ / chunk.scaleFactor - (chunk.offsetZ / chunk.scaleFactor);
|
||||||
|
|
||||||
// Check if position is within this chunk's heightmap bounds
|
|
||||||
if (heightI >= 0.0f && heightI < static_cast<float>(chunk.width) &&
|
if (heightI >= 0.0f && heightI < static_cast<float>(chunk.width) &&
|
||||||
heightJ >= 0.0f && heightJ < static_cast<float>(chunk.height)) {
|
heightJ >= 0.0f && heightJ < static_cast<float>(chunk.height)) {
|
||||||
|
|
||||||
const float sceneMapI = (heightI / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
const uint32_t gridI = std::min(static_cast<uint32_t>(heightI), chunk.width - 1);
|
||||||
const float sceneMapJ = (heightJ / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
const uint32_t gridJ = std::min(static_cast<uint32_t>(heightJ), chunk.height - 1);
|
||||||
|
return LWOSCENEID(chunk.GetSceneIDAtGrid(gridI, gridJ), 0);
|
||||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
|
||||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
|
||||||
|
|
||||||
// Scene map uses the same indexing pattern as heightmap: row * width + col
|
|
||||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
|
||||||
|
|
||||||
// Bounds check: if this chunk's sceneMap is inconsistent, skip this chunk
|
|
||||||
if (sceneIndex >= chunk.sceneMap.size()) {
|
|
||||||
LOG_DEBUG("GetSceneIDFromPosition: sceneIndex %u out of bounds (sceneMap size: %zu), skipping malformed chunk.", sceneIndex, chunk.sceneMap.size());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get scene ID from sceneMap
|
|
||||||
const uint8_t sceneID = chunk.sceneMap[sceneIndex];
|
|
||||||
|
|
||||||
// Return the scene ID
|
|
||||||
return LWOSCENEID(sceneID, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user