diff --git a/GLTFSerialization/GLTFSerialization/Schema/Accessor.cs b/GLTFSerialization/GLTFSerialization/Schema/Accessor.cs
index 9d2696c42..08107e00b 100644
--- a/GLTFSerialization/GLTFSerialization/Schema/Accessor.cs
+++ b/GLTFSerialization/GLTFSerialization/Schema/Accessor.cs
@@ -102,10 +102,10 @@ public Accessor()
public Accessor(Accessor accessor, GLTFRoot gltfRoot) : base(accessor, gltfRoot)
{
- if (accessor == null)
- {
- return;
- }
+ if (accessor == null)
+ {
+ return;
+ }
if (accessor.BufferView != null)
{
@@ -322,15 +322,15 @@ private static void GetTypeDetails(
public uint[] AsUIntArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsUInts != null)
- {
- return contents.AsUInts;
- }
+ if (contents.AsUInts != null)
+ {
+ return contents.AsUInts;
+ }
- if (Type != GLTFAccessorAttributeType.SCALAR)
- {
- return null;
- }
+ if (Type != GLTFAccessorAttributeType.SCALAR)
+ {
+ return null;
+ }
var arr = new uint[Count];
var totalByteOffset = ByteOffset + offset;
@@ -355,15 +355,15 @@ public uint[] AsUIntArray(ref NumericArray contents, byte[] bufferViewData, int
public float[] AsFloatArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsUInts != null)
- {
- return contents.AsFloats;
- }
+ if (contents.AsUInts != null)
+ {
+ return contents.AsFloats;
+ }
- if (Type != GLTFAccessorAttributeType.SCALAR)
- {
- return null;
- }
+ if (Type != GLTFAccessorAttributeType.SCALAR)
+ {
+ return null;
+ }
var arr = new float[Count];
var totalByteOffset = ByteOffset + offset;
@@ -388,20 +388,20 @@ public float[] AsFloatArray(ref NumericArray contents, byte[] bufferViewData, in
public Vector2[] AsVector2Array(ref NumericArray contents, byte[] bufferViewData, int offset, bool normalizeIntValues = true)
{
- if (contents.AsVec2s != null)
- {
- return contents.AsVec2s;
- }
+ if (contents.AsVec2s != null)
+ {
+ return contents.AsVec2s;
+ }
- if (Type != GLTFAccessorAttributeType.VEC2)
- {
- return null;
- }
+ if (Type != GLTFAccessorAttributeType.VEC2)
+ {
+ return null;
+ }
- if (ComponentType == GLTFComponentType.UnsignedInt)
- {
- return null;
- }
+ if (ComponentType == GLTFComponentType.UnsignedInt)
+ {
+ return null;
+ }
var arr = new Vector2[Count];
var totalByteOffset = ByteOffset + offset;
@@ -433,20 +433,20 @@ public Vector2[] AsVector2Array(ref NumericArray contents, byte[] bufferViewData
public Vector3[] AsVector3Array(ref NumericArray contents, byte[] bufferViewData, int offset, bool normalizeIntValues = true)
{
- if (contents.AsVec3s != null)
- {
- return contents.AsVec3s;
- }
+ if (contents.AsVec3s != null)
+ {
+ return contents.AsVec3s;
+ }
- if (Type != GLTFAccessorAttributeType.VEC3)
- {
- return null;
- }
+ if (Type != GLTFAccessorAttributeType.VEC3)
+ {
+ return null;
+ }
- if (ComponentType == GLTFComponentType.UnsignedInt)
- {
- return null;
- }
+ if (ComponentType == GLTFComponentType.UnsignedInt)
+ {
+ return null;
+ }
var arr = new Vector3[Count];
var totalByteOffset = ByteOffset + offset;
@@ -478,22 +478,22 @@ public Vector3[] AsVector3Array(ref NumericArray contents, byte[] bufferViewData
return arr;
}
- public Vector4[] AsVector4Array(ref NumericArray contents, byte[] bufferViewData, int offset, bool normalizeIntValues = true)
- {
- if (contents.AsVec4s != null)
- {
- return contents.AsVec4s;
- }
-
- if (Type != GLTFAccessorAttributeType.VEC4)
- {
- return null;
- }
-
- if (ComponentType == GLTFComponentType.UnsignedInt)
- {
- return null;
- }
+ public Vector4[] AsVector4Array(ref NumericArray contents, byte[] bufferViewData, int offset, bool normalizeIntValues = true)
+ {
+ if (contents.AsVec4s != null)
+ {
+ return contents.AsVec4s;
+ }
+
+ if (Type != GLTFAccessorAttributeType.VEC4)
+ {
+ return null;
+ }
+
+ if (ComponentType == GLTFComponentType.UnsignedInt)
+ {
+ return null;
+ }
var arr = new Vector4[Count];
var totalByteOffset = ByteOffset + offset;
@@ -529,20 +529,20 @@ public Vector4[] AsVector4Array(ref NumericArray contents, byte[] bufferViewData
public Color[] AsColorArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsColors != null)
- {
- return contents.AsColors;
- }
-
- if (Type != GLTFAccessorAttributeType.VEC3 && Type != GLTFAccessorAttributeType.VEC4)
- {
- return null;
- }
-
- if (ComponentType == GLTFComponentType.UnsignedInt)
- {
- return null;
- }
+ if (contents.AsColors != null)
+ {
+ return contents.AsColors;
+ }
+
+ if (Type != GLTFAccessorAttributeType.VEC3 && Type != GLTFAccessorAttributeType.VEC4)
+ {
+ return null;
+ }
+
+ if (ComponentType == GLTFComponentType.UnsignedInt)
+ {
+ return null;
+ }
var arr = new Color[Count];
var totalByteOffset = ByteOffset + offset;
@@ -584,10 +584,10 @@ public Color[] AsColorArray(ref NumericArray contents, byte[] bufferViewData, in
public Vector2[] AsTexcoordArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsTexcoords != null)
- {
- return contents.AsTexcoords;
- }
+ if (contents.AsTexcoords != null)
+ {
+ return contents.AsTexcoords;
+ }
contents.AsTexcoords = AsVector2Array(ref contents, bufferViewData, offset);
@@ -596,10 +596,10 @@ public Vector2[] AsTexcoordArray(ref NumericArray contents, byte[] bufferViewDat
public Vector3[] AsVertexArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsVertices != null)
- {
- return contents.AsVertices;
- }
+ if (contents.AsVertices != null)
+ {
+ return contents.AsVertices;
+ }
contents.AsVertices = AsVector3Array(ref contents, bufferViewData, offset);
@@ -608,10 +608,10 @@ public Vector3[] AsVertexArray(ref NumericArray contents, byte[] bufferViewData,
public Vector3[] AsNormalArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsNormals != null)
- {
- return contents.AsNormals;
- }
+ if (contents.AsNormals != null)
+ {
+ return contents.AsNormals;
+ }
contents.AsNormals = AsVector3Array(ref contents, bufferViewData, offset);
@@ -620,10 +620,10 @@ public Vector3[] AsNormalArray(ref NumericArray contents, byte[] bufferViewData,
public Vector4[] AsTangentArray(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsTangents != null)
- {
- return contents.AsTangents;
- }
+ if (contents.AsTangents != null)
+ {
+ return contents.AsTangents;
+ }
contents.AsTangents = AsVector4Array(ref contents, bufferViewData, offset);
@@ -632,10 +632,10 @@ public Vector4[] AsTangentArray(ref NumericArray contents, byte[] bufferViewData
public uint[] AsTriangles(ref NumericArray contents, byte[] bufferViewData, int offset)
{
- if (contents.AsTriangles != null)
- {
- return contents.AsTriangles;
- }
+ if (contents.AsTriangles != null)
+ {
+ return contents.AsTriangles;
+ }
contents.AsTriangles = AsUIntArray(ref contents, bufferViewData, offset);
@@ -703,15 +703,15 @@ private static uint GetUnsignedDiscreteElement(byte[] bufferViewData, int offset
public Matrix4x4[] AsMatrix4x4Array(ref NumericArray contents, byte[] bufferViewData, int offset, bool normalizeIntValues = true)
{
- if (contents.AsMatrix4x4s != null)
- {
- return contents.AsMatrix4x4s;
- }
+ if (contents.AsMatrix4x4s != null)
+ {
+ return contents.AsMatrix4x4s;
+ }
- if (Type != GLTFAccessorAttributeType.MAT4)
- {
- return null;
- }
+ if (Type != GLTFAccessorAttributeType.MAT4)
+ {
+ return null;
+ }
Matrix4x4[] arr = new Matrix4x4[Count];
var totalByteOffset = ByteOffset + offset;
@@ -720,12 +720,12 @@ public Matrix4x4[] AsMatrix4x4Array(ref NumericArray contents, byte[] bufferView
float maxValue;
GetTypeDetails(ComponentType, out componentSize, out maxValue);
- if (normalizeIntValues)
- {
- maxValue = 1;
- }
+ if (normalizeIntValues)
+ {
+ maxValue = 1;
+ }
- var stride = BufferView.Value.ByteStride > 0 ? BufferView.Value.ByteStride : componentSize * 16;
+ var stride = BufferView.Value.ByteStride > 0 ? BufferView.Value.ByteStride : componentSize * 16;
for (var idx = 0; idx < Count; idx++)
{
@@ -775,9 +775,9 @@ public enum GLTFAccessorAttributeType
MAT4
}
- ///
- /// This struct is a union, and should be used as such
- ///
+ ///
+ /// This struct is a union, and should be used as such
+ ///
[StructLayout(LayoutKind.Explicit)]
public struct NumericArray
{
diff --git a/GLTFSerialization/GLTFSerialization/Schema/Image.cs b/GLTFSerialization/GLTFSerialization/Schema/Image.cs
index 233211356..7144919de 100644
--- a/GLTFSerialization/GLTFSerialization/Schema/Image.cs
+++ b/GLTFSerialization/GLTFSerialization/Schema/Image.cs
@@ -91,7 +91,7 @@ public override void Serialize(JsonWriter writer)
if (BufferView != null)
{
writer.WritePropertyName("bufferView");
- writer.WriteValue(BufferView);
+ writer.WriteValue(BufferView.Id);
}
base.Serialize(writer);
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFExportMenu.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFExportMenu.cs
index 8243eace9..b61942f69 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFExportMenu.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFExportMenu.cs
@@ -6,32 +6,32 @@
public class GLTFExportMenu : EditorWindow
{
- public static string RetrieveTexturePath(UnityEngine.Texture texture)
- {
- return AssetDatabase.GetAssetPath(texture);
- }
+ public static string RetrieveTexturePath(UnityEngine.Texture texture)
+ {
+ return AssetDatabase.GetAssetPath(texture);
+ }
- [MenuItem("GLTF/Settings")]
- static void Init()
- {
- GLTFExportMenu window = (GLTFExportMenu)EditorWindow.GetWindow(typeof(GLTFExportMenu), false, "GLTF Settings");
- window.Show();
- }
+ [MenuItem("GLTF/Settings")]
+ static void Init()
+ {
+ GLTFExportMenu window = (GLTFExportMenu)EditorWindow.GetWindow(typeof(GLTFExportMenu), false, "GLTF Settings");
+ window.Show();
+ }
- void OnGUI()
- {
- EditorGUILayout.LabelField("Exporter", EditorStyles.boldLabel);
- GLTFSceneExporter.ExportFullPath = EditorGUILayout.Toggle("Export using original path", GLTFSceneExporter.ExportFullPath);
- GLTFSceneExporter.ExportNames = EditorGUILayout.Toggle("Export names of nodes", GLTFSceneExporter.ExportNames);
- GLTFSceneExporter.RequireExtensions= EditorGUILayout.Toggle("Require extensions", GLTFSceneExporter.RequireExtensions);
- EditorGUILayout.Separator();
- EditorGUILayout.LabelField("Importer", EditorStyles.boldLabel);
- EditorGUILayout.Separator();
- EditorGUILayout.HelpBox("UnityGLTF version 0.1", MessageType.Info);
- EditorGUILayout.HelpBox("Supported extensions: KHR_material_pbrSpecularGlossiness, ExtTextureTransform", MessageType.Info);
- }
+ void OnGUI()
+ {
+ EditorGUILayout.LabelField("Exporter", EditorStyles.boldLabel);
+ GLTFSceneExporter.ExportFullPath = EditorGUILayout.Toggle("Export using original path", GLTFSceneExporter.ExportFullPath);
+ GLTFSceneExporter.ExportNames = EditorGUILayout.Toggle("Export names of nodes", GLTFSceneExporter.ExportNames);
+ GLTFSceneExporter.RequireExtensions= EditorGUILayout.Toggle("Require extensions", GLTFSceneExporter.RequireExtensions);
+ EditorGUILayout.Separator();
+ EditorGUILayout.LabelField("Importer", EditorStyles.boldLabel);
+ EditorGUILayout.Separator();
+ EditorGUILayout.HelpBox("UnityGLTF version 0.1", MessageType.Info);
+ EditorGUILayout.HelpBox("Supported extensions: KHR_material_pbrSpecularGlossiness, ExtTextureTransform", MessageType.Info);
+ }
- [MenuItem("GLTF/Export Selected")]
+ [MenuItem("GLTF/Export Selected")]
static void ExportSelected()
{
string name;
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporter.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporter.cs
index cda4dae32..a1fb35eed 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporter.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporter.cs
@@ -14,299 +14,299 @@
namespace UnityGLTF
{
- [ScriptedImporter(1, new[] { "glb" })]
- public class GLTFImporter : ScriptedImporter
- {
- [SerializeField] private bool _removeEmptyRootObjects = true;
- [SerializeField] private float _scaleFactor = 1.0f;
- [SerializeField] private int _maximumLod = 300;
- [SerializeField] private bool _readWriteEnabled = true;
- [SerializeField] private bool _generateColliders = false;
- [SerializeField] private bool _swapUvs = false;
- [SerializeField] private GLTFImporterNormals _importNormals = GLTFImporterNormals.Import;
- [SerializeField] private bool _importMaterials = true;
- [SerializeField] private bool _useJpgTextures = false;
-
- public override void OnImportAsset(AssetImportContext ctx)
- {
- string sceneName = null;
- GameObject gltfScene = null;
- UnityEngine.Mesh[] meshes = null;
- try
- {
- sceneName = Path.GetFileNameWithoutExtension(ctx.assetPath);
- gltfScene = CreateGLTFScene(ctx.assetPath);
-
- // Remove empty roots
- if (_removeEmptyRootObjects)
- {
- var t = gltfScene.transform;
- while (
- gltfScene.transform.childCount == 1 &&
- gltfScene.GetComponents().Length == 1)
- {
- var parent = gltfScene;
- gltfScene = gltfScene.transform.GetChild(0).gameObject;
- t = gltfScene.transform;
- t.parent = null; // To keep transform information in the new parent
- Object.DestroyImmediate(parent); // Get rid of the parent
- }
- }
-
- // Ensure there are no hide flags present (will cause problems when saving)
- gltfScene.hideFlags &= ~(HideFlags.HideAndDontSave);
- foreach (Transform child in gltfScene.transform)
- {
- child.gameObject.hideFlags &= ~(HideFlags.HideAndDontSave);
- }
-
- // Zero position
- gltfScene.transform.position = Vector3.zero;
-
- // Get meshes
- var meshNames = new List();
- var meshHash = new HashSet();
- var meshFilters = gltfScene.GetComponentsInChildren();
- var vertexBuffer = new List();
- meshes = meshFilters.Select(mf =>
- {
- var mesh = mf.sharedMesh;
- vertexBuffer.Clear();
- mesh.GetVertices(vertexBuffer);
- for (var i = 0; i < vertexBuffer.Count; ++i)
- {
- vertexBuffer[i] *= _scaleFactor;
- }
- mesh.SetVertices(vertexBuffer);
- if (_swapUvs)
- {
- var uv = mesh.uv;
- var uv2 = mesh.uv2;
- mesh.uv = uv2;
- mesh.uv2 = uv2;
- }
- if (_importNormals == GLTFImporterNormals.None)
- {
- mesh.normals = new Vector3[0];
- }
- if (_importNormals == GLTFImporterNormals.Calculate)
- {
- mesh.RecalculateNormals();
- }
- mesh.UploadMeshData(!_readWriteEnabled);
-
- if (_generateColliders)
- {
- var collider = mf.gameObject.AddComponent();
- collider.sharedMesh = mesh;
- }
-
- if (meshHash.Add(mesh))
- {
- var meshName = string.IsNullOrEmpty(mesh.name) ? mf.gameObject.name : mesh.name;
- mesh.name = ObjectNames.GetUniqueName(meshNames.ToArray(), meshName);
- meshNames.Add(mesh.name);
- }
-
- return mesh;
- }).ToArray();
-
- var renderers = gltfScene.GetComponentsInChildren();
-
- if (_importMaterials)
- {
- // Get materials
- var materialNames = new List();
- var materialHash = new HashSet();
- var materials = renderers.SelectMany(r =>
- {
- return r.sharedMaterials.Select(mat =>
- {
- if (materialHash.Add(mat))
- {
- var matName = string.IsNullOrEmpty(mat.name) ? mat.shader.name : mat.name;
- if (matName == mat.shader.name)
- {
- matName = matName.Substring(Mathf.Min(matName.LastIndexOf("/") + 1, matName.Length - 1));
- }
-
- // Ensure name is unique
- matName = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(matName));
- matName = ObjectNames.GetUniqueName(materialNames.ToArray(), matName);
-
- mat.name = matName;
- materialNames.Add(matName);
- }
-
- return mat;
- });
- }).ToArray();
-
- // Get textures
- var textureNames = new List();
- var textureHash = new HashSet();
- var texMaterialMap = new Dictionary>();
- var textures = materials.SelectMany(mat =>
- {
- var shader = mat.shader;
- if (!shader) return Enumerable.Empty();
-
- var matTextures = new List();
- for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); ++i)
- {
- if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
- {
- var propertyName = ShaderUtil.GetPropertyName(shader, i);
- var tex = mat.GetTexture(propertyName) as Texture2D;
- if (tex)
- {
- if (textureHash.Add(tex))
- {
- var texName = tex.name;
- if (string.IsNullOrEmpty(texName))
- {
- if (propertyName.StartsWith("_")) texName = propertyName.Substring(Mathf.Min(1, propertyName.Length - 1));
- }
-
- // Ensure name is unique
- texName = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(texName));
- texName = ObjectNames.GetUniqueName(textureNames.ToArray(), texName);
-
- tex.name = texName;
- textureNames.Add(texName);
- matTextures.Add(tex);
- }
-
- List materialMaps;
- if (!texMaterialMap.TryGetValue(tex, out materialMaps))
- {
- materialMaps = new List();
- texMaterialMap.Add(tex, materialMaps);
- }
-
- materialMaps.Add(new TexMaterialMap(mat, propertyName, propertyName == "_BumpMap"));
- }
- }
- }
- return matTextures;
- }).ToArray();
-
- var folderName = Path.GetDirectoryName(ctx.assetPath);
-
- // Save textures as separate assets and rewrite refs
- // TODO: Support for other texture types
- if (textures.Length > 0)
- {
- var texturesRoot = string.Concat(folderName, "/", "Textures/");
- Directory.CreateDirectory(texturesRoot);
-
- foreach (var tex in textures)
- {
- var ext = _useJpgTextures ? ".jpg" : ".png";
- var texPath = string.Concat(texturesRoot, tex.name, ext);
- File.WriteAllBytes(texPath, _useJpgTextures ? tex.EncodeToJPG() : tex.EncodeToPNG());
-
- AssetDatabase.ImportAsset(texPath);
- }
- }
-
- // Save materials as separate assets and rewrite refs
- if (materials.Length > 0)
- {
- var materialRoot = string.Concat(folderName, "/", "Materials/");
- Directory.CreateDirectory(materialRoot);
-
- foreach (var mat in materials)
- {
- var materialPath = string.Concat(materialRoot, mat.name, ".mat");
- var newMat = mat;
- CopyOrNew(mat, materialPath, m =>
- {
- // Fix references
- newMat = m;
- foreach (var r in renderers)
- {
- var sharedMaterials = r.sharedMaterials;
- for (var i = 0; i < sharedMaterials.Length; ++i)
- {
- var sharedMaterial = sharedMaterials[i];
- if (sharedMaterial.name == mat.name) sharedMaterials[i] = m;
- }
- sharedMaterials = sharedMaterials.Where(sm => sm).ToArray();
- r.sharedMaterials = sharedMaterials;
- }
- });
- // Fix textures
- // HACK: This needs to be a delayed call.
- // Unity needs a frame to kick off the texture import so we can rewrite the ref
- if (textures.Length > 0)
- {
- EditorApplication.delayCall += () =>
- {
- for (var i = 0; i < textures.Length; ++i)
- {
- var tex = textures[i];
- var texturesRoot = string.Concat(folderName, "/", "Textures/");
- var ext = _useJpgTextures ? ".jpg" : ".png";
- var texPath = string.Concat(texturesRoot, tex.name, ext);
-
- // Grab new imported texture
- var materialMaps = texMaterialMap[tex];
- var importer = (TextureImporter)TextureImporter.GetAtPath(texPath);
- var importedTex = AssetDatabase.LoadAssetAtPath(texPath);
- if (importer != null)
- {
- var isNormalMap = false;
- foreach (var materialMap in materialMaps)
- {
- if (materialMap.Material == mat)
- {
- isNormalMap |= materialMap.IsNormalMap;
- newMat.SetTexture(materialMap.Property, importedTex);
- }
- };
-
- if (isNormalMap)
- {
- // Try to auto-detect normal maps
- importer.textureType = TextureImporterType.NormalMap;
- }
- else if (importer.textureType == TextureImporterType.Sprite)
- {
- // Force disable sprite mode, even for 2D projects
- importer.textureType = TextureImporterType.Default;
- }
-
- importer.SaveAndReimport();
- }
- else
- {
- Debug.LogWarning(string.Format("GLTFImporter: Unable to import texture at path: {0}", texPath));
- }
- }
- };
- }
- }
- }
- }
- else
- {
- var temp = GameObject.CreatePrimitive(PrimitiveType.Plane);
- temp.SetActive(false);
- var defaultMat = new[] { temp.GetComponent().sharedMaterial };
- DestroyImmediate(temp);
-
- foreach (var rend in renderers)
- {
- rend.sharedMaterials = defaultMat;
- }
- }
- }
- catch
- {
- if (gltfScene) DestroyImmediate(gltfScene);
- throw;
- }
+ [ScriptedImporter(1, new[] { "glb" })]
+ public class GLTFImporter : ScriptedImporter
+ {
+ [SerializeField] private bool _removeEmptyRootObjects = true;
+ [SerializeField] private float _scaleFactor = 1.0f;
+ [SerializeField] private int _maximumLod = 300;
+ [SerializeField] private bool _readWriteEnabled = true;
+ [SerializeField] private bool _generateColliders = false;
+ [SerializeField] private bool _swapUvs = false;
+ [SerializeField] private GLTFImporterNormals _importNormals = GLTFImporterNormals.Import;
+ [SerializeField] private bool _importMaterials = true;
+ [SerializeField] private bool _useJpgTextures = false;
+
+ public override void OnImportAsset(AssetImportContext ctx)
+ {
+ string sceneName = null;
+ GameObject gltfScene = null;
+ UnityEngine.Mesh[] meshes = null;
+ try
+ {
+ sceneName = Path.GetFileNameWithoutExtension(ctx.assetPath);
+ gltfScene = CreateGLTFScene(ctx.assetPath);
+
+ // Remove empty roots
+ if (_removeEmptyRootObjects)
+ {
+ var t = gltfScene.transform;
+ while (
+ gltfScene.transform.childCount == 1 &&
+ gltfScene.GetComponents().Length == 1)
+ {
+ var parent = gltfScene;
+ gltfScene = gltfScene.transform.GetChild(0).gameObject;
+ t = gltfScene.transform;
+ t.parent = null; // To keep transform information in the new parent
+ Object.DestroyImmediate(parent); // Get rid of the parent
+ }
+ }
+
+ // Ensure there are no hide flags present (will cause problems when saving)
+ gltfScene.hideFlags &= ~(HideFlags.HideAndDontSave);
+ foreach (Transform child in gltfScene.transform)
+ {
+ child.gameObject.hideFlags &= ~(HideFlags.HideAndDontSave);
+ }
+
+ // Zero position
+ gltfScene.transform.position = Vector3.zero;
+
+ // Get meshes
+ var meshNames = new List();
+ var meshHash = new HashSet();
+ var meshFilters = gltfScene.GetComponentsInChildren();
+ var vertexBuffer = new List();
+ meshes = meshFilters.Select(mf =>
+ {
+ var mesh = mf.sharedMesh;
+ vertexBuffer.Clear();
+ mesh.GetVertices(vertexBuffer);
+ for (var i = 0; i < vertexBuffer.Count; ++i)
+ {
+ vertexBuffer[i] *= _scaleFactor;
+ }
+ mesh.SetVertices(vertexBuffer);
+ if (_swapUvs)
+ {
+ var uv = mesh.uv;
+ var uv2 = mesh.uv2;
+ mesh.uv = uv2;
+ mesh.uv2 = uv2;
+ }
+ if (_importNormals == GLTFImporterNormals.None)
+ {
+ mesh.normals = new Vector3[0];
+ }
+ if (_importNormals == GLTFImporterNormals.Calculate)
+ {
+ mesh.RecalculateNormals();
+ }
+ mesh.UploadMeshData(!_readWriteEnabled);
+
+ if (_generateColliders)
+ {
+ var collider = mf.gameObject.AddComponent();
+ collider.sharedMesh = mesh;
+ }
+
+ if (meshHash.Add(mesh))
+ {
+ var meshName = string.IsNullOrEmpty(mesh.name) ? mf.gameObject.name : mesh.name;
+ mesh.name = ObjectNames.GetUniqueName(meshNames.ToArray(), meshName);
+ meshNames.Add(mesh.name);
+ }
+
+ return mesh;
+ }).ToArray();
+
+ var renderers = gltfScene.GetComponentsInChildren();
+
+ if (_importMaterials)
+ {
+ // Get materials
+ var materialNames = new List();
+ var materialHash = new HashSet();
+ var materials = renderers.SelectMany(r =>
+ {
+ return r.sharedMaterials.Select(mat =>
+ {
+ if (materialHash.Add(mat))
+ {
+ var matName = string.IsNullOrEmpty(mat.name) ? mat.shader.name : mat.name;
+ if (matName == mat.shader.name)
+ {
+ matName = matName.Substring(Mathf.Min(matName.LastIndexOf("/") + 1, matName.Length - 1));
+ }
+
+ // Ensure name is unique
+ matName = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(matName));
+ matName = ObjectNames.GetUniqueName(materialNames.ToArray(), matName);
+
+ mat.name = matName;
+ materialNames.Add(matName);
+ }
+
+ return mat;
+ });
+ }).ToArray();
+
+ // Get textures
+ var textureNames = new List();
+ var textureHash = new HashSet();
+ var texMaterialMap = new Dictionary>();
+ var textures = materials.SelectMany(mat =>
+ {
+ var shader = mat.shader;
+ if (!shader) return Enumerable.Empty();
+
+ var matTextures = new List();
+ for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); ++i)
+ {
+ if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
+ {
+ var propertyName = ShaderUtil.GetPropertyName(shader, i);
+ var tex = mat.GetTexture(propertyName) as Texture2D;
+ if (tex)
+ {
+ if (textureHash.Add(tex))
+ {
+ var texName = tex.name;
+ if (string.IsNullOrEmpty(texName))
+ {
+ if (propertyName.StartsWith("_")) texName = propertyName.Substring(Mathf.Min(1, propertyName.Length - 1));
+ }
+
+ // Ensure name is unique
+ texName = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(texName));
+ texName = ObjectNames.GetUniqueName(textureNames.ToArray(), texName);
+
+ tex.name = texName;
+ textureNames.Add(texName);
+ matTextures.Add(tex);
+ }
+
+ List materialMaps;
+ if (!texMaterialMap.TryGetValue(tex, out materialMaps))
+ {
+ materialMaps = new List();
+ texMaterialMap.Add(tex, materialMaps);
+ }
+
+ materialMaps.Add(new TexMaterialMap(mat, propertyName, propertyName == "_BumpMap"));
+ }
+ }
+ }
+ return matTextures;
+ }).ToArray();
+
+ var folderName = Path.GetDirectoryName(ctx.assetPath);
+
+ // Save textures as separate assets and rewrite refs
+ // TODO: Support for other texture types
+ if (textures.Length > 0)
+ {
+ var texturesRoot = string.Concat(folderName, "/", "Textures/");
+ Directory.CreateDirectory(texturesRoot);
+
+ foreach (var tex in textures)
+ {
+ var ext = _useJpgTextures ? ".jpg" : ".png";
+ var texPath = string.Concat(texturesRoot, tex.name, ext);
+ File.WriteAllBytes(texPath, _useJpgTextures ? tex.EncodeToJPG() : tex.EncodeToPNG());
+
+ AssetDatabase.ImportAsset(texPath);
+ }
+ }
+
+ // Save materials as separate assets and rewrite refs
+ if (materials.Length > 0)
+ {
+ var materialRoot = string.Concat(folderName, "/", "Materials/");
+ Directory.CreateDirectory(materialRoot);
+
+ foreach (var mat in materials)
+ {
+ var materialPath = string.Concat(materialRoot, mat.name, ".mat");
+ var newMat = mat;
+ CopyOrNew(mat, materialPath, m =>
+ {
+ // Fix references
+ newMat = m;
+ foreach (var r in renderers)
+ {
+ var sharedMaterials = r.sharedMaterials;
+ for (var i = 0; i < sharedMaterials.Length; ++i)
+ {
+ var sharedMaterial = sharedMaterials[i];
+ if (sharedMaterial.name == mat.name) sharedMaterials[i] = m;
+ }
+ sharedMaterials = sharedMaterials.Where(sm => sm).ToArray();
+ r.sharedMaterials = sharedMaterials;
+ }
+ });
+ // Fix textures
+ // HACK: This needs to be a delayed call.
+ // Unity needs a frame to kick off the texture import so we can rewrite the ref
+ if (textures.Length > 0)
+ {
+ EditorApplication.delayCall += () =>
+ {
+ for (var i = 0; i < textures.Length; ++i)
+ {
+ var tex = textures[i];
+ var texturesRoot = string.Concat(folderName, "/", "Textures/");
+ var ext = _useJpgTextures ? ".jpg" : ".png";
+ var texPath = string.Concat(texturesRoot, tex.name, ext);
+
+ // Grab new imported texture
+ var materialMaps = texMaterialMap[tex];
+ var importer = (TextureImporter)TextureImporter.GetAtPath(texPath);
+ var importedTex = AssetDatabase.LoadAssetAtPath(texPath);
+ if (importer != null)
+ {
+ var isNormalMap = false;
+ foreach (var materialMap in materialMaps)
+ {
+ if (materialMap.Material == mat)
+ {
+ isNormalMap |= materialMap.IsNormalMap;
+ newMat.SetTexture(materialMap.Property, importedTex);
+ }
+ };
+
+ if (isNormalMap)
+ {
+ // Try to auto-detect normal maps
+ importer.textureType = TextureImporterType.NormalMap;
+ }
+ else if (importer.textureType == TextureImporterType.Sprite)
+ {
+ // Force disable sprite mode, even for 2D projects
+ importer.textureType = TextureImporterType.Default;
+ }
+
+ importer.SaveAndReimport();
+ }
+ else
+ {
+ Debug.LogWarning(string.Format("GLTFImporter: Unable to import texture at path: {0}", texPath));
+ }
+ }
+ };
+ }
+ }
+ }
+ }
+ else
+ {
+ var temp = GameObject.CreatePrimitive(PrimitiveType.Plane);
+ temp.SetActive(false);
+ var defaultMat = new[] { temp.GetComponent().sharedMaterial };
+ DestroyImmediate(temp);
+
+ foreach (var rend in renderers)
+ {
+ rend.sharedMaterials = defaultMat;
+ }
+ }
+ }
+ catch
+ {
+ if (gltfScene) DestroyImmediate(gltfScene);
+ throw;
+ }
#if UNITY_2017_3_OR_NEWER
// Set main asset
@@ -320,74 +320,74 @@ public override void OnImportAsset(AssetImportContext ctx)
ctx.SetMainObject(gltfScene);
#else
- // Set main asset
- ctx.SetMainAsset("main asset", gltfScene);
-
- // Add meshes
- foreach (var mesh in meshes)
- {
- ctx.AddSubAsset("mesh " + mesh.name, mesh);
- }
+ // Set main asset
+ ctx.SetMainAsset("main asset", gltfScene);
+
+ // Add meshes
+ foreach (var mesh in meshes)
+ {
+ ctx.AddSubAsset("mesh " + mesh.name, mesh);
+ }
#endif
- }
-
- private GameObject CreateGLTFScene(string projectFilePath)
- {
- ILoader fileLoader = new FileLoader(Path.GetDirectoryName(projectFilePath));
- using (var stream = File.OpenRead(projectFilePath))
- {
- GLTFRoot gLTFRoot = GLTFParser.ParseJson(stream);
- var loader = new GLTFSceneImporter(gLTFRoot, fileLoader, stream);
-
- loader.MaximumLod = _maximumLod;
-
- // HACK: Force the coroutine to run synchronously in the editor
- var stack = new Stack();
- stack.Push(loader.LoadScene(isMultithreaded: true));
-
- while (stack.Count > 0)
- {
- var enumerator = stack.Pop();
- if (enumerator.MoveNext())
- {
- stack.Push(enumerator);
- var subEnumerator = enumerator.Current as IEnumerator;
- if (subEnumerator != null)
- {
- stack.Push(subEnumerator);
- }
- }
- }
- return loader.LastLoadedScene;
- }
- }
-
- private void CopyOrNew(T asset, string assetPath, Action replaceReferences) where T : Object
- {
- var existingAsset = AssetDatabase.LoadAssetAtPath(assetPath);
- if (existingAsset)
- {
- EditorUtility.CopySerialized(asset, existingAsset);
- replaceReferences(existingAsset);
- return;
- }
-
- AssetDatabase.CreateAsset(asset, assetPath);
- }
-
- private class TexMaterialMap
- {
- public UnityEngine.Material Material { get; set; }
- public string Property { get; set; }
- public bool IsNormalMap { get; set; }
-
- public TexMaterialMap(UnityEngine.Material material, string property, bool isNormalMap)
- {
- Material = material;
- Property = property;
- IsNormalMap = isNormalMap;
- }
- }
- }
+ }
+
+ private GameObject CreateGLTFScene(string projectFilePath)
+ {
+ ILoader fileLoader = new FileLoader(Path.GetDirectoryName(projectFilePath));
+ using (var stream = File.OpenRead(projectFilePath))
+ {
+ GLTFRoot gLTFRoot = GLTFParser.ParseJson(stream);
+ var loader = new GLTFSceneImporter(gLTFRoot, fileLoader, stream);
+
+ loader.MaximumLod = _maximumLod;
+
+ // HACK: Force the coroutine to run synchronously in the editor
+ var stack = new Stack();
+ stack.Push(loader.LoadScene(isMultithreaded: true));
+
+ while (stack.Count > 0)
+ {
+ var enumerator = stack.Pop();
+ if (enumerator.MoveNext())
+ {
+ stack.Push(enumerator);
+ var subEnumerator = enumerator.Current as IEnumerator;
+ if (subEnumerator != null)
+ {
+ stack.Push(subEnumerator);
+ }
+ }
+ }
+ return loader.LastLoadedScene;
+ }
+ }
+
+ private void CopyOrNew(T asset, string assetPath, Action replaceReferences) where T : Object
+ {
+ var existingAsset = AssetDatabase.LoadAssetAtPath(assetPath);
+ if (existingAsset)
+ {
+ EditorUtility.CopySerialized(asset, existingAsset);
+ replaceReferences(existingAsset);
+ return;
+ }
+
+ AssetDatabase.CreateAsset(asset, assetPath);
+ }
+
+ private class TexMaterialMap
+ {
+ public UnityEngine.Material Material { get; set; }
+ public string Property { get; set; }
+ public bool IsNormalMap { get; set; }
+
+ public TexMaterialMap(UnityEngine.Material material, string property, bool isNormalMap)
+ {
+ Material = material;
+ Property = property;
+ IsNormalMap = isNormalMap;
+ }
+ }
+ }
}
#endif
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporterNormals.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporterNormals.cs
index 31f4b9a65..7d43b7b26 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporterNormals.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/GLTFImporterNormals.cs
@@ -1,11 +1,11 @@
#if UNITY_2017_1_OR_NEWER
namespace UnityGLTF
{
- public enum GLTFImporterNormals
- {
- Import,
- Calculate,
- None
- }
+ public enum GLTFImporterNormals
+ {
+ Import,
+ Calculate,
+ None
+ }
}
#endif
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/PbrShaderGUI.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/PbrShaderGUI.cs
index 0130eee6b..cf6935dc1 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/PbrShaderGUI.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/PbrShaderGUI.cs
@@ -5,269 +5,269 @@
namespace UnityEditor
{
- internal class PbrShaderGUI : ShaderGUI
- {
- private enum WorkflowMode
- {
- SpecularGlossiness,
- MetallicRoughness,
- Unlit
- }
-
- public enum BlendMode
- {
- Opaque,
- Mask,
- Blend
- }
-
- private static class Styles
- {
- public static GUIContent albedoText = new GUIContent("Base Color", "Albedo (RGB) and Transparency (A)");
- public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
- public static GUIContent specularMapText = new GUIContent("Spec Gloss", "Specular (RGB) and Glossiness (A)");
- public static GUIContent metallicMapText = new GUIContent("Metal Rough", "Metallic (B) and Roughness (G)");
- public static GUIContent metallicText = new GUIContent("Metallic", "Metallic value");
- public static GUIContent metallicScaleText = new GUIContent("Metallic", "Metallic scale factor");
- public static GUIContent roughnessText = new GUIContent("Roughness", "Roughness value");
-
- public static GUIContent roughnessScaleText = new GUIContent("Roughness", "Roughness scale factor");
- public static GUIContent glossinessText = new GUIContent("Glossiness", "Glossiness value");
- public static GUIContent glossinessScaleText = new GUIContent("Glossiness", "Glossiness scale factor");
- public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
- public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (R)");
- public static GUIContent emissionText = new GUIContent("Emissive", "Emissive (RGB)");
-
- public static string primaryMapsText = "Main Maps";
- public static string renderingMode = "Rendering Mode";
- public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
- public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
- }
-
- MaterialProperty blendMode = null;
- MaterialProperty albedoMap = null;
- MaterialProperty albedoColor = null;
- MaterialProperty alphaCutoff = null;
- MaterialProperty specularMap = null;
- MaterialProperty specularColor = null;
- MaterialProperty metallicMap = null;
- MaterialProperty metallic = null;
- MaterialProperty smoothness = null;
- MaterialProperty bumpScale = null;
- MaterialProperty bumpMap = null;
- MaterialProperty occlusionStrength = null;
- MaterialProperty occlusionMap = null;
- MaterialProperty emissionColor = null;
- MaterialProperty emissionMap = null;
-
- MaterialEditor m_MaterialEditor;
- WorkflowMode m_WorkflowMode = WorkflowMode.MetallicRoughness;
-
- bool m_FirstTimeApply = true;
-
- public void FindProperties(MaterialProperty[] props)
- {
- blendMode = FindProperty("_Mode", props);
- albedoMap = FindProperty("_MainTex", props);
- albedoColor = FindProperty("_Color", props);
- alphaCutoff = FindProperty("_Cutoff", props);
- specularMap = FindProperty("_SpecGlossMap", props, false);
- specularColor = FindProperty("_SpecColor", props, false);
- metallicMap = FindProperty("_MetallicGlossMap", props, false);
- metallic = FindProperty("_Metallic", props, false);
- if (specularMap != null && specularColor != null)
- m_WorkflowMode = WorkflowMode.SpecularGlossiness;
- else if (metallicMap != null && metallic != null)
- m_WorkflowMode = WorkflowMode.MetallicRoughness;
- else
- m_WorkflowMode = WorkflowMode.Unlit;
- smoothness = FindProperty("_Glossiness", props);
- bumpScale = FindProperty("_BumpScale", props);
- bumpMap = FindProperty("_BumpMap", props);
- occlusionStrength = FindProperty("_OcclusionStrength", props);
- occlusionMap = FindProperty("_OcclusionMap", props);
- emissionColor = FindProperty("_EmissionColor", props);
- emissionMap = FindProperty("_EmissionMap", props);
- }
-
- public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
- {
- FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
- m_MaterialEditor = materialEditor;
- Material material = materialEditor.target as Material;
-
- // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
- // material to a standard shader.
- // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)
- if (m_FirstTimeApply)
- {
- MaterialChanged(material, m_WorkflowMode);
- m_FirstTimeApply = false;
- }
-
- ShaderPropertiesGUI(material);
- }
-
- public void ShaderPropertiesGUI(Material material)
- {
- // Use default labelWidth
- EditorGUIUtility.labelWidth = 0f;
-
- // Detect any changes to the material
- EditorGUI.BeginChangeCheck();
- {
- BlendModePopup();
-
- // Primary properties
- GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);
- DoAlbedoArea(material);
- DoSpecularMetallicArea();
- m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
- m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
- DoEmissionArea(material);
-
- EditorGUILayout.Space();
- }
- if (EditorGUI.EndChangeCheck())
- {
- foreach (var obj in blendMode.targets)
- MaterialChanged((Material)obj, m_WorkflowMode);
- }
- }
-
- internal void DetermineWorkflow(MaterialProperty[] props)
- {
- if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
- m_WorkflowMode = WorkflowMode.SpecularGlossiness;
- else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
- m_WorkflowMode = WorkflowMode.MetallicRoughness;
- else
- m_WorkflowMode = WorkflowMode.Unlit;
- }
-
- void BlendModePopup()
- {
- EditorGUI.showMixedValue = blendMode.hasMixedValue;
- var mode = (BlendMode)blendMode.floatValue;
-
- EditorGUI.BeginChangeCheck();
- mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
- if (EditorGUI.EndChangeCheck())
- {
- m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
- blendMode.floatValue = (float)mode;
- }
-
- EditorGUI.showMixedValue = false;
- }
-
- void DoAlbedoArea(Material material)
- {
- m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
- if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Mask))
- {
- m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
- }
- }
-
- void DoEmissionArea(Material material)
- {
- bool hadEmissionTexture = emissionMap.textureValue != null;
-
- // Texture and HDR color controls
- m_MaterialEditor.TexturePropertySingleLine(Styles.emissionText, emissionMap, emissionColor);
-
- // If texture was assigned and color was black set color to white
- float brightness = emissionColor.colorValue.maxColorComponent;
- if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
- emissionColor.colorValue = Color.white;
- }
-
- void DoSpecularMetallicArea()
- {
- bool hasGlossMap = false;
- if (m_WorkflowMode == WorkflowMode.SpecularGlossiness)
- {
- hasGlossMap = specularMap.textureValue != null;
- m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);
- m_MaterialEditor.ShaderProperty(smoothness, hasGlossMap ? Styles.glossinessScaleText : Styles.glossinessText, 2);
- }
- else if (m_WorkflowMode == WorkflowMode.MetallicRoughness)
- {
- hasGlossMap = metallicMap.textureValue != null;
- m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
- m_MaterialEditor.ShaderProperty(metallic, hasGlossMap ? Styles.metallicScaleText : Styles.metallicText, 2);
- m_MaterialEditor.ShaderProperty(smoothness, hasGlossMap ? Styles.roughnessScaleText : Styles.roughnessText, 2);
- }
- }
-
- public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode, float alphaCutoff)
- {
- switch (blendMode)
- {
- case BlendMode.Opaque:
- material.SetOverrideTag("RenderType", "Opaque");
- material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
- material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
- material.SetInt("_ZWrite", 1);
- material.DisableKeyword("_ALPHATEST_ON");
- material.DisableKeyword("_ALPHABLEND_ON");
- material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
- material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
- break;
- case BlendMode.Mask:
- material.SetOverrideTag("RenderType", "TransparentCutout");
- material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
- material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
- material.SetInt("_ZWrite", 1);
- material.EnableKeyword("_ALPHATEST_ON");
- material.DisableKeyword("_ALPHABLEND_ON");
- material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
- material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
- material.SetFloat("_Cutoff", alphaCutoff);
- break;
- case BlendMode.Blend:
- material.SetOverrideTag("RenderType", "Transparent");
- material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
- material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
- material.SetInt("_ZWrite", 0);
- material.DisableKeyword("_ALPHATEST_ON");
- material.EnableKeyword("_ALPHABLEND_ON");
- material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
- material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
- break;
- }
-
- material.SetFloat("_Mode", (float)blendMode);
- }
-
- static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
- {
- // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
- // (MaterialProperty value might come from renderer material property block)
- SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
- if (workflowMode == WorkflowMode.SpecularGlossiness)
- SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
- else if (workflowMode == WorkflowMode.MetallicRoughness)
- SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
-
- bool shouldEmissionBeEnabled = material.GetColor("_EmissionColor") != Color.black;
- SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
- }
-
- static void MaterialChanged(Material material, WorkflowMode workflowMode)
- {
- SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"), material.GetFloat("_Cutoff"));
-
- SetMaterialKeywords(material, workflowMode);
- }
-
- static void SetKeyword(Material m, string keyword, bool state)
- {
- if (state)
- m.EnableKeyword(keyword);
- else
- m.DisableKeyword(keyword);
- }
- }
+ internal class PbrShaderGUI : ShaderGUI
+ {
+ private enum WorkflowMode
+ {
+ SpecularGlossiness,
+ MetallicRoughness,
+ Unlit
+ }
+
+ public enum BlendMode
+ {
+ Opaque,
+ Mask,
+ Blend
+ }
+
+ private static class Styles
+ {
+ public static GUIContent albedoText = new GUIContent("Base Color", "Albedo (RGB) and Transparency (A)");
+ public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
+ public static GUIContent specularMapText = new GUIContent("Spec Gloss", "Specular (RGB) and Glossiness (A)");
+ public static GUIContent metallicMapText = new GUIContent("Metal Rough", "Metallic (B) and Roughness (G)");
+ public static GUIContent metallicText = new GUIContent("Metallic", "Metallic value");
+ public static GUIContent metallicScaleText = new GUIContent("Metallic", "Metallic scale factor");
+ public static GUIContent roughnessText = new GUIContent("Roughness", "Roughness value");
+
+ public static GUIContent roughnessScaleText = new GUIContent("Roughness", "Roughness scale factor");
+ public static GUIContent glossinessText = new GUIContent("Glossiness", "Glossiness value");
+ public static GUIContent glossinessScaleText = new GUIContent("Glossiness", "Glossiness scale factor");
+ public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
+ public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (R)");
+ public static GUIContent emissionText = new GUIContent("Emissive", "Emissive (RGB)");
+
+ public static string primaryMapsText = "Main Maps";
+ public static string renderingMode = "Rendering Mode";
+ public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
+ public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
+ }
+
+ MaterialProperty blendMode = null;
+ MaterialProperty albedoMap = null;
+ MaterialProperty albedoColor = null;
+ MaterialProperty alphaCutoff = null;
+ MaterialProperty specularMap = null;
+ MaterialProperty specularColor = null;
+ MaterialProperty metallicMap = null;
+ MaterialProperty metallic = null;
+ MaterialProperty smoothness = null;
+ MaterialProperty bumpScale = null;
+ MaterialProperty bumpMap = null;
+ MaterialProperty occlusionStrength = null;
+ MaterialProperty occlusionMap = null;
+ MaterialProperty emissionColor = null;
+ MaterialProperty emissionMap = null;
+
+ MaterialEditor m_MaterialEditor;
+ WorkflowMode m_WorkflowMode = WorkflowMode.MetallicRoughness;
+
+ bool m_FirstTimeApply = true;
+
+ public void FindProperties(MaterialProperty[] props)
+ {
+ blendMode = FindProperty("_Mode", props);
+ albedoMap = FindProperty("_MainTex", props);
+ albedoColor = FindProperty("_Color", props);
+ alphaCutoff = FindProperty("_Cutoff", props);
+ specularMap = FindProperty("_SpecGlossMap", props, false);
+ specularColor = FindProperty("_SpecColor", props, false);
+ metallicMap = FindProperty("_MetallicGlossMap", props, false);
+ metallic = FindProperty("_Metallic", props, false);
+ if (specularMap != null && specularColor != null)
+ m_WorkflowMode = WorkflowMode.SpecularGlossiness;
+ else if (metallicMap != null && metallic != null)
+ m_WorkflowMode = WorkflowMode.MetallicRoughness;
+ else
+ m_WorkflowMode = WorkflowMode.Unlit;
+ smoothness = FindProperty("_Glossiness", props);
+ bumpScale = FindProperty("_BumpScale", props);
+ bumpMap = FindProperty("_BumpMap", props);
+ occlusionStrength = FindProperty("_OcclusionStrength", props);
+ occlusionMap = FindProperty("_OcclusionMap", props);
+ emissionColor = FindProperty("_EmissionColor", props);
+ emissionMap = FindProperty("_EmissionMap", props);
+ }
+
+ public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
+ {
+ FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
+ m_MaterialEditor = materialEditor;
+ Material material = materialEditor.target as Material;
+
+ // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
+ // material to a standard shader.
+ // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)
+ if (m_FirstTimeApply)
+ {
+ MaterialChanged(material, m_WorkflowMode);
+ m_FirstTimeApply = false;
+ }
+
+ ShaderPropertiesGUI(material);
+ }
+
+ public void ShaderPropertiesGUI(Material material)
+ {
+ // Use default labelWidth
+ EditorGUIUtility.labelWidth = 0f;
+
+ // Detect any changes to the material
+ EditorGUI.BeginChangeCheck();
+ {
+ BlendModePopup();
+
+ // Primary properties
+ GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);
+ DoAlbedoArea(material);
+ DoSpecularMetallicArea();
+ m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
+ DoEmissionArea(material);
+
+ EditorGUILayout.Space();
+ }
+ if (EditorGUI.EndChangeCheck())
+ {
+ foreach (var obj in blendMode.targets)
+ MaterialChanged((Material)obj, m_WorkflowMode);
+ }
+ }
+
+ internal void DetermineWorkflow(MaterialProperty[] props)
+ {
+ if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
+ m_WorkflowMode = WorkflowMode.SpecularGlossiness;
+ else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
+ m_WorkflowMode = WorkflowMode.MetallicRoughness;
+ else
+ m_WorkflowMode = WorkflowMode.Unlit;
+ }
+
+ void BlendModePopup()
+ {
+ EditorGUI.showMixedValue = blendMode.hasMixedValue;
+ var mode = (BlendMode)blendMode.floatValue;
+
+ EditorGUI.BeginChangeCheck();
+ mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
+ if (EditorGUI.EndChangeCheck())
+ {
+ m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
+ blendMode.floatValue = (float)mode;
+ }
+
+ EditorGUI.showMixedValue = false;
+ }
+
+ void DoAlbedoArea(Material material)
+ {
+ m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
+ if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Mask))
+ {
+ m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
+ }
+ }
+
+ void DoEmissionArea(Material material)
+ {
+ bool hadEmissionTexture = emissionMap.textureValue != null;
+
+ // Texture and HDR color controls
+ m_MaterialEditor.TexturePropertySingleLine(Styles.emissionText, emissionMap, emissionColor);
+
+ // If texture was assigned and color was black set color to white
+ float brightness = emissionColor.colorValue.maxColorComponent;
+ if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
+ emissionColor.colorValue = Color.white;
+ }
+
+ void DoSpecularMetallicArea()
+ {
+ bool hasGlossMap = false;
+ if (m_WorkflowMode == WorkflowMode.SpecularGlossiness)
+ {
+ hasGlossMap = specularMap.textureValue != null;
+ m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);
+ m_MaterialEditor.ShaderProperty(smoothness, hasGlossMap ? Styles.glossinessScaleText : Styles.glossinessText, 2);
+ }
+ else if (m_WorkflowMode == WorkflowMode.MetallicRoughness)
+ {
+ hasGlossMap = metallicMap.textureValue != null;
+ m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
+ m_MaterialEditor.ShaderProperty(metallic, hasGlossMap ? Styles.metallicScaleText : Styles.metallicText, 2);
+ m_MaterialEditor.ShaderProperty(smoothness, hasGlossMap ? Styles.roughnessScaleText : Styles.roughnessText, 2);
+ }
+ }
+
+ public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode, float alphaCutoff)
+ {
+ switch (blendMode)
+ {
+ case BlendMode.Opaque:
+ material.SetOverrideTag("RenderType", "Opaque");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+ material.SetInt("_ZWrite", 1);
+ material.DisableKeyword("_ALPHATEST_ON");
+ material.DisableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
+ break;
+ case BlendMode.Mask:
+ material.SetOverrideTag("RenderType", "TransparentCutout");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+ material.SetInt("_ZWrite", 1);
+ material.EnableKeyword("_ALPHATEST_ON");
+ material.DisableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
+ material.SetFloat("_Cutoff", alphaCutoff);
+ break;
+ case BlendMode.Blend:
+ material.SetOverrideTag("RenderType", "Transparent");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+ material.SetInt("_ZWrite", 0);
+ material.DisableKeyword("_ALPHATEST_ON");
+ material.EnableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
+ break;
+ }
+
+ material.SetFloat("_Mode", (float)blendMode);
+ }
+
+ static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
+ {
+ // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
+ // (MaterialProperty value might come from renderer material property block)
+ SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
+ if (workflowMode == WorkflowMode.SpecularGlossiness)
+ SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
+ else if (workflowMode == WorkflowMode.MetallicRoughness)
+ SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
+
+ bool shouldEmissionBeEnabled = material.GetColor("_EmissionColor") != Color.black;
+ SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
+ }
+
+ static void MaterialChanged(Material material, WorkflowMode workflowMode)
+ {
+ SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"), material.GetFloat("_Cutoff"));
+
+ SetMaterialKeywords(material, workflowMode);
+ }
+
+ static void SetKeyword(Material m, string keyword, bool state)
+ {
+ if (state)
+ m.EnableKeyword(keyword);
+ else
+ m.DisableKeyword(keyword);
+ }
+ }
} // namespace UnityEditor
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneExporter.cs
index b224bcde3..ed75d4a0f 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneExporter.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneExporter.cs
@@ -30,7 +30,8 @@ private enum TextureMapType
Emission,
MetallicGloss,
Light,
- Occlusion}
+ Occlusion
+ }
;
@@ -48,19 +49,20 @@ private struct ImageInfo
private List _imageInfos;
private List _textures;
private List _materials;
+ private bool _imagesInInternalBuffer;
private RetrieveTexturePathDelegate _retrieveTexturePathDelegate;
private UnityEngine.Material _metalGlossChannelSwapMaterial;
private UnityEngine.Material _normalChannelMaterial;
- private const uint MagicGLTF = 0x46546C67;
- private const uint Version = 2;
- private const uint MagicJson = 0x4E4F534A;
- private const uint MagicBin = 0x004E4942;
+ private const uint MagicGLTF = 0x46546C67;
+ private const uint Version = 2;
+ private const uint MagicJson = 0x4E4F534A;
+ private const uint MagicBin = 0x004E4942;
private const int GLTFHeaderSize = 12;
private const int SectionHeaderSize = 8;
-
+
protected struct PrimKey
{
public UnityEngine.Mesh Mesh;
@@ -74,6 +76,7 @@ protected struct PrimKey
public static bool ExportFullPath = true;
public static bool RequireExtensions = false;
+
///
/// Create a GLTFExporter that exports out a transform
///
@@ -82,11 +85,11 @@ public GLTFSceneExporter(Transform[] rootTransforms, RetrieveTexturePathDelegate
{
_retrieveTexturePathDelegate = retrieveTexturePathDelegate;
- var metalGlossChannelSwapShader = Resources.Load ("MetalGlossChannelSwap", typeof(UnityEngine.Shader)) as UnityEngine.Shader;
- _metalGlossChannelSwapMaterial = new UnityEngine.Material (metalGlossChannelSwapShader);
+ var metalGlossChannelSwapShader = Resources.Load("MetalGlossChannelSwap", typeof(UnityEngine.Shader)) as UnityEngine.Shader;
+ _metalGlossChannelSwapMaterial = new UnityEngine.Material(metalGlossChannelSwapShader);
- var normalChannelShader = Resources.Load ("NormalChannel", typeof(UnityEngine.Shader)) as UnityEngine.Shader;
- _normalChannelMaterial = new UnityEngine.Material (normalChannelShader);
+ var normalChannelShader = Resources.Load("NormalChannel", typeof(UnityEngine.Shader)) as UnityEngine.Shader;
+ _normalChannelMaterial = new UnityEngine.Material(normalChannelShader);
_rootTransforms = rootTransforms;
_root = new GLTFRoot
@@ -108,9 +111,9 @@ public GLTFSceneExporter(Transform[] rootTransforms, RetrieveTexturePathDelegate
Textures = new List(),
};
- _imageInfos = new List ();
- _materials = new List ();
- _textures = new List ();
+ _imageInfos = new List();
+ _materials = new List();
+ _textures = new List();
_buffer = new GLTF.Schema.Buffer();
_bufferId = new BufferId
@@ -118,7 +121,7 @@ public GLTFSceneExporter(Transform[] rootTransforms, RetrieveTexturePathDelegate
Id = _root.Buffers.Count,
Root = _root
};
- _root.Buffers.Add (_buffer);
+ _root.Buffers.Add(_buffer);
}
///
@@ -137,6 +140,7 @@ public GLTFRoot GetRoot()
/// The name of the GLTF file
public void SaveGLB(string path, string fileName)
{
+ _imagesInInternalBuffer = true;
Stream binStream = new MemoryStream();
Stream jsonStream = new MemoryStream();
@@ -188,8 +192,10 @@ public void SaveGLB(string path, string fileName)
writer.Flush();
}
-
- ExportImages(path);
+ if (!_imagesInInternalBuffer)
+ {
+ ExportImages(path);
+ }
}
///
@@ -220,7 +226,7 @@ private static void CopyStream(Stream input, BinaryWriter output)
///
private static void AlignToBoundary(Stream stream, byte pad = (byte)' ', uint boundary = 4)
{
- uint currentLength = (uint) stream.Length;
+ uint currentLength = (uint)stream.Length;
uint newLength = CalculateAlignment(currentLength, boundary);
for (int i = 0; i < newLength - currentLength; i++)
{
@@ -248,6 +254,8 @@ public static uint CalculateAlignment(uint currentSize, uint byteAlignment)
/// The name of the GLTF file
public void SaveGLTFandBin(string path, string fileName)
{
+ _imagesInInternalBuffer = false;
+
var binFile = File.Create(Path.Combine(path, fileName + ".bin"));
_bufferWriter = new BinaryWriter(binFile);
@@ -263,30 +271,32 @@ public void SaveGLTFandBin(string path, string fileName)
gltfFile.Dispose();
binFile.Dispose();
#else
- gltfFile.Close ();
- binFile.Close ();
+ gltfFile.Close();
+ binFile.Close();
#endif
- ExportImages (path);
-
+ ExportImages(path);
+
}
- private void ExportImages (string outputPath)
+ private void ExportImages(string outputPath)
{
- for (int t = 0; t < _imageInfos.Count; ++t) {
- var image = _imageInfos [t].texture;
+ for (int t = 0; t < _imageInfos.Count; ++t)
+ {
+ var image = _imageInfos[t].texture;
int height = image.height;
int width = image.width;
- switch (_imageInfos [t].textureMapType) {
- case TextureMapType.MetallicGloss:
- ExportMetallicGlossTexture (image, outputPath);
- break;
- case TextureMapType.Bump:
- ExportNormalTexture (image, outputPath);
- break;
- default:
- ExportTexture (image, outputPath);
- break;
+ switch (_imageInfos[t].textureMapType)
+ {
+ case TextureMapType.MetallicGloss:
+ ExportMetallicGlossTexture(image, outputPath);
+ break;
+ case TextureMapType.Bump:
+ ExportNormalTexture(image, outputPath);
+ break;
+ default:
+ ExportTexture(image, outputPath);
+ break;
}
}
}
@@ -298,19 +308,19 @@ private void ExportImages (string outputPath)
///
/// Unity's metallic-gloss texture to be exported
/// The location to export the texture
- private void ExportMetallicGlossTexture (Texture2D texture, string outputPath)
+ private void ExportMetallicGlossTexture(Texture2D texture, string outputPath)
{
var destRenderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
- Graphics.Blit (texture, destRenderTexture, _metalGlossChannelSwapMaterial);
-
- var exportTexture = new Texture2D (texture.width, texture.height);
- exportTexture.ReadPixels (new Rect (0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
- exportTexture.Apply ();
+ Graphics.Blit(texture, destRenderTexture, _metalGlossChannelSwapMaterial);
- var finalFilenamePath = ConstructImageFilenamePath (texture, outputPath);
- File.WriteAllBytes (finalFilenamePath, exportTexture.EncodeToPNG ());
+ var exportTexture = new Texture2D(texture.width, texture.height);
+ exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
+ exportTexture.Apply();
+ var finalFilenamePath = ConstructImageFilenamePath(texture, outputPath);
+ File.WriteAllBytes(finalFilenamePath, exportTexture.EncodeToPNG());
+ RenderTexture.active = null;
destRenderTexture.Release();
if (Application.isEditor)
{
@@ -328,19 +338,19 @@ private void ExportMetallicGlossTexture (Texture2D texture, string outputPath)
///
/// Unity's normal texture to be exported
/// The location to export the texture
- private void ExportNormalTexture (Texture2D texture, string outputPath)
+ private void ExportNormalTexture(Texture2D texture, string outputPath)
{
var destRenderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
- Graphics.Blit (texture, destRenderTexture, _normalChannelMaterial);
+ Graphics.Blit(texture, destRenderTexture, _normalChannelMaterial);
- var exportTexture = new Texture2D (texture.width, texture.height);
- exportTexture.ReadPixels (new Rect (0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
- exportTexture.Apply ();
-
- var finalFilenamePath = ConstructImageFilenamePath (texture, outputPath);
- File.WriteAllBytes (finalFilenamePath, exportTexture.EncodeToPNG ());
+ var exportTexture = new Texture2D(texture.width, texture.height);
+ exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
+ exportTexture.Apply();
+ var finalFilenamePath = ConstructImageFilenamePath(texture, outputPath);
+ File.WriteAllBytes(finalFilenamePath, exportTexture.EncodeToPNG());
+ RenderTexture.active = null;
destRenderTexture.Release();
if (Application.isEditor)
@@ -353,19 +363,19 @@ private void ExportNormalTexture (Texture2D texture, string outputPath)
}
}
- private void ExportTexture (Texture2D texture, string outputPath)
+ private void ExportTexture(Texture2D texture, string outputPath)
{
var destRenderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
- Graphics.Blit (texture, destRenderTexture);
-
- var exportTexture = new Texture2D (texture.width, texture.height);
- exportTexture.ReadPixels (new Rect (0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
- exportTexture.Apply ();
+ Graphics.Blit(texture, destRenderTexture);
- var finalFilenamePath = ConstructImageFilenamePath (texture, outputPath);
- File.WriteAllBytes (finalFilenamePath, exportTexture.EncodeToPNG ());
+ var exportTexture = new Texture2D(texture.width, texture.height);
+ exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
+ exportTexture.Apply();
+ var finalFilenamePath = ConstructImageFilenamePath(texture, outputPath);
+ File.WriteAllBytes(finalFilenamePath, exportTexture.EncodeToPNG());
+ RenderTexture.active = null;
destRenderTexture.Release();
if (Application.isEditor)
{
@@ -377,35 +387,35 @@ private void ExportTexture (Texture2D texture, string outputPath)
}
}
- private string ConstructImageFilenamePath (Texture2D texture, string outputPath)
+ private string ConstructImageFilenamePath(Texture2D texture, string outputPath)
{
var imagePath = _retrieveTexturePathDelegate(texture);
- var filenamePath = Path.Combine (outputPath, imagePath);
+ var filenamePath = Path.Combine(outputPath, imagePath);
if (!ExportFullPath)
{
filenamePath = outputPath + "/" + texture.name;
}
- var file = new System.IO.FileInfo (filenamePath);
- file.Directory.Create ();
- return Path.ChangeExtension (filenamePath, ".png");
+ var file = new System.IO.FileInfo(filenamePath);
+ file.Directory.Create();
+ return Path.ChangeExtension(filenamePath, ".png");
}
- private SceneId ExportScene (string name, Transform[] rootObjTransforms)
+ private SceneId ExportScene(string name, Transform[] rootObjTransforms)
{
- var scene = new Scene ();
+ var scene = new Scene();
- if (ExportNames)
+ if (ExportNames)
{
scene.Name = name;
}
- scene.Nodes = new List (rootObjTransforms.Length);
- foreach (var transform in rootObjTransforms)
+ scene.Nodes = new List(rootObjTransforms.Length);
+ foreach (var transform in rootObjTransforms)
{
- scene.Nodes.Add (ExportNode (transform));
+ scene.Nodes.Add(ExportNode(transform));
}
- _root.Scenes.Add (scene);
+ _root.Scenes.Add(scene);
return new SceneId
{
@@ -502,12 +512,13 @@ private CameraId ExportCamera(UnityEngine.Camera unityCamera)
perspective.YFov = fov;
perspective.AspectRatio = aspectRatio;
- if (matrix[2,2] == -1)
+ if (matrix[2, 2] == -1)
{
//infinite projection matrix
float nearClip = matrix[2, 3] * -0.5f;
perspective.ZNear = nearClip;
- } else
+ }
+ else
{
//finite projection matrix
float farClip = matrix[2, 3] / (matrix[2, 2] + 1);
@@ -788,13 +799,13 @@ private MaterialId ExportMaterial(UnityEngine.Material materialObj)
}
}
- if (IsPBRMetallicRoughness (materialObj))
+ if (IsPBRMetallicRoughness(materialObj))
{
- material.PbrMetallicRoughness = ExportPBRMetallicRoughness (materialObj);
- }
- else if (IsCommonConstant (materialObj))
+ material.PbrMetallicRoughness = ExportPBRMetallicRoughness(materialObj);
+ }
+ else if (IsCommonConstant(materialObj))
{
- material.CommonConstant = ExportCommonConstant (materialObj);
+ material.CommonConstant = ExportCommonConstant(materialObj);
}
_materials.Add(materialObj);
@@ -809,16 +820,16 @@ private MaterialId ExportMaterial(UnityEngine.Material materialObj)
return id;
}
- private bool IsPBRMetallicRoughness (UnityEngine.Material material)
+ private bool IsPBRMetallicRoughness(UnityEngine.Material material)
{
- return material.HasProperty ("_Metallic") && material.HasProperty ("_MetallicGlossMap");
+ return material.HasProperty("_Metallic") && material.HasProperty("_MetallicGlossMap");
}
- private bool IsCommonConstant (UnityEngine.Material material)
+ private bool IsCommonConstant(UnityEngine.Material material)
{
- return material.HasProperty ("_AmbientFactor") &&
- material.HasProperty ("_LightMap") &&
- material.HasProperty ("_LightFactor");
+ return material.HasProperty("_AmbientFactor") &&
+ material.HasProperty("_LightMap") &&
+ material.HasProperty("_LightFactor");
}
private void ExportTextureTransform(TextureInfo def, UnityEngine.Material mat, string texName)
@@ -863,33 +874,35 @@ private void ExportTextureTransform(TextureInfo def, UnityEngine.Material mat, s
);
}
- private NormalTextureInfo ExportNormalTextureInfo (
- UnityEngine.Texture texture,
- TextureMapType textureMapType,
+ private NormalTextureInfo ExportNormalTextureInfo(
+ UnityEngine.Texture texture,
+ TextureMapType textureMapType,
UnityEngine.Material material)
{
- var info = new NormalTextureInfo ();
+ var info = new NormalTextureInfo();
- info.Index = ExportTexture (texture, textureMapType);
+ info.Index = ExportTexture(texture, textureMapType);
- if (material.HasProperty ("_BumpScale")) {
- info.Scale = material.GetFloat ("_BumpScale");
+ if (material.HasProperty("_BumpScale"))
+ {
+ info.Scale = material.GetFloat("_BumpScale");
}
return info;
}
- private OcclusionTextureInfo ExportOcclusionTextureInfo (
- UnityEngine.Texture texture,
+ private OcclusionTextureInfo ExportOcclusionTextureInfo(
+ UnityEngine.Texture texture,
TextureMapType textureMapType,
UnityEngine.Material material)
{
- var info = new OcclusionTextureInfo ();
+ var info = new OcclusionTextureInfo();
- info.Index = ExportTexture (texture, textureMapType);
+ info.Index = ExportTexture(texture, textureMapType);
- if (material.HasProperty ("_OcclusionStrength")) {
- info.Strength = material.GetFloat ("_OcclusionStrength");
+ if (material.HasProperty("_OcclusionStrength"))
+ {
+ info.Strength = material.GetFloat("_OcclusionStrength");
}
return info;
@@ -915,16 +928,16 @@ private PbrMetallicRoughness ExportPBRMetallicRoughness(UnityEngine.Material mat
}
}
- if (material.HasProperty ("_Metallic"))
+ if (material.HasProperty("_Metallic"))
{
- var metallicGlossMap = material.GetTexture ("_MetallicGlossMap");
- pbr.MetallicFactor = (metallicGlossMap != null) ? 1.0 : material.GetFloat ("_Metallic");
+ var metallicGlossMap = material.GetTexture("_MetallicGlossMap");
+ pbr.MetallicFactor = (metallicGlossMap != null) ? 1.0 : material.GetFloat("_Metallic");
}
- if (material.HasProperty ("_Glossiness"))
+ if (material.HasProperty("_Glossiness"))
{
- var metallicGlossMap = material.GetTexture ("_MetallicGlossMap");
- pbr.RoughnessFactor = (metallicGlossMap != null) ? 1.0 : material.GetFloat ("_Glossiness");
+ var metallicGlossMap = material.GetTexture("_MetallicGlossMap");
+ pbr.RoughnessFactor = (metallicGlossMap != null) ? 1.0 : material.GetFloat("_Glossiness");
}
if (material.HasProperty("_MetallicGlossMap"))
@@ -1031,7 +1044,14 @@ private TextureId ExportTexture(UnityEngine.Texture textureObj, TextureMapType t
texture.Name = textureObj.name;
}
- texture.Source = ExportImage(textureObj, textureMapType);
+ if (_imagesInInternalBuffer)
+ {
+ texture.Source = ExportImageInternalBuffer(textureObj);
+ }
+ else
+ {
+ texture.Source = ExportImage(textureObj, textureMapType);
+ }
texture.Sampler = ExportSampler(textureObj);
_textures.Add(textureObj);
@@ -1062,7 +1082,8 @@ private ImageId ExportImage(UnityEngine.Texture texture, TextureMapType texturMa
image.Name = texture.name;
}
- _imageInfos.Add (new ImageInfo {
+ _imageInfos.Add(new ImageInfo
+ {
texture = texture as Texture2D,
textureMapType = texturMapType
});
@@ -1086,6 +1107,60 @@ private ImageId ExportImage(UnityEngine.Texture texture, TextureMapType texturMa
return id;
}
+ private ImageId ExportImageInternalBuffer(UnityEngine.Texture texture)
+ {
+
+ if (texture == null)
+ {
+ throw new Exception("texture can not be NULL.");
+ }
+
+ var image = new Image();
+ image.MimeType = "image/png";
+
+ var byteOffset = _bufferWriter.BaseStream.Position;
+
+ {//
+ var destRenderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
+ GL.sRGBWrite = true;
+ Graphics.Blit(texture, destRenderTexture);
+
+ var exportTexture = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false);
+ exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
+ exportTexture.Apply();
+
+ var pngImageData = exportTexture.EncodeToPNG();
+ _bufferWriter.Write(pngImageData);
+ RenderTexture.active = null;
+ destRenderTexture.Release();
+ GL.sRGBWrite = false;
+ if (Application.isEditor)
+ {
+ UnityEngine.Object.DestroyImmediate(exportTexture);
+ }
+ else
+ {
+ UnityEngine.Object.Destroy(exportTexture);
+ }
+ }
+
+ var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
+ image.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
+
+
+ var id = new ImageId
+ {
+ Id = _root.Images.Count,
+ Root = _root
+ };
+ _root.Images.Add(image);
+
+ return id;
+ }
+
private SamplerId ExportSampler(UnityEngine.Texture texture)
{
var samplerId = GetSamplerId(_root, texture);
@@ -1164,6 +1239,8 @@ private AccessorId ExportAccessor(int[] arr, bool isIndices = false)
var byteOffset = _bufferWriter.BaseStream.Position;
+
+
if (max <= byte.MaxValue && min >= byte.MinValue)
{
accessor.ComponentType = GLTFComponentType.UnsignedByte;
@@ -1221,9 +1298,12 @@ private AccessorId ExportAccessor(int[] arr, bool isIndices = false)
accessor.Min = new List { min };
accessor.Max = new List { max };
+ //byteOffset = AppendToBufferSizeTo4(accessor, byteOffset);
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId
@@ -1236,6 +1316,21 @@ private AccessorId ExportAccessor(int[] arr, bool isIndices = false)
return id;
}
+ private long AppendToBufferMultiplyOf4(long byteOffset, long byteLength)
+ {
+ var moduloOffset = byteLength % 4;
+ if (moduloOffset > 0)
+ {
+ for (int i = 0; i < (4 - moduloOffset); i++)
+ {
+ _bufferWriter.Write((byte)0x00);
+ }
+ byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ }
+
+ return byteLength;
+ }
+
private AccessorId ExportAccessor(Vector2[] arr)
{
var count = arr.Length;
@@ -1288,8 +1383,11 @@ private AccessorId ExportAccessor(Vector2[] arr)
_bufferWriter.Write(vec.y);
}
+
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId
@@ -1367,6 +1465,8 @@ private AccessorId ExportAccessor(Vector3[] arr)
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId
@@ -1452,9 +1552,10 @@ private AccessorId ExportAccessor(Vector4[] arr)
_bufferWriter.Write(vec.z);
_bufferWriter.Write(vec.w);
}
-
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId
@@ -1540,9 +1641,10 @@ private AccessorId ExportAccessor(UnityEngine.Color[] arr)
_bufferWriter.Write(color.b);
_bufferWriter.Write(color.a);
}
-
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
+ byteLength = AppendToBufferMultiplyOf4(byteOffset, byteLength);
+
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId
@@ -1555,8 +1657,11 @@ private AccessorId ExportAccessor(UnityEngine.Color[] arr)
return id;
}
+
+
private BufferViewId ExportBufferView(int byteOffset, int byteLength)
{
+
var bufferView = new BufferView
{
Buffer = _bufferId,
@@ -1570,6 +1675,7 @@ private BufferViewId ExportBufferView(int byteOffset, int byteLength)
Root = _root
};
+
_root.BufferViews.Add(bufferView);
return id;
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs
index bd1cff220..8228b77b8 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs
@@ -99,8 +99,8 @@ private GLTFSceneImporter(ILoader externalDataLoader)
{
_loader = externalDataLoader;
_asyncAction = new AsyncAction();
- }
-
+ }
+
public void Dispose()
{
if (_assetCache != null)
@@ -1388,18 +1388,18 @@ protected virtual IEnumerator ConstructTexture(GLTF.Schema.Texture texture, int
var sampler = texture.Sampler.Value;
switch (sampler.MinFilter)
{
- case MinFilterMode.Nearest:
- case MinFilterMode.NearestMipmapNearest:
- case MinFilterMode.NearestMipmapLinear:
+ case MinFilterMode.Nearest:
+ case MinFilterMode.NearestMipmapNearest:
+ case MinFilterMode.NearestMipmapLinear:
desiredFilterMode = FilterMode.Point;
break;
- case MinFilterMode.Linear:
- case MinFilterMode.LinearMipmapNearest:
- case MinFilterMode.LinearMipmapLinear:
- desiredFilterMode = FilterMode.Bilinear;
- break;
- default:
- Debug.LogWarning("Unsupported Sampler.MinFilter: " + sampler.MinFilter);
+ case MinFilterMode.Linear:
+ case MinFilterMode.LinearMipmapNearest:
+ case MinFilterMode.LinearMipmapLinear:
+ desiredFilterMode = FilterMode.Bilinear;
+ break;
+ default:
+ Debug.LogWarning("Unsupported Sampler.MinFilter: " + sampler.MinFilter);
break;
}
diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/InstantiatedGLTFObject.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/InstantiatedGLTFObject.cs
index cf92f31ab..aec907f9d 100644
--- a/UnityGLTF/Assets/UnityGLTF/Scripts/InstantiatedGLTFObject.cs
+++ b/UnityGLTF/Assets/UnityGLTF/Scripts/InstantiatedGLTFObject.cs
@@ -3,63 +3,63 @@
namespace UnityGLTF
{
- ///
- /// Instantiated GLTF Object component that gets added to the root of every GLTF game object created by a scene importer.
- ///
- public class InstantiatedGLTFObject : MonoBehaviour
- {
- ///
- /// Ref-counted cache data for this object.
- /// The same instance of this cached data will be used for all copies of this GLTF object,
- /// and the data gets cleaned up when the ref counts goes to 0.
- ///
- private RefCountedCacheData cachedData;
- public RefCountedCacheData CachedData
- {
- get
- {
- return cachedData;
- }
+ ///
+ /// Instantiated GLTF Object component that gets added to the root of every GLTF game object created by a scene importer.
+ ///
+ public class InstantiatedGLTFObject : MonoBehaviour
+ {
+ ///
+ /// Ref-counted cache data for this object.
+ /// The same instance of this cached data will be used for all copies of this GLTF object,
+ /// and the data gets cleaned up when the ref counts goes to 0.
+ ///
+ private RefCountedCacheData cachedData;
+ public RefCountedCacheData CachedData
+ {
+ get
+ {
+ return cachedData;
+ }
- set
- {
- if (cachedData != value)
- {
- if (cachedData != null)
- {
- cachedData.DecreaseRefCount();
- }
+ set
+ {
+ if (cachedData != value)
+ {
+ if (cachedData != null)
+ {
+ cachedData.DecreaseRefCount();
+ }
- cachedData = value;
+ cachedData = value;
- if (cachedData != null)
- {
- cachedData.IncreaseRefCount();
- }
- }
- }
- }
+ if (cachedData != null)
+ {
+ cachedData.IncreaseRefCount();
+ }
+ }
+ }
+ }
- ///
- /// Duplicates the instantiated GLTF object.
- /// Note that this should always be called if you intend to create a new instance of a GLTF object,
- /// in order to properly preserve the ref count of the dynamically loaded mesh data, otherwise
- /// you will run into a memory leak due to non-destroyed meshes, textures and materials.
- ///
- ///
- public InstantiatedGLTFObject Duplicate()
- {
- GameObject duplicatedObject = Instantiate(gameObject);
+ ///
+ /// Duplicates the instantiated GLTF object.
+ /// Note that this should always be called if you intend to create a new instance of a GLTF object,
+ /// in order to properly preserve the ref count of the dynamically loaded mesh data, otherwise
+ /// you will run into a memory leak due to non-destroyed meshes, textures and materials.
+ ///
+ ///
+ public InstantiatedGLTFObject Duplicate()
+ {
+ GameObject duplicatedObject = Instantiate(gameObject);
- InstantiatedGLTFObject newGltfObjectComponent = duplicatedObject.GetComponent();
- newGltfObjectComponent.CachedData = CachedData;
+ InstantiatedGLTFObject newGltfObjectComponent = duplicatedObject.GetComponent();
+ newGltfObjectComponent.CachedData = CachedData;
- return newGltfObjectComponent;
- }
+ return newGltfObjectComponent;
+ }
- private void OnDestroy()
- {
- CachedData = null;
- }
- }
+ private void OnDestroy()
+ {
+ CachedData = null;
+ }
+ }
}