Sfoglia il codice sorgente

Comments and small fixes.
WIP on normals and tangents builder.

Vicente Penades 6 anni fa
parent
commit
587963c3a9

+ 8 - 1
src/SharpGLTF.Toolkit/Geometry/PackedMeshBuilder.cs

@@ -16,6 +16,13 @@ namespace SharpGLTF.Geometry
     {
         #region lifecycle
 
+        /// <summary>
+        /// Converts a collection of <see cref="IMeshBuilder{TMaterial}"/> meshes into a collection of <see cref="PackedMeshBuilder{TMaterial}"/> meshes,
+        /// ensuring that the resources are shared across all meshes.
+        /// </summary>
+        /// <param name="meshBuilders">A collection of <see cref="IMeshBuilder{TMaterial}"/> meshes.</param>
+        /// <param name="prefferStrided">true to create strided vertex buffers.</param>
+        /// <returns>A collectio of <see cref="PackedMeshBuilder{TMaterial}"/> meshes.</returns>
         internal static IEnumerable<PackedMeshBuilder<TMaterial>> CreatePackedMeshes(IEnumerable<IMeshBuilder<TMaterial>> meshBuilders, bool prefferStrided)
         {
             try
@@ -41,7 +48,7 @@ namespace SharpGLTF.Geometry
                     var dstPrim = dstMesh.AddPrimitive(srcPrim.Material, srcPrim.VerticesPerPrimitive);
 
                     bool useStrided = prefferStrided;
-                    if (srcPrim.MorphTargets.Count > 0) useStrided = false;
+                    if (srcPrim.MorphTargets.Count > 0) useStrided = false; // if the primitive has morphing, it is better not to use strided vertex buffers.
 
                     if (useStrided) dstPrim.SetStridedVertices(srcPrim, jointEncoding);
                     else dstPrim.SetStreamedVertices(srcPrim, jointEncoding);

+ 88 - 0
src/SharpGLTF.Toolkit/Geometry/PrimitiveBuilder.cs

@@ -791,4 +791,92 @@ namespace SharpGLTF.Geometry
 
         #endregion
     }
+
+    /// <summary>
+    /// Helper class used to calculate Normals and Tangents of missing meshes.
+    /// </summary>
+    /// <typeparam name="TMaterial">default material</typeparam>
+    class MeshPrimitiveNormalsAndTangents<TMaterial> : VertexNormalsFactory.IMeshPrimitive, VertexTangentsFactory.IMeshPrimitive
+    {
+        #region constructor
+
+        // TODO: we need a solution for morph targets.
+
+        public static IReadOnlyDictionary<IPrimitiveReader<TMaterial>, MeshPrimitiveNormalsAndTangents<TMaterial>> GenerateNormalsTangents(IMeshBuilder<TMaterial> mesh)
+        {
+            var pairs = mesh.Primitives
+                .Where(item => item.VerticesPerPrimitive > 2)
+                .ToDictionary(p => p, p => new MeshPrimitiveNormalsAndTangents<TMaterial>(p));
+
+            // we can safaly generate both sets because MeshPrimitiveNormalsAndTangents will still return the good normals and tangets if they exist.
+
+            VertexNormalsFactory.CalculateSmoothNormals(pairs.Values.ToList());
+            VertexTangentsFactory.CalculateTangents(pairs.Values.ToList());
+
+            return pairs;
+        }
+
+        public MeshPrimitiveNormalsAndTangents(IPrimitiveReader<TMaterial> source)
+        {
+            _Source = source;
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly IPrimitiveReader<TMaterial> _Source;
+        private Vector3[] _Normals;
+        private Vector4[] _Tangents;
+
+        #endregion
+
+        #region API
+
+        public int VertexCount => _Source.Vertices.Count;
+
+        public IEnumerable<(int A, int B, int C)> GetTriangleIndices()
+        {
+            return _Source.Triangles;
+        }
+
+        public Vector3 GetVertexPosition(int idx)
+        {
+            var v = _Source.Vertices[idx];
+            return v.GetGeometry().GetPosition();
+        }
+
+        public Vector3 GetVertexNormal(int idx)
+        {
+            var v = _Source.Vertices[idx];
+            return v.GetGeometry().TryGetNormal(out Vector3 normal) ? normal : _Normals[idx];
+        }
+
+        public Vector4 GetVertexTangent(int idx)
+        {
+            var v = _Source.Vertices[idx];
+            return v.GetGeometry().TryGetTangent(out Vector4 tangent) ? tangent : _Tangents[idx];
+        }
+
+        public Vector2 GetVertexTexCoord(int idx)
+        {
+            var v = _Source.Vertices[idx];
+            var m = v.GetMaterial();
+            return m.MaxTextCoords > 0 ? m.GetTexCoord(0) : Vector2.Zero;
+        }
+
+        public void SetVertexNormal(int idx, Vector3 normal)
+        {
+            if (_Normals == null) _Normals = new Vector3[VertexCount];
+            _Normals[idx] = normal;
+        }
+
+        public void SetVertexTangent(int idx, Vector4 tangent)
+        {
+            if (_Tangents == null) _Tangents = new Vector4[VertexCount];
+            _Tangents[idx] = tangent;
+        }
+
+        #endregion
+    }
 }

+ 10 - 6
src/SharpGLTF.Toolkit/Geometry/VertexBufferColumns.cs

@@ -272,11 +272,11 @@ namespace SharpGLTF.Geometry
         {
             var m = default(TvM);
 
-            if (Colors0 != null && m.MaxColors > 0) m.SetColor(0, Colors0[index]);
-            if (Colors1 != null && m.MaxColors > 1) m.SetColor(1, Colors1[index]);
+            if (m.MaxColors > 0) m.SetColor(0, Colors0 == null ? Vector4.One : Colors0[index]);
+            if (m.MaxColors > 1) m.SetColor(1, Colors1 == null ? Vector4.One : Colors1[index]);
 
-            if (TexCoords0 != null && m.MaxTextCoords > 0) m.SetTexCoord(0, TexCoords0[index]);
-            if (TexCoords1 != null && m.MaxTextCoords > 1) m.SetTexCoord(1, TexCoords1[index]);
+            if (m.MaxTextCoords > 0) m.SetTexCoord(0, TexCoords0 == null ? Vector2.Zero : TexCoords0[index]);
+            if (m.MaxTextCoords > 1) m.SetTexCoord(1, TexCoords1 == null ? Vector2.Zero : TexCoords1[index]);
 
             return m;
         }
@@ -386,7 +386,9 @@ namespace SharpGLTF.Geometry
         {
             Guard.NotNull(primitives, nameof(primitives));
 
-            var agents = primitives.Select(item => new _NormalTangentAgent(item.Vertices, item.Indices)).ToList();
+            var agents = primitives
+                .Select(item => new _NormalTangentAgent(item.Vertices, item.Indices))
+                .ToList();
 
             VertexNormalsFactory.CalculateSmoothNormals(agents);
         }
@@ -395,7 +397,9 @@ namespace SharpGLTF.Geometry
         {
             Guard.NotNull(primitives, nameof(primitives));
 
-            var agents = primitives.Select(item => new _NormalTangentAgent(item.Vertices, item.Indices)).ToList();
+            var agents = primitives
+                .Select(item => new _NormalTangentAgent(item.Vertices, item.Indices))
+                .ToList();
 
             VertexTangentsFactory.CalculateTangents(agents);
         }