// // fix node's coordinate. z-back to z-forward // public static void FixCoordinate(ImporterContext context, List <TransformWithSkin> nodes, AxisInverter inverter) { var globalTransformMap = nodes.ToDictionary(x => x.Transform, x => new PosRot { Position = x.Transform.position, Rotation = x.Transform.rotation, }); foreach (var x in context.GLTF.rootnodes) { // fix nodes coordinate // reverse Z in global var t = nodes[x].Transform; //t.SetParent(root.transform, false); foreach (var transform in t.Traverse()) { var g = globalTransformMap[transform]; transform.position = inverter.InvertVector3(g.Position); transform.rotation = inverter.InvertQuaternion(g.Rotation); } } }
public static AnimationClip ConvertAnimationClip(glTF gltf, glTFAnimation animation, AxisInverter 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(gltf.nodes, root, gltf.nodes[channel.target.node]); switch (channel.target.path) { case glTFAnimationTarget.PATH_TRANSLATION: { var sampler = animation.samplers[channel.sampler]; var input = gltf.GetArrayFromAccessor <float>(sampler.input); var output = gltf.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 = gltf.GetArrayFromAccessor <float>(sampler.input); var output = gltf.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 = gltf.GetArrayFromAccessor <float>(sampler.input); var output = gltf.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 = gltf.nodes[channel.target.node]; var mesh = 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 Exception("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 = gltf.GetArrayFromAccessor <float>(sampler.input); var output = gltf.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); }