mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-01 09:27:14 +00:00
feat: UGC server that makes and serves player models' meshes and icons
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>
This commit is contained in:
56
dUgcServer/UgcRender.h
Normal file
56
dUgcServer/UgcRender.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "UgcModel.h"
|
||||
|
||||
/**
|
||||
* A small software rasterizer (no GPU or display needed) for what the UGC server draws: the icons, and the renders
|
||||
* from many directions that find the faces nobody can see and bake ambient occlusion into the vertex colors.
|
||||
*/
|
||||
namespace UgcRender {
|
||||
// 8-bit RGBA, rows top to bottom, not premultiplied
|
||||
struct Image {
|
||||
int width{};
|
||||
int height{};
|
||||
std::vector<uint8_t> rgba;
|
||||
};
|
||||
|
||||
struct IconOptions {
|
||||
int size{ 128 };
|
||||
int supersample{ 4 };
|
||||
float yawDegrees{ 35.0f }; // camera around the model, from +Z towards +X
|
||||
float pitchDegrees{ 25.0f }; // camera above the model
|
||||
float fovDegrees{ 30.0f };
|
||||
float margin{ 1.03f }; // 1 fills the icon, more leaves a border
|
||||
glm::mat4 modelRotation{ 1.0f }; // applied to the model before the camera looks at it
|
||||
};
|
||||
|
||||
// The model drawn from the icon's camera, framed to fit, on a transparent background
|
||||
Image RenderIcon(const UgcModel::Model& model, const IconOptions& options);
|
||||
|
||||
struct OptimizeOptions {
|
||||
int resolution{ 1024 }; // of each direction's render
|
||||
bool removeHidden{ true };
|
||||
bool bakeAo{ true };
|
||||
float aoStrength{ 0.6f }; // 0 leaves the colors, 1 makes fully hidden corners black
|
||||
};
|
||||
|
||||
struct OptimizeResult {
|
||||
size_t trianglesBefore{};
|
||||
size_t trianglesRemoved{};
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the opaque mesh from 42 directions around it: triangles that show in none of them are removed (with a
|
||||
* conservative test, so small visible ones stay), and each vertex's share of the directions it can be seen from
|
||||
* darkens its color (ambient occlusion). Transparent bricks hide nothing but are darkened too.
|
||||
*/
|
||||
OptimizeResult Optimize(UgcModel::Model& model, const OptimizeOptions& options);
|
||||
|
||||
// The 42 directions Optimize renders from (an icosahedron's corners and edge centres), unit length
|
||||
std::vector<glm::vec3> SphereDirections();
|
||||
}
|
||||
Reference in New Issue
Block a user