mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-12 15:53:44 +00:00
feat(ugc): make models like LU Toolbox does, within CPU and memory budgets
Parity with LU Toolbox's Process Model, Bake Lighting and icon renderer, with its defaults as the settings' defaults: - Colors from its LU palette (UgcPalette: LU colors, LDD colors mapped to the nearest LU one, unknown ones black), transparent bricks at 58.82% opacity, a brick transparent only when all of its materials are. - Color variation: each brick's material gets its HSV value shifted in a 2.224 gamma by up to 5% (times the color's own amount), from a random number of the model, brick and material, so reprocessing gives the same colors in every LOD. Icons get none, and the icon renderer's color corrections. - LODs 0 and 2 with its distance logic, written as NiLODNode/NiRangeLODData like its exports and the game's own brick models, shapes divided at 65535 vertices along the longest side like divide_mesh. - Ambient occlusion like its AO-only bake: 64 rays per vertex, distance 5, after hidden surface removal, transparent bricks neither baked nor occluding, glow colors added. - Icons from its icon scene: 50 mm lens at 53.4/19.5 degrees, sun of 2.5 at 21/50.3 degrees with soft shadows, grey world light with occlusion; LOD 0's hidden surface removal and occlusion are reused for them. - Optional ground plane for hidden surface removal; stats.json per model and the previous version's previews kept for comparing. Budgets, applied live on config reload: max_cpu_percent (workers account their thread CPU time and sleep to stay under it, long renders included), worker_nice, max_memory_mb (jobs are estimated from their brick count and wait until they fit), max_model_bricks and pause_hours. /status and the traffic report show CPU, memory and throttling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -185,14 +185,16 @@ namespace UgcBricks {
|
||||
return it != m_Materials.end() ? it->second : Material{};
|
||||
}
|
||||
|
||||
std::shared_ptr<const std::vector<Geometry>> BrickLibrary::GetDesign(uint32_t design) {
|
||||
std::shared_ptr<const std::vector<Geometry>> BrickLibrary::GetDesign(uint32_t design, std::optional<uint32_t> lodLevel) {
|
||||
const uint32_t lod = std::min<uint32_t>(lodLevel.value_or(m_Lod), 2);
|
||||
const uint64_t key = (static_cast<uint64_t>(lod) << 32) | design;
|
||||
{
|
||||
std::lock_guard lock(m_Mutex);
|
||||
if (const auto it = m_Designs.find(design); it != m_Designs.end()) return it->second;
|
||||
if (const auto it = m_Designs.find(key); it != m_Designs.end()) return it->second;
|
||||
}
|
||||
// Loaded outside the lock; two threads loading the same design at once is harmless
|
||||
auto parts = std::make_shared<std::vector<Geometry>>();
|
||||
const auto folder = "brickprimitives/lod" + std::to_string(m_Lod) + "/";
|
||||
const auto folder = "brickprimitives/lod" + std::to_string(lod) + "/";
|
||||
for (uint32_t index = 0; index < MAX_GEOMETRY_PARTS; index++) {
|
||||
const auto name = std::to_string(design) + ".g" + (index == 0 ? "" : std::to_string(index));
|
||||
const auto path = ResolvePath(m_Res, folder + name);
|
||||
@@ -202,7 +204,13 @@ namespace UgcBricks {
|
||||
if (!geometry) break;
|
||||
parts->push_back(std::move(*geometry));
|
||||
}
|
||||
if (parts->empty() && lod > 0) return GetDesign(design, lod - 1);
|
||||
std::lock_guard lock(m_Mutex);
|
||||
return m_Designs.emplace(design, std::move(parts)).first->second;
|
||||
return m_Designs.emplace(key, std::move(parts)).first->second;
|
||||
}
|
||||
|
||||
size_t BrickLibrary::CachedDesigns() const {
|
||||
std::lock_guard lock(m_Mutex);
|
||||
return m_Designs.size();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user