/// <summary> /// Merges the right root into the left root /// This function combines all of the lists of objects on each glTF root together and updates the relative indicies /// All properties all merged except Asset and Default, which will stay "mergeToRoot"'s value /// </summary> /// <param name="mergeToRoot">The node to merge into</param> /// <param name="mergeFromRoot">The node to merge from</param> public static void MergeGLTF(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot) { PreviousGLTFSizes previousGLTFSize = new PreviousGLTFSizes() { PreviousAccessorCount = mergeToRoot.Accessors?.Count ?? 0, PreviousBufferCount = mergeToRoot.Buffers?.Count ?? 0, PreviousAnimationCount = mergeToRoot.Animations?.Count ?? 0, PreviousBufferViewCount = mergeToRoot.BufferViews?.Count ?? 0, PreviousCameraCount = mergeToRoot.Cameras?.Count ?? 0, PreviousImageCount = mergeToRoot.Images?.Count ?? 0, PreviousMaterialCount = mergeToRoot.Materials?.Count ?? 0, PreviousMeshCount = mergeToRoot.Meshes?.Count ?? 0, PreviousNodeCount = mergeToRoot.Nodes?.Count ?? 0, PreviousSamplerCount = mergeToRoot.Samplers?.Count ?? 0, PreviousSceneCount = mergeToRoot.Scenes?.Count ?? 0, PreviousSkinCount = mergeToRoot.Skins?.Count ?? 0, PreviousTextureCount = mergeToRoot.Textures?.Count ?? 0 }; GLTFRoot mergeFromRootCopy = new GLTFRoot(mergeFromRoot); // for each type: // 1) add the right hand range to the left hand object // 2) update all ids to be based off of the appended size // merge extensions MergeExtensions(mergeToRoot, mergeFromRootCopy); // merge accessors, buffers, and bufferviews MergeAccessorsBufferViewsAndBuffers(mergeToRoot, mergeFromRootCopy, previousGLTFSize); // merge materials, samplers, images, and textures MergeMaterialsImagesTexturesAndSamplers(mergeToRoot, mergeFromRootCopy, previousGLTFSize); // merge meshes MergeMeshes(mergeToRoot, mergeFromRootCopy, previousGLTFSize); // merge cameras MergeCameras(mergeToRoot, mergeFromRootCopy); // merge nodes MergeNodes(mergeToRoot, mergeFromRootCopy, previousGLTFSize); // merge animation, and skin MergeAnimationsAndSkins(mergeToRoot, mergeFromRootCopy, previousGLTFSize); // merge scenes MergeScenes(mergeToRoot, mergeFromRootCopy, previousGLTFSize); }
private static void MergeNodes(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Nodes == null) { return; } if (mergeToRoot.Nodes == null) { mergeToRoot.Nodes = new List <Node>(mergeFromRoot.Nodes.Count); } mergeToRoot.Nodes.AddRange(mergeFromRoot.Nodes); for (int i = previousGLTFSizes.PreviousNodeCount; i < mergeToRoot.Nodes.Count; ++i) { Node node = mergeToRoot.Nodes[i]; if (node.Mesh != null) { MeshId meshId = node.Mesh; meshId.Id += previousGLTFSizes.PreviousMeshCount; node.Mesh.Root = mergeToRoot; } if (node.Camera != null) { CameraId cameraId = node.Camera; cameraId.Id += previousGLTFSizes.PreviousCameraCount; cameraId.Root = mergeToRoot; } if (node.Children != null) { foreach (NodeId child in node.Children) { child.Id += previousGLTFSizes.PreviousNodeCount; child.Root = mergeToRoot; } } if (node.Skin != null) { SkinId skinId = node.Skin; skinId.Id += previousGLTFSizes.PreviousSkinCount; skinId.Root = mergeToRoot; } } }
private static void MergeScenes(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Scenes == null) { return; } if (mergeToRoot.Scenes == null) { mergeToRoot.Scenes = new List <Scene>(mergeFromRoot.Scenes.Count); } mergeToRoot.Scenes.AddRange(mergeFromRoot.Scenes); for (int i = previousGLTFSizes.PreviousSceneCount; i < mergeToRoot.Scenes.Count; ++i) { Scene scene = mergeToRoot.Scenes[i]; foreach (NodeId nodeId in scene.Nodes) { nodeId.Id += previousGLTFSizes.PreviousNodeCount; nodeId.Root = mergeToRoot; } } }
private static void MergeAnimationsAndSkins(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Skins != null) { if (mergeToRoot.Skins == null) { mergeToRoot.Skins = new List <Skin>(mergeFromRoot.Skins.Count); } mergeToRoot.Skins.AddRange(mergeFromRoot.Skins); for (int i = previousGLTFSizes.PreviousSkinCount; i < mergeToRoot.Skins.Count; ++i) { Skin skin = mergeToRoot.Skins[i]; if (skin.InverseBindMatrices != null) { skin.InverseBindMatrices.Id += previousGLTFSizes.PreviousAccessorCount; } if (skin.Skeleton != null) { skin.Skeleton.Id += previousGLTFSizes.PreviousNodeCount; } if (skin.Joints != null) { foreach (NodeId joint in skin.Joints) { joint.Id += previousGLTFSizes.PreviousNodeCount; } } } } if (mergeFromRoot.Animations != null) { if (mergeToRoot.Animations == null) { mergeToRoot.Animations = new List <Animation>(mergeFromRoot.Animations.Count); } mergeToRoot.Animations.AddRange(mergeFromRoot.Animations); for (int i = previousGLTFSizes.PreviousAnimationCount; i < mergeToRoot.Animations.Count; ++i) { Animation animation = mergeToRoot.Animations[i]; foreach (AnimationSampler sampler in animation.Samplers) { AccessorId inputId = sampler.Input; inputId.Id += previousGLTFSizes.PreviousAccessorCount; inputId.Root = mergeToRoot; AccessorId outputId = sampler.Output; outputId.Id += previousGLTFSizes.PreviousAccessorCount; outputId.Root = mergeToRoot; } foreach (AnimationChannel channel in animation.Channels) { SamplerId samplerId = channel.Sampler; samplerId.Id += previousGLTFSizes.PreviousSamplerCount; samplerId.Root = mergeToRoot; NodeId nodeId = channel.Target.Node; nodeId.Id += previousGLTFSizes.PreviousNodeCount; nodeId.Root = mergeToRoot; } } } }
private static void MergeMeshes(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Meshes == null) { return; } if (mergeToRoot.Meshes == null) { mergeToRoot.Meshes = new List <Mesh>(mergeFromRoot.Meshes.Count); } mergeToRoot.Meshes.AddRange(mergeFromRoot.Meshes); for (int i = previousGLTFSizes.PreviousMeshCount; i < mergeToRoot.Meshes.Count; ++i) { Mesh mesh = mergeToRoot.Meshes[i]; if (mesh.Primitives != null) { foreach (MeshPrimitive primitive in mesh.Primitives) { foreach (var attributeAccessorPair in primitive.Attributes) { AccessorId accessorId = attributeAccessorPair.Value; accessorId.Id += previousGLTFSizes.PreviousAccessorCount; accessorId.Root = mergeToRoot; } if (primitive.Indices != null) { AccessorId accessorId = primitive.Indices; accessorId.Id += previousGLTFSizes.PreviousAccessorCount; accessorId.Root = mergeToRoot; } if (primitive.Material != null) { MaterialId materialId = primitive.Material; materialId.Id += previousGLTFSizes.PreviousMaterialCount; materialId.Root = mergeToRoot; } if (primitive.Targets != null) { foreach (Dictionary <string, AccessorId> targetsDictionary in primitive.Targets) { foreach (var targetsPair in targetsDictionary) { AccessorId accessorId = targetsPair.Value; accessorId.Id += previousGLTFSizes.PreviousAccessorCount; accessorId.Root = mergeToRoot; } } } } } } }
private static void MergeMaterialsImagesTexturesAndSamplers(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Samplers != null) { if (mergeToRoot.Samplers == null) { mergeToRoot.Samplers = new List <Sampler>(mergeFromRoot.Samplers.Count); } mergeToRoot.Samplers.AddRange(mergeFromRoot.Samplers); } if (mergeFromRoot.Images != null) { if (mergeToRoot.Images == null) { mergeToRoot.Images = new List <Image>(mergeFromRoot.Images.Count); } mergeToRoot.Images.AddRange(mergeFromRoot.Images); for (int i = previousGLTFSizes.PreviousImageCount; i < mergeToRoot.Images.Count; ++i) { Image image = mergeToRoot.Images[i]; if (image.BufferView != null) { BufferViewId bufferViewId = image.BufferView; bufferViewId.Id += previousGLTFSizes.PreviousBufferViewCount; bufferViewId.Root = mergeToRoot; } } } if (mergeFromRoot.Textures != null) { if (mergeToRoot.Textures == null) { mergeToRoot.Textures = new List <Texture>(mergeFromRoot.Textures.Count); } mergeToRoot.Textures.AddRange(mergeFromRoot.Textures); for (int i = previousGLTFSizes.PreviousTextureCount; i < mergeToRoot.Textures.Count; ++i) { Texture texture = mergeToRoot.Textures[i]; if (texture.Sampler != null) { SamplerId samplerId = texture.Sampler; samplerId.Id += previousGLTFSizes.PreviousSamplerCount; samplerId.Root = mergeToRoot; } if (texture.Source != null) { ImageId samplerId = texture.Source; samplerId.Id += previousGLTFSizes.PreviousImageCount; samplerId.Root = mergeToRoot; } } } if (mergeFromRoot.Materials != null) { if (mergeToRoot.Materials == null) { mergeToRoot.Materials = new List <Material>(mergeFromRoot.Materials.Count); } mergeToRoot.Materials.AddRange(mergeFromRoot.Materials); for (int i = previousGLTFSizes.PreviousMaterialCount; i < mergeToRoot.Materials.Count; ++i) { Material material = mergeToRoot.Materials[i]; PbrMetallicRoughness pbrMetallicRoughness = material.PbrMetallicRoughness; if (pbrMetallicRoughness != null) { if (pbrMetallicRoughness.BaseColorTexture != null) { TextureId textureId = pbrMetallicRoughness.BaseColorTexture.Index; textureId.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } if (pbrMetallicRoughness.MetallicRoughnessTexture != null) { TextureId textureId = pbrMetallicRoughness.MetallicRoughnessTexture.Index; textureId.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } } MaterialCommonConstant commonConstant = material.CommonConstant; if (commonConstant?.LightmapTexture != null) { TextureId textureId = material.CommonConstant.LightmapTexture.Index; textureId.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } if (material.EmissiveTexture != null) { TextureId textureId = material.EmissiveTexture.Index; material.EmissiveTexture.Index.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } if (material.NormalTexture != null) { TextureId textureId = material.NormalTexture.Index; textureId.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } if (material.OcclusionTexture != null) { TextureId textureId = material.OcclusionTexture.Index; textureId.Id += previousGLTFSizes.PreviousTextureCount; textureId.Root = mergeToRoot; } } } }
private static void MergeAccessorsBufferViewsAndBuffers(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { if (mergeFromRoot.Buffers != null) { if (mergeToRoot.Buffers == null) { mergeToRoot.Buffers = new List <Buffer>(mergeFromRoot.Buffers.Count); } mergeToRoot.Buffers.AddRange(mergeFromRoot.Buffers); } if (mergeFromRoot.BufferViews != null) { if (mergeToRoot.BufferViews == null) { mergeToRoot.BufferViews = new List <BufferView>(mergeFromRoot.BufferViews.Count); } mergeToRoot.BufferViews.AddRange(mergeFromRoot.BufferViews); for (int i = previousGLTFSizes.PreviousBufferViewCount; i < mergeToRoot.BufferViews.Count; ++i) { GLTFId <Buffer> bufferId = mergeToRoot.BufferViews[i].Buffer; bufferId.Id += previousGLTFSizes.PreviousBufferCount; bufferId.Root = mergeToRoot; } } if (mergeFromRoot.Accessors != null) { if (mergeToRoot.Accessors == null) { mergeToRoot.Accessors = new List <Accessor>(mergeFromRoot.Accessors.Count); } mergeToRoot.Accessors.AddRange(mergeFromRoot.Accessors); for (int i = previousGLTFSizes.PreviousAccessorCount; i < mergeToRoot.Accessors.Count; ++i) { Accessor accessor = mergeToRoot.Accessors[i]; if (accessor.BufferView != null) { BufferViewId bufferViewId = accessor.BufferView; bufferViewId.Id += previousGLTFSizes.PreviousBufferViewCount; bufferViewId.Root = mergeToRoot; } AccessorSparse accessorSparse = accessor.Sparse; if (accessorSparse != null) { BufferViewId indicesId = accessorSparse.Indices.BufferView; indicesId.Id += previousGLTFSizes.PreviousBufferViewCount; indicesId.Root = mergeToRoot; BufferViewId valuesId = accessorSparse.Values.BufferView; valuesId.Id += previousGLTFSizes.PreviousBufferViewCount; valuesId.Root = mergeToRoot; } } } }
private static void MergeAccessorsBufferViewsAndBuffers(GLTFRoot mergeToRoot, GLTFRoot mergeFromRoot, PreviousGLTFSizes previousGLTFSizes) { bool isGLB = false; if (mergeFromRoot.Buffers != null) { if (mergeToRoot.Buffers == null) { mergeToRoot.Buffers = new List <GLTFBuffer>(mergeFromRoot.Buffers.Count); } foreach (GLTFBuffer buffer in mergeFromRoot.Buffers) { if (buffer.Uri != null) { mergeToRoot.Buffers.Add(buffer); } else { isGLB = true; // assume glb is a uri is null } } } if (mergeFromRoot.BufferViews != null) { if (mergeToRoot.BufferViews == null) { mergeToRoot.BufferViews = new List <BufferView>(mergeFromRoot.BufferViews.Count); } mergeToRoot.BufferViews.AddRange(mergeFromRoot.BufferViews); for (int i = previousGLTFSizes.PreviousBufferViewCount; i < mergeToRoot.BufferViews.Count; ++i) { GLTFId <GLTFBuffer> bufferId = mergeToRoot.BufferViews[i].Buffer; if (!(isGLB && bufferId.Id == 0)) // if it is pointing a the special glb buffer (index 0 of a glb) then we dont want to adjust the buffer view, otherwise we do { // adjusting bufferview id based on merge amount bufferId.Id += previousGLTFSizes.PreviousBufferCount; bufferId.Root = mergeToRoot; } } } if (mergeFromRoot.Accessors != null) { if (mergeToRoot.Accessors == null) { mergeToRoot.Accessors = new List <Accessor>(mergeFromRoot.Accessors.Count); } mergeToRoot.Accessors.AddRange(mergeFromRoot.Accessors); for (int i = previousGLTFSizes.PreviousAccessorCount; i < mergeToRoot.Accessors.Count; ++i) { Accessor accessor = mergeToRoot.Accessors[i]; if (accessor.BufferView != null) { BufferViewId bufferViewId = accessor.BufferView; bufferViewId.Id += previousGLTFSizes.PreviousBufferViewCount; bufferViewId.Root = mergeToRoot; } AccessorSparse accessorSparse = accessor.Sparse; if (accessorSparse != null) { BufferViewId indicesId = accessorSparse.Indices.BufferView; indicesId.Id += previousGLTFSizes.PreviousBufferViewCount; indicesId.Root = mergeToRoot; BufferViewId valuesId = accessorSparse.Values.BufferView; valuesId.Id += previousGLTFSizes.PreviousBufferViewCount; valuesId.Root = mergeToRoot; } } } }