|
|
@@ -9,10 +9,23 @@ namespace SharpGLTF.Geometry
|
|
|
using Collections;
|
|
|
using VertexTypes;
|
|
|
|
|
|
+ public interface IMeshBuilder<TMaterial>
|
|
|
+ {
|
|
|
+ string Name { get; set; }
|
|
|
+
|
|
|
+ IReadOnlyCollection<TMaterial> Materials { get; }
|
|
|
+
|
|
|
+ IPrimitiveBuilder UsePrimitive(TMaterial material);
|
|
|
+
|
|
|
+ IPrimitive<TMaterial> GetPrimitive(TMaterial material);
|
|
|
+
|
|
|
+ void Validate();
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
- /// Represents an utility class to help build mesh primitives by adding triangles
|
|
|
+ /// Represents an utility class to help build meshes by adding primitives associated with a given material.
|
|
|
/// </summary>
|
|
|
- /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, JvS}"/> instance.</typeparam>
|
|
|
+ /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvS}"/> instance.</typeparam>
|
|
|
/// <typeparam name="TvP">
|
|
|
/// The vertex fragment type with Position, Normal and Tangent.
|
|
|
/// Valid types are:
|
|
|
@@ -28,7 +41,7 @@ namespace SharpGLTF.Geometry
|
|
|
/// <see cref="VertexTexture1"/>,
|
|
|
/// <see cref="VertexColor1Texture1"/>.
|
|
|
/// </typeparam>
|
|
|
- /// <typeparam name="JvS">
|
|
|
+ /// <typeparam name="TvS">
|
|
|
/// The vertex fragment type with Skin Joint Weights.
|
|
|
/// Valid types are:
|
|
|
/// <see cref="VertexEmpty"/>,
|
|
|
@@ -37,162 +50,82 @@ namespace SharpGLTF.Geometry
|
|
|
/// <see cref="VertexJoints16x4"/>,
|
|
|
/// <see cref="VertexJoints16x8"/>.
|
|
|
/// </typeparam>
|
|
|
- public class PrimitiveBuilder<TMaterial, TvP, TvM, JvS>
|
|
|
+ public class MeshBuilder<TMaterial, TvP, TvM, TvS> : IMeshBuilder<TMaterial>
|
|
|
where TvP : struct, IVertexPosition
|
|
|
where TvM : struct, IVertexMaterial
|
|
|
- where JvS : struct, IVertexSkinning
|
|
|
+ where TvS : struct, IVertexSkinning
|
|
|
{
|
|
|
#region lifecycle
|
|
|
|
|
|
- internal PrimitiveBuilder(MeshBuilder<TMaterial, TvP, TvM, JvS> mesh, TMaterial material, bool strict)
|
|
|
+ public MeshBuilder(string name = null)
|
|
|
{
|
|
|
- this._Scrict = strict;
|
|
|
- this._Mesh = mesh;
|
|
|
- this._Material = material;
|
|
|
+ this.Name = name;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region data
|
|
|
|
|
|
- private readonly bool _Scrict;
|
|
|
-
|
|
|
- private readonly MeshBuilder<TMaterial, TvP, TvM, JvS> _Mesh;
|
|
|
-
|
|
|
- private readonly TMaterial _Material;
|
|
|
-
|
|
|
- private readonly VertexList<(TvP, TvM, JvS)> _Vertices = new VertexList<(TvP, TvM, JvS)>();
|
|
|
- private readonly List<int> _Indices = new List<int>();
|
|
|
+ private readonly Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, TvS>> _Primitives = new Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, TvS>>();
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region properties
|
|
|
|
|
|
- public MeshBuilder<TMaterial, TvP, TvM, JvS> Mesh => _Mesh;
|
|
|
+ public Boolean StrictMode { get; set; }
|
|
|
|
|
|
- public TMaterial Material => _Material;
|
|
|
+ public string Name { get; set; }
|
|
|
|
|
|
- public IReadOnlyList<(TvP, TvM, JvS)> Vertices => _Vertices;
|
|
|
+ public IReadOnlyCollection<TMaterial> Materials => _Primitives.Keys;
|
|
|
|
|
|
- public IReadOnlyList<int> Indices => _Indices;
|
|
|
+ public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvP, TvM, TvS>> Primitives => _Primitives.Values;
|
|
|
|
|
|
- public IEnumerable<(int, int, int)> Triangles
|
|
|
- {
|
|
|
- get
|
|
|
- {
|
|
|
- for (int i = 2; i < _Indices.Count; i += 3)
|
|
|
- {
|
|
|
- yield return (_Indices[i - 2], _Indices[i - 1], _Indices[i]);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ string IMeshBuilder<TMaterial>.Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+
|
|
|
+ IReadOnlyCollection<TMaterial> IMeshBuilder<TMaterial>.Materials => throw new NotImplementedException();
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region API
|
|
|
|
|
|
- public int UseVertex((TvP, TvM, JvS) vertex)
|
|
|
+ private PrimitiveBuilder<TMaterial, TvP, TvM, TvS> _UsePrimitive(TMaterial material)
|
|
|
{
|
|
|
- if (_Scrict)
|
|
|
+ if (!_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, TvS> primitive))
|
|
|
{
|
|
|
- vertex.Item1.Validate();
|
|
|
- vertex.Item2.Validate();
|
|
|
- vertex.Item3.Validate();
|
|
|
- }
|
|
|
-
|
|
|
- return _Vertices.Use(vertex);
|
|
|
- }
|
|
|
-
|
|
|
- public void AddTriangle((TvP, TvM, JvS) a, (TvP, TvM, JvS) b, (TvP, TvM, JvS) c)
|
|
|
- {
|
|
|
- var aa = UseVertex(a);
|
|
|
- var bb = UseVertex(b);
|
|
|
- var cc = UseVertex(c);
|
|
|
-
|
|
|
- // check for degenerated triangles:
|
|
|
- if (aa == bb || aa == cc || bb == cc)
|
|
|
- {
|
|
|
- if (_Scrict) throw new ArgumentException($"Invalid triangle {aa} {bb} {cc}");
|
|
|
- return;
|
|
|
+ primitive = new PrimitiveBuilder<TMaterial, TvP, TvM, TvS>(this, material, StrictMode);
|
|
|
+ _Primitives[material] = primitive;
|
|
|
}
|
|
|
|
|
|
- _Indices.Add(aa);
|
|
|
- _Indices.Add(bb);
|
|
|
- _Indices.Add(cc);
|
|
|
- }
|
|
|
-
|
|
|
- public void AddTriangle((TvP, TvM) a, (TvP, TvM) b, (TvP, TvM) c)
|
|
|
- {
|
|
|
- AddTriangle((a.Item1, a.Item2, default), (b.Item1, b.Item2, default), (c.Item1, c.Item2, default));
|
|
|
- }
|
|
|
-
|
|
|
- public void AddTriangle((TvP, JvS) a, (TvP, JvS) b, (TvP, JvS) c)
|
|
|
- {
|
|
|
- AddTriangle((a.Item1, default, a.Item2), (b.Item1, default, b.Item2), (c.Item1, default, c.Item2));
|
|
|
- }
|
|
|
-
|
|
|
- public void AddTriangle(TvP a, TvP b, TvP c)
|
|
|
- {
|
|
|
- AddTriangle((a, default, default), (b, default, default), (c, default, default));
|
|
|
+ return primitive;
|
|
|
}
|
|
|
|
|
|
- public void AddPolygon(params (TvP, TvM, JvS)[] points)
|
|
|
- {
|
|
|
- for (int i = 2; i < points.Length; ++i)
|
|
|
- {
|
|
|
- AddTriangle(points[0], points[i - 1], points[i]);
|
|
|
- }
|
|
|
- }
|
|
|
+ public PrimitiveBuilder<TMaterial, TvP, TvM, TvS> UsePrimitive(TMaterial material) { return _UsePrimitive(material); }
|
|
|
|
|
|
- public void AddPolygon(params (TvP, TvM)[] points)
|
|
|
- {
|
|
|
- for (int i = 2; i < points.Length; ++i)
|
|
|
- {
|
|
|
- AddTriangle(points[0], points[i - 1], points[i]);
|
|
|
- }
|
|
|
- }
|
|
|
+ IPrimitiveBuilder IMeshBuilder<TMaterial>.UsePrimitive(TMaterial material) { return _UsePrimitive(material); }
|
|
|
|
|
|
- public void AddPolygon(params (TvP, JvS)[] points)
|
|
|
+ IPrimitive<TMaterial> IMeshBuilder<TMaterial>.GetPrimitive(TMaterial material)
|
|
|
{
|
|
|
- for (int i = 2; i < points.Length; ++i)
|
|
|
+ if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, TvS> primitive))
|
|
|
{
|
|
|
- AddTriangle(points[0], points[i - 1], points[i]);
|
|
|
+ return primitive;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- public void AddPolygon(params TvP[] points)
|
|
|
- {
|
|
|
- for (int i = 2; i < points.Length; ++i)
|
|
|
- {
|
|
|
- AddTriangle(points[0], points[i - 1], points[i]);
|
|
|
- }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- public void AddPrimitive(PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive, Matrix4x4 transform)
|
|
|
+ public void AddMesh(MeshBuilder<TMaterial, TvP, TvM, TvS> mesh, Matrix4x4 transform)
|
|
|
{
|
|
|
- if (primitive == null) throw new ArgumentNullException(nameof(primitive));
|
|
|
-
|
|
|
- foreach (var t in primitive.Triangles)
|
|
|
+ foreach (var p in mesh.Primitives)
|
|
|
{
|
|
|
- var a = primitive.Vertices[t.Item1];
|
|
|
- var b = primitive.Vertices[t.Item2];
|
|
|
- var c = primitive.Vertices[t.Item3];
|
|
|
-
|
|
|
- var aa = a.Item1; aa.Transform(transform); a.Item1 = aa;
|
|
|
- var bb = b.Item1; bb.Transform(transform); b.Item1 = bb;
|
|
|
- var cc = c.Item1; cc.Transform(transform); c.Item1 = cc;
|
|
|
-
|
|
|
- AddTriangle(a, b, c);
|
|
|
+ UsePrimitive(p.Material).AddPrimitive(p, transform);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void Validate()
|
|
|
{
|
|
|
- foreach (var v in _Vertices)
|
|
|
+ foreach (var p in _Primitives.Values)
|
|
|
{
|
|
|
- v.Item1.Validate();
|
|
|
- v.Item2.Validate();
|
|
|
- v.Item3.Validate();
|
|
|
+ p.Validate();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -202,7 +135,6 @@ namespace SharpGLTF.Geometry
|
|
|
/// <summary>
|
|
|
/// Represents an utility class to help build meshes by adding primitives associated with a given material.
|
|
|
/// </summary>
|
|
|
- /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, JvS}"/> instance.</typeparam>
|
|
|
/// <typeparam name="TvP">
|
|
|
/// The vertex fragment type with Position, Normal and Tangent.
|
|
|
/// Valid types are:
|
|
|
@@ -218,7 +150,7 @@ namespace SharpGLTF.Geometry
|
|
|
/// <see cref="VertexTexture1"/>,
|
|
|
/// <see cref="VertexColor1Texture1"/>.
|
|
|
/// </typeparam>
|
|
|
- /// <typeparam name="JvS">
|
|
|
+ /// <typeparam name="TvS">
|
|
|
/// The vertex fragment type with Skin Joint Weights.
|
|
|
/// Valid types are:
|
|
|
/// <see cref="VertexEmpty"/>,
|
|
|
@@ -227,79 +159,55 @@ namespace SharpGLTF.Geometry
|
|
|
/// <see cref="VertexJoints16x4"/>,
|
|
|
/// <see cref="VertexJoints16x8"/>.
|
|
|
/// </typeparam>
|
|
|
- public class MeshBuilder<TMaterial, TvP, TvM, JvS>
|
|
|
+ public class MeshBuilder<TvP, TvM, TvS> : MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvS>
|
|
|
where TvP : struct, IVertexPosition
|
|
|
where TvM : struct, IVertexMaterial
|
|
|
- where JvS : struct, IVertexSkinning
|
|
|
+ where TvS : struct, IVertexSkinning
|
|
|
{
|
|
|
- #region lifecycle
|
|
|
-
|
|
|
public MeshBuilder(string name = null)
|
|
|
- {
|
|
|
- this.Name = name;
|
|
|
- }
|
|
|
-
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region data
|
|
|
-
|
|
|
- private readonly Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, JvS>> _Primitives = new Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, JvS>>();
|
|
|
-
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region properties
|
|
|
-
|
|
|
- public Boolean StrictMode { get; set; }
|
|
|
-
|
|
|
- public string Name { get; set; }
|
|
|
-
|
|
|
- public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvP, TvM, JvS>> Primitives => _Primitives.Values;
|
|
|
-
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region API
|
|
|
-
|
|
|
- public PrimitiveBuilder<TMaterial, TvP, TvM, JvS> UsePrimitive(TMaterial material)
|
|
|
- {
|
|
|
- if (!_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive))
|
|
|
- {
|
|
|
- primitive = new PrimitiveBuilder<TMaterial, TvP, TvM, JvS>(this, material, StrictMode);
|
|
|
- _Primitives[material] = primitive;
|
|
|
- }
|
|
|
-
|
|
|
- return primitive;
|
|
|
- }
|
|
|
-
|
|
|
- public IEnumerable<(int, int, int)> GetTriangles(TMaterial material)
|
|
|
- {
|
|
|
- if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive)) return primitive.Triangles;
|
|
|
-
|
|
|
- return Enumerable.Empty<(int, int, int)>();
|
|
|
- }
|
|
|
-
|
|
|
- public IReadOnlyList<int> GetIndices(TMaterial material)
|
|
|
- {
|
|
|
- if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive)) return primitive.Indices;
|
|
|
-
|
|
|
- return new int[0];
|
|
|
- }
|
|
|
-
|
|
|
- public void AddMesh(MeshBuilder<TMaterial, TvP, TvM, JvS> mesh, Matrix4x4 transform)
|
|
|
- {
|
|
|
- foreach (var p in mesh.Primitives)
|
|
|
- {
|
|
|
- UsePrimitive(p.Material).AddPrimitive(p, transform);
|
|
|
- }
|
|
|
- }
|
|
|
+ : base(name) { }
|
|
|
+ }
|
|
|
|
|
|
- public void Validate()
|
|
|
- {
|
|
|
- foreach (var p in _Primitives.Values)
|
|
|
- {
|
|
|
- p.Validate();
|
|
|
- }
|
|
|
- }
|
|
|
+ /// <summary>
|
|
|
+ /// Represents an utility class to help build meshes by adding primitives associated with a given material.
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TvP">
|
|
|
+ /// The vertex fragment type with Position, Normal and Tangent.
|
|
|
+ /// Valid types are:
|
|
|
+ /// <see cref="VertexPosition"/>,
|
|
|
+ /// <see cref="VertexPositionNormal"/>,
|
|
|
+ /// <see cref="VertexPositionNormalTangent"/>.
|
|
|
+ /// </typeparam>
|
|
|
+ /// <typeparam name="TvM">
|
|
|
+ /// The vertex fragment type with Colors and Texture Coordinates.
|
|
|
+ /// Valid types are:
|
|
|
+ /// <see cref="VertexEmpty"/>,
|
|
|
+ /// <see cref="VertexColor1"/>,
|
|
|
+ /// <see cref="VertexTexture1"/>,
|
|
|
+ /// <see cref="VertexColor1Texture1"/>.
|
|
|
+ /// </typeparam>
|
|
|
+ public class MeshBuilder<TvP, TvM> : MeshBuilder<Materials.MaterialBuilder, TvP, TvM, VertexEmpty>
|
|
|
+ where TvP : struct, IVertexPosition
|
|
|
+ where TvM : struct, IVertexMaterial
|
|
|
+ {
|
|
|
+ public MeshBuilder(string name = null)
|
|
|
+ : base(name) { }
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ /// <summary>
|
|
|
+ /// Represents an utility class to help build meshes by adding primitives associated with a given material.
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TvP">
|
|
|
+ /// The vertex fragment type with Position, Normal and Tangent.
|
|
|
+ /// Valid types are:
|
|
|
+ /// <see cref="VertexPosition"/>,
|
|
|
+ /// <see cref="VertexPositionNormal"/>,
|
|
|
+ /// <see cref="VertexPositionNormalTangent"/>.
|
|
|
+ /// </typeparam>
|
|
|
+ public class MeshBuilder<TvP> : MeshBuilder<Materials.MaterialBuilder, TvP, VertexEmpty, VertexEmpty>
|
|
|
+ where TvP : struct, IVertexPosition
|
|
|
+ {
|
|
|
+ public MeshBuilder(string name = null)
|
|
|
+ : base(name) { }
|
|
|
}
|
|
|
}
|