Files
DarkflameServer/dUgcServer/Render/UgcIconPose.h
Aaron Kimbrell 7c32779e89 fix(ugc): transparent bricks drawn see-through in mixed models; dUgcServer in folders by role
- The client puts a shape in its sorted, blended pass only when its
  NiMaterialProperty alpha is under 0.99999 (ShaderCommon::GetAlphaFlags
  0x0109f5a0; the NiAlphaProperty blend flag isn't read); at 1.0 it's drawn
  solid with blending off. Transparent (and transparent glitter) shapes now
  get a material with alpha 0.9999, as the S01_Alpha shapes of the game's own
  brick models (res/BrickModels/ndmade) do; opaque shapes keep 1.0. Models
  with a transparent brick change; the others are byte for byte the same.
- dUgcServer's files move into Bricks/, Model/, Render/, Formats/ and
  Processing/ (the CMakeLists says what each holds); includes are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:26 -05:00

57 lines
2.5 KiB
C++

#pragma once
#include <vector>
#include <glm/glm.hpp>
/**
* Where the icon's camera is and how the model is turned for it, worked out the same way in the icon renderer and in
* the dashboard's pose editor (static/js/ugc-pose.js mirrors these functions, so its 3D view shows what the icon
* will). Angles are degrees. Pure.
*
* The model is turned first (ModelRotation, about its origin), then the camera looks at the centre of its bounds from
* CameraDirection, as far away as makes the bounding sphere fill the field of view, and last the picture is cropped to
* the model's projected bounds (Frame): scaled so the larger side fills the icon less the margin, then shifted.
*/
namespace UgcIconPose {
// From the model towards the camera: yaw around +Y from +Z towards +X, pitch up from the ground
glm::vec3 CameraDirection(float yawDegrees, float pitchDegrees);
// The inverse: {yaw, pitch} of a direction (need not be unit length)
glm::vec2 DirectionAngles(const glm::vec3& direction);
// The model's turn: yaw around +Y, then pitch around +X, then roll around +Z (R = Ry * Rx * Rz, three.js's 'YXZ' Euler order)
glm::mat4 ModelRotation(float yawDegrees, float pitchDegrees, float rollDegrees);
// The inverse: {yaw, pitch, roll} of a rotation (pitch in -90..90; at +-90 the roll is folded into the yaw)
glm::vec3 RotationAngles(const glm::mat4& rotation);
struct Camera {
float yawDegrees{};
float pitchDegrees{};
float fovDegrees{ 40.0f };
float margin{ 1.0f }; // 1: the model's larger projected side fills the icon
float offsetX{}; // share of the icon's width the model is moved right
float offsetY{}; // and up
};
struct Frame {
bool ok{};
glm::vec3 center{}; // of the model's bounds
float radius{}; // half their diagonal
glm::vec3 eye{};
float fov{}; // radians
float distance{};
glm::mat4 viewProjection{ 1.0f };
float centerX{}, centerY{}; // centre of the projected bounds (NDC)
float scale{ 1.0f }; // NDC -> icon: 2 / (larger projected side * margin)
glm::vec2 offset{};
// A point's place in the icon: x right and y down, 0..1 across it, and its depth (NDC z)
glm::vec3 IconPoint(const glm::vec3& position) const;
// The icon's square in the camera's NDC: {minX, minY, maxX, maxY}
glm::vec4 IconRect() const;
};
// The frame of an already turned model's vertices (any number of lists)
Frame Compute(const std::vector<const std::vector<glm::vec3>*>& positions, const Camera& camera);
}