예제 #1
0
        private static IEnumerator LoadAsync(string json, string filepath, byte[] bytefile, long binChunkStart, ImportSettings importSettings, Action <GameObject, GLTFAnimation.ImportResult[]> onFinished, Action <float> onProgress = null)
        {
            // Threaded deserialization
            Task <GLTFObject> deserializeTask = new Task <GLTFObject>(() => JsonConvert.DeserializeObject <GLTFObject>(json));

            deserializeTask.Start();
            while (!deserializeTask.IsCompleted)
            {
                yield return(null);
            }
            GLTFObject gltfObject = deserializeTask.Result;

            // directory root is sometimes used for loading buffers from containing file, or local images
            string directoryRoot = filepath != null?Directory.GetParent(filepath).ToString() + "/" : null;

            importSettings.shaderOverrides.CacheDefaultShaders();

            // Setup import tasks
            List <ImportTask> importTasks = new List <ImportTask>();

            GLTFBuffer.ImportTask bufferTask = new GLTFBuffer.ImportTask(gltfObject.buffers, filepath, bytefile, binChunkStart);
            importTasks.Add(bufferTask);
            GLTFBufferView.ImportTask bufferViewTask = new GLTFBufferView.ImportTask(gltfObject.bufferViews, bufferTask);
            importTasks.Add(bufferViewTask);
            GLTFAccessor.ImportTask accessorTask = new GLTFAccessor.ImportTask(gltfObject.accessors, bufferViewTask);
            importTasks.Add(accessorTask);
            GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images, directoryRoot, bufferViewTask);
            importTasks.Add(imageTask);
            GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures, imageTask);
            importTasks.Add(textureTask);
            GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials, textureTask, importSettings);
            importTasks.Add(materialTask);
            GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes, accessorTask, materialTask, importSettings);
            importTasks.Add(meshTask);
            GLTFSkin.ImportTask skinTask = new GLTFSkin.ImportTask(gltfObject.skins, accessorTask);
            importTasks.Add(skinTask);
            GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes, meshTask, skinTask, gltfObject.cameras);
            importTasks.Add(nodeTask);

            // Ignite
            for (int i = 0; i < importTasks.Count; i++)
            {
                TaskSupervisor(importTasks[i], onProgress).RunCoroutine();
            }

            // Wait for all tasks to finish
            while (!importTasks.All(x => x.IsCompleted))
            {
                yield return(null);
            }

            // Close file streams
            foreach (var item in bufferTask.Result)
            {
                item.Dispose();
            }

            // Fire onFinished when all tasks have completed
            GameObject root = nodeTask.Result.GetRoot();

            GLTFAnimation.ImportResult[] animations = gltfObject.animations.Import(accessorTask.Result, nodeTask.Result, importSettings);
            if (onFinished != null)
            {
                onFinished(nodeTask.Result.GetRoot(), animations);
            }
        }
예제 #2
0
 public static GameObject LoadFromFile(string filepath, ImportSettings importSettings, Format format = Format.AUTO)
 {
     GLTFAnimation.ImportResult[] animations;
     return(LoadFromFile(filepath, importSettings, out animations, format));
 }
예제 #3
0
        private static GameObject LoadInternal(this GLTFObject gltfObject, string filepath, byte[] bytefile, long binChunkStart, ImportSettings importSettings, out GLTFAnimation.ImportResult[] animations)
        {
            // directory root is sometimes used for loading buffers from containing file, or local images
            string directoryRoot = filepath != null?Directory.GetParent(filepath).ToString() + "/" : null;

            importSettings.shaderOverrides.CacheDefaultShaders();

            // Import tasks synchronously
            GLTFBuffer.ImportTask bufferTask = new GLTFBuffer.ImportTask(gltfObject.buffers, filepath, bytefile, binChunkStart);
            bufferTask.RunSynchronously();
            GLTFBufferView.ImportTask bufferViewTask = new GLTFBufferView.ImportTask(gltfObject.bufferViews, bufferTask);
            bufferViewTask.RunSynchronously();
            GLTFAccessor.ImportTask accessorTask = new GLTFAccessor.ImportTask(gltfObject.accessors, bufferViewTask);
            accessorTask.RunSynchronously();
            GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images, directoryRoot, bufferViewTask);
            imageTask.RunSynchronously();
            GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures, imageTask);
            textureTask.RunSynchronously();
            GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials, textureTask, importSettings);
            materialTask.RunSynchronously();
            GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes, accessorTask, materialTask, importSettings);
            meshTask.RunSynchronously();
            GLTFSkin.ImportTask skinTask = new GLTFSkin.ImportTask(gltfObject.skins, accessorTask);
            skinTask.RunSynchronously();
            GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes, meshTask, skinTask, gltfObject.cameras);
            nodeTask.RunSynchronously();
            animations = gltfObject.animations.Import(accessorTask.Result, nodeTask.Result, importSettings);

            foreach (var item in bufferTask.Result)
            {
                item.Dispose();
            }

            return(nodeTask.Result.GetRoot());
        }
