Browse Source

Fixed extension handling when the parent class type is a derived class of the registered type.

This was preventing Normals and Occlusion channels to load the TextureTransform extension correctly.
Vicente Penades 5 years ago
parent
commit
495512883e

+ 16 - 4
src/SharpGLTF.Core/Schema2/gltf.ExtensionsFactory.cs

@@ -51,11 +51,17 @@ namespace SharpGLTF.Schema2
             _Extensions.Add( (persistentName, typeof(TParent), typeof(TExtension)) );
             _Extensions.Add( (persistentName, typeof(TParent), typeof(TExtension)) );
         }
         }
 
 
-        internal static JsonSerializable Create(JsonSerializable parent, string key)
+        /// <summary>
+        /// Creates an extension object based on the parent object and the extension code.
+        /// </summary>
+        /// <param name="parent">The parent object that will own the created object.</param>
+        /// <param name="extensionName">The extension code, like "KHR_texture_transform".</param>
+        /// <returns>The created object, or null.</returns>
+        internal static JsonSerializable Create(JsonSerializable parent, string extensionName)
         {
         {
             var ptype = parent.GetType();
             var ptype = parent.GetType();
 
 
-            var (name, parentType, extType) = _Extensions.FirstOrDefault(item => item.Name == key && item.ParentType == ptype);
+            var (name, parentType, extType) = _Extensions.FirstOrDefault(item => item.Name == extensionName && item.ParentType.IsAssignableFrom(ptype));
 
 
             if (name == null) return null;
             if (name == null) return null;
 
 
@@ -71,11 +77,17 @@ namespace SharpGLTF.Schema2
             return instance as JsonSerializable;
             return instance as JsonSerializable;
         }
         }
 
 
+        /// <summary>
+        /// Given a parentType and an extensionType, it identifies the extension code.
+        /// </summary>
+        /// <param name="parentType">The type of the parent object.</param>
+        /// <param name="extensionType">The type of the extension object.</param>
+        /// <returns>An extension identifier code, like "KHR_texture_transform".</returns>
         internal static string Identify(Type parentType, Type extensionType)
         internal static string Identify(Type parentType, Type extensionType)
         {
         {
-            foreach (var entry in _Extensions)
+            foreach (var (name, baseType, extType) in _Extensions)
             {
             {
-                if (entry.ParentType == parentType && entry.ExtType == extensionType) return entry.Name;
+                if (baseType.IsAssignableFrom(parentType) && extType == extensionType) return name;
             }
             }
 
 
             return null;
             return null;

+ 12 - 0
src/SharpGLTF.Core/Schema2/gltf.TextureInfo.cs

@@ -112,6 +112,18 @@ namespace SharpGLTF.Schema2
             }
             }
         }
         }
 
 
+        public Matrix3x2 Matrix
+        {
+            get
+            {
+                var s = Matrix3x2.CreateScale(Scale);
+                var r = Matrix3x2.CreateRotation(-Rotation);
+                var t = Matrix3x2.CreateTranslation(Offset);
+
+                return s * r * t;
+            }
+        }
+
         #endregion
         #endregion
     }
     }
 
 

+ 68 - 1
src/SharpGLTF.Core/Schema2/gltf.Textures.cs

@@ -238,8 +238,20 @@ namespace SharpGLTF.Schema2
         /// </summary>
         /// </summary>
         public int LogicalIndex => this.LogicalParent.LogicalTextureSamplers.IndexOfReference(this);
         public int LogicalIndex => this.LogicalParent.LogicalTextureSamplers.IndexOfReference(this);
 
 
+        /// <summary>
+        /// Gets the texture minification filter.
+        /// </summary>
+        /// <remarks>
+        /// If value is Default, it must be interpreted by the runtime as "best fit"
+        /// </remarks>
         public TEXMIPMAP MinFilter => _minFilter.AsValue(TEXMIPMAP.DEFAULT);
         public TEXMIPMAP MinFilter => _minFilter.AsValue(TEXMIPMAP.DEFAULT);
 
 
