Files
LightlessClient/LightlessSync/ThirdParty/Nanomesh/Algo/Decimation/SceneDecimator.cs
2026-01-19 09:50:54 +09:00

72 lines
2.3 KiB
C#

using System.Collections.Generic;
using System.Linq;
namespace Nanomesh
{
public class SceneDecimator
{
private class ModifierAndOccurrences
{
public int occurrences = 1;
public DecimateModifier modifier = new DecimateModifier();
}
private Dictionary<ConnectedMesh, ModifierAndOccurrences> _modifiers;
public void Initialize(IEnumerable<ConnectedMesh> meshes)
{
_modifiers = new Dictionary<ConnectedMesh, ModifierAndOccurrences>();
foreach (ConnectedMesh mesh in meshes)
{
ModifierAndOccurrences modifier;
if (_modifiers.ContainsKey(mesh))
{
modifier = _modifiers[mesh];
modifier.occurrences++;
}
else
{
_modifiers.Add(mesh, modifier = new ModifierAndOccurrences());
//System.Console.WriteLine($"Faces:{mesh.FaceCount}");
modifier.modifier.Initialize(mesh);
}
_faceCount += mesh.FaceCount;
}
_initalFaceCount = _faceCount;
}
private int _faceCount;
private int _initalFaceCount;
public void DecimateToRatio(float targetTriangleRatio)
{
targetTriangleRatio = MathF.Clamp(targetTriangleRatio, 0f, 1f);
DecimateToPolycount((int)MathF.Round(targetTriangleRatio * _initalFaceCount));
}
public void DecimatePolycount(int polycount)
{
DecimateToPolycount((int)MathF.Round(_initalFaceCount - polycount));
}
public void DecimateToPolycount(int targetTriangleCount)
{
//System.Console.WriteLine($"Faces:{_faceCount} Target:{targetTriangleCount}");
while (_faceCount > targetTriangleCount)
{
KeyValuePair<ConnectedMesh, ModifierAndOccurrences> pair = _modifiers.OrderBy(x => x.Value.modifier.GetMinimumError()).First();
int facesBefore = pair.Key.FaceCount;
pair.Value.modifier.Iterate();
if (facesBefore == pair.Key.FaceCount)
break; // Exit !
_faceCount -= (facesBefore - pair.Key.FaceCount) * pair.Value.occurrences;
}
}
}
}