예제 #4
0
 /// <param name="bytes">GLB file is supported</param>
 public static GameObject LoadFromBytes(byte[] bytes, ImportSettings importSettings, out AnimationClip[] animations, Action <GameObject, Dictionary <string, object> > handleExtensions = null)
 {
     return(ImportGLB(bytes, importSettings, out animations, handleExtensions));
 }
        private static GameObject LoadInternal(this GLTFObject gltfObject, string filepath, ImportSettings importSettings, out GLTFAnimation.ImportResult[] animations)
        {
            // directory root is sometimes used for loading buffers from containing file, or local images
            string directoryRoot = Directory.GetParent(filepath).ToString() + "/";

            // Import tasks synchronously
            GLTFBuffer.ImportTask bufferTask = new GLTFBuffer.ImportTask(gltfObject.buffers, filepath);
            bufferTask.RunSynchronously();
            GLTFBufferView.ImportTask bufferViewTask = new GLTFBufferView.ImportTask(gltfObject.bufferViews, bufferTask);
            bufferViewTask.RunSynchronously();
            GLTFAccessor.ImportTask accessorTask = new GLTFAccessor.ImportTask(gltfObject.accessors, bufferViewTask);
            accessorTask.RunSynchronously();
            GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images, directoryRoot, bufferViewTask);
            imageTask.RunSynchronously();
            GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures, imageTask);
            textureTask.RunSynchronously();
            GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials, textureTask, importSettings);
            materialTask.RunSynchronously();
            GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes, accessorTask, materialTask, importSettings);
            meshTask.RunSynchronously();
            GLTFSkin.ImportTask skinTask = new GLTFSkin.ImportTask(gltfObject.skins, accessorTask);
            skinTask.RunSynchronously();
            GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes, meshTask, skinTask, gltfObject.cameras);
            nodeTask.RunSynchronously();
            animations = gltfObject.animations.Import(accessorTask.Result, nodeTask.Result);

            return(nodeTask.Result.GetRoot());
        }
예제 #6
0
        private static GameObject LoadInternal(this GLTFObject gltfObject, string filepath, ImportSettings importSettings, out GLTFAnimation.ImportResult[] animations)
        {
            string directoryRoot = Directory.GetParent(filepath).ToString() + "/";

            GLTFBuffer.ImportResult[]     buffers     = gltfObject.buffers.Select(x => x.Import(filepath)).ToArray();
            GLTFBufferView.ImportResult[] bufferViews = gltfObject.bufferViews.Select(x => x.Import(buffers)).ToArray();
            GLTFAccessor.ImportResult[]   accessors   = gltfObject.accessors.Select(x => x.Import(bufferViews)).ToArray();
            GLTFImage.ImportResult[]      images      = gltfObject.images.Import(directoryRoot, bufferViews);
            GLTFTexture.ImportResult[]    textures    = gltfObject.textures.Import(images);
            GLTFMaterial.ImportResult     materials   = gltfObject.materials.Import(textures, importSettings);
            GLTFMesh.ImportResult[]       meshes      = gltfObject.meshes.Import(accessors, materials, importSettings);
            GLTFSkin.ImportResult[]       skins       = gltfObject.skins.Import(accessors);
            GLTFNode.ImportResult[]       nodes       = gltfObject.nodes.Import(meshes, skins);
            animations = gltfObject.animations.Import(accessors, nodes);

            return(nodes.GetRoot());
        }
예제 #7
0
            public ImportTask(List <GLTFMesh> meshes, GLTFAccessor.ImportTask accessorTask, GLTFBufferView.ImportTask bufferViewTask, GLTFMaterial.ImportTask materialTask, ImportSettings importSettings) : base(accessorTask, materialTask)
            {
                this.meshes       = meshes;
                this.materialTask = materialTask;

                task = new Task(() => {
                    if (meshes == null)
                    {
                        return;
                    }

                    meshData = new MeshData[meshes.Count];
                    for (int i = 0; i < meshData.Length; i++)
                    {
                        meshData[i] = new MeshData(meshes[i], accessorTask.Result, bufferViewTask.Result);
                    }
                });
            }
예제 #8
0
        public static void SaveToAsset(GameObject root, AnimationClip[] animations, AssetImportContext ctx, ImportSettings settings)
        {
#if UNITY_2018_2_OR_NEWER
            ctx.AddObjectToAsset("main", root);
            ctx.SetMainObject(root);
#else
            ctx.SetMainAsset("main obj", root);
#endif
            MeshRenderer[]        renderers        = root.GetComponentsInChildren <MeshRenderer>(true);
            SkinnedMeshRenderer[] skinnedRenderers = root.GetComponentsInChildren <SkinnedMeshRenderer>(true);
            MeshFilter[]          filters          = root.GetComponentsInChildren <MeshFilter>(true);
            AddMeshes(filters, skinnedRenderers, ctx, settings.generateLightmapUVs);
            AddMaterials(renderers, skinnedRenderers, ctx);
            AddAnimations(animations, ctx, settings.animationSettings);
        }
예제 #9
0
 public static GLTFMesh.ImportResult[] Import(this List <GLTFMesh> meshes, GLTFAccessor.ImportResult[] accessors, GLTFMaterial.ImportResult materials, ImportSettings importSettings)
 {
     GLTFMesh.ImportResult[] results = new GLTFMesh.ImportResult[meshes.Count];
     for (int i = 0; i < results.Length; i++)
     {
         results[i]           = new GLTFMesh.ImportResult();
         results[i].mesh      = meshes[i].CreateMesh(accessors);
         results[i].materials = new Material[meshes[i].primitives.Count];
         for (int k = 0; k < meshes[i].primitives.Count; k++)
         {
             int?matIndex = meshes[i].primitives[k].material;
             if (matIndex.HasValue && materials != null)
             {
                 results[i].materials[k] = materials.materials[matIndex.Value];
             }
             else
             {
                 results[i].materials[k] = GLTFMaterial.defaultMaterial;
             }
         }
         if (meshes[i].name == null)
         {
             meshes[i].name = "mesh" + i;
         }
     }
     return(results);
 }
