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); }
public static CreateMaterialFunc GetMaterialFunc(List <glTF_VRM_Material> materials) { var CreateDefault = gltfImporter.CreateMaterialFuncFromShader(Shader.Find("VRM/UnlitTexture")); var CreateZWrite = gltfImporter.CreateMaterialFuncFromShader(Shader.Find("VRM/UnlitTransparentZWrite")); CreateMaterialFunc fallback = (ctx, i) => { var vrm = ctx.GLTF as glTF_VRM; if (vrm != null && vrm.materials[i].name.ToLower().Contains("zwrite")) { // 一応。不要かも Debug.Log("fallback to VRM/UnlitTransparentZWrite"); return(CreateZWrite(ctx, i)); } else { Debug.Log("fallback to VRM/UnlitTexture"); return(CreateDefault(ctx, i)); } }; if (materials == null && materials.Count == 0) { return(fallback); } return((ctx, i) => { var item = materials[i]; var shaderName = item.shader; var shader = Shader.Find(shaderName); if (shader == null) { if (VRM_SHADER_NAMES.Contains(shaderName)) { Debug.LogErrorFormat("shader {0} not found. set Assets/VRM/Shaders/VRMShaders to Edit - project setting - Graphics - preloaded shaders", shaderName); return fallback(ctx, i); } else { Debug.LogWarningFormat("unknown shader {0}.", shaderName); return fallback(ctx, i); } } else { var material = new Material(shader); material.name = item.name; material.renderQueue = item.renderQueue; foreach (var kv in item.floatProperties) { material.SetFloat(kv.Key, kv.Value); } foreach (var kv in item.vectorProperties) { if (item.textureProperties.ContainsKey(kv.Key)) { // texture offset & scale material.SetTextureOffset(kv.Key, new Vector2(kv.Value[0], kv.Value[1])); material.SetTextureScale(kv.Key, new Vector2(kv.Value[2], kv.Value[3])); } else { // vector4 var v = new Vector4(kv.Value[0], kv.Value[1], kv.Value[2], kv.Value[3]); material.SetVector(kv.Key, v); } } foreach (var kv in item.textureProperties) { material.SetTexture(kv.Key, ctx.Textures[kv.Value].Texture); } foreach (var kv in item.keywordMap) { if (kv.Value) { material.EnableKeyword(kv.Key); } else { material.DisableKeyword(kv.Key); } } foreach (var kv in item.tagMap) { material.SetOverrideTag(kv.Key, kv.Value); } return material; } }); }
/// StandardShader vaiables /// /// _Color /// _MainTex /// _Cutoff /// _Glossiness /// _Metallic /// _MetallicGlossMap /// _BumpScale /// _BumpMap /// _Parallax /// _ParallaxMap /// _OcclusionStrength /// _OcclusionMap /// _EmissionColor /// _EmissionMap /// _DetailMask /// _DetailAlbedoMap /// _DetailNormalMapScale /// _DetailNormalMap /// _UVSec /// _EmissionScaleUI /// _EmissionColorUI /// _Mode /// _SrcBlend /// _DstBlend /// _ZWrite public static CreateMaterialFunc CreateMaterialFuncFromShader(Shader shader) { if (shader == null) { return(null); } CreateMaterialFunc func = (ctx, i, x, textures) => { var material = new Material(shader); if (string.IsNullOrEmpty(x.name)) { material.name = string.Format("material:{0:00}", i); } else { material.name = x.name; } if (x.pbrMetallicRoughness != null) { if (x.pbrMetallicRoughness.baseColorFactor != null) { var color = x.pbrMetallicRoughness.baseColorFactor; material.color = new Color(color[0], color[1], color[2], color[3]); } if (x.pbrMetallicRoughness.baseColorTexture.index != -1) { var texture = textures[x.pbrMetallicRoughness.baseColorTexture.index]; material.mainTexture = texture.Texture; } if (x.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { var texture = textures[x.pbrMetallicRoughness.metallicRoughnessTexture.index]; material.SetTexture("_MetallicGlossMap", texture.GetMetallicRoughnessConverted(ctx)); } } if (x.normalTexture.index != -1) { var texture = textures[x.normalTexture.index]; material.SetTexture("_BumpMap", texture.Texture); } if (x.occlusionTexture.index != -1) { var texture = textures[x.occlusionTexture.index]; material.SetTexture("_OcclusionMap", texture.Texture); } if (x.emissiveFactor != null) { material.EnableKeyword("_EMISSION"); material.SetColor("_EmissionColor", new Color(x.emissiveFactor[0], x.emissiveFactor[1], x.emissiveFactor[2])); } if (x.emissiveTexture.index != -1) { material.EnableKeyword("_EMISSION"); var texture = textures[x.emissiveTexture.index]; material.SetTexture("_EmissionMap", texture.Texture); } return(material); }; return(func); }