Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
504f2a2a4This file is pinned to the selected release. Download the original to open it in your design tool.
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
{
/// <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, TvS}"/> instance.</typeparam>
/// <typeparam name="TvG">
/// 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"/>.
/// <see cref="VertexColor1Texture2"/>.
/// <see cref="VertexColor2Texture2"/>.
/// </typeparam>
/// <typeparam name="TvS">
/// The vertex fragment type with Skin Joint Weights.
/// Valid types are:
/// <see cref="VertexEmpty"/>,
/// <see cref="VertexJoints4"/>,
/// <see cref="VertexJoints8"/>.
/// </typeparam>
public class MeshBuilder<TMaterial, TvG, TvM, TvS> : IMeshBuilder<TMaterial>
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<TvG, TvM, TvS>();
_VertexPreprocessor.SetSanitizerPreprocessors();
}
IMeshBuilder<TMaterial> IMeshBuilder<TMaterial>.Clone(Func<TMaterial, TMaterial> materialCloneCallback)
{
return new MeshBuilder<TMaterial, TvG, TvM, TvS>(this, materialCloneCallback);
}
public MeshBuilder<TMaterial, TvG, TvM, TvS> Clone(Func<TMaterial, TMaterial> materialCloneCallback = null)
{
return new MeshBuilder<TMaterial, TvG, TvM, TvS>(this, materialCloneCallback);
}
private MeshBuilder(MeshBuilder<TMaterial, TvG, TvM, TvS> other, Func<TMaterial, TMaterial> materialCloneCallback = null)
{
Guard.NotNull(other, nameof(other));
this.Name = other.Name;
this.Extras = other.Extras.DeepClone();
this._VertexPreprocessor = other._VertexPreprocessor;
foreach (var kvp in other._Primitives)
{
var material = kvp.Key.Material;
if (materialCloneCallback != null)
{
material = materialCloneCallback(material);
if (material == null) continue;
}
var key = (material, kvp.Key.PrimType);
if (_Primitives.TryGetValue(key, out PrimitiveBuilder<TMaterial, TvG, TvM, TvS> existing))
{
existing.AddPrimitive(kvp.Value, null);
}
else
{
_Primitives[key] = kvp.Value.Clone(this, material);
}
}
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly Dictionary<(TMaterial Material, int PrimType), PrimitiveBuilder<TMaterial, TvG, TvM, TvS>> _Primitives = new Dictionary<(TMaterial, int), PrimitiveBuilder<TMaterial, TvG, TvM, TvS>>();
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private VertexPreprocessor<TvG, TvM, TvS> _VertexPreprocessor;
#endregion
#region properties
public string Name { get; set; }
public IO.JsonContent Extras { get; set; }
public VertexPreprocessor<TvG, TvM, TvS> VertexPreprocessor
{
get => _VertexPreprocessor;
set => _VertexPreprocessor = value;
}
public IEnumerable<TMaterial> Materials => _Primitives.Keys.Select(item => item.Material).Distinct();
public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvG, TvM, TvS>> Primitives => _Primitives.Values;
IReadOnlyCollection<IPrimitiveReader<TMaterial>> IMeshBuilder<TMaterial>.Primitives => _Primitives.Values;
#endregion
#region API
public MorphTargetBuilder<TMaterial, TvG, TvS, TvM> UseMorphTarget(int index)
{
return new MorphTargetBuilder<TMaterial, TvG, TvS, TvM>(this, index);
}
IMorphTargetBuilder IMeshBuilder<TMaterial>.UseMorphTarget(int index)
{
return UseMorphTarget(index);
}
private PrimitiveBuilder<TMaterial, TvG, TvM, TvS> _UsePrimitive((TMaterial Material, int PrimType) key)
{
if (!_Primitives.TryGetValue(key, out PrimitiveBuilder<TMaterial, TvG, TvM, TvS> primitive))
{
if (key.PrimType == 1) primitive = new PointsPrimitiveBuilder<TMaterial, TvG, TvM, TvS>(this, key.Material);
if (key.PrimType == 2) primitive = new LinesPrimitiveBuilder<TMaterial, TvG, TvM, TvS>(this, key.Material);
if (key.PrimType == 3) primitive = new TrianglesPrimitiveBuilder<TMaterial, TvG, TvM, TvS>(this, key.Material);
Guard.NotNull(primitive, nameof(key));
_Primitives[key] = primitive;
}
return primitive;
}
public PrimitiveBuilder<TMaterial, TvG, TvM, TvS> UsePrimitive(TMaterial material, int primitiveVertexCount = 3)
{
Guard.NotNull(material, nameof(material));
Guard.MustBeBetweenOrEqualTo(primitiveVertexCount, 1, 3, nameof(primitiveVertexCount));
return _UsePrimitive((material, primitiveVertexCount));
}
IPrimitiveBuilder IMeshBuilder<TMaterial>.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<TMaterial, TvG, TvM, TvS> mesh, Func<TMaterial, TMaterial> materialTransform, Converter<VertexBuilder<TvG, TvM, TvS>, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
{
if (mesh == null) return;
if (materialTransform == null) materialTransform = m => m;
if (vertexTransform == null) vertexTransform = v => v;
AddMesh<TMaterial>(mesh, materialTransform, v => vertexTransform(VertexBuilder<TvG, TvM, TvS>.CreateFrom(v)));
}
public void AddMesh(IMeshBuilder<TMaterial> mesh, Matrix4x4 vertexTransform)
{
if (mesh == null) return;
if (vertexTransform == Matrix4x4.Identity)
{
AddMesh<TMaterial>(mesh, m => m, null);
return;
}
AddMesh<TMaterial>(mesh, m => m, v => VertexBuilder<TvG, TvM, TvS>.CreateFrom(v).TransformedBy(vertexTransform));
}
public void AddMesh(IMeshBuilder<TMaterial> mesh, Func<TMaterial, TMaterial> materialTransform, Converter<IVertexBuilder, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
{
if (mesh == null) return;
if (materialTransform == null) materialTransform = m => m;
AddMesh<TMaterial>(mesh, materialTransform, vertexTransform);
}
public void AddMesh<TSourceMaterial>(IMeshBuilder<TSourceMaterial> mesh, Func<TSourceMaterial, TMaterial> materialTransform, Converter<IVertexBuilder, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
{
if (mesh == null) return;
Guard.NotNull(materialTransform, nameof(materialTransform));
if (vertexTransform == null) vertexTransform = v => VertexBuilder<TvG, TvM, TvS>.CreateFrom(v);
foreach (var p in mesh.Primitives)
{
var materialKey = materialTransform(p.Material);
UsePrimitive(materialKey).AddPrimitive(p, vertexTransform);
}
}
/// <summary>
/// Transforms all the points of all the <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvS}"/>
/// of the this <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/> using the given lambfa function.
/// </summary>
/// <param name="vertexTransform">A lambda function to transform <see cref="VertexBuilder{TvP, TvM, TvS}"/> vertices.</param>
public void TransformVertices(Func<VertexBuilder<TvG, TvM, TvS>, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
{
foreach (var p in Primitives) p.TransformVertices(vertexTransform);
}
public void Validate()
{
foreach (var p in _Primitives.Values)
{
p.Validate();
}
}
#endregion
}
/// <summary>
/// Represents an utility class to help build meshes by adding primitives associated with a given material.
/// </summary>
/// <typeparam name="TvG">
/// 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"/>.
/// <see cref="VertexColor1Texture2"/>.
/// <see cref="VertexColor2Texture2"/>.
/// </typeparam>
/// <typeparam name="TvS">
/// The vertex fragment type with Skin Joint Weights.
/// Valid types are:
/// <see cref="VertexEmpty"/>,
/// <see cref="VertexJoints4"/>,
/// <see cref="VertexJoints8"/>.
/// </typeparam>
public class MeshBuilder<TvG, TvM, TvS> : MeshBuilder<Materials.MaterialBuilder, TvG, TvM, TvS>
where TvG : struct, IVertexGeometry
where TvM : struct, IVertexMaterial
where TvS : struct, IVertexSkinning
{
public MeshBuilder(string name = null)
: base(name) { }
}
/// <summary>
/// Represents an utility class to help build meshes by adding primitives associated with a given material.
/// </summary>
/// <typeparam name="TvG">
/// 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"/>.
/// <see cref="VertexColor1Texture2"/>.
/// <see cref="VertexColor2Texture2"/>.
/// </typeparam>
public class MeshBuilder<TvG, TvM> : MeshBuilder<Materials.MaterialBuilder, TvG, TvM, VertexEmpty>
where TvG : struct, IVertexGeometry
where TvM : struct, IVertexMaterial
{
public MeshBuilder(string name = null)
: base(name) { }
}
/// <summary>
/// Represents an utility class to help build meshes by adding primitives associated with a given material.
/// </summary>
/// <typeparam name="TvG">
/// 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<TvG> : MeshBuilder<Materials.MaterialBuilder, TvG, VertexEmpty, VertexEmpty>
where TvG : struct, IVertexGeometry
{
public MeshBuilder(string name = null)
: base(name) { }
}
}