예제 #1
0
        static void ImportDelayed(GLTFImporter context, UnityPath prefabPath)
        {
            EditorApplication.delayCall += () =>
            {
                //
                // After textures imported(To ensure TextureImporter be accessible).
                //
                // try
                // {

                var t = Save(context, prefabPath);
                // }
                // catch (UniGLTFNotSupportedException ex)
                // {
                //     Debug.LogWarningFormat($"{src}: {ex.Message}");
                //     context.EditorDestroyRootAndAssets();
                // }
                // catch (Exception ex)
                // {
                //     Debug.LogErrorFormat("import error: {0}", src);
                //     Debug.LogErrorFormat("{0}", ex);
                //     context.EditorDestroyRootAndAssets();
                // }
            };
        }
예제 #2
0
        private static async Task Save(GLTFImporter context, UnityPath path)
        {
            await context.Load(context.storage, p => Debug.Log(p));

            context.ShowMeshes();
            await SaveAsAsset(context, path);

            context.EditorDestroyRoot();
        }
예제 #3
0
 public void VersionChecker()
 {
     Assert.False(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("hoge", 1, 16));
     Assert.False(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("UniGLTF-1.16", 1, 16));
     Assert.True(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("UniGLTF-1.15", 1, 16));
     Assert.False(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("UniGLTF-11.16", 1, 16));
     Assert.True(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("UniGLTF-0.16", 1, 16));
     Assert.True(GLTFImporter.IsGeneratedGLTFumaAndOlderThan("UniGLTF", 1, 16));
 }
예제 #4
0
 public void Unload()
 {
     _unloaded = true;
     if (_loader != null)
     {
         _loader.Dispose();
         _loader = null;
     }
     if (_storage != null)
     {
         _storage.Dispose();
         _storage = null;
     }
 }
예제 #5
0
        public static void ImportAsset(string src, string ext, UnityPath prefabPath)
        {
            if (!prefabPath.isUnderAssetsFolder)
            {
                Debug.LogWarningFormat("out of asset path: {0}", prefabPath);
                return;
            }
            var context = new GLTFImporter();

            context.Parse(src);

            // Extract textures to assets folder
            ExtranctImages(context, prefabPath);

            ImportDelayed(context, prefabPath);
        }
예제 #6
0
        /// <summary>
        /// Extract images from glb or gltf out of Assets folder.
        /// </summary>
        /// <param name="prefabPath"></param>
        public static void ExtranctImages(GLTFImporter context, UnityPath prefabPath)
        {
            var prefabParentDir = prefabPath.parent;

            // glb buffer
            var folder = prefabPath.GetAssetFolder(".Textures");

            //
            // https://answers.unity.com/questions/647615/how-to-update-import-settings-for-newly-created-as.html
            //
            int created = 0;

            //for (int i = 0; i < GLTF.textures.Count; ++i)
            for (int i = 0; i < context.gltf.images.Count; ++i)
            {
                folder.EnsureFolder();

                //var x = GLTF.textures[i];
                var image = context.gltf.images[i];
                var src   = context.storage.GetPath(image.uri);
                if (UnityPath.FromFullpath(src).isUnderAssetsFolder)
                {
                    // asset is exists.
                }
                else
                {
                    string textureName;
                    var    byteSegment = context.gltf.GetImageBytes(context.storage, i, out textureName, out var url);

                    // path
                    var dst = folder.Child(textureName + image.GetExt());
                    File.WriteAllBytes(dst.fullPath, byteSegment.ToArray());
                    dst.ImportAsset();

                    // make relative path from PrefabParentDir
                    image.uri = dst.value.Substring(prefabParentDir.value.Length + 1);
                    ++created;
                }
            }

            if (created > 0)
            {
                AssetDatabase.Refresh();
            }

            context.CreateTextureItems(prefabParentDir);
        }
예제 #7
0
 public void ImportAnimation(GLTFImporter importer)
 {
     //Debug.Log("import animations " + importer.gltf.animations?.Count);
     // animation
     if (importer.gltf.animations != null && importer.gltf.animations.Any())
     {
         var animation = importer.root.AddComponent <Animation>();
         importer.animationClips = ImportAnimationClip(importer);
         foreach (var clip in importer.animationClips)
         {
             animation.AddClip(clip, clip.name);
         }
         if (importer.animationClips.Count > 0)
         {
             animation.clip = importer.animationClips.First();
         }
     }
 }
