MeshBuilder.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Linq;
  5. using System.Numerics;
  6. using SharpGLTF.Collections;
  7. using SharpGLTF.Geometry.VertexTypes;
  8. namespace SharpGLTF.Geometry
  9. {
  10. /// <summary>
  11. /// Represents an utility class to help build meshes by adding primitives associated with a given material.
  12. /// </summary>
  13. /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvS}"/> instance.</typeparam>
  14. /// <typeparam name="TvG">
  15. /// The vertex fragment type with Position, Normal and Tangent.
  16. /// Valid types are:
  17. /// <see cref="VertexPosition"/>,
  18. /// <see cref="VertexPositionNormal"/>,
  19. /// <see cref="VertexPositionNormalTangent"/>.
  20. /// </typeparam>
  21. /// <typeparam name="TvM">
  22. /// The vertex fragment type with Colors and Texture Coordinates.
  23. /// Valid types are:
  24. /// <see cref="VertexEmpty"/>,
  25. /// <see cref="VertexColor1"/>,
  26. /// <see cref="VertexTexture1"/>,
  27. /// <see cref="VertexColor1Texture1"/>.
  28. /// <see cref="VertexColor1Texture2"/>.
  29. /// <see cref="VertexColor2Texture2"/>.
  30. /// </typeparam>
  31. /// <typeparam name="TvS">
  32. /// The vertex fragment type with Skin Joint Weights.
  33. /// Valid types are:
  34. /// <see cref="VertexEmpty"/>,
  35. /// <see cref="VertexJoints8x4"/>,
  36. /// <see cref="VertexJoints8x8"/>,
  37. /// <see cref="VertexJoints16x4"/>,
  38. /// <see cref="VertexJoints16x8"/>.
  39. /// </typeparam>
  40. public class MeshBuilder<TMaterial, TvG, TvM, TvS> : IMeshBuilder<TMaterial>
  41. where TvG : struct, IVertexGeometry
  42. where TvM : struct, IVertexMaterial
  43. where TvS : struct, IVertexSkinning
  44. {
  45. #region lifecycle
  46. public MeshBuilder(string name = null)
  47. {
  48. this.Name = name;
  49. // this is the recomended preprocesor for release/production
  50. _VertexPreprocessor = new VertexPreprocessor<TvG, TvM, TvS>();
  51. _VertexPreprocessor.SetSanitizerPreprocessors();
  52. }
  53. #endregion
  54. #region data
  55. private readonly Dictionary<(TMaterial, int), PrimitiveBuilder<TMaterial, TvG, TvM, TvS>> _Primitives = new Dictionary<(TMaterial, int), PrimitiveBuilder<TMaterial, TvG, TvM, TvS>>();
  56. private VertexPreprocessor<TvG, TvM, TvS> _VertexPreprocessor;
  57. #endregion
  58. #region properties
  59. public string Name { get; set; }
  60. public VertexPreprocessor<TvG, TvM, TvS> VertexPreprocessor
  61. {
  62. get => _VertexPreprocessor;
  63. set => _VertexPreprocessor = value;
  64. }
  65. public IEnumerable<TMaterial> Materials => _Primitives.Keys.Select(item => item.Item1).Distinct();
  66. public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvG, TvM, TvS>> Primitives => _Primitives.Values;
  67. IReadOnlyCollection<IPrimitive<TMaterial>> IMeshBuilder<TMaterial>.Primitives => _Primitives.Values;
  68. #endregion
  69. #region API
  70. private PrimitiveBuilder<TMaterial, TvG, TvM, TvS> _UsePrimitive((TMaterial, int) key)
  71. {
  72. if (!_Primitives.TryGetValue(key, out PrimitiveBuilder<TMaterial, TvG, TvM, TvS> primitive))
  73. {
  74. primitive = new PrimitiveBuilder<TMaterial, TvG, TvM, TvS>(this, key.Item1, key.Item2);
  75. _Primitives[key] = primitive;
  76. }
  77. return primitive;
  78. }
  79. public PrimitiveBuilder<TMaterial, TvG, TvM, TvS> UsePrimitive(TMaterial material, int primitiveVertexCount = 3)
  80. {
  81. Guard.NotNull(material, nameof(material));
  82. Guard.MustBeBetweenOrEqualTo(primitiveVertexCount, 1, 3, nameof(primitiveVertexCount));
  83. return _UsePrimitive((material, primitiveVertexCount));
  84. }
  85. IPrimitiveBuilder IMeshBuilder<TMaterial>.UsePrimitive(TMaterial material, int primitiveVertexCount)
  86. {
  87. Guard.NotNull(material, nameof(material));
  88. Guard.MustBeBetweenOrEqualTo(primitiveVertexCount, 1, 3, nameof(primitiveVertexCount));
  89. return _UsePrimitive((material, primitiveVertexCount));
  90. }
  91. public void AddMesh(MeshBuilder<TMaterial, TvG, TvM, TvS> mesh, Func<TMaterial, TMaterial> materialTransform, Func<VertexBuilder<TvG, TvM, TvS>, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
  92. {
  93. if (mesh == null) return;
  94. Guard.NotNull(materialTransform, nameof(materialTransform));
  95. foreach (var p in mesh.Primitives)
  96. {
  97. var materialKey = materialTransform(p.Material);
  98. UsePrimitive(materialKey).AddPrimitive(p, vertexTransform);
  99. }
  100. }
  101. /// <summary>
  102. /// Transforms all the points of all the <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvS}"/>
  103. /// of the this <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/> using the given lambfa function.
  104. /// </summary>
  105. /// <param name="vertexTransform">A lambda function to transform <see cref="VertexBuilder{TvP, TvM, TvS}"/> vertices.</param>
  106. public void TransformVertices(Func<VertexBuilder<TvG, TvM, TvS>, VertexBuilder<TvG, TvM, TvS>> vertexTransform)
  107. {
  108. foreach (var p in Primitives) p.TransformVertices(vertexTransform);
  109. }
  110. public void Validate()
  111. {
  112. foreach (var p in _Primitives.Values)
  113. {
  114. p.Validate();
  115. }
  116. }
  117. #endregion
  118. }
  119. /// <summary>
  120. /// Represents an utility class to help build meshes by adding primitives associated with a given material.
  121. /// </summary>
  122. /// <typeparam name="TvG">
  123. /// The vertex fragment type with Position, Normal and Tangent.
  124. /// Valid types are:
  125. /// <see cref="VertexPosition"/>,
  126. /// <see cref="VertexPositionNormal"/>,
  127. /// <see cref="VertexPositionNormalTangent"/>.
  128. /// </typeparam>
  129. /// <typeparam name="TvM">
  130. /// The vertex fragment type with Colors and Texture Coordinates.
  131. /// Valid types are:
  132. /// <see cref="VertexEmpty"/>,
  133. /// <see cref="VertexColor1"/>,
  134. /// <see cref="VertexTexture1"/>,
  135. /// <see cref="VertexColor1Texture1"/>.
  136. /// <see cref="VertexColor1Texture2"/>.
  137. /// <see cref="VertexColor2Texture2"/>.
  138. /// </typeparam>
  139. /// <typeparam name="TvS">
  140. /// The vertex fragment type with Skin Joint Weights.
  141. /// Valid types are:
  142. /// <see cref="VertexEmpty"/>,
  143. /// <see cref="VertexJoints8x4"/>,
  144. /// <see cref="VertexJoints8x8"/>,
  145. /// <see cref="VertexJoints16x4"/>,
  146. /// <see cref="VertexJoints16x8"/>.
  147. /// </typeparam>
  148. public class MeshBuilder<TvG, TvM, TvS> : MeshBuilder<Materials.MaterialBuilder, TvG, TvM, TvS>
  149. where TvG : struct, IVertexGeometry
  150. where TvM : struct, IVertexMaterial
  151. where TvS : struct, IVertexSkinning
  152. {
  153. public MeshBuilder(string name = null)
  154. : base(name) { }
  155. }
  156. /// <summary>
  157. /// Represents an utility class to help build meshes by adding primitives associated with a given material.
  158. /// </summary>
  159. /// <typeparam name="TvG">
  160. /// The vertex fragment type with Position, Normal and Tangent.
  161. /// Valid types are:
  162. /// <see cref="VertexPosition"/>,
  163. /// <see cref="VertexPositionNormal"/>,
  164. /// <see cref="VertexPositionNormalTangent"/>.
  165. /// </typeparam>
  166. /// <typeparam name="TvM">
  167. /// The vertex fragment type with Colors and Texture Coordinates.
  168. /// Valid types are:
  169. /// <see cref="VertexEmpty"/>,
  170. /// <see cref="VertexColor1"/>,
  171. /// <see cref="VertexTexture1"/>,
  172. /// <see cref="VertexColor1Texture1"/>.
  173. /// <see cref="VertexColor1Texture2"/>.
  174. /// <see cref="VertexColor2Texture2"/>.
  175. /// </typeparam>
  176. public class MeshBuilder<TvG, TvM> : MeshBuilder<Materials.MaterialBuilder, TvG, TvM, VertexEmpty>
  177. where TvG : struct, IVertexGeometry
  178. where TvM : struct, IVertexMaterial
  179. {
  180. public MeshBuilder(string name = null)
  181. : base(name) { }
  182. }
  183. /// <summary>
  184. /// Represents an utility class to help build meshes by adding primitives associated with a given material.
  185. /// </summary>
  186. /// <typeparam name="TvG">
  187. /// The vertex fragment type with Position, Normal and Tangent.
  188. /// Valid types are:
  189. /// <see cref="VertexPosition"/>,
  190. /// <see cref="VertexPositionNormal"/>,
  191. /// <see cref="VertexPositionNormalTangent"/>.
  192. /// </typeparam>
  193. public class MeshBuilder<TvG> : MeshBuilder<Materials.MaterialBuilder, TvG, VertexEmpty, VertexEmpty>
  194. where TvG : struct, IVertexGeometry
  195. {
  196. public MeshBuilder(string name = null)
  197. : base(name) { }
  198. }
  199. }