Browse Source

MeshBuilder: added some performance optimizations when adding triangles

Vicente Penades 5 years ago
parent
commit
7b463a0545

+ 56 - 0
src/SharpGLTF.Toolkit/Collections/Triple.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF.Collections
+{
+    public readonly struct Triple<T> : IReadOnlyList<T>
+    {
+        public static implicit operator Triple<T>(in (T A, T B, T C) triple)
+        {
+            return new Triple<T>(triple.A, triple.B, triple.C);
+        }
+
+        public Triple(T @a, T @b, T @c)
+        {
+            A = @a;
+            B = @b;
+            C = @c;
+        }
+
+        public readonly T A;
+        public readonly T B;
+        public readonly T C;
+
+        public int Count => 3;
+
+        public T this[int index]
+        {
+            get
+            {
+                switch (index)
+                {
+                    case 0: return A;
+                    case 1: return B;
+                    case 2: return C;
+                    default: throw new ArgumentOutOfRangeException(nameof(index));
+                }
+            }
+        }
+
+        public IEnumerator<T> GetEnumerator()
+        {
+            yield return A;
+            yield return B;
+            yield return C;
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            yield return A;
+            yield return B;
+            yield return C;
+        }
+    }
+}

+ 9 - 11
src/SharpGLTF.Toolkit/Collections/VertexList.cs

@@ -30,7 +30,7 @@ namespace SharpGLTF.Collections
 
         IEnumerator IEnumerable.GetEnumerator() { return _Vertices.GetEnumerator(); }
 
-        public int Use(T v)
+        public int Use(in T v)
         {
             if (_VertexCache.TryGetValue(new QueryKey(v), out int index))
             {
@@ -77,11 +77,12 @@ namespace SharpGLTF.Collections
 
         #endregion
 
-        #region types
+        #region nested types
 
         interface IVertexKey
         {
             T GetValue();
+            int HashCode { get; }
         }
 
         sealed class _KeyComparer : IEqualityComparer<IVertexKey>
@@ -100,25 +101,21 @@ namespace SharpGLTF.Collections
                 return object.Equals(xx, yy);
             }
 
-            public int GetHashCode(IVertexKey obj)
-            {
-                return obj
-                    .GetValue()
-                    .GetHashCode();
-            }
+            public int GetHashCode(IVertexKey obj) { return obj.HashCode; }
         }
 
-        [System.Diagnostics.DebuggerDisplay("{GetValue()} {GetHashCode()}")]
+        [System.Diagnostics.DebuggerDisplay("{GetValue()} {HashCode}")]
         private readonly struct QueryKey : IVertexKey
         {
-            public QueryKey(T value) { _Value = value; }
+            public QueryKey(in T value) { _Value = value; }
 
             private readonly T _Value;
 
+            public int HashCode => _Value.GetHashCode();
             public T GetValue() { return _Value; }
         }
 
-        [System.Diagnostics.DebuggerDisplay("{GetValue()} {GetHashCode()}")]
+        [System.Diagnostics.DebuggerDisplay("{GetValue()} {HashCode}")]
         private readonly struct StoredKey : IVertexKey
         {
             public StoredKey(IReadOnlyList<T> src, int idx)
@@ -130,6 +127,7 @@ namespace SharpGLTF.Collections
             private readonly IReadOnlyList<T> _Source;
             private readonly int _Index;
 
+            public int HashCode => _Source[_Index].GetHashCode();
             public T GetValue() { return _Source[_Index]; }
         }
 

+ 2 - 75
src/SharpGLTF.Toolkit/Geometry/PrimitiveBuilder.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Text;
 using System.Linq;
 using System.Numerics;
 
