// Copyright IHY. #pragma once #include "CoreMinimal.h" class UStaticMesh; /** * Rotation/translation-invariant geometry fingerprint of a single UStaticMesh, plus the * (lazily loaded) welded vertex cloud used for exact pairwise verification. * * Source is always LOD0 FMeshDescription (the imported authoring geometry) so the fingerprint * is stable across LOD reduction / Nanite / build settings. Render data is a tagged fallback. */ struct FOptMeshGeom { static constexpr int32 NumRadialBins = 16; bool bValid = false; bool bRenderDerived = false; // true if extracted from render data (compare only against other render-derived) int32 RawVertexCount = 0; int32 WeldedVertexCount = 0; // unique positions after welding -> the hard fingerprint gate int32 TriangleCount = 0; double SurfaceArea = 0.0; // local space, rigid-invariant, scales as s^2 double Volume = 0.0; // |signed tetrahedron sum|, scales as s^3 FVector Centroid = FVector::ZeroVector; // mean of welded positions (local origin for cov/hist) double EigenValues[3] = { 0.0, 0.0, 0.0 }; // covariance eigenvalues, sorted DESC (rotation-invariant) double RadialHistogram[NumRadialBins] = { 0.0 }; // normalized hist of |v - centroid| FBox LocalBounds = FBox(ForceInit); // Heavy payload, populated only when this mesh enters pairwise recovery (bWantPositions). TArray Positions; // welded unique positions, local space // Material / section signature (NOT part of geometry grouping; used to partition for HISM). uint32 MaterialHash = 0; int32 SectionCount = 0; }; namespace OptimizerGeometry { /** * Extract the fingerprint (and optionally the welded position cloud) for a static mesh. * @param WeldEps position weld grid in cm. * @param bWantPositions also fill Out.Positions (the expensive part) for verification. * @return false if no usable geometry could be read. */ bool ExtractGeom(const UStaticMesh* Mesh, float WeldEps, bool bWantPositions, FOptMeshGeom& Out); /** Symmetric 3x3 Jacobi eigensolver. Eigenvalues returned sorted DESC; eigenvectors as columns of OutVecs. */ void SymmetricEigen3x3(const double M[3][3], double OutValues[3], double OutVecs[3][3]); }