mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
Why the glitter never moved: player models (LOT 14) are wrapped in weeblewobble.kfm (RenderComponentWrapper 9845), so the client makes them an LWOSkinnedRenderComponent, whose Run (0x00d6d3d0) updates the scene graph (and so any NiTextureTransformController) only while animation is enabled, and LWOModelBehaviorComponent::EnableAnimation (0x00be2740) turns it off for modelType 2, which every placed property model is. The root flags 0x102 added earlier are only read by the base render component. Nothing in a placed model's .nif can move. What does move: shader classes set globals in their own per-frame Run. Distortion Directional (Ocean) (mapShaders 79, Run 0x010b90c0) slides its texture layers by fixed shares of a tile a second, as the game's own pond ripples (S79__pond_ripplesShape). Glitter bricks now get a sparkle group, S79_GlitterSparkle_Model: their triangles lifted 0.005 off the brick, vertex colors white tinted by the brick, UVs placed per brick, alpha tested (ShaderCommon's alpha test phase, GREATEREQUAL 127), with a stored texture of flat sparkles at alpha 230: one layer's sparkle alone averages under the test, two meeting pass, so sparkles flash and go out as the layers cross. The flecks stay (LEGO-AnimUV, now without the controllers and flags that never ran). The icon and the dashboard's 3D view leave the sparkles out. New settings: shader_glitter_sparkle (79, 0 off), glitter_sparkle_size, glitter_sparkle_amount, glitter_sparkle_tint, glitter_sparkle_brightness; glitter_speed is now how fast sparkles flash (the sparkle tile). Only glitter output changes; non-glitter models are byte-identical. Check in game: reprocess a property with glitter models, then look at them from a few angles and distances, on each graphics quality: - sparkles flash on and off all over the glitter bricks, continuously - no flickering fight between the sparkles and the brick surface - transparent glitter bricks still see-through, flecks still visible - nothing drawn where there is no glitter brick; icons unchanged apart from the flecks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
3.6 KiB
C++
85 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "UgcGlitter.h"
|
|
#include "UgcModel.h"
|
|
#include "UgcRender.h"
|
|
|
|
/**
|
|
* The files the UGC server writes: the mesh as a Gamebryo .nif the client loads, icons as .png and .dds, and the
|
|
* client's .checksum files for its downloads. Pure (data in, bytes out).
|
|
*/
|
|
namespace UgcFormats {
|
|
struct NifShape {
|
|
std::string name;
|
|
const UgcModel::Mesh* mesh{};
|
|
bool transparent{};
|
|
};
|
|
|
|
/**
|
|
* A Gamebryo 20.3.0.9 file (user version 0, as the client's own meshes): a root NiNode named `rootName` with one
|
|
* NiTriShape per shape (at most 65535 vertices and triangles each: UgcModel::Split), with vertex colors that are
|
|
* the diffuse and ambient color (NiVertexColorProperty), a white NiMaterialProperty, and for transparent shapes an
|
|
* NiAlphaProperty blending with the vertex alpha.
|
|
*/
|
|
std::string WriteNif(const std::string& rootName, const std::vector<NifShape>& shapes);
|
|
|
|
struct NifLod {
|
|
float nearDistance{};
|
|
float farDistance{};
|
|
std::string name; // the level's node, e.g. LOD_0
|
|
std::vector<const UgcModel::Mesh*> pieces; // its shapes (UgcModel::Divide's pieces)
|
|
};
|
|
|
|
struct NifLodGroup {
|
|
std::string name; // S01_Opaque_Model: the NiLODNode and its shapes
|
|
bool transparent{};
|
|
std::vector<NifLod> lods;
|
|
// NiMaterialProperty's emissive color (grey) of the group's shapes; 0 the shared white material with none.
|
|
// The client's emissive shader (S46) lerps from the lit color to the vertex color by vertex alpha times its red.
|
|
float emissive{};
|
|
// The glitter of the UGC server's glitter groups (docs/UgcServer.md, "Glitter"): the shapes get UVs
|
|
// (UgcGlitter::Uv) and an NiTexturingProperty whose base map is the fleck texture stored in the file
|
|
// (NiSourceTexture, NiPersistentSrcTextureRendererData). Null: none.
|
|
const UgcGlitter::Params* glitter{};
|
|
// With `glitter`: the group is the sparkles over its pieces (the glitter bricks) instead: each piece lifted off
|
|
// along its normals, the sparkles' vertex colors, UVs for the sparkle texture, alpha tested (UgcGlitter.h)
|
|
bool sparkle{};
|
|
};
|
|
|
|
/**
|
|
* The layout LU Toolbox exports (setup_lod_data) and the game's own brick models (res/BrickModels/ndmade) have:
|
|
* the root node, an NiLODNode per group with NiRangeLODData holding each level's distances, a node per level and
|
|
* the level's shapes under it, named like the group. Properties as WriteNif; a group with
|
|
* an emissive color gets a material of its own, a glitter group the glitter texture's NiTexturingProperty (one
|
|
* for every glitter group of the file).
|
|
*/
|
|
std::string WriteLodNif(const std::string& rootName, const std::vector<NifLodGroup>& groups);
|
|
|
|
// PNG (8-bit RGBA)
|
|
std::string EncodePng(const UgcRender::Image& image);
|
|
|
|
// DDS as the client's own icons are: DXT5 (BC3), without mipmaps, header flags caps|height|width|pixel format|linear
|
|
// size (0x81007), caps texture (0x1000)
|
|
std::string EncodeDds(const UgcRender::Image& image);
|
|
|
|
// One 4x4 block (RGBA, 64 bytes, row by row) as DXT5's 16 bytes: alpha endpoints and 3-bit indices, then the
|
|
// color's two RGB565 endpoints and 2-bit indices
|
|
std::array<uint8_t, 16> EncodeDxt5Block(const std::array<uint8_t, 64>& rgba);
|
|
|
|
// Lowercase hex MD5 of `data`
|
|
std::string Md5Hex(std::string_view data);
|
|
|
|
// What the client reads from a UGC file's .checksum: the MD5 and size of the file as it is after inflating it
|
|
std::string ChecksumXml(std::string_view data);
|
|
|
|
// The MD5 (lowercase hex) and size a .checksum (ChecksumXml) holds; false when it doesn't hold both
|
|
bool ReadChecksumXml(std::string_view xml, std::string& md5, uint32_t& size);
|
|
}
|