@@ -10,78 +9,6 @@ using SharpGLTF.Geometry.VertexTypes;
 
 namespace SharpGLTF.Geometry
 {
-    public interface IPrimitiveReader<TMaterial>
-    {
-        /// <summary>
-        /// Gets a generic type of <see cref="VertexBuilder{TvG, TvM, TvS}"/>.
-        /// </summary>
-        Type VertexType { get; }
-
-        /// <summary>
-        /// Gets the current <typeparamref name="TMaterial"/> instance used by this primitive.
-        /// </summary>
-        TMaterial Material { get; }
-
-        /// <summary>
-        /// Gets the number of vertices used by each primitive shape.
-        /// </summary>
-        int VerticesPerPrimitive { get; }
-
-        /// <summary>
-        /// Gets the list of <see cref="IVertexBuilder"/> vertices.
-        /// </summary>
-        IReadOnlyList<IVertexBuilder> Vertices { get; }
-
-        /// <summary>
-        /// Gets the list of <see cref="IPrimitiveMorphTargetReader"/>.
-        /// </summary>
-        IReadOnlyList<IPrimitiveMorphTargetReader> MorphTargets { get; }
-
-        /// <summary>
-        /// Gets the indices of all points, given that <see cref="VerticesPerPrimitive"/> is 1.
-        /// </summary>
-        IReadOnlyList<int> Points { get; }
-
-        /// <summary>
-        /// Gets the indices of all lines, given that <see cref="VerticesPerPrimitive"/> is 2.
-        /// </summary>
-        IReadOnlyList<(int A, int B)> Lines { get; }
-
-        /// <summary>
-        /// Gets the indices of all the surfaces as triangles, given that <see cref="VerticesPerPrimitive"/> is 3.
-        /// </summary>
-        IReadOnlyList<(int A, int B, int C)> Triangles { get; }
-
-        /// <summary>
-        /// Gets the indices of all the surfaces, given that <see cref="VerticesPerPrimitive"/> is 3.
-        /// </summary>
-        IReadOnlyList<(int A, int B, int C, int? D)> Surfaces { get; }
-
-        /// <summary>
-        /// Calculates the raw list of indices to use for this primitive.
-        /// </summary>
-        /// <returns>a list of indices.</returns>
-        IReadOnlyList<int> GetIndices();
-    }
-
-    public interface IPrimitiveBuilder
-    {
-        /// <summary>
-        /// Gets a generic type of <see cref="VertexBuilder{TvG, TvM, TvS}"/>.
-        /// </summary>
-        Type VertexType { get; }
-
-        void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta delta);
-
-        int AddPoint(IVertexBuilder a);
-
-        (int A, int B) AddLine(IVertexBuilder a, IVertexBuilder b);
-
-        (int A, int B, int C) AddTriangle(IVertexBuilder a, IVertexBuilder b, IVertexBuilder c);
-
-        (int A, int B, int C, int D) AddQuadrangle(IVertexBuilder a, IVertexBuilder b, IVertexBuilder c, IVertexBuilder d);
-    }
-
     /// <summary>
     /// Represents an utility class to help build mesh primitives by adding triangles
     /// </summary>
@@ -228,7 +155,7 @@ namespace SharpGLTF.Geometry
         /// <typeparamref name="TvS"/> fragments.
         /// </param>
         /// <returns>The index of the vertex.</returns>
-        protected int UseVertex(VertexBuilder<TvG, TvM, TvS> vertex)
+        protected int UseVertex(in VertexBuilder<TvG, TvM, TvS> vertex)
         {
             return _Vertices.Use(vertex);
         }
@@ -746,7 +673,7 @@ namespace SharpGLTF.Geometry
             }
         }
 