예제 #10
0
        public ImportResult Import(GLTFAccessor.ImportResult[] accessors, GLTFNode.ImportResult[] nodes, ImportSettings importSettings)
        {
            bool multiRoots = nodes.Where(x => x.IsRoot).Count() > 1;

            ImportResult result = new ImportResult();

            result.clip           = new AnimationClip();
            result.clip.name      = name;
            result.clip.frameRate = importSettings.animationSettings.frameRate;

            result.clip.legacy = importSettings.animationSettings.useLegacyClips;

            if (result.clip.legacy && importSettings.animationSettings.looping)
            {
                result.clip.wrapMode = WrapMode.Loop;
            }

            for (int i = 0; i < channels.Length; i++)
            {
                Channel channel = channels[i];
                if (samplers.Length <= channel.sampler)
                {
                    Debug.LogWarning($"GLTFUtility: Animation channel points to sampler at index {channel.sampler} which doesn't exist. Skipping animation clip.");
                    continue;
                }
                Sampler sampler = samplers[channel.sampler];

                // Get interpolation mode
                InterpolationMode interpolationMode = importSettings.animationSettings.interpolationMode;
                if (interpolationMode == InterpolationMode.ImportFromFile)
                {
                    interpolationMode = sampler.interpolation;
                }
                if (interpolationMode == InterpolationMode.CUBICSPLINE)
                {
                    Debug.LogWarning("Animation interpolation mode CUBICSPLINE not fully supported, result might look different.");
                }

                string relativePath = "";

                GLTFNode.ImportResult node = nodes[channel.target.node.Value];
                while (node != null && !node.IsRoot)
                {
                    if (string.IsNullOrEmpty(relativePath))
                    {
                        relativePath = node.transform.name;
                    }
                    else
                    {
                        relativePath = node.transform.name + "/" + relativePath;
                    }

                    if (node.parent.HasValue)
                    {
                        node = nodes[node.parent.Value];
                    }
                    else
                    {
                        node = null;
                    }
                }

                // If file has multiple root nodes, a new parent will be created for them as a final step of the import process. This parent f***s up the curve relative paths.
                // Add node.transform.name to path if there are multiple roots. This is not the most elegant fix but it works.
                // See GLTFNodeExtensions.GetRoot
                if (multiRoots)
                {
                    relativePath = node.transform.name + "/" + relativePath;
                }

                System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
                float[] keyframeInput = accessors[sampler.input].ReadFloat().ToArray();
                switch (channel.target.path)
                {
                case "translation":
                    Vector3[]      pos  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve posX = new AnimationCurve();
                    AnimationCurve posY = new AnimationCurve();
                    AnimationCurve posZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        posX.AddKey(CreateKeyframe(k, keyframeInput, pos, x => - x.x, interpolationMode));
                        posY.AddKey(CreateKeyframe(k, keyframeInput, pos, x => x.y, interpolationMode));
                        posZ.AddKey(CreateKeyframe(k, keyframeInput, pos, x => x.z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", posX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", posY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", posZ);
                    break;

                case "rotation":
                    Vector4[]      rot  = accessors[sampler.output].ReadVec4().ToArray();
                    AnimationCurve rotX = new AnimationCurve();
                    AnimationCurve rotY = new AnimationCurve();
                    AnimationCurve rotZ = new AnimationCurve();
                    AnimationCurve rotW = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        // The Animation window in Unity shows keyframes incorrectly converted to euler. This is only to deceive you. The quaternions underneath work correctly
                        rotX.AddKey(CreateKeyframe(k, keyframeInput, rot, x => x.x, interpolationMode));
                        rotY.AddKey(CreateKeyframe(k, keyframeInput, rot, x => - x.y, interpolationMode));
                        rotZ.AddKey(CreateKeyframe(k, keyframeInput, rot, x => - x.z, interpolationMode));
                        rotW.AddKey(CreateKeyframe(k, keyframeInput, rot, x => x.w, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.x", rotX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.y", rotY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.z", rotZ);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.w", rotW);
                    break;

                case "scale":
                    Vector3[]      scale  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve scaleX = new AnimationCurve();
                    AnimationCurve scaleY = new AnimationCurve();
                    AnimationCurve scaleZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        scaleX.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.x, interpolationMode));
                        scaleY.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.y, interpolationMode));
                        scaleZ.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.x", scaleX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.y", scaleY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.z", scaleZ);
                    break;

                case "weights":
                    GLTFNode.ImportResult skinnedMeshNode     = nodes[channel.target.node.Value];
                    SkinnedMeshRenderer   skinnedMeshRenderer = skinnedMeshNode.transform.GetComponent <SkinnedMeshRenderer>();

                    int numberOfBlendShapes           = skinnedMeshRenderer.sharedMesh.blendShapeCount;
                    AnimationCurve[] blendShapeCurves = new AnimationCurve[numberOfBlendShapes];
                    for (int j = 0; j < numberOfBlendShapes; ++j)
                    {
                        blendShapeCurves[j] = new AnimationCurve();
                    }

                    float[] weights      = accessors[sampler.output].ReadFloat().ToArray();
                    float[] weightValues = new float[keyframeInput.Length];

                    float[] previouslyKeyedValues = new float[numberOfBlendShapes];

                    // Reference for my future self:
                    // keyframeInput.Length = number of keyframes
                    // keyframeInput[ k ] = timestamp of keyframe
                    // weights.Length = number of keyframes * number of blendshapes
                    // weights[ j ] = actual animated weight of a specific blend shape
                    // (index into weights[] array accounts for keyframe index and blend shape index)

                    for (int k = 0; k < keyframeInput.Length; ++k)
                    {
                        for (int j = 0; j < numberOfBlendShapes; ++j)
                        {
                            int weightIndex = (k * numberOfBlendShapes) + j;
                            weightValues[k] = weights[weightIndex];

                            bool addKey = true;
                            if (importSettings.animationSettings.compressBlendShapeKeyFrames)
                            {
                                if (k == 0 || !Mathf.Approximately(weightValues[k], previouslyKeyedValues[j]))
                                {
                                    if (k > 0)
                                    {
                                        weightValues[k - 1] = previouslyKeyedValues[j];
                                        blendShapeCurves[j].AddKey(CreateKeyframe(k - 1, keyframeInput, weightValues, x => x, interpolationMode));
                                    }
                                    addKey = true;
                                    previouslyKeyedValues[j] = weightValues[k];
                                }
                                else
                                {
                                    addKey = false;
                                }
                            }

                            if (addKey)
                            {
                                blendShapeCurves[j].AddKey(CreateKeyframe(k, keyframeInput, weightValues, x => x, interpolationMode));
                            }
                        }
                    }

                    for (int j = 0; j < numberOfBlendShapes; ++j)
                    {
                        string propertyName = "blendShape." + skinnedMeshRenderer.sharedMesh.GetBlendShapeName(j);
                        result.clip.SetCurve(relativePath, typeof(SkinnedMeshRenderer), propertyName, blendShapeCurves[j]);
                    }
                    break;
                }
            }
            return(result);
        }
