public static glTF Export(GameObject go, string path = null, Action <glTF_VRM> callback = null) { var gltf = new glTF_VRM(); gltf.asset.generator = string.Format("UniVRM-{0}.{1}", VRMVersion.MAJOR, VRMVersion.MINOR); using (var exporter = new VRMExporter(gltf) { #if VRM_EXPORTER_USE_SPARSE // experimental UseSparseAccessorForBlendShape = true #endif }) { _Export(gltf, exporter, go); if (callback != null) { callback(gltf); } if (!string.IsNullOrEmpty(path)) { exporter.WriteTo(path); } } return(gltf); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param> static void Export(string path, VRMExportSettings settings, List <GameObject> destroy) { var target = settings.Source; // 常にコピーする。シーンを変化させない target = GameObject.Instantiate(target); destroy.Add(target); // 正規化 if (settings.PoseFreeze) { // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用 target = BoneNormalizer.Execute(target, settings.ForceTPose, false); destroy.Add(target); } // 元のBlendShapeClipに変更を加えないように複製 var proxy = target.GetComponent <VRMBlendShapeProxy>(); var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip); proxy.BlendShapeAvatar = copyBlendShapeAvatar; // BlendShape削減 if (settings.ReduceBlendshape) { foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>()) { // 未使用のBlendShapeを間引く ReplaceMesh(target, smr, copyBlendShapeAvatar); } } // 出力 { var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target, new VRMExporterConfiguration { UseSparseAccessorForBlendShape = settings.UseSparseAccessor, ExportOnlyBlendShapePosition = settings.OnlyBlendshapePosition, RemoveVertexColor = settings.RemoveVertexColor }); vrm.extensions.VRM.meta.title = settings.Title; vrm.extensions.VRM.meta.version = settings.Version; vrm.extensions.VRM.meta.author = settings.Author; vrm.extensions.VRM.meta.contactInformation = settings.ContactInformation; vrm.extensions.VRM.meta.reference = settings.Reference; var bytes = vrm.ToGlbBytes(settings.UseExperimentalExporter ? SerializerTypes.Generated : SerializerTypes.UniJSON); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); } if (path.StartsWithUnityAssetPath()) { // 出力ファイルのインポートを発動 AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }
public void ImportExportTest() { var path = UniGLTF.UnityPath.FromUnityPath("Models/Alicia_vrm-0.40/AliciaSolid_vrm-0.40.vrm"); var context = new VRMImporterContext(path); context.ParseGlb(File.ReadAllBytes(path.FullPath)); VRMImporter.LoadFromBytes(context); using (new ActionDisposer(() => { GameObject.DestroyImmediate(context.Root); })) { var importJson = JsonParser.Parse(context.Json); importJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION); importJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION); importJson.SetValue("/scene", 0); importJson.SetValue("/materials/*/doubleSided", false); //importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0); //importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 }); importJson.SetValue("/accessors/*/normalized", false); importJson.RemoveValue("/nodes/*/extras"); importJson.SetValue("/bufferViews/12/byteStride", 4); importJson.SetValue("/bufferViews/13/byteStride", 4); importJson.SetValue("/bufferViews/14/byteStride", 4); importJson.SetValue("/bufferViews/15/byteStride", 4); importJson.SetValue("/bufferViews/22/byteStride", 4); importJson.SetValue("/bufferViews/29/byteStride", 4); importJson.SetValue("/bufferViews/45/byteStride", 4); importJson.SetValue("/bufferViews/46/byteStride", 4); importJson.SetValue("/bufferViews/47/byteStride", 4); importJson.SetValue("/bufferViews/201/byteStride", 4); importJson.SetValue("/bufferViews/202/byteStride", 4); importJson.SetValue("/bufferViews/203/byteStride", 4); importJson.SetValue("/bufferViews/204/byteStride", 4); importJson.SetValue("/bufferViews/211/byteStride", 4); importJson.SetValue("/bufferViews/212/byteStride", 4); importJson.SetValue("/bufferViews/213/byteStride", 4); importJson.SetValue("/bufferViews/214/byteStride", 4); importJson.SetValue("/bufferViews/215/byteStride", 4); importJson.SetValue("/bufferViews/243/byteStride", 4); importJson.SetValue("/bufferViews/247/byteStride", 64); importJson.SetValue("/bufferViews/248/byteStride", 64); importJson.SetValue("/bufferViews/249/byteStride", 64); importJson.SetValue("/bufferViews/250/byteStride", 64); importJson.SetValue("/bufferViews/251/byteStride", 64); importJson.SetValue("/bufferViews/252/byteStride", 64); importJson.SetValue("/bufferViews/253/byteStride", 64); var vrm = VRMExporter.Export(context.Root); var exportJson = JsonParser.Parse(vrm.ToJson()); foreach (var kv in importJson.Diff(exportJson)) { Debug.Log(kv); } Assert.AreEqual(importJson, exportJson); } }
public static ExportingGltfData Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer) { var data = new ExportingGltfData(); using (var exporter = new VRMExporter(data, configuration)) { exporter.Prepare(go); exporter.Export(textureSerializer); } return data; }
public static glTF Export(MeshExportSettings configuration, GameObject go, Func <Texture, bool> useAsset, GetBytesWithMimeFromTexture2D getTextureBytes) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf)) { exporter.Prepare(go); exporter.Export(configuration, useAsset, getTextureBytes); } return(gltf); }
public static glTF Export(MeshExportSettings configuration, GameObject go, Func <Texture, bool> useAsset) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf)) { exporter.Prepare(go); exporter.Export(configuration, useAsset); } return(gltf); }
public static glTF Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf)) { exporter.Prepare(go); exporter.Export(configuration, textureSerializer); } return(gltf); }
public static glTF Export(MeshExportSettings configuration, GameObject go) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf)) { exporter.Prepare(go); exporter.Export(configuration); } return(gltf); }
public new static glTF Export(GameObject go) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf) { #if VRM_EXPORTER_USE_SPARSE // experimental UseSparseAccessorForBlendShape=true #endif }) { _Export(gltf, exporter, go); } return gltf; }
public static glTF Export(GameObject go, VRMExporterConfiguration configuration) { var gltf = new glTF(); using (var exporter = new VRMExporter(gltf) { UseSparseAccessorForBlendShape = configuration.UseSparseAccessorForBlendShape, ExportOnlyBlendShapePosition = configuration.ExportOnlyBlendShapePosition, RemoveVertexColor = configuration.RemoveVertexColor, }) { _Export(gltf, exporter, go); } return(gltf); }
void OnWizardCreate() { // save dialog Debug.LogFormat("OnWizardCreate: {0}", Dir); var path = EditorUtility.SaveFilePanel( "Save vrm", Dir, Target.name + EXTENSION, EXTENSION.Substring(1)); if (string.IsNullOrEmpty(path)) { return; } Dir = Path.GetDirectoryName(path); // export var target = Target.gameObject; if (PoseFreeze) { Undo.RecordObjects(Target.transform.Traverse().ToArray(), "before normalize"); var map = new Dictionary <Transform, Transform>(); target = VRM.BoneNormalizer.Execute(Target.gameObject, map, ForceTPose); VRMHumanoidNorimalizerMenu.CopyVRMComponents(Target.gameObject, target, map); Undo.PerformUndo(); } var sw = System.Diagnostics.Stopwatch.StartNew(); VRMExporter.Export(target, path, gltf => { gltf.extensions.VRM.meta.title = Title; gltf.extensions.VRM.meta.author = Author; }); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); if (Target.gameObject != target) { GameObject.DestroyImmediate(target); } if (path.StartsWithUnityAssetPath()) { AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }
public void ExportDividedMeshTest() { var path = AliciaPath; var loaded = Load(File.ReadAllBytes(path), path); var exported = VRMExporter.Export(new UniGLTF.MeshExportSettings { DivideVertexBuffer = true, // test this ExportOnlyBlendShapePosition = true, ExportTangents = false, UseSparseAccessorForMorphTarget = true, }, loaded, new EditorTextureSerializer()); var bytes = exported.ToGlbBytes(); var divided = Load(bytes, path); var src = GetMeshes(loaded).ToArray(); var div = GetMeshes(divided).ToArray(); Assert.AreEqual(src[0].triangles.Length, div[0].triangles.Length); }
public static glTF Export(GameObject go, string path = null, Action <glTF_VRM> callback = null) { var gltf = new glTF_VRM(); gltf.asset.generator = string.Format("UniVRM-{0}.{1}", VRMVersion.MAJOR, VRMVersion.MINOR); using (var exporter = new VRMExporter(gltf)) { _Export(gltf, exporter, go); if (callback != null) { callback(gltf); } if (!string.IsNullOrEmpty(path)) { exporter.WriteTo(path); } } return(gltf); }
void Export(string path, List <GameObject> destroy) { var target = Source; if (IsPrefab(target)) { using (new RecordDisposer(Source.transform.Traverse().ToArray(), "before normalize")) { target = GameObject.Instantiate(target); destroy.Add(target); } } if (PoseFreeze) { using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize")) { var normalized = BoneNormalizer.Execute(target, ForceTPose, false); CopyVRMComponents(target, normalized.Root, normalized.BoneMap); target = normalized.Root; destroy.Add(target); } } { var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target); vrm.extensions.VRM.meta.title = Title; vrm.extensions.VRM.meta.author = Author; var bytes = vrm.ToGlbBytes(); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); } if (path.StartsWithUnityAssetPath()) { AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }
public void VrmTestModelsTests() { var env = System.Environment.GetEnvironmentVariable("VRM_TEST_MODELS"); if (string.IsNullOrEmpty(env)) { return; } var root = new DirectoryInfo(env); if (!root.Exists) { return; } foreach (var gltf in EnumerateGltfFiles(root)) { // import var go = Load(gltf, root); try { // export var vrm = VRMExporter.Export(new UniGLTF.GltfExportSettings(), go, new EditorTextureSerializer()); // re import if (vrm != null) { Load(gltf, root, vrm.ToGlbBytes()); } } finally { GameObject.DestroyImmediate(go); } } }
void Export(string path, List <GameObject> destroy) { var target = Source; if (IsPrefab(target)) { using (new RecordDisposer(Source.transform.Traverse().ToArray(), "before normalize")) { target = GameObject.Instantiate(target); destroy.Add(target); } } if (PoseFreeze) { using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize")) { var normalized = BoneNormalizer.Execute(target, ForceTPose, false); CopyVRMComponents(target, normalized.Root, normalized.BoneMap); target = normalized.Root; destroy.Add(target); } } // remove unused blendShape if (ReduceBlendshapeSize) { var proxy = target.GetComponent <VRMBlendShapeProxy>(); // 元のBlendShapeClipに変更を加えないように複製 var copyBlendShapeAvatar = GameObject.Instantiate(proxy.BlendShapeAvatar); var copyBlendShapClips = new List <BlendShapeClip>(); foreach (var clip in proxy.BlendShapeAvatar.Clips) { copyBlendShapClips.Add(GameObject.Instantiate(clip)); } var skinnedMeshRenderers = target.GetComponentsInChildren <SkinnedMeshRenderer>(); var names = new Dictionary <int, string>(); var vs = new Dictionary <int, Vector3[]>(); var ns = new Dictionary <int, Vector3[]>(); var ts = new Dictionary <int, Vector3[]>(); foreach (SkinnedMeshRenderer smr in skinnedMeshRenderers) { Mesh mesh = smr.sharedMesh; if (mesh == null) { continue; } if (mesh.blendShapeCount == 0) { continue; } var copyMesh = mesh.Copy(true); var vCount = copyMesh.vertexCount; names.Clear(); vs.Clear(); ns.Clear(); ts.Clear(); var usedBlendshapeIndexArray = copyBlendShapClips .SelectMany(clip => clip.Values) .Where(val => target.transform.Find(val.RelativePath) == smr.transform) .Select(val => val.Index) .Distinct() .ToArray(); foreach (var i in usedBlendshapeIndexArray) { var name = copyMesh.GetBlendShapeName(i); var vertices = new Vector3[vCount]; var normals = new Vector3[vCount]; var tangents = new Vector3[vCount]; copyMesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents); names.Add(i, name); vs.Add(i, vertices); ns.Add(i, normals); ts.Add(i, tangents); } copyMesh.ClearBlendShapes(); foreach (var i in usedBlendshapeIndexArray) { copyMesh.AddBlendShapeFrame(names[i], 100f, vs[i], ns[i], ts[i]); } var indexMapper = usedBlendshapeIndexArray .Select((x, i) => new { x, i }) .ToDictionary(pair => pair.x, pair => pair.i); foreach (var clip in copyBlendShapClips) { for (var i = 0; i < clip.Values.Length; ++i) { var value = clip.Values[i]; if (target.transform.Find(value.RelativePath) != smr.transform) { continue; } value.Index = indexMapper[value.Index]; clip.Values[i] = value; } } copyBlendShapeAvatar.Clips = copyBlendShapClips; proxy.BlendShapeAvatar = copyBlendShapeAvatar; smr.sharedMesh = copyMesh; } } { var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target, ReduceBlendshapeSize); vrm.extensions.VRM.meta.title = Title; vrm.extensions.VRM.meta.version = Version; vrm.extensions.VRM.meta.author = Author; vrm.extensions.VRM.meta.contactInformation = ContactInformation; vrm.extensions.VRM.meta.reference = Reference; var bytes = vrm.ToGlbBytes(UseExperimentalExporter?SerializerTypes.Generated:SerializerTypes.UniJSON); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); } if (IsPrefab(Source)) { #if UNITY_2018_3_OR_NEWER PrefabUtility.RevertPrefabInstance(Source, InteractionMode.AutomatedAction); #else PrefabUtility.RevertPrefabInstance(target); #endif } if (path.StartsWithUnityAssetPath()) { AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param> static byte[] Export(GameObject exportRoot, VRMMetaObject meta, VRMExportSettings settings, List <GameObject> destroy) { var target = exportRoot; // 常にコピーする。シーンを変化させない target = GameObject.Instantiate(target); destroy.Add(target); var metaBehaviour = target.GetComponent <VRMMeta>(); if (metaBehaviour == null) { metaBehaviour = target.AddComponent <VRMMeta>(); metaBehaviour.Meta = meta; } if (metaBehaviour.Meta == null) { // 来ないはず throw new Exception("meta required"); } { // copy元 var animator = exportRoot.GetComponent <Animator>(); var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>(); // copy先 var afterTransforms = target.GetComponentsInChildren <Transform>(); // copy先のhumanoidBoneのリストを得る var bones = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones)); var humanTransforms = bones .Where(x => x != HumanBodyBones.LastBone) .Select(x => animator.GetBoneTransform(x)) .Where(x => x != null) .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る .ToArray(); var nameCount = target.GetComponentsInChildren <Transform>() .GroupBy(x => x.name) .ToDictionary(x => x.Key, x => x.Count()); foreach (var t in target.GetComponentsInChildren <Transform>()) { if (humanTransforms.Contains(t)) { // keep original name continue; } if (nameCount[t.name] > 1) { // 重複するボーン名をリネームする ForceUniqueName(t, nameCount); } } } // 正規化 if (settings.PoseFreeze) { // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用 target = VRMBoneNormalizer.Execute(target, settings.ForceTPose); destroy.Add(target); } var fp = target.GetComponent <VRMFirstPerson>(); // 元のBlendShapeClipに変更を加えないように複製 var proxy = target.GetComponent <VRMBlendShapeProxy>(); if (proxy != null) { var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip); proxy.BlendShapeAvatar = copyBlendShapeAvatar; // BlendShape削減 if (settings.ReduceBlendshape) { foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>()) { // 未使用のBlendShapeを間引く ReplaceMesh(target, smr, copyBlendShapeAvatar); } } } // 出力 var sw = System.Diagnostics.Stopwatch.StartNew(); var data = new UniGLTF.ExportingGltfData(); var gltfExportSettings = settings.GltfExportSettings; using (var exporter = new VRMExporter(data, gltfExportSettings, settings.KeepAnimation ? new EditorAnimationExporter() : null)) { exporter.Prepare(target); exporter.Export(new EditorTextureSerializer()); } var bytes = data.ToGlbBytes(); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); return(bytes); }
public static void _Export(glTF_VRM gltf, VRMExporter exporter, GameObject go) { exporter.Prepare(go); exporter.Export(); // avatar var animator = go.GetComponent <Animator>(); if (animator != null) { var humanoid = go.GetComponent <VRMHumanoidDescription>(); UniHumanoid.AvatarDescription description = null; var nodes = go.transform.Traverse().Skip(1).ToList(); { var isCreated = false; if (humanoid != null) { description = humanoid.GetDescription(out isCreated); } if (description != null) { // use description gltf.extensions.VRM.humanoid.Apply(description, nodes); } if (isCreated) { GameObject.DestroyImmediate(description); } } { // set humanoid bone mapping var avatar = animator.avatar; foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones))) { if (key == HumanBodyBones.LastBone) { break; } var transform = animator.GetBoneTransform(key); if (transform != null) { gltf.extensions.VRM.humanoid.SetNodeIndex(key, nodes.IndexOf(transform)); } } } } // morph var master = go.GetComponent <VRMBlendShapeProxy>(); if (master != null) { var avatar = master.BlendShapeAvatar; if (avatar != null) { var meshes = exporter.Meshes; foreach (var x in avatar.Clips) { gltf.extensions.VRM.blendShapeMaster.Add(x, exporter.Copy.transform, meshes); } } } // secondary var secondary = exporter.Copy.transform.Find("secondary"); if (secondary == null) { secondary = exporter.Copy.transform; } var colliders = new List <VRMSpringBoneColliderGroup>(); foreach (var vrmColliderGroup in exporter.Copy.transform.Traverse().Select(x => x.GetComponent <VRMSpringBoneColliderGroup>()).Where(x => x != null)) { colliders.Add(vrmColliderGroup); var colliderGroup = new glTF_VRM_SecondaryAnimationColliderGroup { node = exporter.Nodes.IndexOf(vrmColliderGroup.transform) }; colliderGroup.colliders = vrmColliderGroup.Colliders.Select(x => { return(new glTF_VRM_SecondaryAnimationCollider { offset = x.Offset, radius = x.Radius, }); }).ToList(); gltf.extensions.VRM.secondaryAnimation.colliderGroups.Add(colliderGroup); } foreach (var spring in secondary.GetComponents <VRMSpringBone>()) { gltf.extensions.VRM.secondaryAnimation.boneGroups.Add(new glTF_VRM_SecondaryAnimationGroup { comment = spring.m_comment, center = exporter.Nodes.IndexOf(spring.m_center), dragForce = spring.m_dragForce, gravityDir = spring.m_gravityDir, gravityPower = spring.m_gravityPower, stiffiness = spring.m_stiffnessForce, hitRadius = spring.m_hitRadius, colliderGroups = spring.ColliderGroups .Select(x => { var index = colliders.IndexOf(x); if (index == -1) { throw new IndexOutOfRangeException(); } return(index); }) .ToArray(), bones = spring.RootBones.Select(x => exporter.Nodes.IndexOf(x)).ToArray(), }); } // meta(obsolete) { var meta = exporter.Copy.GetComponent <VRMMetaInformation>(); if (meta != null) { gltf.extensions.VRM.meta.author = meta.Author; gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation; gltf.extensions.VRM.meta.title = meta.Title; if (meta.Thumbnail != null) { gltf.extensions.VRM.meta.texture = gltfExporter.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail); } gltf.extensions.VRM.meta.licenseType = meta.LicenseType; gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl; gltf.extensions.VRM.meta.reference = meta.Reference; } } // meta { var _meta = exporter.Copy.GetComponent <VRMMeta>(); if (_meta != null && _meta.Meta != null) { var meta = _meta.Meta; // info gltf.extensions.VRM.meta.version = meta.Version; gltf.extensions.VRM.meta.author = meta.Author; gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation; gltf.extensions.VRM.meta.reference = meta.Reference; gltf.extensions.VRM.meta.title = meta.Title; if (meta.Thumbnail != null) { gltf.extensions.VRM.meta.texture = gltfExporter.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail); } // ussage pemission gltf.extensions.VRM.meta.allowedUser = meta.AllowedUser; gltf.extensions.VRM.meta.violentUssage = meta.ViolentUssage; gltf.extensions.VRM.meta.sexualUssage = meta.SexualUssage; gltf.extensions.VRM.meta.commercialUssage = meta.CommercialUssage; gltf.extensions.VRM.meta.otherPermissionUrl = meta.OtherPermissionUrl; // distribution license gltf.extensions.VRM.meta.licenseType = meta.LicenseType; if (meta.LicenseType == LicenseType.Other) { gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl; } } } // firstPerson var firstPerson = exporter.Copy.GetComponent <VRMFirstPerson>(); if (firstPerson != null) { if (firstPerson.FirstPersonBone != null) { gltf.extensions.VRM.firstPerson.firstPersonBone = exporter.Nodes.IndexOf(firstPerson.FirstPersonBone); gltf.extensions.VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset; gltf.extensions.VRM.firstPerson.meshAnnotations = firstPerson.Renderers.Select(x => new glTF_VRM_MeshAnnotation { mesh = exporter.Meshes.IndexOf(x.SharedMesh), firstPersonFlag = x.FirstPersonFlag.ToString(), }).ToList(); } // lookAt { var lookAtHead = exporter.Copy.GetComponent <VRMLookAtHead>(); var lookAt = exporter.Copy.GetComponent <VRMLookAt>(); if (lookAtHead != null) { var boneApplyer = exporter.Copy.GetComponent <VRMLookAtBoneApplyer>(); var blendShapeApplyer = exporter.Copy.GetComponent <VRMLookAtBlendShapeApplyer>(); if (boneApplyer != null) { gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.Bone; gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner); gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp); } else if (blendShapeApplyer != null) { gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.BlendShape; gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(blendShapeApplyer.Horizontal); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(blendShapeApplyer.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(blendShapeApplyer.VerticalUp); } } else if (lookAt != null) { gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(lookAt.HorizontalInner); gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(lookAt.HorizontalOuter); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(lookAt.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(lookAt.VerticalUp); } } } // materials foreach (var m in exporter.Materials) { gltf.extensions.VRM.materialProperties.Add(glTF_VRM_Material.CreateFromMaterial(m, exporter.Textures)); } }
public static void _Export(glTF gltf, VRMExporter exporter, GameObject go) { exporter.Prepare(go); exporter.Export(); // avatar var animator = go.GetComponent <Animator>(); if (animator != null) { var humanoid = go.GetComponent <VRMHumanoidDescription>(); UniHumanoid.AvatarDescription description = null; var nodes = go.transform.Traverse().Skip(1).ToList(); { var isCreated = false; if (humanoid != null) { description = humanoid.GetDescription(out isCreated); } if (description != null) { // use description gltf.extensions.VRM.humanoid.Apply(description, nodes); } if (isCreated) { GameObject.DestroyImmediate(description); } } { // set humanoid bone mapping var avatar = animator.avatar; foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones))) { if (key == HumanBodyBones.LastBone) { break; } var transform = animator.GetBoneTransform(key); if (transform != null) { gltf.extensions.VRM.humanoid.SetNodeIndex(key, nodes.IndexOf(transform)); } } } } // morph var master = go.GetComponent <VRMBlendShapeProxy>(); if (master != null) { var avatar = master.BlendShapeAvatar; if (avatar != null) { var meshes = exporter.Meshes; foreach (var x in avatar.Clips) { gltf.extensions.VRM.blendShapeMaster.Add(x, exporter.Copy.transform, meshes); } } } // secondary VRMSpringUtility.ExportSecondary(exporter.Copy.transform, exporter.Nodes, x => gltf.extensions.VRM.secondaryAnimation.colliderGroups.Add(x), x => gltf.extensions.VRM.secondaryAnimation.boneGroups.Add(x) ); // meta(obsolete) { var meta = exporter.Copy.GetComponent <VRMMetaInformation>(); if (meta != null) { gltf.extensions.VRM.meta.author = meta.Author; gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation; gltf.extensions.VRM.meta.title = meta.Title; if (meta.Thumbnail != null) { gltf.extensions.VRM.meta.texture = TextureIO.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail, false); } gltf.extensions.VRM.meta.licenseType = meta.LicenseType; gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl; gltf.extensions.VRM.meta.reference = meta.Reference; } } // meta { var _meta = exporter.Copy.GetComponent <VRMMeta>(); if (_meta != null && _meta.Meta != null) { var meta = _meta.Meta; // info gltf.extensions.VRM.meta.version = meta.Version; gltf.extensions.VRM.meta.author = meta.Author; gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation; gltf.extensions.VRM.meta.reference = meta.Reference; gltf.extensions.VRM.meta.title = meta.Title; if (meta.Thumbnail != null) { gltf.extensions.VRM.meta.texture = TextureIO.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail, false); } // ussage pemission gltf.extensions.VRM.meta.allowedUser = meta.AllowedUser; gltf.extensions.VRM.meta.violentUssage = meta.ViolentUssage; gltf.extensions.VRM.meta.sexualUssage = meta.SexualUssage; gltf.extensions.VRM.meta.commercialUssage = meta.CommercialUssage; gltf.extensions.VRM.meta.otherPermissionUrl = meta.OtherPermissionUrl; // distribution license gltf.extensions.VRM.meta.licenseType = meta.LicenseType; if (meta.LicenseType == LicenseType.Other) { gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl; } } } // firstPerson var firstPerson = exporter.Copy.GetComponent <VRMFirstPerson>(); if (firstPerson != null) { if (firstPerson.FirstPersonBone != null) { gltf.extensions.VRM.firstPerson.firstPersonBone = exporter.Nodes.IndexOf(firstPerson.FirstPersonBone); gltf.extensions.VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset; gltf.extensions.VRM.firstPerson.meshAnnotations = firstPerson.Renderers.Select(x => new glTF_VRM_MeshAnnotation { mesh = exporter.Meshes.IndexOf(x.SharedMesh), firstPersonFlag = x.FirstPersonFlag.ToString(), }).ToList(); } // lookAt { var lookAtHead = exporter.Copy.GetComponent <VRMLookAtHead>(); var lookAt = exporter.Copy.GetComponent <VRMLookAt>(); if (lookAtHead != null) { var boneApplyer = exporter.Copy.GetComponent <VRMLookAtBoneApplyer>(); var blendShapeApplyer = exporter.Copy.GetComponent <VRMLookAtBlendShapeApplyer>(); if (boneApplyer != null) { gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.Bone; gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner); gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp); } else if (blendShapeApplyer != null) { gltf.extensions.VRM.firstPerson.lookAtType = LookAtType.BlendShape; gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(blendShapeApplyer.Horizontal); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(blendShapeApplyer.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(blendShapeApplyer.VerticalUp); } } else if (lookAt != null) { gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(lookAt.HorizontalInner); gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(lookAt.HorizontalOuter); gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(lookAt.VerticalDown); gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(lookAt.VerticalUp); } } } // materials foreach (var m in exporter.Materials) { gltf.extensions.VRM.materialProperties.Add(glTF_VRM_Material.CreateFromMaterial(m, exporter.Textures)); } }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param> static void Export(string path, GameObject exportRoot, VRMMetaObject meta, VRMExportSettings settings, IReadOnlyList <MeshUtility.MeshExportInfo> info, List <GameObject> destroy) { var target = exportRoot; // 常にコピーする。シーンを変化させない target = GameObject.Instantiate(target); destroy.Add(target); var metaBehaviour = target.GetComponent <VRMMeta>(); if (metaBehaviour == null) { metaBehaviour = target.AddComponent <VRMMeta>(); metaBehaviour.Meta = meta; } if (metaBehaviour.Meta == null) { // 来ないはず throw new Exception("meta required"); } { // copy元 var animator = exportRoot.GetComponent <Animator>(); var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>(); // copy先 var afterTransforms = target.GetComponentsInChildren <Transform>(); // copy先のhumanoidBoneのリストを得る var bones = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones)); var humanTransforms = bones .Where(x => x != HumanBodyBones.LastBone) .Select(x => animator.GetBoneTransform(x)) .Where(x => x != null) .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る .ToArray(); var nameCount = target.GetComponentsInChildren <Transform>() .GroupBy(x => x.name) .ToDictionary(x => x.Key, x => x.Count()); foreach (var t in target.GetComponentsInChildren <Transform>()) { if (humanTransforms.Contains(t)) { // keep original name continue; } if (nameCount[t.name] > 1) { // 重複するボーン名をリネームする ForceUniqueName(t, nameCount); } } } // 正規化 if (settings.PoseFreeze) { // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用 target = VRMBoneNormalizer.Execute(target, settings.ForceTPose, false); destroy.Add(target); } // 元のBlendShapeClipに変更を加えないように複製 var proxy = target.GetComponent <VRMBlendShapeProxy>(); if (proxy != null) { var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip); proxy.BlendShapeAvatar = copyBlendShapeAvatar; // BlendShape削減 if (settings.ReduceBlendshape) { foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>()) { // 未使用のBlendShapeを間引く ReplaceMesh(target, smr, copyBlendShapeAvatar); } } } // 出力 var sw = System.Diagnostics.Stopwatch.StartNew(); var gltf = new UniGLTF.glTF(); using (var exporter = new VRMExporter(gltf)) { exporter.Prepare(target); exporter.Export(settings.MeshExportSettings); } var bytes = gltf.ToGlbBytes(); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); if (path.StartsWithUnityAssetPath()) { // 出力ファイルのインポートを発動 AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param> static void Export(string path, GameObject exportRoot, VRMExportSettings settings, List <GameObject> destroy) { var target = exportRoot; // 常にコピーする。シーンを変化させない target = GameObject.Instantiate(target); destroy.Add(target); { // copy元 var animator = exportRoot.GetComponent <Animator>(); var beforeTransforms = exportRoot.GetComponentsInChildren <Transform>(); // copy先 var afterTransforms = target.GetComponentsInChildren <Transform>(); // copy先のhumanoidBoneのリストを得る var bones = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones)); var humanTransforms = bones .Where(x => x != HumanBodyBones.LastBone) .Select(x => animator.GetBoneTransform(x)) .Where(x => x != null) .Select(x => afterTransforms[Array.IndexOf(beforeTransforms, x)]) // copy 先を得る .ToArray(); var nameCount = target.GetComponentsInChildren <Transform>() .GroupBy(x => x.name) .ToDictionary(x => x.Key, x => x.Count()); foreach (var t in target.GetComponentsInChildren <Transform>()) { if (humanTransforms.Contains(t)) { // keep original name continue; } if (nameCount[t.name] > 1) { // 重複するボーン名をリネームする ForceUniqueName(t, nameCount); } } } // 正規化 if (settings.PoseFreeze) { // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用 target = VRMBoneNormalizer.Execute(target, settings.ForceTPose, false); destroy.Add(target); } // 元のBlendShapeClipに変更を加えないように複製 var proxy = target.GetComponent <VRMBlendShapeProxy>(); if (proxy != null) { var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar, settings.ReduceBlendshapeClip); proxy.BlendShapeAvatar = copyBlendShapeAvatar; // BlendShape削減 if (settings.ReduceBlendshape) { foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren <SkinnedMeshRenderer>()) { // 未使用のBlendShapeを間引く ReplaceMesh(target, smr, copyBlendShapeAvatar); } } } // 出力 { var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target, new VRMExporterConfiguration { UseSparseAccessorForBlendShape = settings.UseSparseAccessor, ExportOnlyBlendShapePosition = settings.OnlyBlendshapePosition, RemoveVertexColor = settings.RemoveVertexColor }); // vrm.extensions.VRM.meta.title = settings.Title; // vrm.extensions.VRM.meta.version = settings.Version; // vrm.extensions.VRM.meta.author = settings.Author; // vrm.extensions.VRM.meta.contactInformation = settings.ContactInformation; // vrm.extensions.VRM.meta.reference = settings.Reference; var bytes = vrm.ToGlbBytes(settings.UseExperimentalExporter ? SerializerTypes.Generated : SerializerTypes.UniJSON); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); } if (path.StartsWithUnityAssetPath()) { // 出力ファイルのインポートを発動 AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } }