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

View File

@@ -0,0 +1,30 @@
namespace Nanomesh
{
public struct AttributeDefinition
{
public double weight;
public AttributeType type;
public int id;
public AttributeDefinition(AttributeType type)
{
this.weight = 1;
this.type = type;
this.id = 0;
}
public AttributeDefinition(AttributeType type, double weight)
{
this.weight = weight;
this.type = type;
this.id = 0;
}
public AttributeDefinition(AttributeType type, double weight, int id)
{
this.weight = weight;
this.type = type;
this.id = id;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace Nanomesh
{
public enum AttributeType
{
Normals,
UVs,
BoneWeights,
Colors,
}
public static class AttributeUtils
{
public static MetaAttributeList CreateAttributesFromDefinitions(IList<AttributeDefinition> attributeDefinitions)
{
MetaAttributeList attributeList = new EmptyMetaAttributeList(0);
for (int i = 0; i < attributeDefinitions.Count; i++)
{
switch (attributeDefinitions[i].type)
{
case AttributeType.Normals:
attributeList = attributeList.AddAttributeType<Vector3F>();
break;
case AttributeType.UVs:
attributeList = attributeList.AddAttributeType<Vector2F>();
break;
case AttributeType.BoneWeights:
attributeList = attributeList.AddAttributeType<BoneWeight>();
break;
default:
throw new NotImplementedException();
}
}
return attributeList;
}
}
}

View File

@@ -0,0 +1,406 @@
using System;
namespace Nanomesh
{
public unsafe interface IMetaAttribute
{
IMetaAttribute Set<K>(int index, K value) where K : unmanaged;
K Get<K>(int index) where K : unmanaged;
}
public unsafe struct MetaAttribute<T0> : IMetaAttribute
where T0 : unmanaged
{
public T0 attr0;
public MetaAttribute(T0 attr0)
{
this.attr0 = attr0;
}
public unsafe K Get<K>(int index) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
return kk[0];
}
default:
throw new ArgumentOutOfRangeException();
}
}
public IMetaAttribute Set<K>(int index, K value) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
default:
throw new ArgumentOutOfRangeException();
}
}
public override int GetHashCode()
{
return attr0.GetHashCode();
}
public override bool Equals(object obj)
{
return ((MetaAttribute<T0>)obj).attr0.Equals(attr0);
}
}
public unsafe struct MetaAttribute<T0, T1> : IMetaAttribute
where T0 : unmanaged
where T1 : unmanaged
{
public T0 attr0;
public T1 attr1;
public MetaAttribute(T0 attr0, T1 attr1)
{
this.attr0 = attr0;
this.attr1 = attr1;
}
public unsafe K Get<K>(int index) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
return kk[0];
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
return kk[0];
}
default:
throw new ArgumentOutOfRangeException();
}
}
public IMetaAttribute Set<K>(int index, K value) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
public unsafe struct MetaAttribute<T0, T1, T2> : IMetaAttribute
where T0 : unmanaged
where T1 : unmanaged
where T2 : unmanaged
{
public T0 attr0;
public T1 attr1;
public T2 attr2;
public MetaAttribute(T0 attr0, T1 attr1, T2 attr2)
{
this.attr0 = attr0;
this.attr1 = attr1;
this.attr2 = attr2;
}
public unsafe K Get<K>(int index) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
return kk[0];
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
return kk[0];
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
return kk[0];
}
default:
throw new ArgumentOutOfRangeException();
}
}
public IMetaAttribute Set<K>(int index, K value) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
public unsafe struct MetaAttribute<T0, T1, T2, T3> : IMetaAttribute
where T0 : unmanaged
where T1 : unmanaged
where T2 : unmanaged
where T3 : unmanaged
{
public T0 attr0;
public T1 attr1;
public T2 attr2;
public T3 attr3;
public MetaAttribute(T0 attr0, T1 attr1, T2 attr2, T3 attr3)
{
this.attr0 = attr0;
this.attr1 = attr1;
this.attr2 = attr2;
this.attr3 = attr3;
}
public unsafe K Get<K>(int index) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
return kk[0];
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
return kk[0];
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
return kk[0];
}
case 3:
fixed (T3* k = &attr3)
{
K* kk = (K*)k;
return kk[0];
}
default:
throw new ArgumentOutOfRangeException();
}
// Shorter idea but only C# 8.0:
//fixed (void* v = &this)
//{
// byte* b = (byte*)v;
// b += Positions[index];
// return ((K*)b)[0];
//};
}
public IMetaAttribute Set<K>(int index, K value) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 3:
fixed (T3* k = &attr3)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
public unsafe struct MetaAttribute<T0, T1, T2, T3, T4> : IMetaAttribute
where T0 : unmanaged
where T1 : unmanaged
where T2 : unmanaged
where T3 : unmanaged
where T4 : unmanaged
{
public T0 attr0;
public T1 attr1;
public T2 attr2;
public T3 attr3;
public T4 attr4;
public MetaAttribute(T0 attr0, T1 attr1, T2 attr2, T3 attr3, T4 attr4)
{
this.attr0 = attr0;
this.attr1 = attr1;
this.attr2 = attr2;
this.attr3 = attr3;
this.attr4 = attr4;
}
public unsafe K Get<K>(int index) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
return kk[0];
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
return kk[0];
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
return kk[0];
}
case 3:
fixed (T3* k = &attr3)
{
K* kk = (K*)k;
return kk[0];
}
case 4:
fixed (T4* k = &attr4)
{
K* kk = (K*)k;
return kk[0];
}
default:
throw new ArgumentOutOfRangeException();
}
// Shorter idea but only C# 8.0:
//fixed (void* v = &this)
//{
// byte* b = (byte*)v;
// b += Positions[index];
// return ((K*)b)[0];
//};
}
public IMetaAttribute Set<K>(int index, K value) where K : unmanaged
{
switch (index)
{
case 0:
fixed (T0* k = &attr0)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 1:
fixed (T1* k = &attr1)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 2:
fixed (T2* k = &attr2)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 3:
fixed (T3* k = &attr3)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
case 4:
fixed (T4* k = &attr4)
{
K* kk = (K*)k;
kk[0] = value;
return this;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@@ -0,0 +1,448 @@
using System;
namespace Nanomesh
{
public abstract class MetaAttributeList
{
public abstract IMetaAttribute this[int index]
{
get;
set;
}
public abstract int Count { get; }
public abstract int CountPerAttribute { get; }
public abstract MetaAttributeList CreateNew(int length);
public abstract MetaAttributeList AddAttributeType<T>()
where T : unmanaged, IInterpolable<T>;
public abstract bool Equals(int indexA, int indexB, int attribute);
public abstract void Interpolate(int attribute, int indexA, int indexB, double ratio);
}
public class EmptyMetaAttributeList : MetaAttributeList
{
private readonly int _length;
public EmptyMetaAttributeList(int length)
{
_length = length;
}
public override IMetaAttribute this[int index]
{
get => throw new System.Exception();
set => throw new System.Exception();
}
public override MetaAttributeList CreateNew(int length) => new EmptyMetaAttributeList(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
return false;
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
throw new System.Exception();
}
public override MetaAttributeList AddAttributeType<T>()
{
return new MetaAttributeList<T>(_length);
}
public override int Count => 0;
public override int CountPerAttribute => 0;
}
public class MetaAttributeList<T0> : MetaAttributeList
where T0 : unmanaged, IInterpolable<T0>
{
private readonly MetaAttribute<T0>[] _attributes;
public MetaAttributeList(int length)
{
_attributes = new MetaAttribute<T0>[length];
}
public override IMetaAttribute this[int index]
{
get => _attributes[index];
set => _attributes[index] = (MetaAttribute<T0>)value;
}
public void Set(MetaAttribute<T0> value, int index)
{
_attributes[index] = value;
}
private void Get(MetaAttribute<T0> value, int index)
{
_attributes[index] = value;
}
public override MetaAttributeList CreateNew(int length) => new MetaAttributeList<T0>(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
switch (attribute)
{
case 0:
return _attributes[indexA].Get<T0>(0).Equals(_attributes[indexB].Get<T0>(0));
default:
throw new ArgumentOutOfRangeException();
}
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
_attributes[indexA].attr0 = _attributes[indexA].Get<T0>(0).Interpolate(_attributes[indexB].Get<T0>(0), ratio);
_attributes[indexB].attr0 = _attributes[indexA].attr0;
}
public override MetaAttributeList AddAttributeType<T>()
{
MetaAttributeList<T0, T> newAttributes = new MetaAttributeList<T0, T>(_attributes.Length);
for (int i = 0; i < Count; i++)
newAttributes.Set(new MetaAttribute<T0, T>(_attributes[i].attr0, default(T)), i);
return newAttributes;
}
public override int Count => _attributes.Length;
public override int CountPerAttribute => 1;
}
public class MetaAttributeList<T0, T1> : MetaAttributeList
where T0 : unmanaged, IInterpolable<T0>
where T1 : unmanaged, IInterpolable<T1>
{
private readonly MetaAttribute<T0, T1>[] _attributes;
public MetaAttributeList(int length)
{
_attributes = new MetaAttribute<T0, T1>[length];
}
public override IMetaAttribute this[int index]
{
get => _attributes[index];
set => _attributes[index] = (MetaAttribute<T0, T1>)value;
}
public void Set(MetaAttribute<T0, T1> value, int index)
{
_attributes[index] = value;
}
private void Get(MetaAttribute<T0, T1> value, int index)
{
_attributes[index] = value;
}
public override MetaAttributeList CreateNew(int length) => new MetaAttributeList<T0, T1>(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
switch (attribute)
{
case 0:
return _attributes[indexA].Get<T0>(0).Equals(_attributes[indexB].Get<T0>(0));
case 1:
return _attributes[indexA].Get<T1>(1).Equals(_attributes[indexB].Get<T1>(1));
default:
throw new ArgumentOutOfRangeException();
}
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
switch (attribute)
{
case 0:
_attributes[indexA].attr0 = _attributes[indexA].Get<T0>(0).Interpolate(_attributes[indexB].Get<T0>(0), ratio);
_attributes[indexB].attr0 = _attributes[indexA].attr0;
break;
case 1:
_attributes[indexA].attr1 = _attributes[indexA].Get<T1>(1).Interpolate(_attributes[indexB].Get<T1>(1), ratio);
_attributes[indexB].attr1 = _attributes[indexA].attr1;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public override MetaAttributeList AddAttributeType<T>()
{
MetaAttributeList<T0, T1, T> newAttributes = new MetaAttributeList<T0, T1, T>(_attributes.Length);
for (int i = 0; i < Count; i++)
newAttributes.Set(new MetaAttribute<T0, T1, T>(_attributes[i].attr0, _attributes[i].attr1, default(T)), i);
return newAttributes;
}
public override int Count => _attributes.Length;
public override int CountPerAttribute => 2;
}
public class MetaAttributeList<T0, T1, T2> : MetaAttributeList
where T0 : unmanaged, IInterpolable<T0>
where T1 : unmanaged, IInterpolable<T1>
where T2 : unmanaged, IInterpolable<T2>
{
private readonly MetaAttribute<T0, T1, T2>[] _attributes;
public MetaAttributeList(int length)
{
_attributes = new MetaAttribute<T0, T1, T2>[length];
}
public override IMetaAttribute this[int index]
{
get => _attributes[index];
set => _attributes[index] = (MetaAttribute<T0, T1, T2>)value;
}
public void Set(MetaAttribute<T0, T1, T2> value, int index)
{
_attributes[index] = value;
}
private void Get(MetaAttribute<T0, T1, T2> value, int index)
{
_attributes[index] = value;
}
public override MetaAttributeList CreateNew(int length) => new MetaAttributeList<T0, T1, T2>(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
switch (attribute)
{
case 0:
return _attributes[indexA].Get<T0>(0).Equals(_attributes[indexB].Get<T0>(0));
case 1:
return _attributes[indexA].Get<T1>(1).Equals(_attributes[indexB].Get<T1>(1));
case 2:
return _attributes[indexA].Get<T2>(2).Equals(_attributes[indexB].Get<T2>(2));
default:
throw new ArgumentOutOfRangeException();
}
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
switch (attribute)
{
case 0:
_attributes[indexA].attr0 = _attributes[indexA].Get<T0>(0).Interpolate(_attributes[indexB].Get<T0>(0), ratio);
_attributes[indexB].attr0 = _attributes[indexA].attr0;
break;
case 1:
_attributes[indexA].attr1 = _attributes[indexA].Get<T1>(1).Interpolate(_attributes[indexB].Get<T1>(1), ratio);
_attributes[indexB].attr1 = _attributes[indexA].attr1;
break;
case 2:
_attributes[indexA].attr2 = _attributes[indexA].Get<T2>(2).Interpolate(_attributes[indexB].Get<T2>(2), ratio);
_attributes[indexB].attr2 = _attributes[indexA].attr2;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public override MetaAttributeList AddAttributeType<T>()
{
MetaAttributeList<T0, T1, T2, T> newAttributes = new MetaAttributeList<T0, T1, T2, T>(_attributes.Length);
for (int i = 0; i < Count; i++)
newAttributes.Set(new MetaAttribute<T0, T1, T2, T>(_attributes[i].attr0, _attributes[i].attr1, _attributes[i].attr2, default(T)), i);
return newAttributes;
}
public override int Count => _attributes.Length;
public override int CountPerAttribute => 3;
}
public class MetaAttributeList<T0, T1, T2, T3> : MetaAttributeList
where T0 : unmanaged, IInterpolable<T0>
where T1 : unmanaged, IInterpolable<T1>
where T2 : unmanaged, IInterpolable<T2>
where T3 : unmanaged, IInterpolable<T3>
{
private readonly MetaAttribute<T0, T1, T2, T3>[] _attributes;
public MetaAttributeList(int length)
{
_attributes = new MetaAttribute<T0, T1, T2, T3>[length];
}
public override IMetaAttribute this[int index]
{
get => _attributes[index];
set => _attributes[index] = (MetaAttribute<T0, T1, T2, T3>)value;
}
public void Set(MetaAttribute<T0, T1, T2, T3> value, int index)
{
_attributes[index] = value;
}
private void Get(MetaAttribute<T0, T1, T2, T3> value, int index)
{
_attributes[index] = value;
}
public override MetaAttributeList CreateNew(int length) => new MetaAttributeList<T0, T1, T2, T3>(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
switch (attribute)
{
case 0:
return _attributes[indexA].Get<T0>(0).Equals(_attributes[indexB].Get<T0>(0));
case 1:
return _attributes[indexA].Get<T1>(1).Equals(_attributes[indexB].Get<T1>(1));
case 2:
return _attributes[indexA].Get<T2>(2).Equals(_attributes[indexB].Get<T2>(2));
case 3:
return _attributes[indexA].Get<T3>(3).Equals(_attributes[indexB].Get<T3>(3));
default:
throw new ArgumentOutOfRangeException();
}
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
switch (attribute)
{
case 0:
_attributes[indexA].attr0 = _attributes[indexA].Get<T0>(0).Interpolate(_attributes[indexB].Get<T0>(0), ratio);
_attributes[indexB].attr0 = _attributes[indexA].attr0;
break;
case 1:
_attributes[indexA].attr1 = _attributes[indexA].Get<T1>(1).Interpolate(_attributes[indexB].Get<T1>(1), ratio);
_attributes[indexB].attr1 = _attributes[indexA].attr1;
break;
case 2:
_attributes[indexA].attr2 = _attributes[indexA].Get<T2>(2).Interpolate(_attributes[indexB].Get<T2>(2), ratio);
_attributes[indexB].attr2 = _attributes[indexA].attr2;
break;
case 3:
_attributes[indexA].attr3 = _attributes[indexA].Get<T3>(3).Interpolate(_attributes[indexB].Get<T3>(3), ratio);
_attributes[indexB].attr3 = _attributes[indexA].attr3;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public override MetaAttributeList AddAttributeType<T>()
{
MetaAttributeList<T0, T1, T2, T3, T> newAttributes = new MetaAttributeList<T0, T1, T2, T3, T>(_attributes.Length);
for (int i = 0; i < Count; i++)
newAttributes.Set(new MetaAttribute<T0, T1, T2, T3, T>(_attributes[i].attr0, _attributes[i].attr1, _attributes[i].attr2, _attributes[i].attr3, default(T)), i);
return newAttributes;
}
public override int Count => _attributes.Length;
public override int CountPerAttribute => 4;
}
public class MetaAttributeList<T0, T1, T2, T3, T4> : MetaAttributeList
where T0 : unmanaged, IInterpolable<T0>
where T1 : unmanaged, IInterpolable<T1>
where T2 : unmanaged, IInterpolable<T2>
where T3 : unmanaged, IInterpolable<T3>
where T4 : unmanaged, IInterpolable<T4>
{
private readonly MetaAttribute<T0, T1, T2, T3, T4>[] _attributes;
public MetaAttributeList(int length)
{
_attributes = new MetaAttribute<T0, T1, T2, T3, T4>[length];
}
public override IMetaAttribute this[int index]
{
get => _attributes[index];
set => _attributes[index] = (MetaAttribute<T0, T1, T2, T3, T4>)value;
}
public void Set(MetaAttribute<T0, T1, T2, T3, T4> value, int index)
{
_attributes[index] = value;
}
private void Get(MetaAttribute<T0, T1, T2, T3, T4> value, int index)
{
_attributes[index] = value;
}
public override MetaAttributeList CreateNew(int length) => new MetaAttributeList<T0, T1, T2, T3, T4>(length);
public override unsafe bool Equals(int indexA, int indexB, int attribute)
{
switch (attribute)
{
case 0:
return _attributes[indexA].Get<T0>(0).Equals(_attributes[indexB].Get<T0>(0));
case 1:
return _attributes[indexA].Get<T1>(1).Equals(_attributes[indexB].Get<T1>(1));
case 2:
return _attributes[indexA].Get<T2>(2).Equals(_attributes[indexB].Get<T2>(2));
case 3:
return _attributes[indexA].Get<T3>(3).Equals(_attributes[indexB].Get<T3>(3));
case 4:
return _attributes[indexA].Get<T3>(3).Equals(_attributes[indexB].Get<T3>(4));
default:
throw new ArgumentOutOfRangeException();
}
}
public override void Interpolate(int attribute, int indexA, int indexB, double ratio)
{
switch (attribute)
{
case 0:
_attributes[indexA].attr0 = _attributes[indexA].Get<T0>(0).Interpolate(_attributes[indexB].Get<T0>(0), ratio);
_attributes[indexB].attr0 = _attributes[indexA].attr0;
break;
case 1:
_attributes[indexA].attr1 = _attributes[indexA].Get<T1>(1).Interpolate(_attributes[indexB].Get<T1>(1), ratio);
_attributes[indexB].attr1 = _attributes[indexA].attr1;
break;
case 2:
_attributes[indexA].attr2 = _attributes[indexA].Get<T2>(2).Interpolate(_attributes[indexB].Get<T2>(2), ratio);
_attributes[indexB].attr2 = _attributes[indexA].attr2;
break;
case 3:
_attributes[indexA].attr3 = _attributes[indexA].Get<T3>(3).Interpolate(_attributes[indexB].Get<T3>(3), ratio);
_attributes[indexB].attr3 = _attributes[indexA].attr3;
break;
case 4:
_attributes[indexA].attr4 = _attributes[indexA].Get<T4>(4).Interpolate(_attributes[indexB].Get<T4>(4), ratio);
_attributes[indexB].attr4 = _attributes[indexA].attr4;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public override MetaAttributeList AddAttributeType<T>()
{
throw new NotImplementedException();
}
public override int Count => _attributes.Length;
public override int CountPerAttribute => 5;
}
}