예제 #11
0
        public ImportResult Import(GLTFAccessor.ImportResult[] accessors, GLTFNode.ImportResult[] nodes, ImportSettings importSettings)
        {
            ImportResult result = new ImportResult();

            result.clip      = new AnimationClip();
            result.clip.name = name;

            if (importSettings.useLegacyClips)
            {
                result.clip.legacy = true;
            }

            for (int i = 0; i < channels.Length; i++)
            {
                Channel channel = channels[i];
                if (samplers.Length <= channel.sampler)
                {
                    Debug.LogWarning($"GLTFUtility: Animation channel points to sampler at index {channel.sampler} which doesn't exist. Skipping animation clip.");
                    continue;
                }
                Sampler sampler = samplers[channel.sampler];

                string relativePath = "";

                GLTFNode.ImportResult node = nodes[channel.target.node.Value];
                while (node != null && !node.IsRoot)
                {
                    if (string.IsNullOrEmpty(relativePath))
                    {
                        relativePath = node.transform.name;
                    }
                    else
                    {
                        relativePath = node.transform.name + "/" + relativePath;
                    }

                    if (node.parent.HasValue)
                    {
                        node = nodes[node.parent.Value];
                    }
                    else
                    {
                        node = null;
                    }
                }

                float[] keyframeInput = accessors[sampler.input].ReadFloat().ToArray();
                switch (channel.target.path)
                {
                case "translation":
                    Vector3[]      pos  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve posX = new AnimationCurve();
                    AnimationCurve posY = new AnimationCurve();
                    AnimationCurve posZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        posX.AddKey(keyframeInput[k], pos[k].x);
                        posY.AddKey(keyframeInput[k], pos[k].y);
                        posZ.AddKey(keyframeInput[k], -pos[k].z);
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", posX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", posY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", posZ);
                    break;

                case "rotation":
                    Vector4[]      rot  = accessors[sampler.output].ReadVec4().ToArray();
                    AnimationCurve rotX = new AnimationCurve();
                    AnimationCurve rotY = new AnimationCurve();
                    AnimationCurve rotZ = new AnimationCurve();
                    AnimationCurve rotW = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        rotX.AddKey(keyframeInput[k], rot[k].x);
                        rotY.AddKey(keyframeInput[k], rot[k].y);
                        rotZ.AddKey(keyframeInput[k], -rot[k].z);
                        rotW.AddKey(keyframeInput[k], -rot[k].w);
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.x", rotX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.y", rotY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.z", rotZ);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.w", rotW);
                    break;

                case "scale":
                    Vector3[]      scale  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve scaleX = new AnimationCurve();
                    AnimationCurve scaleY = new AnimationCurve();
                    AnimationCurve scaleZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        scaleX.AddKey(keyframeInput[k], scale[k].x);
                        scaleY.AddKey(keyframeInput[k], scale[k].y);
                        scaleZ.AddKey(keyframeInput[k], scale[k].z);
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.x", scaleX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.y", scaleY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.z", scaleZ);
                    break;

                case "weights":
                    Debug.LogWarning("GLTFUtility: Morph weights in animation is not supported");
                    break;
                }
            }
            return(result);
        }
예제 #12
0
 /// <param name="bytes">GLB file is supported</param>
 public static void LoadFromBytes(byte[] bytes, Action <GameObject, AnimationClip[]> onFinished, ImportSettings importSettings = null)
 {
     if (importSettings == null)
     {
         importSettings = new ImportSettings();
     }
     ImportGLB(bytes, importSettings, onFinished);
 }
예제 #13
0
        private static IEnumerator LoadInternal(this GLTFObject gltfObject, string filepath, byte[] bytefile, long binChunkStart, ImportSettings importSettings, Action <GameObject, AnimationClip[]> onFinished)
        {
            CheckExtensions(gltfObject);

            // directory root is sometimes used for loading buffers from containing file, or local images
            string directoryRoot = filepath != null?Directory.GetParent(filepath).ToString() + "/" : null;

            importSettings.shaderOverrides.CacheDefaultShaders();

            // Import tasks synchronously
            GLTFBuffer.ImportTask bufferTask = new GLTFBuffer.ImportTask(gltfObject.buffers, filepath, bytefile, binChunkStart);
            yield return(StaticCoroutine.Start(bufferTask.RunSynchronously()));

            GLTFBufferView.ImportTask bufferViewTask = new GLTFBufferView.ImportTask(gltfObject.bufferViews, bufferTask);
            yield return(StaticCoroutine.Start(bufferViewTask.RunSynchronously()));

            GLTFAccessor.ImportTask accessorTask = new GLTFAccessor.ImportTask(gltfObject.accessors, bufferViewTask);
            yield return(StaticCoroutine.Start(accessorTask.RunSynchronously()));

            GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images, directoryRoot, bufferViewTask);
            yield return(StaticCoroutine.Start(imageTask.RunSynchronously()));

            GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures, imageTask);
            yield return(StaticCoroutine.Start(textureTask.RunSynchronously()));

            GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials, textureTask, importSettings);
            yield return(StaticCoroutine.Start(materialTask.RunSynchronously()));

            GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes, accessorTask, bufferViewTask, materialTask, importSettings);
            yield return(StaticCoroutine.Start(meshTask.RunSynchronously()));

            GLTFSkin.ImportTask skinTask = new GLTFSkin.ImportTask(gltfObject.skins, accessorTask);
            yield return(StaticCoroutine.Start(skinTask.RunSynchronously()));

            GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes, meshTask, skinTask, gltfObject.cameras);
            yield return(StaticCoroutine.Start(nodeTask.RunSynchronously()));

            GLTFAnimation.ImportResult[] animationResult = gltfObject.animations.Import(accessorTask.Result, nodeTask.Result, importSettings);
            AnimationClip[] animations = null;
            if (animationResult != null)
            {
                animations = animationResult.Select(x => x.clip).ToArray();
            }
            else
            {
                animations = new AnimationClip[0];
            }

            foreach (var item in bufferTask.Result)
            {
                item.Dispose();
            }

            onFinished?.Invoke(nodeTask.Result.GetRoot(), animations);
        }
