reworked mesh decimation yes

This commit is contained in:
2026-01-19 09:50:54 +09:00
parent b57d54d69c
commit 54d6a0a1a4
74 changed files with 15788 additions and 8308 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
using System;
namespace Nanomesh
{
public partial class DecimateModifier
{
public class EdgeCollapse : IComparable<EdgeCollapse>, IEquatable<EdgeCollapse>
{
public int posA;
public int posB;
public Vector3 result;
public double error;
private double _weight = -1;
public ref double Weight => ref _weight;
public void SetWeight(double weight)
{
_weight = weight;
}
public EdgeCollapse(int posA, int posB)
{
this.posA = posA;
this.posB = posB;
}
public override int GetHashCode()
{
unchecked
{
return posA + posB;
}
}
public override bool Equals(object obj)
{
return Equals((EdgeCollapse)obj);
}
public bool Equals(EdgeCollapse pc)
{
if (ReferenceEquals(pc, null))
return false;
if (ReferenceEquals(this, pc))
{
return true;
}
else
{
return (posA == pc.posA && posB == pc.posB) || (posA == pc.posB && posB == pc.posA);
}
}
public int CompareTo(EdgeCollapse other)
{
return error > other.error ? 1 : error < other.error ? -1 : 0;
}
public static bool operator >(EdgeCollapse x, EdgeCollapse y)
{
return x.error > y.error;
}
public static bool operator >=(EdgeCollapse x, EdgeCollapse y)
{
return x.error >= y.error;
}
public static bool operator <(EdgeCollapse x, EdgeCollapse y)
{
return x.error < y.error;
}
public static bool operator <=(EdgeCollapse x, EdgeCollapse y)
{
return x.error <= y.error;
}
public override string ToString()
{
return $"<A:{posA} B:{posB} error:{error} topology:{_weight}>";
}
}
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Nanomesh
{
public partial class DecimateModifier
{
private class EdgeComparer : IComparer<EdgeCollapse>
{
public int Compare(EdgeCollapse x, EdgeCollapse y)
{
return x.CompareTo(y);
}
}
}
}

View File

@@ -0,0 +1,72 @@
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;
}
}
}
}