public void LoadAsset(string prefabName, Action <GameObject> onGameObjectLoaded, Action <Exception> onError) { var callBackPair = new OnLoadCallback { onSuccess = onGameObjectLoaded, onFail = onError }; if (!mapPrefabToLoadCallbacks.ContainsKey(prefabName)) { mapPrefabToLoadCallbacks.Add(prefabName, new List <OnLoadCallback> { callBackPair }); } else { mapPrefabToLoadCallbacks[prefabName].Add(callBackPair); } if (!inFlightAssetRequests.Contains(prefabName)) { inFlightAssetRequests.Add(prefabName); assetBundleLoader.LoadAsset(prefabName, loadedAssetBundle => OnAssetBundleLoaded(loadedAssetBundle, prefabName), ex => OnAssetLoadFailure(prefabName, ex)); } }
public static GameObject Import(IImporterContext ctx, string json, ArraySegment <Byte> glbBinChunk, OnLoadCallback callback = null, GetBlendShapeName getBlendShapeName = null, CreateMaterialFunc createMaterial = null ) { if (getBlendShapeName == null) { getBlendShapeName = DefaultGetBlendShapeName; } // exclude not gltf-2.0 var parsed = json.ParseAsJson(); try { if (parsed["asset"]["version"].GetString() != "2.0") { Debug.LogWarningFormat("is not gltf-2.0: {0}", ctx.Path); return(null); } } catch (Exception) { Debug.LogWarningFormat("{0}: fail to parse json", ctx.Path); return(null); } // parse json glTF gltf = null; try { gltf = JsonUtility.FromJson <glTF>(json); } catch (Exception) { Debug.LogWarningFormat("{0}: fail to parse json", ctx.Path); return(null); } if (gltf == null) { Debug.LogWarningFormat("{0}: fail to parse json", ctx.Path); return(null); } if (gltf.asset.version != "2.0") { Debug.LogWarningFormat("unknown gltf version {0}", gltf.asset.version); return(null); } gltf.baseDir = Path.GetDirectoryName(ctx.Path); //Debug.LogFormat("{0}: {1}", ctx.Path, gltf); foreach (var buffer in gltf.buffers) { buffer.OpenStorage(gltf.baseDir, glbBinChunk); } // textures var textures = ImportTextures(gltf) .Select(x => { var samplerIndex = gltf.textures[x.TextureIndex].sampler; var sampler = gltf.samplers[samplerIndex]; if (x.Texture == null) { Debug.LogWarningFormat("May be import order, not yet texture is not imported. Later, manualy reimport {0}", ctx.Path); } else { SetSampler(x.Texture, sampler); if (!x.IsAsset) { ctx.AddObjectToAsset(x.Texture.name, x.Texture); } } return(x); }) .ToArray(); if (createMaterial == null) { createMaterial = CreateMaterialFuncFromShader(Shader.Find("Standard")); } // materials List <Material> materials = new List <Material>(); if (gltf.materials == null || !gltf.materials.Any()) { materials.Add(createMaterial(ctx, 0, null, textures)); } else { for (int i = 0; i < gltf.materials.Count; ++i) { Material mat = null; // [Maquette Code] if (Maquette.Unity.MqAddonUtility.NeedsMaquetteMaterial(gltf.materials[i].name)) { string materialName = gltf.materials[i].name; materialName = materialName.Replace(" (Instance)", ""); mat = Maquette.Unity.MqAddonUtility.CreateMaquetteMaterial(materialName); if (gltf.materials[i].pbrMetallicRoughness.baseColorTexture != null) { int baseTextureIndex = gltf.materials[i].pbrMetallicRoughness.baseColorTexture.index; if (baseTextureIndex >= 0 && baseTextureIndex < textures.Length) { var texture = textures[baseTextureIndex]; mat.mainTexture = texture.Texture; } } } else { mat = createMaterial(ctx, i, gltf.materials[i], textures); } materials.Add(mat); } } foreach (var material in materials) { if (material != null) { ctx.AddObjectToAsset(material.name, material); } } // meshes var meshes = gltf.meshes.Select((x, i) => { var meshWithMaterials = ImportMesh(gltf, i, x, materials, getBlendShapeName); var mesh = meshWithMaterials.Mesh; if (string.IsNullOrEmpty(mesh.name)) { mesh.name = string.Format("UniGLTF import#{0}", i); } ctx.AddObjectToAsset(mesh.name, mesh); return(meshWithMaterials); }).ToArray(); // nodes var _nodes = gltf.nodes.Select(x => ImportNode(x)).ToArray(); var nodes = _nodes.Select((go, i) => { if (string.IsNullOrEmpty(go.name)) { go.name = string.Format("node{0:000}", i); } var nodeWithSkin = new TransformWithSkin { Transform = go.transform, }; var node = gltf.nodes[i]; // // build hierachy // if (node.children != null) { foreach (var child in node.children) { _nodes[child].transform.SetParent(_nodes[i].transform, false // node has local transform ); } } // // attach mesh // if (node.mesh != -1) { var mesh = meshes[node.mesh]; if (mesh.Mesh.blendShapeCount == 0 && node.skin == -1) { // without blendshape and bone skinning var filter = go.AddComponent <MeshFilter>(); filter.sharedMesh = mesh.Mesh; var renderer = go.AddComponent <MeshRenderer>(); renderer.sharedMaterials = mesh.Materials; } else { var renderer = go.AddComponent <SkinnedMeshRenderer>(); if (node.skin != -1) { nodeWithSkin.SkinIndex = node.skin; } renderer.sharedMesh = mesh.Mesh; renderer.sharedMaterials = mesh.Materials; } } return(nodeWithSkin); }).ToArray(); // // fix node's coordinate. z-back to z-forward // var globalTransformMap = nodes.ToDictionary(x => x.Transform, x => new PosRot { Position = x.Transform.position, Rotation = x.Transform.rotation, }); foreach (var x in gltf.rootnodes) { // fix nodes coordinate // reverse Z in global var t = nodes[x].Transform; //t.SetParent(root.transform, false); foreach (var transform in t.Traverse()) { var g = globalTransformMap[transform]; transform.position = g.Position.ReverseZ(); transform.rotation = g.Rotation.ReverseZ(); } } // skinning foreach (var x in nodes) { var skinnedMeshRenderer = x.Transform.GetComponent <SkinnedMeshRenderer>(); if (skinnedMeshRenderer != null) { var mesh = skinnedMeshRenderer.sharedMesh; if (x.SkinIndex.HasValue) { if (mesh == null) { throw new Exception(); } if (skinnedMeshRenderer == null) { throw new Exception(); } if (x.SkinIndex.Value < gltf.skins.Count) { var skin = gltf.skins[x.SkinIndex.Value]; skinnedMeshRenderer.sharedMesh = null; var joints = skin.joints.Select(y => nodes[y].Transform).ToArray(); skinnedMeshRenderer.bones = joints; //skinnedMeshRenderer.rootBone = nodes[skin.skeleton].Transform; if (skin.inverseBindMatrices != -1) { // BlendShape only ? #if false // https://docs.unity3d.com/ScriptReference/Mesh-bindposes.html var hipsParent = nodes[0].Transform; var calculatedBindPoses = joints.Select(y => y.worldToLocalMatrix * hipsParent.localToWorldMatrix).ToArray(); mesh.bindposes = calculatedBindPoses; #else var bindPoses = gltf.GetArrayFromAccessor <Matrix4x4>(skin.inverseBindMatrices) .Select(y => y.ReverseZ()) .ToArray() ; mesh.bindposes = bindPoses; #endif } skinnedMeshRenderer.sharedMesh = mesh; } } } } var root = new GameObject("_root_"); ctx.SetMainGameObject("root", root); foreach (var x in gltf.rootnodes) { // fix nodes coordinate // reverse Z in global var t = nodes[x].Transform; t.SetParent(root.transform, false); } // animation if (gltf.animations != null && gltf.animations.Any()) { var clip = new AnimationClip(); clip.name = ANIMATION_NAME; clip.ClearCurves(); ImportAnimation(root.transform, clip, gltf.animations, nodes.Select(x => x.Transform).ToArray(), gltf); clip.legacy = true; clip.name = "legacy"; clip.wrapMode = WrapMode.Loop; var animation = root.AddComponent <Animation>(); animation.clip = clip; ctx.AddObjectToAsset(ANIMATION_NAME, clip); } if (callback != null) { callback(ctx, json, nodes.Select(x => x.Transform).ToArray(), meshes.Select(x => x.Mesh).ToList() ); } Debug.LogFormat("Import {0}", ctx.Path); return(root); }