예제 #14
0
        public static void SaveToAsset(GameObject root, AnimationClip[] animations, AssetImportContext ctx, ImportSettings settings)
        {
#if UNITY_2018_2_OR_NEWER
            ctx.AddObjectToAsset("main", root);
            ctx.SetMainObject(root);
#else
            ctx.SetMainAsset("main obj", root);
#endif
            UnwrapParam?unwrapParams = new UnwrapParam()
            {
                angleError = settings.angleError,
                areaError  = settings.areaError,
                hardAngle  = settings.hardAngle,
                packMargin = settings.packMargin
            };

            MeshRenderer[]        renderers        = root.GetComponentsInChildren <MeshRenderer>(true);
            SkinnedMeshRenderer[] skinnedRenderers = root.GetComponentsInChildren <SkinnedMeshRenderer>(true);
            MeshFilter[]          filters          = root.GetComponentsInChildren <MeshFilter>(true);
            AddMeshes(filters, skinnedRenderers, ctx, settings.generateLightmapUVs ? unwrapParams : null);
            AddMaterials(renderers, skinnedRenderers, ctx);
            AddAnimations(animations, ctx, settings.animationSettings);
        }
예제 #15
0
 /// <param name="bytes">GLB file is supported</param>
 public static GameObject LoadFromBytes(byte[] bytes, ImportSettings importSettings, out GLTFAnimation.ImportResult[] animations)
 {
     return(ImportGLB(bytes, importSettings, out animations));
 }