예제 #8
0
        public static void ImportMenu()
        {
            var path = EditorUtility.OpenFilePanel("open gltf", "", "gltf,glb,zip");

            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            if (Application.isPlaying)
            {
                //
                // load into scene
                //
                var context = new GLTFImporter();
                //context.Load(path);
                context.ShowMeshes();
                Selection.activeGameObject = context.root;
            }
            else
            {
                //
                // save as asset
                //
                if (path.StartsWithUnityAssetPath())
                {
                    Debug.LogWarningFormat("disallow import from folder under the Assets");
                    return;
                }

                var assetPath = EditorUtility.SaveFilePanel("save prefab", "Assets", Path.GetFileNameWithoutExtension(path), "prefab");
                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                // import as asset
                GLTFAssetPostprocessor.ImportAsset(path, Path.GetExtension(path).ToLower(), UnityPath.FromFullpath(assetPath));
            }
        }
예제 #9
0
        public void UniGLTFSimpleSceneTest()
        {
            var go      = CreateSimpelScene();
            var context = new GLTFImporter();

            try
            {
                // export
                var gltf = new GLTFRoot();

                string json = null;
                using (var exporter = new GLTFExporter(gltf))
                {
                    exporter.Prepare(go);
                    exporter.Export();

                    // remove empty buffer
                    gltf.buffers.Clear();

                    json = gltf.ToJson();
                }

                // import
                context.ParseJson(json, new SimpleStorage(new ArraySegment <byte>()));
                //Debug.LogFormat("{0}", context.Json);
                //context.Load();

                AssertAreEqual(go.transform, context.root.transform);
            }
            finally
            {
                //Debug.LogFormat("Destory, {0}", go.name);
                GameObject.DestroyImmediate(go);
                context.EditorDestroyRootAndAssets();
            }
        }
예제 #10
0
 public MaterialImporter(IShaderStore shaderStore, GLTFImporter context)
 {
     m_shaderStore = shaderStore;
     m_context     = context;
 }
예제 #11
0
        public static async Task SaveAsAsset(GLTFImporter context, UnityPath prefabPath)
        {
            //var prefabPath = PrefabPath;
            if (prefabPath.isFileExists)
            {
                // clear SubAssets
                foreach (var x in prefabPath.GetSubAssets().Where(x => !(x is GameObject) && !(x is Component)))
                {
                    GameObject.DestroyImmediate(x, true);
                }
            }

            //
            // save sub assets
            //
            var paths = new List <UnityPath>()
            {
                prefabPath
            };

            foreach (var o in context.ObjectsForSubAsset())
            {
                if (o == null)
                {
                    continue;
                }

                var assetPath = GetAssetPath(prefabPath, o);
                if (!assetPath.isNull)
                {
                    if (assetPath.isFileExists)
                    {
                        if (!IsOverwrite(o))
                        {
                            // 上書きしない
                            Debug.LogWarningFormat("already exists. skip {0}", assetPath);
                            continue;
                        }
                    }
                    assetPath.parent.EnsureFolder();
                    assetPath.CreateAsset(o);
                    paths.Add(assetPath);
                }
                else
                {
                    // save as subasset
                    prefabPath.AddObjectToAsset(o);
                }
            }
            await Task.Yield();

            // Create or upate Main Asset
            // if (prefabPath.isFileExists)
            // {
            //     Debug.LogFormat("replace prefab: {0}", prefabPath);
            //     //var prefab = prefabPath.LoadAsset<GameObject>();
            // }
            // else
            // {
            //     Debug.LogFormat("create prefab: {0}", prefabPath);
            //     PrefabUtility.SaveAsPrefabAsset(context.root, prefabPath.value);//.CreatePrefab(prefabPath.Value, context.root);
            // }
            PrefabUtility.SaveAsPrefabAssetAndConnect(context.root, prefabPath.value, InteractionMode.AutomatedAction);    //.ReplacePrefab(context.root, prefab, ReplacePrefabOptions.ReplaceNameBased);
            await Task.Yield();

            AssetDatabase.Refresh();
            // foreach (var x in paths)
            // {
            //     x.ImportAsset();
            // }
            await Task.Yield();
        }
