using System; using System.Collections.Generic; using System.Text; using System.Linq; using System.Numerics; using SharpGLTF.Collections; using SharpGLTF.Geometry.VertexTypes; namespace SharpGLTF.Geometry { /// /// Represents an utility class to help build meshes by adding primitives associated with a given material. /// /// The material type used by this instance. /// /// The vertex fragment type with Position, Normal and Tangent. /// Valid types are: /// , /// , /// . /// /// /// The vertex fragment type with Colors and Texture Coordinates. /// Valid types are: /// , /// , /// , /// . /// . /// . /// /// /// The vertex fragment type with Skin Joint Weights. /// Valid types are: /// , /// , /// , /// , /// . /// public class MeshBuilder : IMeshBuilder where TvG : struct, IVertexGeometry where TvM : struct, IVertexMaterial where TvS : struct, IVertexSkinning { #region lifecycle public MeshBuilder(string name = null) { this.Name = name; // this is the recomended preprocesor for release/production _VertexPreprocessor = new VertexPreprocessor(); _VertexPreprocessor.SetSanitizerPreprocessors(); } #endregion #region data private readonly Dictionary<(TMaterial, int), PrimitiveBuilder> _Primitives = new Dictionary<(TMaterial, int), PrimitiveBuilder>(); private VertexPreprocessor _VertexPreprocessor; #endregion #region properties public string Name { get; set; } public VertexPreprocessor VertexPreprocessor { get => _VertexPreprocessor; set => _VertexPreprocessor = value; } public IEnumerable Materials => _Primitives.Keys.Select(item => item.Item1).Distinct(); public IReadOnlyCollection> Primitives => _Primitives.Values; IReadOnlyCollection> IMeshBuilder.Primitives => _Primitives.Values; #endregion #region API private PrimitiveBuilder _UsePrimitive((TMaterial, int) key) { if (!_Primitives.TryGetValue(key, out PrimitiveBuilder primitive)) { primitive = new PrimitiveBuilder(this, key.Item1, key.Item2); _Primitives[key] = primitive; } return primitive; } public PrimitiveBuilder UsePrimitive(TMaterial material, int primitiveVertexCount = 3) { Guard.NotNull(material, nameof(material)); Guard.MustBeBetweenOrEqualTo(primitiveVertexCount, 1, 3, nameof(primitiveVertexCount)); return _UsePrimitive((material, primitiveVertexCount)); } IPrimitiveBuilder IMeshBuilder.UsePrimitive(TMaterial material, int primitiveVertexCount) { Guard.NotNull(material, nameof(material)); Guard.MustBeBetweenOrEqualTo(primitiveVertexCount, 1, 3, nameof(primitiveVertexCount)); return _UsePrimitive((material, primitiveVertexCount)); } public void AddMesh(MeshBuilder mesh, Func materialTransform, Func, VertexBuilder> vertexTransform) { if (mesh == null) return; Guard.NotNull(materialTransform, nameof(materialTransform)); foreach (var p in mesh.Primitives) { var materialKey = materialTransform(p.Material); UsePrimitive(materialKey).AddPrimitive(p, vertexTransform); } } /// /// Transforms all the points of all the /// of the this using the given lambfa function. /// /// A lambda function to transform vertices. public void TransformVertices(Func, VertexBuilder> vertexTransform) { foreach (var p in Primitives) p.TransformVertices(vertexTransform); } public void Validate() { foreach (var p in _Primitives.Values) { p.Validate(); } } #endregion } /// /// Represents an utility class to help build meshes by adding primitives associated with a given material. /// /// /// The vertex fragment type with Position, Normal and Tangent. /// Valid types are: /// , /// , /// . /// /// /// The vertex fragment type with Colors and Texture Coordinates. /// Valid types are: /// , /// , /// , /// . /// . /// . /// /// /// The vertex fragment type with Skin Joint Weights. /// Valid types are: /// , /// , /// , /// , /// . /// public class MeshBuilder : MeshBuilder where TvG : struct, IVertexGeometry where TvM : struct, IVertexMaterial where TvS : struct, IVertexSkinning { public MeshBuilder(string name = null) : base(name) { } } /// /// Represents an utility class to help build meshes by adding primitives associated with a given material. /// /// /// The vertex fragment type with Position, Normal and Tangent. /// Valid types are: /// , /// , /// . /// /// /// The vertex fragment type with Colors and Texture Coordinates. /// Valid types are: /// , /// , /// , /// . /// . /// . /// public class MeshBuilder : MeshBuilder where TvG : struct, IVertexGeometry where TvM : struct, IVertexMaterial { public MeshBuilder(string name = null) : base(name) { } } /// /// Represents an utility class to help build meshes by adding primitives associated with a given material. /// /// /// The vertex fragment type with Position, Normal and Tangent. /// Valid types are: /// , /// , /// . /// public class MeshBuilder : MeshBuilder where TvG : struct, IVertexGeometry { public MeshBuilder(string name = null) : base(name) { } } }