private static glTFNode ExportNode(Transform x, List <Transform> nodes, List <Renderer> renderers, List <SkinnedMeshRenderer> skins) { var node = new glTFNode { name = x.name, children = x.transform.GetChildren().Select(y => nodes.IndexOf(y)).ToArray(), rotation = x.transform.localRotation.ToArray(), translation = x.transform.localPosition.ToArray(), scale = x.transform.localScale.ToArray(), }; if (x.gameObject.activeInHierarchy) { var meshRenderer = x.GetComponent <MeshRenderer>(); if (meshRenderer != null) { node.mesh = renderers.IndexOf(meshRenderer); } var skinnredMeshRenderer = x.GetComponent <SkinnedMeshRenderer>(); if (skinnredMeshRenderer != null) { node.mesh = renderers.IndexOf(skinnredMeshRenderer); node.skin = skins.IndexOf(skinnredMeshRenderer); } } return(node); }
private static string RelativePathFrom(List <glTFNode> nodes, glTFNode root, glTFNode target, List <string> path) { if (path.Count == 0) { path.Add(target.name); } var targetIndex = nodes.IndexOf(target); foreach (var parent in nodes) { if (parent.children == null || parent.children.Length == 0) { continue; } foreach (var child in parent.children) { if (child != targetIndex) { continue; } if (parent == root) { return(string.Join("/", path)); } path.Insert(0, parent.name); return(RelativePathFrom(nodes, root, parent, path)); } } return(string.Join("/", path)); }
public static string RelativePathFrom(List <glTFNode> nodes, glTFNode root, glTFNode target) { if (root == target) { return(""); } var path = new List <string>(); return(RelativePathFrom(nodes, root, target, path)); }
public static GameObject ImportNode(glTFNode node, int nodeIndex) { var nodeName = node.name; if (!string.IsNullOrEmpty(nodeName) && nodeName.Contains("/")) { Debug.LogWarningFormat("node {0} contains /. replace _", node.name); nodeName = nodeName.Replace("/", "_"); } if (string.IsNullOrEmpty(nodeName)) { nodeName = string.Format("nodeIndex_{0}", nodeIndex); } var go = new GameObject(nodeName); // // transform // if (node.translation != null && node.translation.Length > 0) { go.transform.localPosition = new Vector3( node.translation[0], node.translation[1], node.translation[2]); } if (node.rotation != null && node.rotation.Length > 0) { go.transform.localRotation = new Quaternion( node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3]); } if (node.scale != null && node.scale.Length > 0) { go.transform.localScale = new Vector3( node.scale[0], node.scale[1], node.scale[2]); } if (node.matrix != null && node.matrix.Length > 0) { var m = UnityExtensions.MatrixFromArray(node.matrix); go.transform.localRotation = m.ExtractRotation(); go.transform.localPosition = m.ExtractPosition(); go.transform.localScale = m.ExtractScale(); } return(go); }
public void NodeTestError() { var model = new glTFNode() { name = "a", camera = -2, }; var c = new JsonSchemaValidationContext("") { EnableDiagnosisForNotRequiredFields = true, }; var ex = Assert.Throws <JsonSchemaValidationException>( () => JsonSchema.FromType <glTFNode>().Serialize(model, c) ); Assert.AreEqual("[camera.String] minimum: ! -2>=0", ex.Message); }
public void NodeMeshTest() { var model = new glTFNode() { name = "a", mesh = 2, skin = 0, camera = -1, }; var c = new JsonSchemaValidationContext("") { EnableDiagnosisForNotRequiredFields = true, }; var json = JsonSchema.FromType <glTFNode>().Serialize(model, c); Assert.AreEqual(@"{""name"":""a"",""mesh"":2,""skin"":0,""extras"":{}}", json); }
static glTFNode ExportNode(Transform x, List <Transform> nodes, List <MeshWithRenderer> meshAndRenderers, List <SkinnedMeshRenderer> skins) { var node = new glTFNode { name = x.name, children = x.transform.GetChildren().Select(y => nodes.IndexOf(y)).ToArray(), rotation = x.transform.localRotation.ToArray(), translation = x.transform.localPosition.ToArray(), scale = x.transform.localScale.ToArray(), }; if (x.gameObject.activeInHierarchy) { var skinnedMeshRenderer = x.GetComponent <SkinnedMeshRenderer>(); if (skinnedMeshRenderer != null) { var mesh = skinnedMeshRenderer.sharedMesh; var materials = skinnedMeshRenderer.sharedMaterials; var meshIndex = -1; for (var i = 0; i < meshAndRenderers.Count; i++) { if (meshAndRenderers[i].IsSameMeshAndMaterials(mesh, materials)) { meshIndex = i; break; } } if (meshIndex == -1) { throw new Exception("Mesh not found."); } node.mesh = meshIndex; node.skin = skins.IndexOf(skinnedMeshRenderer); } else { var meshFilter = x.GetComponent <MeshFilter>(); var meshRenderer = x.GetComponent <MeshRenderer>(); if (meshFilter != null && meshRenderer != null && !x.HasTextMeshProComponent()) { var mesh = meshFilter.sharedMesh; var materials = meshRenderer.sharedMaterials; if (mesh != null && materials != null && materials.Length > 0) { var meshIndex = -1; for (var i = 0; i < meshAndRenderers.Count; i++) { if (meshAndRenderers[i].IsSameMeshAndMaterials(mesh, materials)) { meshIndex = i; break; } } if (meshIndex == -1) { throw new Exception("Mesh not found."); } node.mesh = meshIndex; } } } } return(node); }
public static AnimationClip ImportAnimationClip(ImporterContext ctx, glTFAnimation animation, 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(ctx.GLTF.nodes, root, ctx.GLTF.nodes[channel.target.node]); switch (channel.target.path) { case glTFAnimationTarget.PATH_TRANSLATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(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(temp.ReverseZ().ToArray()); } ); } break; case glTFAnimationTarget.PATH_ROTATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(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, currentQuaternion.ReverseZ()).ToArray()); } ); clip.EnsureQuaternionContinuity(); } break; case glTFAnimationTarget.PATH_SCALE: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(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 = ctx.GLTF.nodes[channel.target.node]; var mesh = ctx.GLTF.meshes[node.mesh]; //var primitive = mesh.primitives.FirstOrDefault(); //var targets = primitive.targets; List <string> blendShapeNames = new List <string>(); var transform = ctx.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 = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.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); }