예제 #12
0
        public TransformWithSkin BuildHierarchy(GLTFImporter context, int i)
        {
            var go = context.nodes[i].gameObject;

            if (string.IsNullOrEmpty(go.name))
            {
                go.name = $"node{i:000}";
            }

            var nodeWithSkin = new TransformWithSkin
            {
                transform = go.transform,
            };

            //
            // build hierachy
            //
            var node = context.gltf.nodes[i];

            if (node.children != null)
            {
                foreach (var child in node.children)
                {
                    // node has local transform
                    context.nodes[child].transform.SetParent(context.nodes[i].transform, false);
                }
            }

            //
            // attach mesh
            //
            //Debug.Log("node mesh ... "+node.name+" == "+node.mesh);
            if (node.mesh != -1)
            {
                var mesh = context.meshes[node.mesh];
                if (mesh.mesh.blendShapeCount == 0 && node.skin == -1)
                {
                    // without blendshape and bone skinning
                    var filter = go.AddComponent <MeshFilter>();
                    filter.sharedMesh = mesh.mesh;
                    var renderer = go.AddComponent <MeshRenderer>();
                    renderer.sharedMaterials = mesh.materials;
                    // invisible in loading
                    renderer.enabled = false;
                    mesh.renderers.Add(renderer);
                }
                else
                {
                    var renderer = go.AddComponent <SkinnedMeshRenderer>();

                    if (node.skin != -1)
                    {
                        nodeWithSkin.skinIndex = node.skin;
                    }

                    renderer.sharedMesh      = mesh.mesh;
                    renderer.sharedMaterials = mesh.materials;
                    // invisible in loading
                    renderer.enabled = false;
                    mesh.renderers.Add(renderer);
                }
            }

            return(nodeWithSkin);
        }
예제 #13
0
        public List <AnimationClip> ImportAnimationClip(GLTFImporter importer)
        {
            List <AnimationClip> animasionClips = new List <AnimationClip>();

            for (int i = 0; i < importer.gltf.animations.Count; ++i)
            {
                var clip = new AnimationClip();
                clip.ClearCurves();
                clip.legacy = true;
                clip.name   = importer.gltf.animations[i].name;
                if (string.IsNullOrEmpty(clip.name))
                {
                    clip.name = "legacy_" + i;
                }
                clip.wrapMode = WrapMode.Loop;

                var animation = importer.gltf.animations[i];
                if (string.IsNullOrEmpty(animation.name))
                {
                    animation.name = string.Format("animation:{0}", i);
                }

                foreach (var channel in animation.channels)
                {
                    var targetTransform = importer.nodes[channel.target.node];
                    var relativePath    = targetTransform.RelativePathFrom(importer.root.transform);
                    switch (channel.target.path)
                    {
                    case GLTFAnimationTarget.PATH_TRANSLATION:
                    {
                        var sampler = animation.samplers[channel.sampler];
                        var input   = importer.gltf.GetArrayFromAccessor <float>(sampler.input);
                        var output  = importer.gltf.GetArrayFromAccessorAsFloat(sampler.output);

                        SetAnimationCurve(
                            clip,
                            relativePath,
                            new string[] { "localPosition.x", "localPosition.y", "localPosition.z" },
                            input,
                            output,
                            sampler.interpolation,
                            typeof(Transform),
                            (values, last) =>
                            {
                                Vector3 temp = new Vector3(values[0], values[1], values[2]);
                                return(temp.ReverseZ().ToArray());
                            }
                            );
                    }
                    break;

                    case GLTFAnimationTarget.PATH_ROTATION:
                    {
                        var sampler = animation.samplers[channel.sampler];
                        var input   = importer.gltf.GetArrayFromAccessor <float>(sampler.input);
                        var output  = importer.gltf.GetArrayFromAccessorAsFloat(sampler.output);

                        SetAnimationCurve(
                            clip,
                            relativePath,
                            new string[] { "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" },
                            input,
                            output,
                            sampler.interpolation,
                            typeof(Transform),
                            (values, last) =>
                            {
                                Quaternion currentQuaternion = new Quaternion(values[0], values[1], values[2], values[3]);
                                Quaternion lastQuaternion    = new Quaternion(last[0], last[1], last[2], last[3]);
                                return(lastQuaternion.GetShortest(currentQuaternion.ReverseZ()).ToArray());
                            }
                            );

                        clip.EnsureQuaternionContinuity();
                    }
                    break;

                    case GLTFAnimationTarget.PATH_SCALE:
                    {
                        var sampler = animation.samplers[channel.sampler];
                        var input   = importer.gltf.GetArrayFromAccessor <float>(sampler.input);
                        var output  = importer.gltf.GetArrayFromAccessorAsFloat(sampler.output);

                        SetAnimationCurve(
                            clip,
                            relativePath,
                            new string[] { "localScale.x", "localScale.y", "localScale.z" },
                            input,
                            output,
                            sampler.interpolation,
                            typeof(Transform),
                            (values, last) => values);
                    }
                    break;

                    case GLTFAnimationTarget.PATH_WEIGHT:
                    {
                        var node = importer.gltf.nodes[channel.target.node];
                        var mesh = importer.gltf.meshes[node.mesh];
                        //var primitive = mesh.primitives.FirstOrDefault();
                        //var targets = primitive.targets;

                        List <string> blendShapeNames     = new List <string>();
                        var           transform           = importer.nodes[channel.target.node];
                        var           skinnedMeshRenderer = transform.GetComponent <SkinnedMeshRenderer>();
                        if (skinnedMeshRenderer == null)
                        {
                            continue;
                        }

                        for (int j = 0; j < skinnedMeshRenderer.sharedMesh.blendShapeCount; j++)
                        {
                            blendShapeNames.Add(skinnedMeshRenderer.sharedMesh.GetBlendShapeName(j));
                        }

                        var keyNames = blendShapeNames
                                       .Where(x => !string.IsNullOrEmpty(x))
                                       .Select(x => "blendShape." + x)
                                       .ToArray();

                        var sampler = animation.samplers[channel.sampler];
                        var input   = importer.gltf.GetArrayFromAccessor <float>(sampler.input);
                        var output  = importer.gltf.GetArrayFromAccessor <float>(sampler.output);
                        SetAnimationCurve(
                            clip,
                            relativePath,
                            keyNames,
                            input,
                            output,
                            sampler.interpolation,
                            typeof(SkinnedMeshRenderer),
                            (values, last) =>
                            {
                                for (int j = 0; j < values.Length; j++)
                                {
                                    values[j] *= 100.0f;
                                }
                                return(values);
                            });
                    }
                    break;

                    case GLTFAnimationTarget.PATH_ACTIVE:
                    {
                        var sampler = animation.samplers[channel.sampler];
                        var input   = importer.gltf.GetArrayFromAccessor <float>(sampler.input);
                        var output  = importer.gltf.GetArrayFromAccessorAsFloat(sampler.output);

                        SetAnimationCurve(
                            clip,
                            relativePath,
                            new string[] { "m_IsActive" },
                            input,
                            output,
                            sampler.interpolation,
                            typeof(GameObject),
                            (values, last) => values);
                    }
                    break;

                    default:
                        Debug.LogWarningFormat("unknown path: {0}", channel.target.path);
                        break;
                    }
                }
                animasionClips.Add(clip);
            }

            return(animasionClips);
        }
