A model with no bricks has nothing to make: it gets its own state
(is_optimized = 3), isn't counted as a failure or retried, shows as Empty
on the UGC page (with its own filter and count), in the status and in
Prometheus, and its downloads answer 404 like HKX. State names come from
the enum (magic_enum). Migrations dlu/mysql/87 and dlu/sqlite/70 move the
rows that failed only because they had no bricks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compared block by block with res/BrickModels/ndmade (and nif.xml for
20.3.0.9, LU's version, user version 0): every shape now has the same four
properties in the same order (material with glossiness 4, alpha blending by
the vertex alpha, specular off, vertex colors as ambient and diffuse), nodes
have flags 0x110 and shapes 0x10. A generated NIF put in place of a game
model and spawned in the 1.10.64 client renders with its colors.
Readers treat a blended shape as transparent only where it is see-through
(material or vertex alpha below 1), for the icons and the 3D view.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LU Toolbox's Combine Transparent is off by default, so each transparent brick
is its own object and shape (the client can sort them). combine_transparent=1
joins them as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
A new server (dUgcServer, started by master with enable_ugc_server=1) that
takes unprocessed ugc and ugc_modular_build rows from the database and makes
what the client downloads with UGCUSE3DSERVICES: an optimized NIF (hidden
faces removed, ambient occlusion baked into vertex colors) and a 128px DDS
icon for player models, rendered by a software rasterizer from the client's
LDD brick primitives, and icons for cars and rockets assembled from their
modules per ModularBuildComponent/ModuleComponent. It serves them, with the
models' LXFML, over HTTP in the client's UGCC<dc>/3DOPTIMIZED and
IMAGE128DDS layout with .gz and .checksum files, and keeps its folder under
a size cap.
Processing state lives in ugc.is_optimized plus new processed_at,
process_attempts and process_error columns (and the same on
ugc_modular_build). ServiceType::UGC is appended. NifFile moves to dCommon
and records named node transforms for the modules' attach points.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>