protected virtual void BuildMeshAttributes(MeshPrimitive primitive, int meshID, int primitiveIndex) { if (_assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes.Count == 0) { Dictionary <string, AttributeAccessor> attributeAccessors = new Dictionary <string, AttributeAccessor>(primitive.Attributes.Count + 1); foreach (var attributePair in primitive.Attributes) { AttributeAccessor AttributeAccessor = new AttributeAccessor() { AccessorId = attributePair.Value, Buffer = _assetCache.BufferCache[attributePair.Value.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[attributePair.Key] = AttributeAccessor; } if (primitive.Indices != null) { AttributeAccessor indexBuilder = new AttributeAccessor() { AccessorId = primitive.Indices, Buffer = _assetCache.BufferCache[primitive.Indices.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[SemanticProperties.INDICES] = indexBuilder; } GLTFHelpers.BuildMeshAttributes(ref attributeAccessors); _assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes = attributeAccessors; } }
// todo undo #if !WINDOWS_UWP IEnumerator Start() { var fullPath0 = Application.streamingAssetsPath + Path.DirectorySeparatorChar + asset0Path; ILoader loader0 = new FileLoader(URIHelper.GetDirectoryName(fullPath0)); var fullPath1 = Application.streamingAssetsPath + Path.DirectorySeparatorChar + asset1Path; ILoader loader1 = new FileLoader(URIHelper.GetDirectoryName(fullPath1)); yield return(loader0.LoadStream(Path.GetFileName(asset0Path))); var asset0Stream = loader0.LoadedStream; var asset0Root = GLTFParser.ParseJson(asset0Stream); yield return(loader1.LoadStream(Path.GetFileName(asset1Path))); var asset1Stream = loader1.LoadedStream; var asset1Root = GLTFParser.ParseJson(asset1Stream); string newPath = "../../" + URIHelper.GetDirectoryName(asset0Path); int previousBufferCount = asset1Root.Buffers.Count; int previousImageCount = asset1Root.Images.Count; int previousSceneCounter = asset1Root.Scenes.Count; GLTFHelpers.MergeGLTF(asset1Root, asset0Root); for (int i = previousBufferCount; i < asset1Root.Buffers.Count; ++i) { GLTF.Schema.Buffer buffer = asset1Root.Buffers[i]; if (!URIHelper.IsBase64Uri(buffer.Uri)) { buffer.Uri = newPath + buffer.Uri; } } for (int i = previousImageCount; i < asset1Root.Images.Count; ++i) { Image image = asset1Root.Images[i]; if (!URIHelper.IsBase64Uri(image.Uri)) { image.Uri = newPath + image.Uri; } } foreach (NodeId node in asset1Root.Scenes[asset0Root.Scene.Id + previousSceneCounter].Nodes) { node.Value.Translation.X += 5f; asset1Root.Scene.Value.Nodes.Add(node); } GLTFSceneImporter importer = new GLTFSceneImporter( asset1Root, loader1 ); importer.MaximumLod = MaximumLod; yield return(importer.LoadScene(-1, Multithreaded)); }
public void MergeNodes() { Assert.IsTrue(File.Exists(GLTF_BOOMBOX_PATH)); Assert.IsTrue(File.Exists(GLTF_LANTERN_PATH)); FileStream gltfBoomBoxStream = File.OpenRead(GLTF_BOOMBOX_PATH); GLTFRoot boomBoxRoot; GLTFParser.ParseJson(gltfBoomBoxStream, out boomBoxRoot); FileStream gltfLanternStream = File.OpenRead(GLTF_LANTERN_PATH); GLTFRoot lanternRoot; GLTFParser.ParseJson(gltfLanternStream, out lanternRoot); GLTFRoot boomBoxCopy = new GLTFRoot(boomBoxRoot); GLTFHelpers.MergeGLTF(boomBoxRoot, lanternRoot); Assert.AreNotEqual(boomBoxRoot.Nodes, boomBoxCopy.Nodes); Assert.AreNotEqual(boomBoxCopy.Accessors.Count, boomBoxRoot.Accessors.Count); Assert.AreNotEqual(boomBoxCopy.Meshes.Count, boomBoxRoot.Meshes.Count); Assert.AreNotEqual(boomBoxCopy.Nodes.Count, boomBoxRoot.Nodes.Count); Assert.AreNotEqual(boomBoxCopy.BufferViews.Count, boomBoxRoot.BufferViews.Count); Assert.AreNotEqual(boomBoxCopy.Buffers.Count, boomBoxRoot.Buffers.Count); Assert.AreNotEqual(boomBoxCopy.Images.Count, boomBoxRoot.Images.Count); Assert.AreNotEqual(boomBoxCopy.Materials.Count, boomBoxRoot.Materials.Count); Assert.AreNotEqual(boomBoxCopy.Textures.Count, boomBoxRoot.Textures.Count); Assert.AreNotEqual(boomBoxCopy.Scenes.Count, boomBoxRoot.Scenes.Count); Assert.AreEqual(boomBoxCopy.Accessors.Count + lanternRoot.Accessors.Count, boomBoxRoot.Accessors.Count); Assert.AreEqual(boomBoxCopy.Meshes.Count + lanternRoot.Meshes.Count, boomBoxRoot.Meshes.Count); Assert.AreEqual(boomBoxCopy.Nodes.Count + lanternRoot.Nodes.Count, boomBoxRoot.Nodes.Count); Assert.AreEqual(boomBoxCopy.BufferViews.Count + lanternRoot.BufferViews.Count, boomBoxRoot.BufferViews.Count); Assert.AreEqual(boomBoxCopy.Buffers.Count + lanternRoot.Buffers.Count, boomBoxRoot.Buffers.Count); Assert.AreEqual(boomBoxCopy.Images.Count + lanternRoot.Images.Count, boomBoxRoot.Images.Count); Assert.AreEqual(boomBoxCopy.Materials.Count + lanternRoot.Materials.Count, boomBoxRoot.Materials.Count); Assert.AreEqual(boomBoxCopy.Textures.Count + lanternRoot.Textures.Count, boomBoxRoot.Textures.Count); Assert.AreEqual(boomBoxCopy.Scenes.Count + lanternRoot.Scenes.Count, boomBoxRoot.Scenes.Count); // test no throw StringWriter stringWriter = new StringWriter(); boomBoxRoot.Serialize(stringWriter); }
protected virtual void BuildMeshAttributes(MeshPrimitive primitive, int meshID, int primitiveIndex) { if (_assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes.Count == 0) { Dictionary <string, AttributeAccessor> attributeAccessors = new Dictionary <string, AttributeAccessor>(primitive.Attributes.Count + 1); foreach (var attributePair in primitive.Attributes) { AttributeAccessor AttributeAccessor = new AttributeAccessor() { AccessorId = attributePair.Value, Buffer = _assetCache.BufferCache[attributePair.Value.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[attributePair.Key] = AttributeAccessor; } if (primitive.Indices != null) { AttributeAccessor indexBuilder = new AttributeAccessor() { AccessorId = primitive.Indices, Buffer = _assetCache.BufferCache[primitive.Indices.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[SemanticProperties.INDICES] = indexBuilder; } GLTFHelpers.BuildMeshAttributes(ref attributeAccessors); // Flip vectors and triangles to the Unity coordinate system. if (attributeAccessors.ContainsKey(SemanticProperties.POSITION)) { NumericArray resultArray = attributeAccessors[SemanticProperties.POSITION].AccessorContent; resultArray.AsVertices = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsVertices); attributeAccessors[SemanticProperties.POSITION].AccessorContent = resultArray; } if (attributeAccessors.ContainsKey(SemanticProperties.INDICES)) { NumericArray resultArray = attributeAccessors[SemanticProperties.INDICES].AccessorContent; resultArray.AsTriangles = GLTFUnityHelpers.FlipFaces(resultArray.AsTriangles); attributeAccessors[SemanticProperties.INDICES].AccessorContent = resultArray; } if (attributeAccessors.ContainsKey(SemanticProperties.NORMAL)) { NumericArray resultArray = attributeAccessors[SemanticProperties.NORMAL].AccessorContent; resultArray.AsNormals = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsNormals); attributeAccessors[SemanticProperties.NORMAL].AccessorContent = resultArray; } // TexCoord goes from 0 to 3 to match GLTFHelpers.BuildMeshAttributes for (int i = 0; i < 4; i++) { if (attributeAccessors.ContainsKey(SemanticProperties.TexCoord(i))) { NumericArray resultArray = attributeAccessors[SemanticProperties.TexCoord(i)].AccessorContent; resultArray.AsTexcoords = GLTFUnityHelpers.FlipTexCoordArrayV(resultArray.AsTexcoords); attributeAccessors[SemanticProperties.TexCoord(i)].AccessorContent = resultArray; } } if (attributeAccessors.ContainsKey(SemanticProperties.TANGENT)) { NumericArray resultArray = attributeAccessors[SemanticProperties.TANGENT].AccessorContent; resultArray.AsTangents = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsTangents); attributeAccessors[SemanticProperties.TANGENT].AccessorContent = resultArray; } _assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes = attributeAccessors; } }
private void addGLTFChannelDataToClip(GLTF.Schema.AnimationChannel channel, AnimationClip clip) { int animatedNodeIndex = channel.Target.Node.Id; if (!_importedObjects.ContainsKey(animatedNodeIndex)) { Debug.Log("Node '" + animatedNodeIndex + "' found for animation, aborting."); } Transform animatedNode = _importedObjects[animatedNodeIndex].transform; string nodePath = AnimationUtility.CalculateTransformPath(animatedNode, _sceneObject.transform); bool isStepInterpolation = channel.Sampler.Value.Interpolation != InterpolationType.LINEAR; byte[] timeBufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] times = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Input.Value, timeBufferData); if (channel.Target.Path == GLTFAnimationChannelPath.translation || channel.Target.Path == GLTFAnimationChannelPath.scale) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; GLTF.Math.Vector3[] keyValues = GLTFHelpers.ParseVector3Keyframes(channel.Sampler.Value.Output.Value, bufferData); if (keyValues == null) { return; } Vector3[] values = keyValues.ToUnityVector3(); AnimationCurve[] vector3Curves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation, channel.Target.Path == GLTFAnimationChannelPath.translation); if (channel.Target.Path == GLTFAnimationChannelPath.translation) { GLTFUtils.addTranslationCurvesToClip(vector3Curves, nodePath, ref clip); } else { GLTFUtils.addScaleCurvesToClip(vector3Curves, nodePath, ref clip); } } else if (channel.Target.Path == GLTFAnimationChannelPath.rotation) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; Vector4[] values = GLTFHelpers.ParseRotationKeyframes(channel.Sampler.Value.Output.Value, bufferData).ToUnityVector4(); AnimationCurve[] rotationCurves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation); GLTFUtils.addRotationCurvesToClip(rotationCurves, nodePath, ref clip); } else if (channel.Target.Path == GLTFAnimationChannelPath.weights) { List <string> morphTargets = new List <string>(); int meshIndex = _root.Nodes[animatedNodeIndex].Mesh.Id; for (int i = 0; i < _root.Meshes[meshIndex].Primitives[0].Targets.Count; ++i) { morphTargets.Add(GLTFUtils.buildBlendShapeName(meshIndex, i)); } byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] values = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Output.Value, bufferData); AnimationCurve[] morphCurves = GLTFUtils.buildMorphAnimationCurves(times, values, morphTargets.Count); GLTFUtils.addMorphAnimationCurvesToClip(morphCurves, nodePath, morphTargets.ToArray(), ref clip); } else { Debug.Log("Unsupported animation channel target: " + channel.Target.Path); } }
// todo undo #if !WINDOWS_UWP private async Task Start() { var fullPath0 = Application.streamingAssetsPath + Path.DirectorySeparatorChar + asset0Path; IDataLoader loader0 = new FileLoader(URIHelper.GetDirectoryName(fullPath0)); var fullPath1 = Application.streamingAssetsPath + Path.DirectorySeparatorChar + asset1Path; IDataLoader loader1 = new FileLoader(URIHelper.GetDirectoryName(fullPath1)); var asset0Stream = await loader0.LoadStreamAsync(Path.GetFileName(asset0Path)); GLTFRoot asset0Root; GLTFParser.ParseJson(asset0Stream, out asset0Root); var asset1Stream = await loader1.LoadStreamAsync(Path.GetFileName(asset1Path)); GLTFRoot asset1Root; GLTFParser.ParseJson(asset1Stream, out asset1Root); string newPath = "../../" + URIHelper.GetDirectoryName(asset0Path); int previousBufferCount = asset1Root.Buffers.Count; int previousImageCount = asset1Root.Images.Count; int previousSceneCounter = asset1Root.Scenes.Count; GLTFHelpers.MergeGLTF(asset1Root, asset0Root); for (int i = previousBufferCount; i < asset1Root.Buffers.Count; ++i) { GLTF.Schema.GLTFBuffer buffer = asset1Root.Buffers[i]; if (!URIHelper.IsBase64Uri(buffer.Uri)) { buffer.Uri = newPath + buffer.Uri; } } for (int i = previousImageCount; i < asset1Root.Images.Count; ++i) { GLTFImage image = asset1Root.Images[i]; if (!URIHelper.IsBase64Uri(image.Uri)) { image.Uri = newPath + image.Uri; } } foreach (NodeId node in asset1Root.Scenes[asset0Root.Scene.Id + previousSceneCounter].Nodes) { node.Value.Translation.X += 5f; asset1Root.Scene.Value.Nodes.Add(node); } GLTFSceneImporter importer = new GLTFSceneImporter( asset1Root, null, new ImportOptions { DataLoader = loader1, AsyncCoroutineHelper = gameObject.AddComponent <AsyncCoroutineHelper>() }); importer.MaximumLod = MaximumLod; importer.IsMultithreaded = Multithreaded; await importer.LoadSceneAsync(-1); }