예제 #16
0
        // hkyoo
        public static GameObject LoadInternal(this GLTFObject gltfObject, string filepath, int index, byte[] bytefile, long binChunkStart, ImportSettings importSettings, out AnimationClip[] animations)
        {
            // directory root is sometimes used for loading buffers from containing file, or local images
            string directoryRoot = filepath != null?Directory.GetParent(filepath).ToString() + "/" : null;

            importSettings.shaderOverrides.CacheDefaultShaders();

            //// for debug
            //Debug.Log(gltfObject.nodes.ToString() + " " + gltfObject.nodes.Count); // 151
            //Debug.Log(gltfObject.meshes.ToString() + " " + gltfObject.meshes.Count); // 151
            ////Debug.Log(gltfObject.animations.ToString() + " " + gltfObject.animations.Count); // null
            //Debug.Log(gltfObject.buffers.ToString() + " " + gltfObject.buffers.Count); // 1
            //Debug.Log(gltfObject.bufferViews.ToString() + " " + gltfObject.bufferViews.Count); // 755
            //Debug.Log(gltfObject.accessors.ToString() + " " + gltfObject.accessors.Count); // 604
            ////Debug.Log(gltfObject.skins.ToString() + " " + gltfObject.skins.Count); // null
            //Debug.Log(gltfObject.textures.ToString() + " " + gltfObject.textures.Count); // 151
            //Debug.Log(gltfObject.images.ToString() + " " + gltfObject.images.Count); // 151
            //Debug.Log(gltfObject.materials.ToString() + " " + gltfObject.materials.Count); // 151
            ////Debug.Log(gltfObject.cameras.ToString() + " " + gltfObject.cameras.Count); // null
            ///

            Stopwatch sw = new Stopwatch();


            // image/material/mesh

            sw.Start();
            // Import tasks synchronously
            GLTFBuffer.ImportTask bufferTask = new GLTFBuffer.ImportTask(gltfObject.buffers, filepath, bytefile, binChunkStart);
            bufferTask.RunSynchronously();
            sw.Stop();
            UnityEngine.Debug.Log("bufferTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            // TODO?
            GLTFBufferView.ImportTask bufferViewTask = new GLTFBufferView.ImportTask(gltfObject.bufferViews, bufferTask);
            bufferViewTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("bufferViewTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();


            GLTFAccessor.ImportTask accessorTask = new GLTFAccessor.ImportTask(gltfObject.accessors, bufferViewTask);
            accessorTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("accessorTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images[index], directoryRoot, bufferViewTask);
            //GLTFImage.ImportTask imageTask = new GLTFImage.ImportTask(gltfObject.images, directoryRoot, bufferViewTask);
            imageTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("imageTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures[index], imageTask);
            //GLTFTexture.ImportTask textureTask = new GLTFTexture.ImportTask(gltfObject.textures, imageTask);
            textureTask.RunSynchronously();

            UnityEngine.Debug.Log("textureTask.Result[0] " + textureTask.Result.Length + " " + textureTask.Result[0]);

            sw.Stop();
            UnityEngine.Debug.Log("textureTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            // TODO : shader setting
            GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials[index], textureTask, importSettings);
            //GLTFMaterial.ImportTask materialTask = new GLTFMaterial.ImportTask(gltfObject.materials, textureTask, importSettings);

            materialTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("materialTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            // TODO :
            GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes[index], accessorTask, bufferViewTask, materialTask, importSettings);
            //GLTFMesh.ImportTask meshTask = new GLTFMesh.ImportTask(gltfObject.meshes, accessorTask, bufferViewTask, materialTask, importSettings);

            meshTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("meshTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();

            GLTFSkin.ImportTask skinTask = new GLTFSkin.ImportTask(gltfObject.skins, accessorTask);
            skinTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("skinTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();

            sw.Start();


            GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes[index], meshTask, skinTask, gltfObject.cameras);
            //GLTFNode.ImportTask nodeTask = new GLTFNode.ImportTask(gltfObject.nodes, meshTask, skinTask, gltfObject.cameras);
            nodeTask.RunSynchronously();

            sw.Stop();
            UnityEngine.Debug.Log("nodeTask : " + sw.ElapsedMilliseconds.ToString() + "ms");
            sw.Reset();



            GLTFAnimation.ImportResult[] animationResult = gltfObject.animations.Import(accessorTask.Result, nodeTask.Result, importSettings);
            if (animationResult != null)
            {
                animations = animationResult.Select(x => x.clip).ToArray();
            }
            else
            {
                animations = new AnimationClip[0];
            }

            foreach (var item in bufferTask.Result)
            {
                item.Dispose();
            }

            return(nodeTask.Result.GetRoot());
        }
            public ImportTask(List <GLTFMaterial> materials, GLTFTexture.ImportTask textureTask, ImportSettings importSettings) : base(textureTask)
            {
                this.materials      = materials;
                this.textureTask    = textureTask;
                this.importSettings = importSettings;

                task = new Task(() => {
                    if (materials == null)
                    {
                        return;
                    }
                    Result = new ImportResult[materials.Count];
                });
            }
예제 #18
0
        public ImportResult Import(GLTFAccessor.ImportResult[] accessors, GLTFNode.ImportResult[] nodes, ImportSettings importSettings)
        {
            ImportResult result = new ImportResult();

            result.clip           = new AnimationClip();
            result.clip.name      = name;
            result.clip.frameRate = importSettings.frameRate;

            if (importSettings.useLegacyClips)
            {
                result.clip.legacy = true;
            }

            for (int i = 0; i < channels.Length; i++)
            {
                Channel channel = channels[i];
                if (samplers.Length <= channel.sampler)
                {
                    Debug.LogWarning($"GLTFUtility: Animation channel points to sampler at index {channel.sampler} which doesn't exist. Skipping animation clip.");
                    continue;
                }
                Sampler sampler = samplers[channel.sampler];

                ImportSettings.InterpolationMode GetInterpolationMode(string samplerInterpolationMode)
                {
                    if (importSettings.interpolationMode == ImportSettings.InterpolationMode.ImportFromFile)
                    {
                        if (samplerInterpolationMode == "STEP")
                        {
                            return(ImportSettings.InterpolationMode.Step);
                        }
                        else if (samplerInterpolationMode == "LINEAR")
                        {
                            return(ImportSettings.InterpolationMode.Linear);
                        }
                        else if (samplerInterpolationMode == "CUBICSPLINE")
                        {
                            return(ImportSettings.InterpolationMode.CubicSpline);
                        }
                        else
                        {
                            Debug.LogWarning($"Unsupported interpolation mode: {samplerInterpolationMode}. Defaulting to STEP.");
                            return(ImportSettings.InterpolationMode.Step);
                        }
                    }
                    else
                    {
                        return(importSettings.interpolationMode);
                    }
                }

                var interpolationMode = GetInterpolationMode(sampler.interpolation);

                string relativePath = "";

                GLTFNode.ImportResult node = nodes[channel.target.node.Value];
                while (node != null && !node.IsRoot)
                {
                    if (string.IsNullOrEmpty(relativePath))
                    {
                        relativePath = node.transform.name;
                    }
                    else
                    {
                        relativePath = node.transform.name + "/" + relativePath;
                    }

                    if (node.parent.HasValue)
                    {
                        node = nodes[node.parent.Value];
                    }
                    else
                    {
                        node = null;
                    }
                }

                float[] keyframeInput = accessors[sampler.input].ReadFloat().ToArray();
                switch (channel.target.path)
                {
                case "translation":
                    Vector3[]      pos  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve posX = new AnimationCurve();
                    AnimationCurve posY = new AnimationCurve();
                    AnimationCurve posZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        posX.AddKey(CreateKeyframe(keyframeInput[k], -pos[k].x, interpolationMode));
                        posY.AddKey(CreateKeyframe(keyframeInput[k], pos[k].y, interpolationMode));
                        posZ.AddKey(CreateKeyframe(keyframeInput[k], pos[k].z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", posX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", posY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", posZ);
                    break;

                case "rotation":
                    Vector4[] rot = accessors[sampler.output].ReadVec4().ToArray();

                    bool willProcessSteppedKeyframes = interpolationMode == ImportSettings.InterpolationMode.Step && Application.isEditor && !Application.isPlaying;

                    // @HACK: Creating stepped tangent keyframes is only supported in-editor -- not at runtime (Unity API restriction)
                                                #if UNITY_EDITOR // 🤢🤮💔
                    if (willProcessSteppedKeyframes)
                    {
                        AnimationCurve rotX = new AnimationCurve();
                        AnimationCurve rotY = new AnimationCurve();
                        AnimationCurve rotZ = new AnimationCurve();
                        for (int k = 0; k < keyframeInput.Length; k++)
                        {
                            Vector3 eulerRotation = new Quaternion(rot[k].x, -rot[k].y, -rot[k].z, rot[k].w).eulerAngles;

                            rotX.AddKey(CreateKeyframe(keyframeInput[k], eulerRotation.x, interpolationMode));
                            rotY.AddKey(CreateKeyframe(keyframeInput[k], eulerRotation.y, interpolationMode));
                            rotZ.AddKey(CreateKeyframe(keyframeInput[k], eulerRotation.z, interpolationMode));
                        }

                        EditorCurveBinding GetEditorBinding(string property)
                        {
                            return(EditorCurveBinding.DiscreteCurve(relativePath, typeof(Transform), property));
                        }

                        // Null out any other euler rotation curves on this clip, just to be safe.
                        // https://forum.unity.com/threads/new-animationclip-property-names.367288/#post-2384172
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAngles.x"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAngles.y"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAngles.z"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAngles.x"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAngles.y"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAngles.z"), null);

                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesBaked.x"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesBaked.y"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesBaked.z"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAnglesBaked.x"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAnglesBaked.y"), null);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("m_LocalEulerAnglesBaked.z"), null);


                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesRaw.x"), rotX);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesRaw.y"), rotY);
                        AnimationUtility.SetEditorCurve(result.clip, GetEditorBinding("localEulerAnglesRaw.z"), rotZ);
                    }
                                                #endif

                    if (!willProcessSteppedKeyframes)
                    {
                        AnimationCurve rotX = new AnimationCurve();
                        AnimationCurve rotY = new AnimationCurve();
                        AnimationCurve rotZ = new AnimationCurve();
                        AnimationCurve rotW = new AnimationCurve();
                        for (int k = 0; k < keyframeInput.Length; k++)
                        {
                            rotX.AddKey(CreateKeyframe(keyframeInput[k], rot[k].x, interpolationMode));
                            rotY.AddKey(CreateKeyframe(keyframeInput[k], -rot[k].y, interpolationMode));
                            rotZ.AddKey(CreateKeyframe(keyframeInput[k], -rot[k].z, interpolationMode));
                            rotW.AddKey(CreateKeyframe(keyframeInput[k], rot[k].w, interpolationMode));
                        }

                        result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.x", rotX);
                        result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.y", rotY);
                        result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.z", rotZ);
                        result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.w", rotW);
                    }

                    break;

                case "scale":
                    Vector3[]      scale  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve scaleX = new AnimationCurve();
                    AnimationCurve scaleY = new AnimationCurve();
                    AnimationCurve scaleZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        scaleX.AddKey(CreateKeyframe(keyframeInput[k], scale[k].x, interpolationMode));
                        scaleY.AddKey(CreateKeyframe(keyframeInput[k], scale[k].y, interpolationMode));
                        scaleZ.AddKey(CreateKeyframe(keyframeInput[k], scale[k].z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.x", scaleX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.y", scaleY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.z", scaleZ);
                    break;

                case "weights":
                    GLTFNode.ImportResult skinnedMeshNode     = nodes[channel.target.node.Value];
                    SkinnedMeshRenderer   skinnedMeshRenderer = skinnedMeshNode.transform.GetComponent <SkinnedMeshRenderer>();

                    int numberOfBlendShapes           = skinnedMeshRenderer.sharedMesh.blendShapeCount;
                    AnimationCurve[] blendShapeCurves = new AnimationCurve[numberOfBlendShapes];
                    for (int j = 0; j < numberOfBlendShapes; ++j)
                    {
                        blendShapeCurves[j] = new AnimationCurve();
                    }

                    float[] weights = accessors[sampler.output].ReadFloat().ToArray();

                    float[] previouslyKeyedValues = new float[numberOfBlendShapes];

                    // Reference for my future self:
                    // keyframeInput.Length = number of keyframes
                    // keyframeInput[ k ] = timestamp of keyframe
                    // weights.Length = number of keyframes * number of blendshapes
                    // weights[ j ] = actual animated weight of a specific blend shape
                    // (index into weights[] array accounts for keyframe index and blend shape index)

                    for (int k = 0; k < keyframeInput.Length; ++k)
                    {
                        for (int j = 0; j < numberOfBlendShapes; ++j)
                        {
                            int   weightIndex = (k * numberOfBlendShapes) + j;
                            float weightValue = weights[weightIndex];

                            bool addKey = true;
                            if (importSettings.compressBlendShapeKeyFrames)
                            {
                                if (k == 0 || !Mathf.Approximately(weightValue, previouslyKeyedValues[j]))
                                {
                                    previouslyKeyedValues[j] = weightValue;
                                    addKey = true;
                                }
                                else
                                {
                                    addKey = false;
                                }
                            }

                            if (addKey)
                            {
                                blendShapeCurves[j].AddKey(CreateKeyframe(keyframeInput[k], weightValue, interpolationMode));
                            }
                        }
                    }

                    for (int j = 0; j < numberOfBlendShapes; ++j)
                    {
                        string propertyName = "blendShape." + skinnedMeshRenderer.sharedMesh.GetBlendShapeName(j);
                        result.clip.SetCurve(relativePath, typeof(SkinnedMeshRenderer), propertyName, blendShapeCurves[j]);
                    }

                    break;
                }
            }
            return(result);
        }
예제 #19
0
 public static GameObject ImportGLTF(string filepath, ImportSettings importSettings)
 {
     GLTFAnimation.ImportResult[] animations;
     return(ImportGLTF(filepath, importSettings, out animations));
 }
예제 #20
0
        public ImportResult Import(GLTFAccessor.ImportResult[] accessors, GLTFNode.ImportResult[] nodes, ImportSettings importSettings)
        {
            bool multiRoots = nodes.Where(x => x.IsRoot).Count() > 1;

            ImportResult result = new ImportResult();

            result.clip      = new AnimationClip();
            result.clip.name = name;

            if (importSettings.useLegacyClips)
            {
                result.clip.legacy = true;
            }

            for (int i = 0; i < channels.Length; i++)
            {
                Channel channel = channels[i];
                if (samplers.Length <= channel.sampler)
                {
                    Debug.LogWarning($"GLTFUtility: Animation channel points to sampler at index {channel.sampler} which doesn't exist. Skipping animation clip.");
                    continue;
                }
                Sampler sampler = samplers[channel.sampler];

                // Get interpolation mode
                InterpolationMode interpolationMode = importSettings.interpolationMode;
                if (interpolationMode == InterpolationMode.ImportFromFile)
                {
                    interpolationMode = sampler.interpolation;
                }
                if (interpolationMode == InterpolationMode.CUBICSPLINE)
                {
                    Debug.LogWarning("Animation interpolation mode CUBICSPLINE not fully supported, result might look different.");
                }

                string relativePath = "";

                GLTFNode.ImportResult node = nodes[channel.target.node.Value];
                while (node != null && !node.IsRoot)
                {
                    if (string.IsNullOrEmpty(relativePath))
                    {
                        relativePath = node.transform.name;
                    }
                    else
                    {
                        relativePath = node.transform.name + "/" + relativePath;
                    }

                    if (node.parent.HasValue)
                    {
                        node = nodes[node.parent.Value];
                    }
                    else
                    {
                        node = null;
                    }
                }

                // If file has multiple root nodes, a new parent will be created for them as a final step of the import process. This parent f***s up the curve relative paths.
                // Add node.transform.name to path if there are multiple roots. This is not the most elegant fix but it works.
                // See GLTFNodeExtensions.GetRoot
                if (multiRoots)
                {
                    relativePath = node.transform.name + "/" + relativePath;
                }

                System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
                float[] keyframeInput = accessors[sampler.input].ReadFloat().ToArray();
                switch (channel.target.path)
                {
                case "translation":
                    Vector3[]      pos  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve posX = new AnimationCurve();
                    AnimationCurve posY = new AnimationCurve();
                    AnimationCurve posZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        posX.AddKey(CreateKeyframe(k, keyframeInput, pos, x => - x.x, interpolationMode));
                        posY.AddKey(CreateKeyframe(k, keyframeInput, pos, x => x.y, interpolationMode));
                        posZ.AddKey(CreateKeyframe(k, keyframeInput, pos, x => x.z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", posX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", posY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", posZ);
                    break;

                case "rotation":
                    Vector4[]      rot  = accessors[sampler.output].ReadVec4().ToArray();
                    AnimationCurve rotX = new AnimationCurve();
                    AnimationCurve rotY = new AnimationCurve();
                    AnimationCurve rotZ = new AnimationCurve();
                    AnimationCurve rotW = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        // The Animation window in Unity shows keyframes incorrectly converted to euler. This is only to deceive you. The quaternions underneath work correctly
                        rotX.AddKey(CreateKeyframe(k, keyframeInput, rot, x => x.x, interpolationMode));
                        rotY.AddKey(CreateKeyframe(k, keyframeInput, rot, x => - x.y, interpolationMode));
                        rotZ.AddKey(CreateKeyframe(k, keyframeInput, rot, x => - x.z, interpolationMode));
                        rotW.AddKey(CreateKeyframe(k, keyframeInput, rot, x => x.w, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.x", rotX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.y", rotY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.z", rotZ);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localRotation.w", rotW);
                    break;

                case "scale":
                    Vector3[]      scale  = accessors[sampler.output].ReadVec3().ToArray();
                    AnimationCurve scaleX = new AnimationCurve();
                    AnimationCurve scaleY = new AnimationCurve();
                    AnimationCurve scaleZ = new AnimationCurve();
                    for (int k = 0; k < keyframeInput.Length; k++)
                    {
                        scaleX.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.x, interpolationMode));
                        scaleY.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.y, interpolationMode));
                        scaleZ.AddKey(CreateKeyframe(k, keyframeInput, scale, x => x.z, interpolationMode));
                    }
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.x", scaleX);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.y", scaleY);
                    result.clip.SetCurve(relativePath, typeof(Transform), "localScale.z", scaleZ);
                    break;

                case "weights":
                    Debug.LogWarning("GLTFUtility: Morph weights in animation is not supported");
                    break;
                }
            }
            return(result);
        }
예제 #21
0
        public static GLTFAnimation.ImportResult[] Import(this List <GLTFAnimation> animations, GLTFAccessor.ImportResult[] accessors, GLTFNode.ImportResult[] nodes, ImportSettings importSettings)
        {
            if (animations == null)
            {
                return(null);
            }

            GLTFAnimation.ImportResult[] results = new GLTFAnimation.ImportResult[animations.Count];
            for (int i = 0; i < results.Length; i++)
            {
                results[i] = animations[i].Import(accessors, nodes, importSettings);
                if (string.IsNullOrEmpty(results[i].clip.name))
                {
                    results[i].clip.name = "animation" + i;
                }
            }
            return(results);
        }
예제 #22
0
        public static GLTFMaterial.ImportResult Import(this List <GLTFMaterial> materials, GLTFTexture.ImportResult[] textures, ImportSettings importSettings)
        {
            if (!importSettings.materials)
            {
                return(null);
            }

            GLTFMaterial.ImportResult result = new GLTFMaterial.ImportResult();
            result.materials = new Material[materials.Count];
            for (int i = 0; i < materials.Count; i++)
            {
                result.materials[i] = materials[i].CreateMaterial(textures, importSettings.shaders);
                if (materials[i].name == null)
                {
                    materials[i].name = "material" + i;
                }
            }
            return(result);
        }