-        private (int A, int B, int C) _AddTriangle(VertexBuilder<TvG, TvM, TvS> a, VertexBuilder<TvG, TvM, TvS> b, VertexBuilder<TvG, TvM, TvS> c)
+        private (int A, int B, int C) _AddTriangle(in VertexBuilder<TvG, TvM, TvS> a, in VertexBuilder<TvG, TvM, TvS> b, in VertexBuilder<TvG, TvM, TvS> c)
         {
             // check for degenerated triangle
             if (a.Position == b.Position || a.Position == c.Position || b.Position == c.Position) return (-1, -1, -1);

+ 87 - 0
src/SharpGLTF.Toolkit/Geometry/PrimitiveInterfaces.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+
+using SharpGLTF.Geometry.VertexTypes;
+
+namespace SharpGLTF.Geometry
+{
+    public interface IPrimitiveReader<TMaterial>
+    {
+        /// <summary>
+        /// Gets a generic type of <see cref="VertexBuilder{TvG, TvM, TvS}"/>.
+        /// </summary>
+        Type VertexType { get; }
+
+        /// <summary>
+        /// Gets the current <typeparamref name="TMaterial"/> instance used by this primitive.
+        /// </summary>
+        TMaterial Material { get; }
+
+        /// <summary>
+        /// Gets the number of vertices used by each primitive shape.
+        /// Valid values:
+        ///   1- Points.
+        ///   2- Lines.
+        ///   3- Triangles.
+        /// </summary>
+        int VerticesPerPrimitive { get; }
+
+        /// <summary>
+        /// Gets the list of <see cref="IVertexBuilder"/> vertices.
+        /// </summary>
+        IReadOnlyList<IVertexBuilder> Vertices { get; }
+
+        /// <summary>
+        /// Gets the list of <see cref="IPrimitiveMorphTargetReader"/>.
+        /// </summary>
+        IReadOnlyList<IPrimitiveMorphTargetReader> MorphTargets { get; }
+
+        /// <summary>
+        /// Gets the indices of all points.
+        /// </summary>
+        /// <exception cref="NotSupportedException">If <see cref="VerticesPerPrimitive"/> is different than 1</exception>
+        IReadOnlyList<int> Points { get; }
+
+        /// <summary>
+        /// Gets the indices of all lines.
+        /// </summary>
+        /// <exception cref="NotSupportedException">If <see cref="VerticesPerPrimitive"/> is different than 2</exception>
+        IReadOnlyList<(int A, int B)> Lines { get; }
+
+        /// <summary>
+        /// Gets the indices of all the surfaces as triangles.
+        /// </summary>
+        /// <exception cref="NotSupportedException">If <see cref="VerticesPerPrimitive"/> is different than 3</exception>
+        IReadOnlyList<(int A, int B, int C)> Triangles { get; }
+
+        /// <summary>
+        /// Gets the indices of all the surfaces.
+        /// </summary>
+        /// <exception cref="NotSupportedException">If <see cref="VerticesPerPrimitive"/> is different than 3</exception>
+        IReadOnlyList<(int A, int B, int C, int? D)> Surfaces { get; }
+
+        /// <summary>
+        /// Calculates the raw list of indices to use for this primitive.
+        /// </summary>
+        /// <returns>a list of indices.</returns>
+        IReadOnlyList<int> GetIndices();
+    }
+
+    public interface IPrimitiveBuilder
+    {
+        /// <summary>
+        /// Gets a generic type of <see cref="VertexBuilder{TvG, TvM, TvS}"/>.
+        /// </summary>
+        Type VertexType { get; }
+
+        void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta delta);
+
+        int AddPoint(IVertexBuilder a);
+
+        (int A, int B) AddLine(IVertexBuilder a, IVertexBuilder b);
+
+        (int A, int B, int C) AddTriangle(IVertexBuilder a, IVertexBuilder b, IVertexBuilder c);
+
+        (int A, int B, int C, int D) AddQuadrangle(IVertexBuilder a, IVertexBuilder b, IVertexBuilder c, IVertexBuilder d);
+    }
+}

+ 23 - 20
src/SharpGLTF.Toolkit/Geometry/VertexBuilder.cs

@@ -133,14 +133,14 @@ namespace SharpGLTF.Geometry
 
         #region constructors
 
-        public VertexBuilder(TvG g, TvM m, TvS s)
+        public VertexBuilder(in TvG g, in TvM m, in TvS s)
         {
             Geometry = g;
             Material = m;
             Skinning = s;
         }
 
-        public VertexBuilder(TvG g, TvM m, params (int, float)[] bindings)
+        public VertexBuilder(in TvG g, in TvM m, params (int, float)[] bindings)
         {
             Geometry = g;
             Material = m;
@@ -151,7 +151,7 @@ namespace SharpGLTF.Geometry
             Skinning.SetWeights(sparse);
         }
 
-        public VertexBuilder(TvG g, TvM m, Transforms.SparseWeight8 bindings)
+        public VertexBuilder(in TvG g, in TvM m, in Transforms.SparseWeight8 bindings)
         {
             Geometry = g;
             Material = m;
@@ -159,28 +159,28 @@ namespace SharpGLTF.Geometry
             Skinning.SetWeights(bindings);
         }
 
-        public VertexBuilder(TvG g, TvM m)
+        public VertexBuilder(in TvG g, in TvM m)
         {
             Geometry = g;
             Material = m;
             Skinning = default;
         }
 
-        public VertexBuilder(TvG g, TvS s)
+        public VertexBuilder(in TvG g, in TvS s)
         {
             Geometry = g;
             Material = default;
             Skinning = s;
         }
 
-        public VertexBuilder(TvG g)
+        public VertexBuilder(in TvG g)
         {
             Geometry = g;
             Material = default;
             Skinning = default;
         }
 
