public static void Load(ImporterContext ctx) { // textures if (ctx.GLTF.textures != null) { ctx.Textures.AddRange(ctx.GLTF.textures.Select((x, i) => new TextureItem(ctx.GLTF, i, ctx.TextureBaseDir))); } foreach (var x in ctx.Textures) { x.Process(ctx.GLTF, ctx.Storage); } // materials if (ctx.CreateMaterial == null) { ctx.CreateMaterial = MaterialIO.CreateMaterialFuncFromShader(new ShaderStore()); } if (ctx.GLTF.materials == null || !ctx.GLTF.materials.Any()) { // no material ctx.Materials.Add(ctx.CreateMaterial(ctx, 0)); } else { for (int i = 0; i < ctx.GLTF.materials.Count; ++i) { var index = i; var material = ctx.CreateMaterial(ctx, index); var originalName = material.name; for (int j = 1; ctx.Materials.Any(x => x.name == material.name); ++j) { material.name = string.Format("{0}({1})", originalName, j); } ctx.Materials.Add(material); } } // meshes if (ctx.GLTF.meshes .SelectMany(x => x.primitives) .Any(x => x.extensions.KHR_draco_mesh_compression != null)) { throw new UniGLTFNotSupportedException("draco is not supported"); } for (int i = 0; i < ctx.GLTF.meshes.Count; ++i) { var meshWithMaterials = ImportMesh(ctx, i); var mesh = meshWithMaterials.Mesh; // mesh name if (string.IsNullOrEmpty(mesh.name)) { mesh.name = string.Format("UniGLTF import#{0}", i); } var originalName = mesh.name; for (int j = 1; ctx.Meshes.Any(x => x.Mesh.name == mesh.name); ++j) { mesh.name = string.Format("{0}({1})", originalName, j); } ctx.Meshes.Add(meshWithMaterials); } // nodes ctx.Nodes.AddRange(ctx.GLTF.nodes.Select(x => ImportNode(x).transform)); var nodes = ctx.Nodes.Select((x, i) => BuildHierarchy(ctx, i)).ToList(); gltfImporter.FixCoordinate(ctx, nodes); // skinning for (int i = 0; i < nodes.Count; ++i) { gltfImporter.SetupSkinning(ctx, nodes, i); } // connect root ctx.Root = new GameObject("_root_"); foreach (var x in ctx.GLTF.rootnodes) { var t = nodes[x].Transform; t.SetParent(ctx.Root.transform, false); } ImportAnimation(ctx); //Debug.LogFormat("Import {0}", ctx.Path); }
public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget = false) { var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]); var bufferIndex = gltf.AddBuffer(bytesBuffer); if (go.transform.childCount == 0) { throw new UniGLTFException("empty root GameObject required"); } var unityNodes = go.transform.Traverse() .Skip(1) // exclude root object for the symmetry with the importer .ToList(); #region Materials and Textures var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList(); var unityTextures = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList(); for (int i = 0; i < unityTextures.Count; ++i) { var texture = unityTextures[i]; TextureIO.ExportTexture(gltf, bufferIndex, texture); } gltf.materials = unityMaterials.Select(x => MaterialIO.ExportMaterial(x, unityTextures)).ToList(); #endregion #region Meshes var unityMeshes = unityNodes .Select(x => new MeshWithRenderer { Mesh = x.GetSharedMesh(), Rendererer = x.GetComponent <Renderer>(), }) .Where(x => { if (x.Mesh == null) { return(false); } if (x.Rendererer.sharedMaterials == null || x.Rendererer.sharedMaterials.Length == 0) { return(false); } return(true); }) .ToList(); ExportMeshes(gltf, bufferIndex, unityMeshes, unityMaterials, useSparseAccessorForMorphTarget); #endregion #region Skins var unitySkins = unityNodes .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x => x != null) .ToList(); gltf.nodes = unityNodes.Select(x => ExportNode(x, unityNodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList(); gltf.scenes = new List <gltfScene> { new gltfScene { nodes = go.transform.GetChildren().Select(x => unityNodes.IndexOf(x)).ToArray(), } }; foreach (var x in unitySkins) { var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray(); var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE); var skin = new glTFSkin { inverseBindMatrices = accessor, joints = x.bones.Select(y => unityNodes.IndexOf(y)).ToArray(), skeleton = unityNodes.IndexOf(x.rootBone), }; var skinIndex = gltf.skins.Count; gltf.skins.Add(skin); foreach (var z in unityNodes.Where(y => y.Has(x))) { var nodeIndex = unityNodes.IndexOf(z); var node = gltf.nodes[nodeIndex]; node.skin = skinIndex; } } #endregion #if UNITY_EDITOR #region Animations var animation = go.GetComponent <Animation>(); if (animation != null) { foreach (AnimationState state in animation) { var animationWithCurve = ExportAnimation(state.clip, go.transform, unityNodes); foreach (var kv in animationWithCurve.SamplerMap) { var sampler = animationWithCurve.Animation.samplers[kv.Key]; var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input); sampler.input = inputAccessorIndex; var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output); sampler.output = outputAccessorIndex; // modify accessors var outputAccessor = gltf.accessors[outputAccessorIndex]; var channel = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key); switch (glTFAnimationTarget.GetElementCount(channel.target.path)) { case 3: outputAccessor.type = "VEC3"; outputAccessor.count /= 3; break; case 4: outputAccessor.type = "VEC4"; outputAccessor.count /= 4; break; default: throw new NotImplementedException(); } } gltf.animations.Add(animationWithCurve.Animation); } } #endregion #endif return(new Exported { Meshes = unityMeshes, Nodes = unityNodes.Select(x => x.transform).ToList(), Materials = unityMaterials, Textures = unityTextures, }); }