예제 #14
0
        private async Task <GameObject> Load(Action <float> progress)
        {
            await Task.Yield();

            _unloaded = false;
            var name = url.Substring(url.LastIndexOf("/") + 1);
            //加载.gltf文件
            await _storage.LoadString(name, p => progress?.Invoke(p * 0.1f));

            if (_unloaded)
            {
                return(null);
            }
            _loader = new GLTFImporter(this, null, null, null, null);
            //用JsonUtility解析到gltf数据
            _loader.ParseJson(_storage.GetString(name));
            //加载buffers里面的.bin数据
            int total       = _loader.gltf.buffers.Count;
            int current     = 0;
            var stepPrecent = showWithTexture ? 0.4f : 0.8f;

            foreach (var buffer in _loader.gltf.buffers)
            {
                Debug.Log(buffer.uri);
                await _storage.LoadBinary(buffer.uri, p => progress?.Invoke(0.1f + stepPrecent * (current + p) / total));

                if (_unloaded)
                {
                    return(null);
                }
                //Debug.Log(buffer.uri + " loaded");
                buffer.OpenStorage(_storage);
                current++;
            }
            //跳过图片的加载
            if (showWithTexture)
            {
                current = 0;
                total   = _loader.gltf.images.Count;
                foreach (var image in _loader.gltf.images)
                {
                    await _storage.LoadTexture(image.uri, p => progress?.Invoke(0.5f + 0.4f * (current + p) / total));

                    current++;
                    if (_unloaded)
                    {
                        return(null);
                    }
                }
            }
            //解析mesh、material、animation等数据
            await _loader.Load(_storage, p => progress?.Invoke(0.9f + p * 0.1f));

            if (_unloaded)
            {
                return(null);
            }
            //loader.Parse(url,www.downloadHandler.data);
            _loader.ShowMeshes();
            _loader.root.SetActive(false);
            _loader.root.transform.SetParent(transform);
            _loader.root.SetActive(true);
            return(_loader.root);
        }
예제 #15
0
 //ImporterContext m_context;
 public ShaderStore(GLTFImporter _)
 {
     //m_context = context;
 }