From 7924d209e61da5e5411d123b49cb44254eb75d81 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Tue, 19 Oct 2021 09:56:25 +0200 Subject: [PATCH 01/10] Added MaterialPropertyBlock scale/offset --- .../Runtime/Scripts/GLTFSceneExporter.cs | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 4d2eb4546..1dc6ea7e0 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -1119,6 +1119,8 @@ private MeshPrimitive[] ExportPrimitive(GameObject gameObject, GLTFMesh mesh) return null; } var materialsObj = renderer ? renderer.sharedMaterials : smr.sharedMaterials; + MaterialPropertyBlock materialProperty = new MaterialPropertyBlock(); + if (renderer) renderer.GetPropertyBlock(materialProperty); var prims = new MeshPrimitive[meshObj.subMeshCount]; List nonEmptyPrims = null; @@ -1205,7 +1207,7 @@ private MeshPrimitive[] ExportPrimitive(GameObject gameObject, GLTFMesh mesh) var submeshPrimitive = accessors.subMeshPrimitives[submesh]; prims[submesh] = new MeshPrimitive(submeshPrimitive, _root) { - Material = ExportMaterial(materialsObj[submesh]), + Material = ExportMaterial(materialsObj[submesh], materialProperty), }; } @@ -1287,7 +1289,7 @@ private static bool EmptyPrimitive(MeshPrimitive prim) return false; } - private MaterialId ExportMaterial(Material materialObj) + private MaterialId ExportMaterial(Material materialObj, MaterialPropertyBlock materialPropertyBlock) { //TODO if material is null MaterialId id = GetMaterialId(_root, materialObj); @@ -1360,7 +1362,7 @@ private MaterialId ExportMaterial(Material materialObj) { material.EmissiveTexture = ExportTextureInfo(emissionTex, TextureMapType.Emission); - ExportTextureTransform(material.EmissiveTexture, materialObj, "_EmissionMap"); + ExportTextureTransform(material.EmissiveTexture, materialObj, materialPropertyBlock, "_EmissionMap"); } else { @@ -1379,7 +1381,7 @@ private MaterialId ExportMaterial(Material materialObj) if(normalTex is Texture2D) { material.NormalTexture = ExportNormalTextureInfo(normalTex, TextureMapType.Bump, materialObj); - ExportTextureTransform(material.NormalTexture, materialObj, "_BumpMap"); + ExportTextureTransform(material.NormalTexture, materialObj, materialPropertyBlock, "_BumpMap"); } else { @@ -1396,7 +1398,7 @@ private MaterialId ExportMaterial(Material materialObj) if(occTex is Texture2D) { material.OcclusionTexture = ExportOcclusionTextureInfo(occTex, TextureMapType.Occlusion, materialObj); - ExportTextureTransform(material.OcclusionTexture, materialObj, "_OcclusionMap"); + ExportTextureTransform(material.OcclusionTexture, materialObj, materialPropertyBlock, "_OcclusionMap"); } else { @@ -1406,19 +1408,19 @@ private MaterialId ExportMaterial(Material materialObj) } if( IsUnlit(materialObj)){ - ExportUnlit( material, materialObj ); + ExportUnlit( material, materialObj, materialPropertyBlock ); } else if (IsPBRMetallicRoughness(materialObj)) { - material.PbrMetallicRoughness = ExportPBRMetallicRoughness(materialObj); + material.PbrMetallicRoughness = ExportPBRMetallicRoughness(materialObj, materialPropertyBlock); } else if (IsPBRSpecularGlossiness(materialObj)) { - ExportPBRSpecularGlossiness(material, materialObj); + ExportPBRSpecularGlossiness(material, materialObj, materialPropertyBlock); } else if (IsCommonConstant(materialObj)) { - material.CommonConstant = ExportCommonConstant(materialObj); + material.CommonConstant = ExportCommonConstant(materialObj, materialPropertyBlock); } else if (materialObj.HasProperty("_BaseMap")) { @@ -1450,7 +1452,7 @@ private MaterialId ExportMaterial(Material materialObj) { material.PbrMetallicRoughness = new PbrMetallicRoughness() { MetallicFactor = 0, RoughnessFactor = 1.0f }; material.PbrMetallicRoughness.BaseColorTexture = ExportTextureInfo(mainTex, TextureMapType.Main); - ExportTextureTransform(material.PbrMetallicRoughness.BaseColorTexture, materialObj, "_MainTex"); + ExportTextureTransform(material.PbrMetallicRoughness.BaseColorTexture, materialObj, materialPropertyBlock, "_MainTex"); } if (materialObj.HasProperty("_TintColor")) //particles use _TintColor instead of _Color { @@ -1620,11 +1622,10 @@ private bool IsCommonConstant(Material material) material.HasProperty("_LightFactor"); } - private void ExportTextureTransform(TextureInfo def, Material mat, string texName) + private void ExportTextureTransform(TextureInfo def, Material mat, MaterialPropertyBlock materialPropertyBlock, string texName) { Vector2 offset = mat.GetTextureOffset(texName); Vector2 scale = mat.GetTextureScale(texName); - if (offset == Vector2.zero && scale == Vector2.one) { // difficult choice here: some shaders might support texture transform per-texture, others use the main transform. @@ -1634,6 +1635,24 @@ private void ExportTextureTransform(TextureInfo def, Material mat, string texNam // return; } + if (materialPropertyBlock.HasVector(texName + "_ST")) + { + var scaleAndOffset = materialPropertyBlock.GetVector(texName + "_ST"); // scale and tile + scale = new Vector2(scaleAndOffset.x, scaleAndOffset.y); + offset = new Vector2(scaleAndOffset.z, scaleAndOffset.w); + } + else if (materialPropertyBlock.HasVector("_MainTex_ST")) + { + // difficult choice here: some shaders might support texture transform per-texture, others use the main transform. + var scaleAndOffset = materialPropertyBlock.GetVector("_MainTex_ST"); // scale and tile + scale = new Vector2(scaleAndOffset.x, scaleAndOffset.y); + offset = new Vector2(scaleAndOffset.z, scaleAndOffset.w); + } + + // uv coordinate system seems to be flipped in unity + if (scale != Vector2.one) + offset.y = -(offset.y + scale.y); + if (_root.ExtensionsUsed == null) { _root.ExtensionsUsed = new List( @@ -1663,7 +1682,7 @@ private void ExportTextureTransform(TextureInfo def, Material mat, string texNam def.Extensions = new Dictionary(); def.Extensions[ExtTextureTransformExtensionFactory.EXTENSION_NAME] = new ExtTextureTransformExtension( - new GLTF.Math.Vector2(offset.x, -offset.y), + new GLTF.Math.Vector2(offset.x, offset.y), 0, // TODO: support rotation new GLTF.Math.Vector2(scale.x, scale.y), 0 // TODO: support UV channels @@ -1704,7 +1723,7 @@ private OcclusionTextureInfo ExportOcclusionTextureInfo( return info; } - private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material) + private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material, MaterialPropertyBlock materialPropertyBlock) { var pbr = new PbrMetallicRoughness() { MetallicFactor = 0, RoughnessFactor = 1.0f }; @@ -1740,7 +1759,7 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material) if(mainTex is Texture2D) { pbr.BaseColorTexture = ExportTextureInfo(mainTex, TextureMapType.Main); - ExportTextureTransform(pbr.BaseColorTexture, material, mainTexPropertyName); + ExportTextureTransform(pbr.BaseColorTexture, material, materialPropertyBlock, mainTexPropertyName); } else { @@ -1776,7 +1795,7 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material) pbr.MetallicRoughnessTexture = ExportTextureInfo(mrTex, TextureMapType.MetallicGloss); if (material.IsKeywordEnabled("_METALLICGLOSSMAP")) pbr.MetallicFactor = 1.0f; - ExportTextureTransform(pbr.MetallicRoughnessTexture, material, "_MetallicGlossMap"); + ExportTextureTransform(pbr.MetallicRoughnessTexture, material, materialPropertyBlock, "_MetallicGlossMap"); } else { @@ -1788,8 +1807,8 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material) return pbr; } - private void ExportUnlit(GLTFMaterial def, Material material){ - + private void ExportUnlit(GLTFMaterial def, Material material, MaterialPropertyBlock materialPropertyBlock) + { const string extname = KHR_MaterialsUnlitExtensionFactory.EXTENSION_NAME; DeclareExtensionUsage( extname, true ); def.AddExtension( extname, new KHR_MaterialsUnlitExtension()); @@ -1809,7 +1828,7 @@ private void ExportUnlit(GLTFMaterial def, Material material){ if(mainTex is Texture2D) { pbr.BaseColorTexture = ExportTextureInfo(mainTex, TextureMapType.Main); - ExportTextureTransform(pbr.BaseColorTexture, material, "_MainTex"); + ExportTextureTransform(pbr.BaseColorTexture, material, materialPropertyBlock, "_MainTex"); } else { @@ -1823,7 +1842,7 @@ private void ExportUnlit(GLTFMaterial def, Material material){ } - private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materialObj) + private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materialObj, MaterialPropertyBlock materialPropertyBlock) { if (_root.ExtensionsUsed == null) { @@ -1871,7 +1890,7 @@ private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materia if (mainTex is Texture2D) { diffuseTexture = ExportTextureInfo(mainTex, TextureMapType.Main); - ExportTextureTransform(diffuseTexture, materialObj, "_MainTex"); + ExportTextureTransform(diffuseTexture, materialObj, materialPropertyBlock, "_MainTex"); } else { @@ -1908,7 +1927,7 @@ private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materia if (mgTex is Texture2D) { specularGlossinessTexture = ExportTextureInfo(mgTex, TextureMapType.SpecGloss); - ExportTextureTransform(specularGlossinessTexture, materialObj, "_SpecGlossMap"); + ExportTextureTransform(specularGlossinessTexture, materialObj, materialPropertyBlock, "_SpecGlossMap"); } else { @@ -1926,7 +1945,7 @@ private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materia ); } - private MaterialCommonConstant ExportCommonConstant(Material materialObj) + private MaterialCommonConstant ExportCommonConstant(Material materialObj, MaterialPropertyBlock materialPropertyBlock) { if (_root.ExtensionsUsed == null) { @@ -1963,7 +1982,7 @@ private MaterialCommonConstant ExportCommonConstant(Material materialObj) if (lmTex != null) { constant.LightmapTexture = ExportTextureInfo(lmTex, TextureMapType.Light); - ExportTextureTransform(constant.LightmapTexture, materialObj, "_LightMap"); + ExportTextureTransform(constant.LightmapTexture, materialObj, materialPropertyBlock, "_LightMap"); } } From 250347a83def1500e10020e60476eae7c1902f6d Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Tue, 19 Oct 2021 11:36:38 +0200 Subject: [PATCH 02/10] Fixed normal map interpretation on export --- .../Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader b/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader index e438325d3..01a1b0878 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader @@ -56,9 +56,9 @@ float4 col = tex2D(_MainTex, i.uv); // If a texture is marked as a normal map // the values are stored in the A and G channel. - float3 unpacked = UnpackNormal(col); + //float3 unpacked = UnpackNormal(col); // unpacked.xyz = LinearToGammaSpace(unpacked.xyz); - float4 result = float4(unpacked * 0.5f + 0.5f, 1); + float4 result = float4(col.rgb * 0.5f + 0.5f, 1); #ifdef UNITY_COLORSPACE_GAMMA #else // hack for linear color space, need to figure out From 145fef13851399df35a2cad0d8aa951a40595718 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 07:29:56 +0200 Subject: [PATCH 03/10] Fixed linear/gamma colorspace color evaluation --- .../Scripts/Extensions/SchemaExtensions.cs | 8 ++++ .../Runtime/Scripts/GLTFSceneExporter.cs | 46 ++++++++++--------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs index 583f35d7c..c2d817411 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs @@ -332,6 +332,14 @@ public static UnityEngine.Color ToUnityColorLinear(this GLTF.Math.Color color) return c; } + public static GLTF.Math.Color ToNumericsColor(this UnityEngine.Color color) + { + if (QualitySettings.activeColorSpace == ColorSpace.Linear) + return color.ToNumericsColorRaw(); + else + return color.ToNumericsColorLinear(); + } + public static GLTF.Math.Color ToNumericsColorRaw(this UnityEngine.Color color) { var c = color; diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 1dc6ea7e0..c75117c05 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -1349,7 +1349,7 @@ private MaterialId ExportMaterial(Material materialObj, MaterialPropertyBlock ma if (materialObj.HasProperty("_EmissionColor")) { var c = materialObj.GetColor("_EmissionColor"); - material.EmissiveFactor = c.ToNumericsColorLinear(); + material.EmissiveFactor = c.ToNumericsColor(); } if (materialObj.HasProperty("_EmissionMap")) @@ -1425,22 +1425,24 @@ private MaterialId ExportMaterial(Material materialObj, MaterialPropertyBlock ma else if (materialObj.HasProperty("_BaseMap")) { var mainTex = materialObj.GetTexture("_BaseMap"); + var color = (materialObj.HasProperty("_BaseColor") + ? materialObj.GetColor("_BaseColor") + : Color.white).ToNumericsColor(); material.PbrMetallicRoughness = new PbrMetallicRoughness() { - BaseColorFactor = (materialObj.HasProperty("_BaseColor") - ? materialObj.GetColor("_BaseColor") - : Color.white).ToNumericsColorLinear(), + BaseColorFactor = color, BaseColorTexture = mainTex ? ExportTextureInfo(mainTex, TextureMapType.Main) : null }; } else if (materialObj.HasProperty("_ColorTexture")) { var mainTex = materialObj.GetTexture("_ColorTexture"); + var color = (materialObj.HasProperty("_BaseColor") + ? materialObj.GetColor("_BaseColor") + : Color.white).ToNumericsColor(); material.PbrMetallicRoughness = new PbrMetallicRoughness() { - BaseColorFactor = (materialObj.HasProperty("_BaseColor") - ? materialObj.GetColor("_BaseColor") - : Color.white).ToNumericsColorLinear(), + BaseColorFactor = color, BaseColorTexture = mainTex ? ExportTextureInfo(mainTex, TextureMapType.Main) : null }; } @@ -1459,7 +1461,7 @@ private MaterialId ExportMaterial(Material materialObj, MaterialPropertyBlock ma if (material.PbrMetallicRoughness == null) material.PbrMetallicRoughness = new PbrMetallicRoughness() { MetallicFactor = 0, RoughnessFactor = 1.0f }; - material.PbrMetallicRoughness.BaseColorFactor = materialObj.GetColor("_TintColor").ToNumericsColorLinear(); + material.PbrMetallicRoughness.BaseColorFactor = materialObj.GetColor("_TintColor").ToNumericsColor(); } material.DoubleSided = true; } @@ -1729,11 +1731,11 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material, Mater if (material.HasProperty("_BaseColor")) { - pbr.BaseColorFactor = material.GetColor("_BaseColor").ToNumericsColorLinear(); + pbr.BaseColorFactor = material.GetColor("_BaseColor").ToNumericsColor(); } else if (material.HasProperty("_Color")) { - pbr.BaseColorFactor = material.GetColor("_Color").ToNumericsColorLinear(); + pbr.BaseColorFactor = material.GetColor("_Color").ToNumericsColor(); } if (material.HasProperty("_TintColor")) //particles use _TintColor instead of _Color @@ -1745,7 +1747,7 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material, Mater white = (c.r + c.g + c.b) / 3.0f; //multiply alpha by overall whiteness of TintColor } - pbr.BaseColorFactor = (material.GetColor("_TintColor") * white).ToNumericsColorLinear() ; + pbr.BaseColorFactor = (material.GetColor("_TintColor") * white).ToNumericsColor() ; } if (material.HasProperty("_MainTex") || material.HasProperty("_BaseMap")) //TODO if additive particle, render black into alpha @@ -1781,7 +1783,9 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(Material material, Mater // legacy workaround: the UnityGLTF shaders misuse "_Glossiness" as roughness but don't have a keyword for it. if(material.shader.name.Equals("GLTF/PbrMetallicRoughness", StringComparison.Ordinal)) smoothness = 1 - smoothness; - pbr.RoughnessFactor = (metallicGlossMap && material.HasProperty("_GlossMapScale")) ? material.GetFloat("_GlossMapScale") : 1.0 - smoothness; + var roughnessFactor = (metallicGlossMap && material.HasProperty("_GlossMapScale")) ? material.GetFloat("_GlossMapScale") : 1.0f - smoothness; + roughnessFactor = Mathf.Clamp01(roughnessFactor); + pbr.RoughnessFactor = roughnessFactor; } if (material.HasProperty("_MetallicGlossMap")) @@ -1817,7 +1821,7 @@ private void ExportUnlit(GLTFMaterial def, Material material, MaterialPropertyBl if (material.HasProperty("_Color")) { - pbr.BaseColorFactor = material.GetColor("_Color").ToNumericsColorLinear(); + pbr.BaseColorFactor = material.GetColor("_Color").ToNumericsColor(); } if (material.HasProperty("_MainTex")) @@ -1878,7 +1882,7 @@ private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materia if (materialObj.HasProperty("_Color")) { - diffuseFactor = materialObj.GetColor("_Color").ToNumericsColorLinear(); + diffuseFactor = materialObj.GetColor("_Color").ToNumericsColor(); } if (materialObj.HasProperty("_MainTex")) @@ -1904,7 +1908,7 @@ private void ExportPBRSpecularGlossiness(GLTFMaterial material, Material materia var specGlossMap = materialObj.GetTexture("_SpecGlossMap"); if (specGlossMap == null) { - var specColor = materialObj.GetColor("_SpecColor").ToNumericsColorLinear(); + var specColor = materialObj.GetColor("_SpecColor").ToNumericsColor(); specularFactor = new GLTF.Math.Vector3(specColor.R, specColor.G, specColor.B); } } @@ -1972,7 +1976,7 @@ private MaterialCommonConstant ExportCommonConstant(Material materialObj, Materi if (materialObj.HasProperty("_AmbientFactor")) { - constant.AmbientFactor = materialObj.GetColor("_AmbientFactor").ToNumericsColorRaw(); + constant.AmbientFactor = materialObj.GetColor("_AmbientFactor").ToNumericsColor(); } if (materialObj.HasProperty("_LightMap")) @@ -1989,7 +1993,7 @@ private MaterialCommonConstant ExportCommonConstant(Material materialObj, Materi if (materialObj.HasProperty("_LightFactor")) { - constant.LightmapFactor = materialObj.GetColor("_LightFactor").ToNumericsColorRaw(); + constant.LightmapFactor = materialObj.GetColor("_LightFactor").ToNumericsColor(); } return constant; @@ -2500,10 +2504,10 @@ private AccessorId ExportAccessor(Vector2[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC2; - float minX = arr[0].x; - float minY = arr[0].y; - float maxX = arr[0].x; - float maxY = arr[0].y; + float minX = arr[0].x == float.NaN ? 0 : arr[0].x; + float minY = arr[0].y == float.NaN ? 0 : arr[0].y; + float maxX = minX; + float maxY = minY; for (var i = 1; i < count; i++) { From 9c2b8354c53519d676d7d9c121d11ab04f63d667 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 07:30:51 +0200 Subject: [PATCH 04/10] Added fix for invalid file names (files with a '.' ) --- .../Runtime/Scripts/GLTFSceneExporter.cs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index c75117c05..9d826508b 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -648,15 +648,16 @@ private void ExportTexture(Texture2D texture, string outputPath) private string ConstructImageFilenamePath(Texture2D texture, string outputPath, string enforceExtension = null) { var imagePath = _exportOptions.TexturePathRetriever(texture); + var textureName = GetTextureName(texture); if (string.IsNullOrEmpty(imagePath)) { - imagePath = Path.Combine(outputPath, texture.name); + imagePath = Path.Combine(outputPath, textureName); } var filenamePath = Path.Combine(outputPath, imagePath); if (!ExportFullPath) { - filenamePath = outputPath + "/" + texture.name; + filenamePath = outputPath + "/" + textureName; } var file = new FileInfo(filenamePath); file.Directory.Create(); @@ -2024,9 +2025,10 @@ private TextureId ExportTexture(Texture textureObj, TextureMapType textureMapTyp textureObj.name = (_root.Textures.Count + 1).ToString(); } + var textureName = GetTextureName(textureObj); if (ExportNames) { - texture.Name = textureObj.name; + texture.Name = textureName; } if (_shouldUseInternalBufferForImages) @@ -2055,9 +2057,10 @@ private TextureId ExportTexture(Texture textureObj, TextureMapType textureMapTyp private string GetImageOutputPath(Texture texture) { var imagePath = _exportOptions.TexturePathRetriever(texture); + var textureName = GetTextureName(texture); if (string.IsNullOrEmpty(imagePath)) { - imagePath = texture.name; + imagePath = textureName; } var filenamePath = imagePath; @@ -2075,7 +2078,7 @@ private string GetImageOutputPath(Texture texture) filenamePath = Path.GetFileName(filenamePath); if (!isGltfCompatible) { - filenamePath = Path.ChangeExtension(texture.name, ".png"); + filenamePath = Path.ChangeExtension(textureName, ".png"); } } @@ -2091,16 +2094,16 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) } var image = new GLTFImage(); - + var textureName = GetTextureName(texture); if (ExportNames) { - image.Name = texture.name; + image.Name = textureName; } if (texture.GetType() == typeof(RenderTexture)) { Texture2D tempTexture = new Texture2D(texture.width, texture.height); - tempTexture.name = texture.name; + tempTexture.name = textureName; RenderTexture.active = texture as RenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); @@ -2111,7 +2114,7 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) if (texture.GetType() == typeof(CustomRenderTexture)) { Texture2D tempTexture = new Texture2D(texture.width, texture.height); - tempTexture.name = texture.name; + tempTexture.name = textureName; RenderTexture.active = texture as CustomRenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); @@ -2141,6 +2144,14 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) return id; } + private string GetTextureName(Texture texture) + { + var name = texture.name; + //name = EnsureValidFileName(name); + name = name.Replace('.', '_'); + return name; + } + bool TryGetTextureDataFromDisk(TextureMapType textureMapType, Texture texture, out string path, out byte[] data) { path = null; From a4215769340a2b6b2506e3b7577b7d57dad8d678 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 08:51:19 +0200 Subject: [PATCH 05/10] fixed normal channel shader --- .../Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader b/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader index 01a1b0878..3dcc580fc 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Resources/NormalChannel.shader @@ -56,14 +56,14 @@ float4 col = tex2D(_MainTex, i.uv); // If a texture is marked as a normal map // the values are stored in the A and G channel. - //float3 unpacked = UnpackNormal(col); + float3 unpacked = UnpackNormal(col); // unpacked.xyz = LinearToGammaSpace(unpacked.xyz); - float4 result = float4(col.rgb * 0.5f + 0.5f, 1); + float4 result = float4(unpacked * 0.5f + 0.5f, 1); #ifdef UNITY_COLORSPACE_GAMMA - #else // hack for linear color space, need to figure out // right way to sample textures. result.xyz = GammaToLinearSpace(result.xyz); + #else #endif return result; } From 975577d50aa969d41df29b61cd55671d2cac4a74 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 08:53:29 +0200 Subject: [PATCH 06/10] Fixed nan values and refactored min/max searching --- .../Scripts/Extensions/SchemaExtensions.cs | 20 +- .../Runtime/Scripts/GLTFSceneExporter.cs | 430 ++++-------------- 2 files changed, 94 insertions(+), 356 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs index c2d817411..d8d9d57e0 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs @@ -444,8 +444,10 @@ public static UnityEngine.Vector2[] FlipTexCoordArrayVAndCopy(UnityEngine.Vector for (var i = 0; i < array.Length; i++) { - returnArray[i].x = array[i].x; - returnArray[i].y = 1.0f - array[i].y; + var x = array[i].x; + var y = 1.0f - array[i].y; + returnArray[i].x = float.IsNaN(x) ? 0 : x; + returnArray[i].y = float.IsNaN(y) ? 0 : y; } return returnArray; @@ -478,9 +480,9 @@ public static UnityEngine.Vector3[] ConvertVector3CoordinateSpaceAndCopy(Vector3 for (int i = 0; i < array.Length; i++) { - returnArray[i].x = array[i].x * coordinateSpaceCoordinateScale.X; - returnArray[i].y = array[i].y * coordinateSpaceCoordinateScale.Y; - returnArray[i].z = array[i].z * coordinateSpaceCoordinateScale.Z; + returnArray[i].x = (float.IsNaN(array[i].x) ? 0 : array[i].x) * coordinateSpaceCoordinateScale.X; + returnArray[i].y = (float.IsNaN(array[i].y) ? 0 : array[i].y) * coordinateSpaceCoordinateScale.Y; + returnArray[i].z = (float.IsNaN(array[i].z) ? 0 : array[i].z) * coordinateSpaceCoordinateScale.Z; } return returnArray; @@ -514,10 +516,10 @@ public static Vector4[] ConvertVector4CoordinateSpaceAndCopy(Vector4[] array, GL for (var i = 0; i < array.Length; i++) { - returnArray[i].x = array[i].x * coordinateSpaceCoordinateScale.X; - returnArray[i].y = array[i].y * coordinateSpaceCoordinateScale.Y; - returnArray[i].z = array[i].z * coordinateSpaceCoordinateScale.Z; - returnArray[i].w = array[i].w * coordinateSpaceCoordinateScale.W; + returnArray[i].x = (float.IsNaN(array[i].x) ? 0 : array[i].x) * coordinateSpaceCoordinateScale.X; + returnArray[i].y = (float.IsNaN(array[i].y) ? 0 : array[i].y) * coordinateSpaceCoordinateScale.Y; + returnArray[i].z = (float.IsNaN(array[i].z) ? 0 : array[i].z) * coordinateSpaceCoordinateScale.Z; + returnArray[i].w = (float.IsNaN(array[i].w) ? 0 : array[i].w) * coordinateSpaceCoordinateScale.W; } return returnArray; diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 9d826508b..ac5540b4d 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -1136,19 +1136,19 @@ private MeshPrimitive[] ExportPrimitive(GameObject gameObject, GLTFMesh mesh) { AccessorId aPosition = null, aNormal = null, aTangent = null, aTexcoord0 = null, aTexcoord1 = null, aColor0 = null; - aPosition = ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(meshObj.vertices, SchemaExtensions.CoordinateSpaceConversionScale)); + aPosition = ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(meshObj.vertices, SchemaExtensions.CoordinateSpaceConversionScale)); if (meshObj.normals.Length != 0) - aNormal = ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(meshObj.normals, SchemaExtensions.CoordinateSpaceConversionScale)); + aNormal = ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(meshObj.normals, SchemaExtensions.CoordinateSpaceConversionScale)); if (meshObj.tangents.Length != 0) - aTangent = ExportAccessor(SchemaExtensions.ConvertVector4CoordinateSpaceAndCopy(meshObj.tangents, SchemaExtensions.TangentSpaceConversionScale)); + aTangent = ExportAccessorVec4(SchemaExtensions.ConvertVector4CoordinateSpaceAndCopy(meshObj.tangents, SchemaExtensions.TangentSpaceConversionScale)); if (meshObj.uv.Length != 0) - aTexcoord0 = ExportAccessor(SchemaExtensions.FlipTexCoordArrayVAndCopy(meshObj.uv)); + aTexcoord0 = ExportAccessorVec2(SchemaExtensions.FlipTexCoordArrayVAndCopy(meshObj.uv)); if (meshObj.uv2.Length != 0) - aTexcoord1 = ExportAccessor(SchemaExtensions.FlipTexCoordArrayVAndCopy(meshObj.uv2)); + aTexcoord1 = ExportAccessorVec2(SchemaExtensions.FlipTexCoordArrayVAndCopy(meshObj.uv2)); if (settings.ExportVertexColors && meshObj.colors.Length != 0) aColor0 = ExportAccessor(QualitySettings.activeColorSpace == ColorSpace.Linear ? meshObj.colors : meshObj.colors.ToLinear()); @@ -1522,7 +1522,7 @@ private void ExportBlendShapes(SkinnedMeshRenderer smr, Mesh meshObj, int submes if (!settings.BlendShapeExportSparseAccessors) { - exportTargets.Add(SemanticProperties.POSITION, ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaVertices, SchemaExtensions.CoordinateSpaceConversionScale))); + exportTargets.Add(SemanticProperties.POSITION, ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaVertices, SchemaExtensions.CoordinateSpaceConversionScale))); } else { @@ -1542,7 +1542,7 @@ private void ExportBlendShapes(SkinnedMeshRenderer smr, Mesh meshObj, int submes { if (!settings.BlendShapeExportSparseAccessors) { - exportTargets.Add(SemanticProperties.NORMAL, ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaNormals, SchemaExtensions.CoordinateSpaceConversionScale))); + exportTargets.Add(SemanticProperties.NORMAL, ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaNormals, SchemaExtensions.CoordinateSpaceConversionScale))); } else { @@ -1554,13 +1554,13 @@ private void ExportBlendShapes(SkinnedMeshRenderer smr, Mesh meshObj, int submes { if (!settings.BlendShapeExportSparseAccessors) { - exportTargets.Add(SemanticProperties.TANGENT, ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaTangents, SchemaExtensions.CoordinateSpaceConversionScale))); + exportTargets.Add(SemanticProperties.TANGENT, ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaTangents, SchemaExtensions.CoordinateSpaceConversionScale))); } else { // var baseAccessor = _meshToPrims[meshObj].aTangent; // exportTargets.Add(SemanticProperties.TANGENT, ExportSparseAccessor(baseAccessor, SchemaExtensions.ConvertVector4CoordinateSpaceAndCopy(meshObj.tangents, SchemaExtensions.TangentSpaceConversionScale), SchemaExtensions.ConvertVector4CoordinateSpaceAndCopy(deltaVertices, SchemaExtensions.TangentSpaceConversionScale))); - exportTargets.Add(SemanticProperties.TANGENT, ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaTangents, SchemaExtensions.CoordinateSpaceConversionScale))); + exportTargets.Add(SemanticProperties.TANGENT, ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(deltaTangents, SchemaExtensions.CoordinateSpaceConversionScale))); Debug.LogWarning("Blend Shape Tangents for " + meshObj + " won't be exported with sparse accessors – sparse accessor for tangents isn't supported right now."); } } @@ -2403,22 +2403,8 @@ private AccessorId ExportAccessor(int[] arr, bool isIndices = false) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.SCALAR; - int min = arr[0]; - int max = arr[0]; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur < min) - { - min = cur; - } - if (cur > max) - { - max = cur; - } - } + int min = arr.Min(v => v); + int max = arr.Max(v => v); AlignToBoundary(_bufferWriter.BaseStream, 0x00); uint byteOffset = CalculateAlignment((uint)_bufferWriter.BaseStream.Position, 4); @@ -2501,7 +2487,7 @@ private AccessorId ExportAccessor(int[] arr, bool isIndices = false) return id; } - private AccessorId ExportAccessor(Vector2[] arr) + private AccessorId ExportAccessorVec2(Vector2[] arr) { uint count = (uint)arr.Length; @@ -2515,32 +2501,10 @@ private AccessorId ExportAccessor(Vector2[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC2; - float minX = arr[0].x == float.NaN ? 0 : arr[0].x; - float minY = arr[0].y == float.NaN ? 0 : arr[0].y; - float maxX = minX; - float maxY = minY; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - } + float minX = arr.Min(v => v.x); + float minY = arr.Min(v => v.y); + float maxX = arr.Max(v => v.x); + float maxY = arr.Max(v => v.y); accessor.Min = new List { minX, minY }; accessor.Max = new List { maxX, maxY }; @@ -2568,7 +2532,7 @@ private AccessorId ExportAccessor(Vector2[] arr) return id; } - private AccessorId ExportAccessor(Vector3[] arr) + private AccessorId ExportAccessorVec3(Vector3[] arr) { uint count = (uint)arr.Length; @@ -2582,42 +2546,12 @@ private AccessorId ExportAccessor(Vector3[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC3; - float minX = arr[0].x; - float minY = arr[0].y; - float minZ = arr[0].z; - float maxX = arr[0].x; - float maxY = arr[0].y; - float maxZ = arr[0].z; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.z < minZ) - { - minZ = cur.z; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - if (cur.z > maxZ) - { - maxZ = cur.z; - } - } + float minX = arr.Min(v => v.x); + float minY = arr.Min(v => v.y); + float minZ = arr.Min(v => v.z); + float maxX = arr.Max(v => v.x); + float maxY = arr.Max(v => v.y); + float maxZ = arr.Max(v => v.z); accessor.Min = new List { minX, minY, minZ }; accessor.Max = new List { maxX, maxY, maxZ }; @@ -2707,43 +2641,14 @@ private AccessorId ExportSparseAccessor(AccessorId baseAccessor, Vector3[] baseD // we need to calculate the min/max of the entire new data array uint count = (uint) arr.Length; - var firstElement = baseData != null ? (baseData[0] + arr[0]) : arr[0]; - float minX = firstElement.x; - float minY = firstElement.y; - float minZ = firstElement.z; - float maxX = firstElement.x; - float maxY = firstElement.y; - float maxZ = firstElement.z; + var arrZippedWithBase = baseData != null ? arr.Zip(baseData, (v, b) => b + v) : arr; - for (var i = 1; i < count; i++) - { - var cur = baseData != null ? (baseData[i] + arr[i]) : arr[i]; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.z < minZ) - { - minZ = cur.z; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - if (cur.z > maxZ) - { - maxZ = cur.z; - } - } + float minX = arrZippedWithBase.Min(v => v.x); + float minY = arrZippedWithBase.Min(v => v.y); + float minZ = arrZippedWithBase.Min(v => v.z); + float maxX = arrZippedWithBase.Max(v => v.x); + float maxY = arrZippedWithBase.Max(v => v.y); + float maxZ = arrZippedWithBase.Max(v => v.z); accessor.Min = new List { minX, minY, minZ }; accessor.Max = new List { maxX, maxY, maxZ }; @@ -2795,7 +2700,7 @@ private AccessorId ExportSparseAccessor(AccessorId baseAccessor, Vector3[] baseD return id; } - private AccessorId ExportAccessor(Vector4[] arr) + private AccessorId ExportAccessorVec4(Vector4[] arr) { uint count = (uint)arr.Length; @@ -2809,52 +2714,14 @@ private AccessorId ExportAccessor(Vector4[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC4; - float minX = arr[0].x; - float minY = arr[0].y; - float minZ = arr[0].z; - float minW = arr[0].w; - float maxX = arr[0].x; - float maxY = arr[0].y; - float maxZ = arr[0].z; - float maxW = arr[0].w; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.z < minZ) - { - minZ = cur.z; - } - if (cur.w < minW) - { - minW = cur.w; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - if (cur.z > maxZ) - { - maxZ = cur.z; - } - if (cur.w > maxW) - { - maxW = cur.w; - } - } + float minX = arr.Min(v => v.x); + float minY = arr.Min(v => v.y); + float minZ = arr.Min(v => v.z); + float minW = arr.Min(v => v.w); + float maxX = arr.Max(v => v.x); + float maxY = arr.Max(v => v.y); + float maxZ = arr.Max(v => v.z); + float maxW = arr.Max(v => v.w); accessor.Min = new List { minX, minY, minZ, minW }; accessor.Max = new List { maxX, maxY, maxZ, maxW }; @@ -2898,52 +2765,15 @@ private AccessorId ExportAccessor(Color[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC4; - float minR = arr[0].r; - float minG = arr[0].g; - float minB = arr[0].b; - float minA = arr[0].a; - float maxR = arr[0].r; - float maxG = arr[0].g; - float maxB = arr[0].b; - float maxA = arr[0].a; - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur.r < minR) - { - minR = cur.r; - } - if (cur.g < minG) - { - minG = cur.g; - } - if (cur.b < minB) - { - minB = cur.b; - } - if (cur.a < minA) - { - minA = cur.a; - } - if (cur.r > maxR) - { - maxR = cur.r; - } - if (cur.g > maxG) - { - maxG = cur.g; - } - if (cur.b > maxB) - { - maxB = cur.b; - } - if (cur.a > maxA) - { - maxA = cur.a; - } - } + float minR = arr.Min(c => c.r); + float minG = arr.Min(c => c.g); + float minB = arr.Min(c => c.b); + float minA = arr.Min(c => c.a); + float maxR = arr.Max(c => c.r); + float maxG = arr.Max(c => c.g); + float maxB = arr.Max(c => c.b); + float maxA = arr.Max(c => c.a); accessor.Min = new List { minR, minG, minB, minA }; accessor.Max = new List { maxR, maxG, maxB, maxA }; @@ -3281,7 +3111,7 @@ private void ConvertClipToGLTFAnimation(ref AnimationClip clip, ref Transform tr if(haveAnimation) { - AccessorId timeAccessor = ExportAccessor(times); + AccessorId timeAccessor = ExportAccessorFloat(times); // Translation if(positions != null) @@ -3299,7 +3129,7 @@ private void ConvertClipToGLTFAnimation(ref AnimationClip clip, ref Transform tr AnimationSampler Tsampler = new AnimationSampler(); Tsampler.Input = timeAccessor; - Tsampler.Output = ExportAccessor(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(positions, SchemaExtensions.CoordinateSpaceConversionScale)); + Tsampler.Output = ExportAccessorVec3(SchemaExtensions.ConvertVector3CoordinateSpaceAndCopy(positions, SchemaExtensions.CoordinateSpaceConversionScale)); Tchannel.Sampler = new AnimationSamplerId { Id = animation.Samplers.Count, @@ -3327,7 +3157,7 @@ private void ConvertClipToGLTFAnimation(ref AnimationClip clip, ref Transform tr AnimationSampler Rsampler = new AnimationSampler(); Rsampler.Input = timeAccessor; // Float, for time - Rsampler.Output = ExportAccessor(rotations, true); // Vec4 for + Rsampler.Output = ExportAccessorVec4(rotations, true); // Vec4 for Rchannel.Sampler = new AnimationSamplerId { Id = animation.Samplers.Count, @@ -3355,7 +3185,7 @@ private void ConvertClipToGLTFAnimation(ref AnimationClip clip, ref Transform tr AnimationSampler Ssampler = new AnimationSampler(); Ssampler.Input = timeAccessor; // Float, for time - Ssampler.Output = ExportAccessor(scales); // Vec3 for scale + Ssampler.Output = ExportAccessorVec3(scales); // Vec3 for scale Schannel.Sampler = new AnimationSamplerId { Id = animation.Samplers.Count, @@ -3382,7 +3212,7 @@ private void ConvertClipToGLTFAnimation(ref AnimationClip clip, ref Transform tr AnimationSampler Wsampler = new AnimationSampler(); Wsampler.Input = timeAccessor; - Wsampler.Output = ExportAccessor(weights); + Wsampler.Output = ExportAccessorFloat(weights); Wchannel.Sampler = new AnimationSamplerId() { Id = animation.Samplers.Count, @@ -3798,7 +3628,7 @@ private void ExportSkinFromNode(Transform transform) }); } - gltfSkin.InverseBindMatrices = ExportAccessor(mesh.bindposes); + gltfSkin.InverseBindMatrices = ExportAccessorMatrix(mesh.bindposes); Vector4[] bones = boneWeightToBoneVec4(mesh.boneWeights); Vector4[] weights = boneWeightToWeightVec4(mesh.boneWeights); @@ -3809,7 +3639,7 @@ private void ExportSkinFromNode(Transform transform) if (!prim.Attributes.ContainsKey("JOINTS_0")) prim.Attributes.Add("JOINTS_0", ExportAccessorUint(bones)); if (!prim.Attributes.ContainsKey("WEIGHTS_0")) - prim.Attributes.Add("WEIGHTS_0", ExportAccessor(weights)); + prim.Attributes.Add("WEIGHTS_0", ExportAccessorVec4(weights)); } _root.Nodes[_exportedTransforms[transform.GetInstanceID()]].Skin = new SkinId() { Id = _root.Skins.Count, Root = _root }; @@ -3852,52 +3682,14 @@ private AccessorId ExportAccessorUint(Vector4[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC4; - float minX = arr[0].x; - float minY = arr[0].y; - float minZ = arr[0].z; - float minW = arr[0].w; - float maxX = arr[0].x; - float maxY = arr[0].y; - float maxZ = arr[0].z; - float maxW = arr[0].w; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.z < minZ) - { - minZ = cur.z; - } - if (cur.w < minW) - { - minW = cur.w; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - if (cur.z > maxZ) - { - maxZ = cur.z; - } - if (cur.w > maxW) - { - maxW = cur.w; - } - } + float minX = arr.Min(v => v.x); + float minY = arr.Min(v => v.y); + float minZ = arr.Min(v => v.z); + float minW = arr.Min(v => v.w); + float maxX = arr.Max(v => v.x); + float maxY = arr.Max(v => v.y); + float maxZ = arr.Max(v => v.z); + float maxW = arr.Max(v => v.w); accessor.Min = new List { minX, minY, minZ, minW }; accessor.Max = new List { maxX, maxY, maxZ, maxW }; @@ -3928,7 +3720,7 @@ private AccessorId ExportAccessorUint(Vector4[] arr) } // This is used for Quaternions / Rotations - private AccessorId ExportAccessor(Vector4[] arr, bool switchHandedness = false) + private AccessorId ExportAccessorVec4(Vector4[] arr, bool switchHandedness = false) { var count = (uint)arr.Length; @@ -3942,57 +3734,17 @@ private AccessorId ExportAccessor(Vector4[] arr, bool switchHandedness = false) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.VEC4; - var a0 = arr[0]; - a0 = switchHandedness ? a0.switchHandedness() : a0; - a0 = a0.normalized; - float minX = a0.x; - float minY = a0.y; - float minZ = a0.z; - float minW = a0.w; - float maxX = a0.x; - float maxY = a0.y; - float maxZ = a0.z; - float maxW = a0.w; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - cur = switchHandedness ? cur.switchHandedness() : cur; - cur = cur.normalized; - - if (cur.x < minX) - { - minX = cur.x; - } - if (cur.y < minY) - { - minY = cur.y; - } - if (cur.z < minZ) - { - minZ = cur.z; - } - if (cur.w < minW) - { - minW = cur.w; - } - if (cur.x > maxX) - { - maxX = cur.x; - } - if (cur.y > maxY) - { - maxY = cur.y; - } - if (cur.z > maxZ) - { - maxZ = cur.z; - } - if (cur.w > maxW) - { - maxW = cur.w; - } - } + var arrSwitched = switchHandedness ? arr.Select(v => v.switchHandedness()) : arr; + arrSwitched = arrSwitched.Select(x => x.normalized); + + float minX = arrSwitched.Min(v => v.x); + float minY = arrSwitched.Min(v => v.y); + float minZ = arrSwitched.Min(v => v.z); + float minW = arrSwitched.Min(v => v.w); + float maxX = arrSwitched.Max(v => v.x); + float maxY = arrSwitched.Max(v => v.y); + float maxZ = arrSwitched.Max(v => v.z); + float maxW = arrSwitched.Max(v => v.w); accessor.Min = new List { minX, minY, minZ, minW }; accessor.Max = new List { maxX, maxY, maxZ, maxW }; @@ -4000,14 +3752,12 @@ private AccessorId ExportAccessor(Vector4[] arr, bool switchHandedness = false) AlignToBoundary(_bufferWriter.BaseStream, 0x00); uint byteOffset = CalculateAlignment((uint)_bufferWriter.BaseStream.Position, 4); - foreach (var vec in arr) + foreach (var vec in arrSwitched) { - Vector4 vect = switchHandedness ? vec.switchHandedness() : vec; - vect = vect.normalized; - _bufferWriter.Write(vect.x); - _bufferWriter.Write(vect.y); - _bufferWriter.Write(vect.z); - _bufferWriter.Write(vect.w); + _bufferWriter.Write(vec.x); + _bufferWriter.Write(vec.y); + _bufferWriter.Write(vec.z); + _bufferWriter.Write(vec.w); } uint byteLength = CalculateAlignment((uint)_bufferWriter.BaseStream.Position - byteOffset, 4); @@ -4024,7 +3774,7 @@ private AccessorId ExportAccessor(Vector4[] arr, bool switchHandedness = false) return id; } - private AccessorId ExportAccessor(float[] arr) + private AccessorId ExportAccessorFloat(float[] arr) { var count = (uint)arr.Length; @@ -4038,22 +3788,8 @@ private AccessorId ExportAccessor(float[] arr) accessor.Count = count; accessor.Type = GLTFAccessorAttributeType.SCALAR; - float min = arr[0]; - float max = arr[0]; - - for (var i = 1; i < count; i++) - { - var cur = arr[i]; - - if (cur < min) - { - min = cur; - } - if (cur > max) - { - max = cur; - } - } + float min = arr.Min(v => v); + float max = arr.Max(v => v); accessor.Min = new List { min }; accessor.Max = new List { max }; @@ -4081,7 +3817,7 @@ private AccessorId ExportAccessor(float[] arr) return id; } - private AccessorId ExportAccessor(Matrix4x4[] arr) + private AccessorId ExportAccessorMatrix(Matrix4x4[] arr) { var count = (uint)arr.Length; From c6e1df86c9f07a0ea1bc13a14ae4405dfcd3f6b0 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 11:33:28 +0200 Subject: [PATCH 07/10] Fixed colors on linear workflow --- .../UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs index d8d9d57e0..485d7d912 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/Extensions/SchemaExtensions.cs @@ -335,9 +335,9 @@ public static UnityEngine.Color ToUnityColorLinear(this GLTF.Math.Color color) public static GLTF.Math.Color ToNumericsColor(this UnityEngine.Color color) { if (QualitySettings.activeColorSpace == ColorSpace.Linear) - return color.ToNumericsColorRaw(); - else return color.ToNumericsColorLinear(); + else + return color.ToNumericsColorRaw(); } public static GLTF.Math.Color ToNumericsColorRaw(this UnityEngine.Color color) From 9af6444814975ec84b2a335de06d2956830724a4 Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 11:34:25 +0200 Subject: [PATCH 08/10] Fixed TextureNames being equal but have different content. Removed unnecessary emission colors --- .../Runtime/Scripts/GLTFSceneExporter.cs | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index ac5540b4d..7e6e15866 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -197,6 +197,7 @@ public static string SaveFolderPath private static int AnimationBakingFramerate = 30; // FPS private static bool BakeAnimationData = true; + private Dictionary _textureNames = new Dictionary(); /// /// Create a GLTFExporter that exports out a transform @@ -254,6 +255,7 @@ public GLTFSceneExporter(Transform[] rootTransforms, ExportOptions options) _imageInfos = new List(); _materials = new List(); _textures = new List(); + _textureNames = new Dictionary(); _buffer = new GLTFBuffer(); _bufferId = new BufferId @@ -1151,7 +1153,7 @@ private MeshPrimitive[] ExportPrimitive(GameObject gameObject, GLTFMesh mesh) aTexcoord1 = ExportAccessorVec2(SchemaExtensions.FlipTexCoordArrayVAndCopy(meshObj.uv2)); if (settings.ExportVertexColors && meshObj.colors.Length != 0) - aColor0 = ExportAccessor(QualitySettings.activeColorSpace == ColorSpace.Linear ? meshObj.colors : meshObj.colors.ToLinear()); + aColor0 = ExportAccessorColor(QualitySettings.activeColorSpace == ColorSpace.Linear ? meshObj.colors : meshObj.colors.ToLinear()); _meshToPrims.Add(meshObj, new MeshAccessors() { @@ -1206,9 +1208,12 @@ private MeshPrimitive[] ExportPrimitive(GameObject gameObject, GLTFMesh mesh) } var submeshPrimitive = accessors.subMeshPrimitives[submesh]; + var hasUVs = accessors.aTexcoord0 != null; + var materialId = ExportMaterial(materialsObj[submesh], materialProperty); + prims[submesh] = new MeshPrimitive(submeshPrimitive, _root) { - Material = ExportMaterial(materialsObj[submesh], materialProperty), + Material = materialId, }; } @@ -1350,7 +1355,8 @@ private MaterialId ExportMaterial(Material materialObj, MaterialPropertyBlock ma if (materialObj.HasProperty("_EmissionColor")) { var c = materialObj.GetColor("_EmissionColor"); - material.EmissiveFactor = c.ToNumericsColor(); + if (c != Color.black && c != Color.clear) + material.EmissiveFactor = c.ToNumericsColor(); } if (materialObj.HasProperty("_EmissionMap")) @@ -2025,7 +2031,7 @@ private TextureId ExportTexture(Texture textureObj, TextureMapType textureMapTyp textureObj.name = (_root.Textures.Count + 1).ToString(); } - var textureName = GetTextureName(textureObj); + var textureName = GetUniqueTextureName(textureObj); if (ExportNames) { texture.Name = textureName; @@ -2094,7 +2100,7 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) } var image = new GLTFImage(); - var textureName = GetTextureName(texture); + var textureName = GetUniqueTextureName(texture); if (ExportNames) { image.Name = textureName; @@ -2149,9 +2155,28 @@ private string GetTextureName(Texture texture) var name = texture.name; //name = EnsureValidFileName(name); name = name.Replace('.', '_'); + var success = _textureNames.TryGetValue(texture.imageContentsHash, out name); return name; } + private string GetUniqueTextureName(Texture texture) + { + var name = texture.name; + var textureHash = texture.imageContentsHash; + //name = EnsureValidFileName(name); + name = name.Replace('.', '_'); + var uniqueName = name; + var number = 0; + var isUniqueTexture = _textures.All(x => x.imageContentsHash != textureHash); + while (isUniqueTexture && _textureNames.ContainsValue(uniqueName) && number++ < 1000) + uniqueName = name + number.ToString(); + + if (!_textureNames.ContainsKey(textureHash)) + _textureNames.Add(textureHash, uniqueName); + + return uniqueName; + } + bool TryGetTextureDataFromDisk(TextureMapType textureMapType, Texture texture, out string path, out byte[] data) { path = null; @@ -2751,7 +2776,7 @@ private AccessorId ExportAccessorVec4(Vector4[] arr) return id; } - private AccessorId ExportAccessor(Color[] arr) + private AccessorId ExportAccessorColor(Color[] arr) { uint count = (uint)arr.Length; From 324b4bc8cf6bafb68d3da64c74d16a3f1fc756da Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 14:00:34 +0200 Subject: [PATCH 09/10] Wrote custom hashcode creator for textures --- .../Runtime/Scripts/GLTFSceneExporter.cs | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 7e6e15866..33bc70019 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -82,6 +82,8 @@ private struct ImageInfo private List _animatedNodes; private List _skinnedNodes; private Dictionary _bakedMeshes; + private Dictionary _textureHashes = new Dictionary(); + private Dictionary _textureNames = new Dictionary(); private int _exportLayerMask; private ExportOptions _exportOptions; @@ -197,7 +199,6 @@ public static string SaveFolderPath private static int AnimationBakingFramerate = 30; // FPS private static bool BakeAnimationData = true; - private Dictionary _textureNames = new Dictionary(); /// /// Create a GLTFExporter that exports out a transform @@ -255,7 +256,8 @@ public GLTFSceneExporter(Transform[] rootTransforms, ExportOptions options) _imageInfos = new List(); _materials = new List(); _textures = new List(); - _textureNames = new Dictionary(); + _textureHashes = new Dictionary(); + _textureNames = new Dictionary(); _buffer = new GLTFBuffer(); _bufferId = new BufferId @@ -2031,10 +2033,10 @@ private TextureId ExportTexture(Texture textureObj, TextureMapType textureMapTyp textureObj.name = (_root.Textures.Count + 1).ToString(); } - var textureName = GetUniqueTextureName(textureObj); + SetUniqueTextureName(textureObj); if (ExportNames) { - texture.Name = textureName; + texture.Name = textureObj.name; } if (_shouldUseInternalBufferForImages) @@ -2100,16 +2102,15 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) } var image = new GLTFImage(); - var textureName = GetUniqueTextureName(texture); + SetUniqueTextureName(texture); if (ExportNames) { - image.Name = textureName; + image.Name = texture.name; } if (texture.GetType() == typeof(RenderTexture)) { Texture2D tempTexture = new Texture2D(texture.width, texture.height); - tempTexture.name = textureName; RenderTexture.active = texture as RenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); @@ -2120,12 +2121,11 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) if (texture.GetType() == typeof(CustomRenderTexture)) { Texture2D tempTexture = new Texture2D(texture.width, texture.height); - tempTexture.name = textureName; RenderTexture.active = texture as CustomRenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); tempTexture.Apply(); - texture = tempTexture; + texture = tempTexture; } #endif @@ -2153,28 +2153,51 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) private string GetTextureName(Texture texture) { var name = texture.name; - //name = EnsureValidFileName(name); name = name.Replace('.', '_'); - var success = _textureNames.TryGetValue(texture.imageContentsHash, out name); return name; } - private string GetUniqueTextureName(Texture texture) + private void SetUniqueTextureName(Texture texture) { var name = texture.name; - var textureHash = texture.imageContentsHash; - //name = EnsureValidFileName(name); + var textureHash = texture.GetInstanceID(); + if (texture is Texture2D tex2D) + textureHash = CreateHashValue(tex2D); name = name.Replace('.', '_'); var uniqueName = name; var number = 0; - var isUniqueTexture = _textures.All(x => x.imageContentsHash != textureHash); - while (isUniqueTexture && _textureNames.ContainsValue(uniqueName) && number++ < 1000) + var isUniqueTexture = !_textureHashes.ContainsKey(textureHash); + while (isUniqueTexture && _textureHashes.ContainsValue(uniqueName) && number++ < 1000) uniqueName = name + number.ToString(); - if (!_textureNames.ContainsKey(textureHash)) - _textureNames.Add(textureHash, uniqueName); + if (isUniqueTexture) + _textureHashes.Add(textureHash, uniqueName); + + texture.name = uniqueName; + } + + /// + /// Creates a hashcode from a number of samples of a texture + /// + /// + /// + private int CreateHashValue(Texture2D tex) + { + var hash = CombineHashCodes(tex.width, tex.height); + var pixels = tex.GetPixels32(); + var numberOfSamples = 10; + var pixelStep = pixels.Length / numberOfSamples; + for (int i = 0; i < numberOfSamples; i++) + { + var c = pixels[pixelStep * i]; + hash += CombineHashCodes(c.r + c.g, c.b + c.a); + } + return hash; + } - return uniqueName; + internal static int CombineHashCodes(int h1, int h2) + { + return ((h1 << 5) + h1) ^ h2; } bool TryGetTextureDataFromDisk(TextureMapType textureMapType, Texture texture, out string path, out byte[] data) From 51b96a5179e98dce78da4c37cebbb8751e0f44ef Mon Sep 17 00:00:00 2001 From: Christian Petry Date: Wed, 20 Oct 2021 14:16:16 +0200 Subject: [PATCH 10/10] Fixed hash check --- .../Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 33bc70019..1182c75fe 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -2102,7 +2102,6 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) } var image = new GLTFImage(); - SetUniqueTextureName(texture); if (ExportNames) { image.Name = texture.name; @@ -2115,6 +2114,7 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) RenderTexture.active = texture as RenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); tempTexture.Apply(); + tempTexture.name = texture.name; texture = tempTexture; } #if UNITY_2017_1_OR_NEWER @@ -2125,6 +2125,7 @@ private ImageId ExportImage(Texture texture, TextureMapType textureMapType) RenderTexture.active = texture as CustomRenderTexture; tempTexture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); tempTexture.Apply(); + tempTexture.name = texture.name; texture = tempTexture; } #endif @@ -2172,7 +2173,8 @@ private void SetUniqueTextureName(Texture texture) if (isUniqueTexture) _textureHashes.Add(textureHash, uniqueName); - + else + uniqueName = _textureHashes[textureHash]; texture.name = uniqueName; } @@ -2185,7 +2187,7 @@ private int CreateHashValue(Texture2D tex) { var hash = CombineHashCodes(tex.width, tex.height); var pixels = tex.GetPixels32(); - var numberOfSamples = 10; + var numberOfSamples = Mathf.Min(59, pixels.Length); var pixelStep = pixels.Length / numberOfSamples; for (int i = 0; i < numberOfSamples; i++) {