mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-25 14:12:49 +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:
@@ -33,6 +33,7 @@ namespace UgcModel {
|
||||
std::vector<glm::vec3> positions;
|
||||
std::vector<glm::vec3> normals;
|
||||
std::vector<glm::vec4> colors; // sRGB, 0..1, alpha is opacity
|
||||
std::vector<glm::vec3> glow; // linear glow color per vertex (LU Toolbox's "Glow" layer); empty when nothing glows
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
size_t TriangleCount() const { return indices.size() / 3; }
|
||||
@@ -52,12 +53,55 @@ namespace UgcModel {
|
||||
bool Bounds(glm::vec3& min, glm::vec3& max) const;
|
||||
};
|
||||
|
||||
// The mesh of a model's parts
|
||||
Model Build(const std::vector<Part>& parts, UgcBricks::BrickLibrary& library);
|
||||
enum class ePalette {
|
||||
LU_TOOLBOX, // LU Toolbox's colors (UgcPalette), what its importer colors models with
|
||||
BRICKDB, // the brick database's Materials.xml
|
||||
};
|
||||
|
||||
struct BuildOptions {
|
||||
ePalette palette{ ePalette::LU_TOOLBOX };
|
||||
float colorVariation{ 5.0f }; // percent, 0: none (LU Toolbox: Apply Color Variation, 5%)
|
||||
uint64_t seed{}; // of the variation's random numbers
|
||||
float transparentOpacity{ 58.82f }; // percent, transparent bricks' vertex alpha (LU Toolbox palette only)
|
||||
bool icon{}; // the icon renderer's color corrections
|
||||
uint32_t lod{}; // brickprimitives level
|
||||
};
|
||||
|
||||
/**
|
||||
* The mesh of a model's parts, colored as LU Toolbox's Process Model does: a brick is transparent only when all of
|
||||
* its materials are, each material of each brick has its brightness shifted by the color variation (the same
|
||||
* random number for a brick's material in every LOD and every time), vertex colors are sRGB with alpha 1 for
|
||||
* opaque bricks and the transparent opacity for transparent ones.
|
||||
*/
|
||||
Model Build(const std::vector<Part>& parts, UgcBricks::BrickLibrary& library, const BuildOptions& options = {});
|
||||
|
||||
/**
|
||||
* The distance range (near, far) of each LOD LU Toolbox makes, for the brickprimitives levels in `used` (0 to 3),
|
||||
* from its settings (lod0..lod3, cull): its setup_lod_data, which picks the ranges by which levels are there.
|
||||
* {0, 0} for a level it has no range for.
|
||||
*/
|
||||
struct LodDistances {
|
||||
float lod0{ 0.0f };
|
||||
float lod1{ 50.0f };
|
||||
float lod2{ 100.0f };
|
||||
float lod3{ 280.0f };
|
||||
float cull{ 10000.0f };
|
||||
};
|
||||
std::vector<std::pair<float, float>> LodRanges(const std::vector<uint32_t>& used, const LodDistances& distances);
|
||||
|
||||
/**
|
||||
* Splits a mesh the way LU Toolbox's divide_mesh does while it has too many vertices (or triangles): at the mean
|
||||
* of its vertices along its longest side, keeping connected pieces whole. Falls back to Split when that can't
|
||||
* divide it.
|
||||
*/
|
||||
std::vector<Mesh> Divide(const Mesh& mesh, size_t maxVertices = 65535, size_t maxTriangles = 65535);
|
||||
|
||||
// A client .nif's meshes as one model (vertex colors times material color; transparent when blended)
|
||||
Model FromNif(const NifFile::Model& nif);
|
||||
|
||||
// Keeps the triangles whose flag is set (and the vertices they use)
|
||||
void KeepTriangles(Mesh& mesh, const std::vector<bool>& keep);
|
||||
|
||||
// Splits a mesh into pieces the .nif format can hold (at most `maxVertices` vertices and `maxTriangles` triangles)
|
||||
std::vector<Mesh> Split(const Mesh& mesh, size_t maxVertices = 65535, size_t maxTriangles = 65535);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user