-        public VertexBuilder(TvG g, params (int Index, float Weight)[] bindings)
+        public VertexBuilder(in TvG g, params (int Index, float Weight)[] bindings)
         {
             Geometry = g;
             Material = default;
@@ -199,36 +199,36 @@ namespace SharpGLTF.Geometry
             Skinning.SetWeights(bindings);
         }
 
-        public static implicit operator VertexBuilder<TvG, TvM, TvS>((TvG Geo, TvM Mat, TvS Skin) tuple)
+        public static implicit operator VertexBuilder<TvG, TvM, TvS>(in (TvG Geo, TvM Mat, TvS Skin) tuple)
         {
             return new VertexBuilder<TvG, TvM, TvS>(tuple.Geo, tuple.Mat, tuple.Skin);
         }
 
-        public static implicit operator VertexBuilder<TvG, TvM, TvS>((TvG Geo, TvM Mat) tuple)
+        public static implicit operator VertexBuilder<TvG, TvM, TvS>(in (TvG Geo, TvM Mat) tuple)
         {
             return new VertexBuilder<TvG, TvM, TvS>(tuple.Geo, tuple.Mat);
         }
 
-        public static implicit operator VertexBuilder<TvG, TvM, TvS>((TvG Geo, TvS Skin) tuple)
+        public static implicit operator VertexBuilder<TvG, TvM, TvS>(in (TvG Geo, TvS Skin) tuple)
         {
             return new VertexBuilder<TvG, TvM, TvS>(tuple.Geo, tuple.Skin);
         }
 
-        public static implicit operator VertexBuilder<TvG, TvM, TvS>(TvG g)
+        public static implicit operator VertexBuilder<TvG, TvM, TvS>(in TvG g)
         {
             return new VertexBuilder<TvG, TvM, TvS>(g);
         }
 
         #pragma warning disable CA1000 // Do not declare static members on generic types
 
-        public static VertexBuilder<TvG, TvM, TvS> Create(Vector3 position)
+        public static VertexBuilder<TvG, TvM, TvS> Create(in Vector3 position)
         {
             var v = default(VertexBuilder<TvG, TvM, TvS>);
             v.Geometry.SetPosition(position);
             return v;
         }
 
-        public static VertexBuilder<TvG, TvM, TvS> Create(Vector3 position, Vector3 normal)
+        public static VertexBuilder<TvG, TvM, TvS> Create(in Vector3 position, in Vector3 normal)
         {
             var v = default(VertexBuilder<TvG, TvM, TvS>);
             v.Geometry.SetPosition(position);
@@ -236,7 +236,7 @@ namespace SharpGLTF.Geometry
             return v;
         }
 
-        public static VertexBuilder<TvG, TvM, TvS> Create(Vector3 position, Vector3 normal, Vector4 tangent)
+        public static VertexBuilder<TvG, TvM, TvS> Create(in Vector3 position, in Vector3 normal, in Vector4 tangent)
         {
             var v = default(VertexBuilder<TvG, TvM, TvS>);
             v.Geometry.SetPosition(position);
@@ -270,6 +270,8 @@ namespace SharpGLTF.Geometry
         public TvM Material;
         public TvS Skinning;
 
+        public override int GetHashCode() { return Geometry.GetHashCode(); }
+
         #endregion
 
         #region properties
@@ -285,14 +287,14 @@ namespace SharpGLTF.Geometry
 
         #region API
 
-        public VertexBuilder<TvG, TvM, TvS> WithGeometry(Vector3 position)
+        public VertexBuilder<TvG, TvM, TvS> WithGeometry(in Vector3 position)
         {
             var v = this;
             v.Geometry.SetPosition(position);
             return v;
         }
 
-        public VertexBuilder<TvG, TvM, TvS> WithGeometry(Vector3 position, Vector3 normal)
+        public VertexBuilder<TvG, TvM, TvS> WithGeometry(in Vector3 position, in Vector3 normal)
         {
             var v = this;
             v.Geometry.SetPosition(position);
@@ -300,7 +302,7 @@ namespace SharpGLTF.Geometry
             return v;
         }
 
-        public VertexBuilder<TvG, TvM, TvS> WithGeometry(Vector3 position, Vector3 normal, Vector4 tangent)
+        public VertexBuilder<TvG, TvM, TvS> WithGeometry(in Vector3 position, in Vector3 normal, in Vector4 tangent)
         {
             var v = this;
             v.Geometry.SetPosition(position);
@@ -316,7 +318,7 @@ namespace SharpGLTF.Geometry
             return v;
         }
 
-        public VertexBuilder<TvG, TvM, TvS> WithMaterial(Vector4 color0, params Vector2[] uvs)
+        public VertexBuilder<TvG, TvM, TvS> WithMaterial(in Vector4 color0, params Vector2[] uvs)
         {
             var v = this;
             v.Material.SetColor(0, color0);
@@ -324,7 +326,7 @@ namespace SharpGLTF.Geometry
             return v;
         }
 
-        public VertexBuilder<TvG, TvM, TvS> WithMaterial(Vector4 color0, Vector4 color1, params Vector2[] uvs)
+        public VertexBuilder<TvG, TvM, TvS> WithMaterial(in Vector4 color0, Vector4 color1, params Vector2[] uvs)
         {
             var v = this;
             v.Material.SetColor(0, color0);
@@ -435,6 +437,8 @@ namespace SharpGLTF.Geometry
         public IVertexMaterial Material;
         public IVertexSkinning Skinning;
 
+        public override int GetHashCode() { return Geometry.GetHashCode(); }
+
         #endregion
 
         #region API
@@ -463,6 +467,5 @@ namespace SharpGLTF.Geometry
         }
 
         #endregion
-
     }
 }

