private static int RecursivelyCopyNode(List <Node> nodes, ProtoNode nodeToCopy) { var newNode = new Node(); newNode.Matrix = nodeToCopy.Matrix; if (nodeToCopy.Mesh != null) { newNode.Mesh = nodeToCopy.Mesh; } nodes.Add(newNode); var nodeIndex = nodes.Count - 1; var childIndices = new List <int>(); foreach (var child in nodeToCopy.Children) { childIndices.Add(RecursivelyCopyNode(nodes, child)); } if (childIndices.Count > 0) { newNode.Children = childIndices.ToArray(); } return(nodeIndex); }
/// <summary> /// We construct a new, recursively-structured 'ProtoNode' from the flat gltf node, and mutate its mesh indices to /// point to the correct mesh in the merged gltf. /// </summary> private static ProtoNode RecursivelyModifyMeshIndices(glTFLoader.Schema.Node node, List <int> meshIndices, glTFLoader.Schema.Node[] loadedNodes) { var protoNode = new ProtoNode(); protoNode.Matrix = node.Matrix; if (node.Mesh != null) { protoNode.Mesh = meshIndices[node.Mesh.Value]; } if (node.Children != null && node.Children.Count() > 0) { foreach (var child in node.Children) { protoNode.Children.Add(RecursivelyModifyMeshIndices(loadedNodes[child], meshIndices, loadedNodes)); } } return(protoNode); }
internal static void AddInstanceAsCopyOfNode( List <glTFLoader.Schema.Node> nodes, ProtoNode nodeToCopy, Transform transform, System.Guid instanceElementId) { // Two new nodes are created: a top-level node, which has the // element's Transform, and one just below that, which handles // flipping the orientation of the glb to have Z up. That node has // the node to copy as its only child. // We use the node to copy exactly as is, with an unmodified // transform. // We need the outermost node to be "purely" the element's // transform, so that the transform can be modified in explore at // runtime (e.g. by a transform override) and have the expected effect. float[] elementTransform = TransformToMatrix(transform); var newNode = new glTFLoader.Schema.Node(); newNode.Name = $"{instanceElementId}"; newNode.Matrix = elementTransform; nodes.Add(newNode); newNode.Children = new[] { nodes.Count }; var rootTransform = new Transform(); // glb has Y up. transform it to have Z up so we // can create instances of it in a Z up world. It will get switched // back to Y up further up in the node hierarchy. rootTransform.Rotate(new Vector3(1, 0, 0), 90.0); float[] glbOrientationTransform = TransformToMatrix(rootTransform); var elementOrientationNode = new glTFLoader.Schema.Node(); elementOrientationNode.Matrix = glbOrientationTransform; nodes.Add(elementOrientationNode); elementOrientationNode.Children = new[] { nodes.Count }; nodes[0].Children = (nodes[0].Children ?? Array.Empty <int>()).Concat(new[] { nodes.Count - 2 }).ToArray(); RecursivelyCopyNode(nodes, nodeToCopy); }
public static List <int> AddAllMeshesFromFromGlb(Stream glbStream, List <Buffer> buffers, List <byte[]> bufferByteArrays, List <BufferView> bufferViews, List <Accessor> accessors, List <glTFLoader.Schema.Mesh> meshes, List <glTFLoader.Schema.Material> materials, List <Texture> textures, List <Image> images, List <Sampler> samplers, bool shouldAddMaterials, System.Guid contentElementId, out ProtoNode parentNode ) { var loadingStream = new MemoryStream(); glbStream.Position = 0; glbStream.CopyTo(loadingStream); loadingStream.Position = 0; var loaded = Interface.LoadModel(loadingStream); var newByteArrays = loaded.GetAllBufferByteArrays(glbStream); bufferByteArrays.AddRange(newByteArrays); var bufferIncrement = buffers.Count; foreach (var originBuffer in loaded.Buffers) { buffers.Add(originBuffer); } var buffViewIncrement = bufferViews.Count; foreach (var originBuffView in loaded.BufferViews) { originBuffView.Buffer = originBuffView.Buffer + bufferIncrement; bufferViews.Add(originBuffView); } var accessorIncrement = accessors.Count; foreach (var originAccessor in loaded.Accessors) { originAccessor.BufferView = originAccessor.BufferView + buffViewIncrement; accessors.Add(originAccessor); } var imageIncrement = images.Count; if (loaded.Images != null) { foreach (var originImage in loaded.Images) { if (originImage.BufferView.HasValue) { originImage.BufferView = originImage.BufferView + buffViewIncrement; } images.Add(originImage); } } var samplerIncrement = samplers.Count; if (loaded.Samplers != null) { foreach (var originSampler in loaded.Samplers) { samplers.Add(originSampler); } } var textureIncrement = textures.Count; if (loaded.Textures != null) { foreach (var originTexture in loaded.Textures) { originTexture.Source = originTexture.Source + imageIncrement; if (originTexture.Sampler.HasValue) { originTexture.Sampler = originTexture.Sampler + samplerIncrement; } textures.Add(originTexture); } } var materialIncrement = materials.Count; if (shouldAddMaterials) { AddMaterials(materials, loaded, textureIncrement); } var meshIndices = new List <int>(); foreach (var originMesh in loaded.Meshes) { foreach (var prim in originMesh.Primitives) { var attributes = new Dictionary <string, int>(); foreach (var kvp in prim.Attributes) { attributes[kvp.Key] = kvp.Value + accessorIncrement; } prim.Attributes = attributes; prim.Indices = prim.Indices + accessorIncrement; if (shouldAddMaterials) { prim.Material = prim.Material + materialIncrement; } else { prim.Material = 0; // This assumes that the default material is at index 0 } } originMesh.Name = $"{contentElementId}_mesh"; meshes.Add(originMesh); meshIndices.Add(meshes.Count - 1); } var topNode = loaded.Nodes[loaded.Scenes[0].Nodes[0]]; parentNode = RecursivelyModifyMeshIndices(topNode, meshIndices, loaded.Nodes); parentNode.Matrix = topNode.Matrix; return(meshIndices); }