// https://github.com/vrm-c/vrm-specification/pull/255 // 1.0 では末端に7cmの遠さに joint を追加する動作をしなくなった。 // その差異に対応して、7cmの遠さに node を追加する。 SpringBoneJoint AddTail7cm(int lastIndex) { var last = _gltf.nodes[lastIndex]; var name = last.name ?? ""; var v1 = new UnityEngine.Vector3(last.translation[0], last.translation[1], last.translation[2]); var delta = v1.normalized * 0.07f; // 7cm var tail = new UniGLTF.glTFNode { name = name + "_end", translation = new float[] { delta.x, delta.y, delta.z }, }; var tail_index = _gltf.nodes.Count; _gltf.nodes.Add(tail); if (last.children != null && last.children.Length > 0) { throw new System.Exception(); } last.children = new[] { tail_index }; // 1.0 では、head + tail のペアでスプリングを表し、 // 揺れ挙動のパラメーターは head の方に入る。 // 要するに 末端の joint では Node しか使われない。 return(new SpringBoneJoint { Node = tail_index, }); }
static void AddTail7cm(UniGLTF.glTF gltf, UniGLTF.glTFNode[] joints) { if (joints.Length < 2) { return; } var last = joints.Last(); var name = last.name ?? ""; var v1 = new UnityEngine.Vector3(last.translation[0], last.translation[1], last.translation[2]); // var last2 = joints[joints.Length - 2]; // var v2 = new UnityEngine.Vector3(last2.translation[0], last2.translation[1], last2.translation[2]); var delta = v1.normalized * 0.07f; // 7cm var tail = new UniGLTF.glTFNode { name = name + "_end", translation = new float[] { delta.x, delta.y, delta.z }, }; var tail_index = gltf.nodes.Count; gltf.nodes.Add(tail); if (last.children != null && last.children.Length > 0) { throw new System.Exception(); } last.children = new[] { tail_index }; }
/// <summary> /// /// </summary> /// <param name="node"></param> /// <param name="level">children[0] のみカウントアップする。その他は0にリセットする</param> /// <param name="spring"></param> void CreateJointsRecursive(UniGLTF.glTFNode node, int level, Spring spring = null) { if (spring == null && level > 0) { // 2番目以降の子ノードの子から新しい Spring を作る。 spring = CreateSpring(); } if (spring != null) { // level==0 のとき(2番目以降の兄弟ボーン)は飛ばす spring.Joints.Add(CreateJoint(_gltf.nodes.IndexOf(node))); } if (node.children != null && node.children.Length > 0) { for (int i = 0; i < node.children.Length; ++i) { var childIndex = node.children[i]; if (childIndex < 0 || childIndex >= _gltf.nodes.Count) { // -1 など? continue; } if (i == 0) { // spring に joint を追加する CreateJointsRecursive(_gltf.nodes[childIndex], level + 1, spring); } else { // 再帰 CreateJointsRecursive(_gltf.nodes[childIndex], 0); } } } else { if (spring != null && spring.Joints.Count > 0) { var last = spring.Joints.Last().Node; if (last.HasValue) { var tailJoint = AddTail7cm(last.Value); spring.Joints.Add(tailJoint); } } } }
public static Node CreateDrawable(int i, UniGLTF.glTFNode node) { var name = $"[{i}]{node.name}"; var drawable = new Node(name); if (node.matrix != null) { var m = new Matrix(node.matrix); //m.Transpose(); drawable.LocalMatrix = m; } else { var t = Vector3.Zero; var r = Quaternion.Identity; var s = Vector3.One; if (node.translation != null) { t.X = node.translation[0]; t.Y = node.translation[1]; t.Z = node.translation[2]; } if (node.rotation != null) { r.X = node.rotation[0]; r.Y = node.rotation[1]; r.Z = node.rotation[2]; r.W = node.rotation[3]; } if (node.scale != null) { s.X = node.scale[0]; s.Y = node.scale[1]; s.Z = node.scale[2]; } var m = Matrix.Transformation(Vector3.Zero, Quaternion.Identity, s, Vector3.Zero, r, t); drawable.LocalMatrix = m; } return(drawable); }
static IEnumerable <UniGLTF.glTFNode> EnumJoint(List <UniGLTF.glTFNode> nodes, UniGLTF.glTFNode node) { yield return(node); if (node.children != null && node.children.Length > 0) { foreach (var x in EnumJoint(nodes, nodes[node.children[0]])) { yield return(x); } } }
static IEnumerable <UniGLTF.glTFNode> TraverseFirstChild(List <UniGLTF.glTFNode> nodes, UniGLTF.glTFNode node) { yield return(node); if (node.children != null && node.children.Length > 0) { foreach (var x in TraverseFirstChild(nodes, nodes[node.children[0]])) { yield return(x); } } }