+ 39 - 39
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexGeometry.cs

@@ -14,15 +14,15 @@ namespace SharpGLTF.Geometry.VertexTypes
         Boolean TryGetNormal(out Vector3 normal);
         Boolean TryGetTangent(out Vector4 tangent);
 
-        void SetPosition(Vector3 position);
-        void SetNormal(Vector3 normal);
-        void SetTangent(Vector4 tangent);
+        void SetPosition(in Vector3 position);
+        void SetNormal(in Vector3 normal);
+        void SetTangent(in Vector4 tangent);
 
-        void ApplyTransform(Matrix4x4 xform);
+        void ApplyTransform(in Matrix4x4 xform);
 
         VertexGeometryDelta Subtract(IVertexGeometry baseValue);
 
-        void Add(VertexGeometryDelta delta);
+        void Add(in VertexGeometryDelta delta);
     }
 
     /// <summary>
@@ -39,7 +39,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region constructors
 
-        public VertexPosition(Vector3 position)
+        public VertexPosition(in Vector3 position)
         {
             this.Position = position;
         }
@@ -55,7 +55,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             this.Position = src.GetPosition();
         }
 
-        public static implicit operator VertexPosition(Vector3 position)
+        public static implicit operator VertexPosition(in Vector3 position)
         {
             return new VertexPosition(position);
         }
@@ -81,18 +81,18 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region API
 
-        void IVertexGeometry.SetPosition(Vector3 position) { this.Position = position; }
+        void IVertexGeometry.SetPosition(in Vector3 position) { this.Position = position; }
 
-        void IVertexGeometry.SetNormal(Vector3 normal) { }
+        void IVertexGeometry.SetNormal(in Vector3 normal) { }
 
-        void IVertexGeometry.SetTangent(Vector4 tangent) { }
+        void IVertexGeometry.SetTangent(in Vector4 tangent) { }
 
         public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
             return new VertexGeometryDelta((VertexPosition)baseValue, this);
         }
 
-        public void Add(VertexGeometryDelta delta)
+        public void Add(in VertexGeometryDelta delta)
         {
             this.Position += delta.PositionDelta;
         }
@@ -103,7 +103,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         public bool TryGetTangent(out Vector4 tangent) { tangent = default; return false; }
 
-        public void ApplyTransform(Matrix4x4 xform)
+        public void ApplyTransform(in Matrix4x4 xform)
         {
             Position = Vector3.Transform(Position, xform);
         }
@@ -127,7 +127,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region constructors
 
-        public VertexPositionNormal(Vector3 p, Vector3 n)
+        public VertexPositionNormal(in Vector3 p, in Vector3 n)
         {
             this.Position = p;
             this.Normal = n;
@@ -147,7 +147,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             src.TryGetNormal(out this.Normal);
         }
 
-        public static implicit operator VertexPositionNormal((Vector3 Pos, Vector3 Nrm) tuple)
+        public static implicit operator VertexPositionNormal(in (Vector3 Pos, Vector3 Nrm) tuple)
         {
             return new VertexPositionNormal(tuple.Pos, tuple.Nrm);
         }
