private List <AnimationClip> ImportAnimationClips(glTF gltf, Axises invertAxis) { var animationClips = new List <AnimationClip>(); for (var i = 0; i < gltf.animations.Count; ++i) { var clip = new AnimationClip(); clip.ClearCurves(); clip.legacy = true; clip.name = gltf.animations[i].name; if (string.IsNullOrEmpty(clip.name)) { clip.name = $"legacy_{i}"; } clip.wrapMode = WrapMode.Loop; var animation = gltf.animations[i]; if (string.IsNullOrEmpty(animation.name)) { animation.name = $"animation:{i}"; } animationClips.Add(AnimationImporterUtil.ConvertAnimationClip(gltf, animation, invertAxis.Create())); } return(animationClips); }
public override void OnEnable() { base.OnEnable(); m_importer = target as ZipArchivedGltfScriptedImporter; m_data = new AutoGltfFileParser(m_importer.assetPath).Parse(); var materialGenerator = new GltfMaterialDescriptorGenerator(); var materialKeys = m_data.GLTF.materials.Select((_, i) => materialGenerator.Get(m_data, i).SubAssetKey); var textureKeys = new GltfTextureDescriptorGenerator(m_data).Get().GetEnumerable().Select(x => x.SubAssetKey); m_materialEditor = new RemapEditorMaterial(materialKeys.Concat(textureKeys), GetEditorMap, SetEditorMap); m_animationEditor = new RemapEditorAnimation(AnimationImporterUtil.EnumerateSubAssetKeys(m_data.GLTF), GetEditorMap, SetEditorMap); }
public virtual async Task LoadAnimationAsync(IAwaitCaller awaitCaller) { if (GLTF.animations != null && GLTF.animations.Any()) { foreach (var(key, gltfAnimation) in Enumerable.Zip(AnimationImporterUtil.EnumerateSubAssetKeys(GLTF), GLTF.animations, (x, y) => (x, y))) { await AnimationClipFactory.LoadAnimationClipAsync(key, async() => { return(AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create())); }); } await awaitCaller.NextFrame(); } }
private List <AnimationClip> ImportAnimationClips(glTF gltf, Axises invertAxis) { var animationClips = new List <AnimationClip>(); for (var i = 0; i < gltf.animations.Count; ++i) { var clip = new AnimationClip(); clip.ClearCurves(); clip.legacy = true; clip.name = gltf.animations[i].name; if (string.IsNullOrEmpty(clip.name)) { clip.name = $"legacy_{i}"; } clip.wrapMode = WrapMode.Loop; var animation = gltf.animations[i]; if (string.IsNullOrEmpty(animation.name)) { animation.name = $"animation:{i}"; } AxisInverter inverter = default; switch (invertAxis) { case Axises.X: inverter = AxisInverter.ReverseX; break; case Axises.Z: inverter = AxisInverter.ReverseZ; break; default: throw new System.Exception(); } animationClips.Add(AnimationImporterUtil.ConvertAnimationClip(gltf, animation, inverter)); } return(animationClips); }
public static AnimationClip ConvertAnimationClip(GltfData data, glTFAnimation animation, IAxisInverter inverter, glTFNode root = null) { var clip = new AnimationClip(); clip.ClearCurves(); clip.legacy = true; clip.name = animation.name; clip.wrapMode = WrapMode.Loop; foreach (var channel in animation.channels) { var relativePath = RelativePathFrom(data.GLTF.nodes, root, data.GLTF.nodes[channel.target.node]); switch (channel.target.path) { case glTFAnimationTarget.PATH_TRANSLATION: { var sampler = animation.samplers[channel.sampler]; var input = data.GetArrayFromAccessor <float>(sampler.input); var output = data.FlatternFloatArrayFromAccessor(sampler.output); AnimationImporterUtil.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(inverter.InvertVector3(temp).ToArray()); } ); } break; case glTFAnimationTarget.PATH_ROTATION: { var sampler = animation.samplers[channel.sampler]; var input = data.GetArrayFromAccessor <float>(sampler.input); var output = data.FlatternFloatArrayFromAccessor(sampler.output); AnimationImporterUtil.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(AnimationImporterUtil.GetShortest(lastQuaternion, inverter.InvertQuaternion(currentQuaternion)).ToArray()); } ); clip.EnsureQuaternionContinuity(); } break; case glTFAnimationTarget.PATH_SCALE: { var sampler = animation.samplers[channel.sampler]; var input = data.GetArrayFromAccessor <float>(sampler.input); var output = data.FlatternFloatArrayFromAccessor(sampler.output); AnimationImporterUtil.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 = data.GLTF.nodes[channel.target.node]; var mesh = data.GLTF.meshes[node.mesh]; var primitive = mesh.primitives.FirstOrDefault(); var targets = primitive.targets; if (!gltf_mesh_extras_targetNames.TryGet(mesh, out List <string> targetNames)) { throw new UniGLTFNotSupportedException("glTF BlendShape Animation. targetNames invalid."); } var keyNames = targetNames .Where(x => !string.IsNullOrEmpty(x)) .Select(x => "blendShape." + x) .ToArray(); var sampler = animation.samplers[channel.sampler]; var input = data.GetArrayFromAccessor <float>(sampler.input); var output = data.GetArrayFromAccessor <float>(sampler.output); AnimationImporterUtil.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; default: Debug.LogWarningFormat("unknown path: {0}", channel.target.path); break; } } return(clip); }