+        /// <summary>
+        /// Gets the texture magnification filter.
+        /// </summary>
+        /// <remarks>
+        /// If value is Default, it must be interpreted by the runtime as "best fit"
+        /// </remarks>
         public TEXLERP MagFilter => _magFilter.AsValue(TEXLERP.DEFAULT);
         public TEXLERP MagFilter => _magFilter.AsValue(TEXLERP.DEFAULT);
 
 
         public TEXWRAP WrapS => _wrapS.AsValue(_wrapSDefault);
         public TEXWRAP WrapS => _wrapS.AsValue(_wrapSDefault);
@@ -259,6 +271,61 @@ namespace SharpGLTF.Schema2
             return true;
             return true;
         }
         }
 
 
+        public static bool AreEqualByContent(TextureSampler x, TextureSampler y)
+        {
+            #pragma warning disable IDE0041 // Use 'is null' check
+            if (Object.ReferenceEquals(x, y)) return true;
+            if (Object.ReferenceEquals(x, null)) return false;
+            if (Object.ReferenceEquals(y, null)) return false;
+            #pragma warning restore IDE0041 // Use 'is null' check
+
+            if (x._minFilter != y._minFilter) return false;
+            if (x._magFilter != y._magFilter) return false;
+            if (x._wrapS != y._wrapS) return false;
+            if (x._wrapT != y._wrapT) return false;
+
+            return true;
+        }
+
+        internal bool IsEqualTo(TEXMIPMAP min, TEXLERP mag, TEXWRAP ws, TEXWRAP wt)
+        {
+            if (this._minFilter != min) return false;
+            if (this._magFilter != mag) return false;
+            if (this._wrapS != ws) return false;
+            if (this._wrapT != wt) return false;
+
+            return true;
+        }
+
+        public int GetContentHashCode()
+        {
+            var h = 0;
+            h ^= this.MinFilter.GetHashCode();
+            h ^= this.MagFilter.GetHashCode();
+            h ^= this.WrapS.GetHashCode();
+            h ^= this.WrapT.GetHashCode();
+            return h;
+        }
+
+        #endregion
+
+        #region nested types
+
+        public static IEqualityComparer<TextureSampler> ContentComparer { get; private set; } = new _ContentComparer();
+
+        private class _ContentComparer : IEqualityComparer<TextureSampler>
+        {
+            public bool Equals(TextureSampler x, TextureSampler y)
+            {
+                return AreEqualByContent(x, y);
+            }
+
+            public int GetHashCode(TextureSampler obj)
+            {
+                return obj == null ? 0 : obj.GetContentHashCode();
+            }
+        }
+
         #endregion
         #endregion
     }
     }
 
 
@@ -279,7 +346,7 @@ namespace SharpGLTF.Schema2
 
 
             foreach (var s in this._samplers)
             foreach (var s in this._samplers)
             {
             {
-                if (s.MinFilter == min && s.MagFilter == mag && s.WrapS == ws && s.WrapT == wt) return s;
+                if (s.IsEqualTo(min, mag, ws, wt)) return s;
             }
             }
 
 
             var ss = new TextureSampler(min, mag, ws, wt);
             var ss = new TextureSampler(min, mag, ws, wt);

+ 19 - 0
tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadSampleTests.cs

@@ -362,7 +362,26 @@ namespace SharpGLTF.Schema2.LoadAndSave
 
 
         }
         }
 
 
+        [Test]
+        public void LoadMultiUVTexture()
+        {
+            TestContext.CurrentContext.AttachShowDirLink();
+
+            var path = TestFiles
+                .GetSampleModelsPaths()
+                .FirstOrDefault(item => item.Contains("TextureTransformMultiTest.glb"));
 
 
+            var model = ModelRoot.Load(path);
+            Assert.NotNull(model);
+
+            var materials = model.LogicalMaterials;
+
+            var normalTest0Mat = materials.FirstOrDefault(item => item.Name == "NormalTest0Mat");
+            var normalTest0Mat_normal = normalTest0Mat.FindChannel("Normal").Value;
+            var normalTest0Mat_normal_xform = normalTest0Mat_normal.TextureTransform;            
+
+            Assert.NotNull(normalTest0Mat_normal_xform);
+        }
 
 
         [Test]
         [Test]
         public void FindDependencyFiles()
         public void FindDependencyFiles()