@@ -177,18 +177,18 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region API
 
-        void IVertexGeometry.SetPosition(Vector3 position) { this.Position = position; }
+        void IVertexGeometry.SetPosition(in Vector3 position) { this.Position = position; }
 
-        void IVertexGeometry.SetNormal(Vector3 normal) { this.Normal = normal; }
+        void IVertexGeometry.SetNormal(in Vector3 normal) { this.Normal = normal; }
 
-        void IVertexGeometry.SetTangent(Vector4 tangent) { }
+        void IVertexGeometry.SetTangent(in Vector4 tangent) { }
 
         public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
             return new VertexGeometryDelta((VertexPositionNormal)baseValue, this);
         }
 
-        public void Add(VertexGeometryDelta delta)
+        public void Add(in VertexGeometryDelta delta)
         {
             this.Position += delta.PositionDelta;
             this.Normal += delta.NormalDelta;
@@ -200,7 +200,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         public bool TryGetTangent(out Vector4 tangent) { tangent = default; return false; }
 
-        public void ApplyTransform(Matrix4x4 xform)
+        public void ApplyTransform(in Matrix4x4 xform)
         {
             Position = Vector3.Transform(Position, xform);
             Normal = Vector3.Normalize(Vector3.TransformNormal(Normal, xform));
@@ -225,7 +225,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region constructors
 
-        public VertexPositionNormalTangent(Vector3 p, Vector3 n, Vector4 t)
+        public VertexPositionNormalTangent(in Vector3 p, in Vector3 n, in Vector4 t)
         {
             this.Position = p;
             this.Normal = n;
@@ -241,7 +241,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             src.TryGetTangent(out this.Tangent);
         }
 
-        public static implicit operator VertexPositionNormalTangent((Vector3 Pos, Vector3 Nrm, Vector4 Tgt) tuple)
+        public static implicit operator VertexPositionNormalTangent(in (Vector3 Pos, Vector3 Nrm, Vector4 Tgt) tuple)
         {
             return new VertexPositionNormalTangent(tuple.Pos, tuple.Nrm, tuple.Tgt);
         }
@@ -274,18 +274,18 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region API
 
-        void IVertexGeometry.SetPosition(Vector3 position) { this.Position = position; }
+        void IVertexGeometry.SetPosition(in Vector3 position) { this.Position = position; }
 
-        void IVertexGeometry.SetNormal(Vector3 normal) { this.Normal = normal; }
+        void IVertexGeometry.SetNormal(in Vector3 normal) { this.Normal = normal; }
 
-        void IVertexGeometry.SetTangent(Vector4 tangent) { this.Tangent = tangent; }
+        void IVertexGeometry.SetTangent(in Vector4 tangent) { this.Tangent = tangent; }
 
         public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
             return new VertexGeometryDelta((VertexPositionNormalTangent)baseValue, this);
         }
 
-        public void Add(VertexGeometryDelta delta)
+        public void Add(in VertexGeometryDelta delta)
         {
             this.Position += delta.PositionDelta;
             this.Normal += delta.NormalDelta;
@@ -298,7 +298,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         public bool TryGetTangent(out Vector4 tangent) { tangent = this.Tangent; return true; }
 
-        public void ApplyTransform(Matrix4x4 xform)
+        public void ApplyTransform(in Matrix4x4 xform)
         {
             Position = Vector3.Transform(Position, xform);
             Normal = Vector3.Normalize(Vector3.TransformNormal(Normal, xform));
@@ -327,17 +327,17 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region constructors
 
-        public static implicit operator VertexGeometryDelta(Vector3 position)
+        public static implicit operator VertexGeometryDelta(in Vector3 position)
         {
             return new VertexGeometryDelta(position, Vector3.Zero, Vector3.Zero);
         }
 
-        public static implicit operator VertexGeometryDelta((Vector3 Pos, Vector3 Nrm) tuple)
+        public static implicit operator VertexGeometryDelta(in (Vector3 Pos, Vector3 Nrm) tuple)
         {
             return new VertexGeometryDelta(tuple.Pos, tuple.Nrm, Vector3.Zero);
         }
 
-        public static implicit operator VertexGeometryDelta((Vector3 Pos, Vector3 Nrm, Vector3 tgt) tuple)
+        public static implicit operator VertexGeometryDelta(in (Vector3 Pos, Vector3 Nrm, Vector3 tgt) tuple)
         {
             return new VertexGeometryDelta(tuple.Pos, tuple.Nrm, tuple.tgt);
         }
@@ -353,28 +353,28 @@ namespace SharpGLTF.Geometry.VertexTypes
             this.TangentDelta = new Vector3(t.X, t.Y, t.Z);
         }
 
-        public VertexGeometryDelta(Vector3 p, Vector3 n, Vector3 t)
+        public VertexGeometryDelta(in Vector3 p, in Vector3 n, in Vector3 t)
         {
             this.PositionDelta = p;
             this.NormalDelta = n;
             this.TangentDelta = t;
         }
 
-        internal VertexGeometryDelta(VertexPosition rootVal, VertexPosition morphVal)
+        internal VertexGeometryDelta(in VertexPosition rootVal, in VertexPosition morphVal)
         {
             PositionDelta = morphVal.Position - rootVal.Position;
             NormalDelta = Vector3.Zero;
             TangentDelta = Vector3.Zero;
         }
 
-        internal VertexGeometryDelta(VertexPositionNormal rootVal, VertexPositionNormal morphVal)
+        internal VertexGeometryDelta(in VertexPositionNormal rootVal, in VertexPositionNormal morphVal)
         {
             PositionDelta = morphVal.Position - rootVal.Position;
             NormalDelta = morphVal.Normal - rootVal.Normal;
             TangentDelta = Vector3.Zero;
         }
 
-        internal VertexGeometryDelta(VertexPositionNormalTangent rootVal, VertexPositionNormalTangent morphVal)
+        internal VertexGeometryDelta(in VertexPositionNormalTangent rootVal, in VertexPositionNormalTangent morphVal)
         {
             PositionDelta = morphVal.Position - rootVal.Position;
             NormalDelta = morphVal.Normal - rootVal.Normal;
@@ -383,7 +383,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             TangentDelta = new Vector3(dt.X, dt.Y, dt.Z);
         }
 
-        internal VertexGeometryDelta(VertexGeometryDelta rootVal, VertexGeometryDelta morphVal)
+        internal VertexGeometryDelta(in VertexGeometryDelta rootVal, in VertexGeometryDelta morphVal)
         {
             PositionDelta = morphVal.PositionDelta - rootVal.PositionDelta;
             NormalDelta = morphVal.NormalDelta - rootVal.NormalDelta;
@@ -418,11 +418,11 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         #region API
 
-        void IVertexGeometry.SetPosition(Vector3 position) { this.PositionDelta = position; }
+        void IVertexGeometry.SetPosition(in Vector3 position) { this.PositionDelta = position; }
 
-        void IVertexGeometry.SetNormal(Vector3 normal) { this.NormalDelta = normal; }
+        void IVertexGeometry.SetNormal(in Vector3 normal) { this.NormalDelta = normal; }
 
-        void IVertexGeometry.SetTangent(Vector4 tangent) { this.TangentDelta = new Vector3(tangent.X, tangent.Y, tangent.Z); }
+        void IVertexGeometry.SetTangent(in Vector4 tangent) { this.TangentDelta = new Vector3(tangent.X, tangent.Y, tangent.Z); }
 
         public Vector3 GetPosition() { return this.PositionDelta; }
 
@@ -430,14 +430,14 @@ namespace SharpGLTF.Geometry.VertexTypes
 
         public bool TryGetTangent(out Vector4 tangent) { tangent = new Vector4(this.TangentDelta, 0); return true; }
 
-        public void ApplyTransform(Matrix4x4 xform) { throw new NotSupportedException(); }
+        public void ApplyTransform(in Matrix4x4 xform) { throw new NotSupportedException(); }
 
         public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
             return new VertexGeometryDelta((VertexGeometryDelta)baseValue, this);
         }
 
-        public void Add(VertexGeometryDelta delta)
+        public void Add(in VertexGeometryDelta delta)
         {
             this.PositionDelta += delta.PositionDelta;
             this.NormalDelta += delta.NormalDelta;

+ 1 - 1
src/SharpGLTF.Toolkit/IO/WavefrontWriter.cs

@@ -40,7 +40,7 @@ namespace SharpGLTF.IO
 
         #region API
 
-        public void AddTriangle(Material material, VERTEX a, VERTEX b, VERTEX c)
+        public void AddTriangle(Material material, in VERTEX a, in VERTEX b, in VERTEX c)
         {
             _Mesh.UsePrimitive(material).AddTriangle(a, b, c);
         }