mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-21 22:47:19 -05:00
233 lines
9.0 KiB
C#
233 lines
9.0 KiB
C#
using System;
|
|
using System.Linq;
|
|
using UniGLTF;
|
|
using UniGLTF.Utils;
|
|
using UniJSON;
|
|
using UnityEngine;
|
|
|
|
namespace VRM
|
|
{
|
|
public class VRMExporter : gltfExporter
|
|
{
|
|
public const Axes Vrm0xSpecificationInverseAxis = Axes.Z;
|
|
|
|
public static ExportingGltfData Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
|
|
{
|
|
var data = new ExportingGltfData();
|
|
using (var exporter = new VRMExporter(data, configuration, textureSerializer: textureSerializer))
|
|
{
|
|
exporter.Prepare(go);
|
|
exporter.Export();
|
|
}
|
|
return data;
|
|
}
|
|
|
|
public readonly VRM.glTF_VRM_extensions VRM = new glTF_VRM_extensions();
|
|
|
|
public VRMExporter(
|
|
ExportingGltfData data,
|
|
GltfExportSettings exportSettings,
|
|
IAnimationExporter animationExporter = null,
|
|
IMaterialExporter materialExporter = null,
|
|
ITextureSerializer textureSerializer = null
|
|
) : base(
|
|
data,
|
|
exportSettings,
|
|
animationExporter: animationExporter,
|
|
materialExporter: materialExporter ?? VrmMaterialExporterUtility.GetValidVrmMaterialExporter(),
|
|
textureSerializer: textureSerializer
|
|
)
|
|
{
|
|
if (exportSettings == null)
|
|
{
|
|
throw new Exception($"VRM specification requires InverseAxis settings as {Vrm0xSpecificationInverseAxis}");
|
|
}
|
|
if (exportSettings.InverseAxis != Vrm0xSpecificationInverseAxis)
|
|
{
|
|
// migration 用に reverseX を許す
|
|
Debug.LogWarning($"VRM specification requires InverseAxis settings as {Vrm0xSpecificationInverseAxis}");
|
|
}
|
|
|
|
_gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
|
|
}
|
|
|
|
public override void ExportExtensions(ITextureSerializer textureSerializer)
|
|
{
|
|
var getBone = UniHumanoid.Humanoid.Get_GetBoneTransform(Copy);
|
|
|
|
UniHumanoid.AvatarDescription description = null;
|
|
var isCreated = false;
|
|
if (Copy.TryGetComponent<VRMHumanoidDescription>(out var humanoid))
|
|
{
|
|
if (humanoid != null)
|
|
{
|
|
description = humanoid.GetDescription(out isCreated);
|
|
}
|
|
}
|
|
var nodes = Copy.transform.Traverse().Skip(1).ToList();
|
|
{
|
|
if (description != null)
|
|
{
|
|
// use description
|
|
VRM.humanoid.Apply(description, nodes);
|
|
}
|
|
|
|
if (isCreated)
|
|
{
|
|
GameObject.DestroyImmediate(description);
|
|
}
|
|
}
|
|
|
|
// set humanoid bone mapping
|
|
// var avatar = animator.avatar;
|
|
foreach (HumanBodyBones key in CachedEnum.GetValues<HumanBodyBones>())
|
|
{
|
|
if (key == HumanBodyBones.LastBone)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var transform = getBone(key);
|
|
if (transform != null)
|
|
{
|
|
var nodeIndex = nodes.IndexOf(transform);
|
|
if (nodeIndex < 0)
|
|
{
|
|
Debug.LogError($"ヒューマンボーンが export 対象に含まれていない?", transform);
|
|
}
|
|
else
|
|
{
|
|
VRM.humanoid.SetNodeIndex(key, nodeIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// morph
|
|
if (Copy.TryGetComponent<VRMBlendShapeProxy>(out var master))
|
|
{
|
|
var avatar = master.BlendShapeAvatar;
|
|
if (avatar != null)
|
|
{
|
|
foreach (var x in avatar.Clips)
|
|
{
|
|
if (x == null)
|
|
{
|
|
continue;
|
|
}
|
|
VRM.blendShapeMaster.Add(x, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
// secondary
|
|
VRMSpringUtility.ExportSecondary(Copy.transform, Nodes,
|
|
x => VRM.secondaryAnimation.colliderGroups.Add(x),
|
|
x => VRM.secondaryAnimation.boneGroups.Add(x)
|
|
);
|
|
|
|
#pragma warning disable 0618
|
|
// meta(obsolete)
|
|
{
|
|
if (Copy.TryGetComponent<VRMMetaInformation>(out var meta))
|
|
{
|
|
VRM.meta.author = meta.Author;
|
|
VRM.meta.contactInformation = meta.ContactInformation;
|
|
VRM.meta.title = meta.Title;
|
|
if (meta.Thumbnail != null)
|
|
{
|
|
VRM.meta.texture = TextureExporter.RegisterExportingAsSRgb(meta.Thumbnail, needsAlpha: true);
|
|
}
|
|
|
|
VRM.meta.licenseType = meta.LicenseType;
|
|
VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
|
|
VRM.meta.reference = meta.Reference;
|
|
}
|
|
}
|
|
#pragma warning restore 0618
|
|
|
|
// meta
|
|
{
|
|
if (Copy.TryGetComponent<VRMMeta>(out var _meta) && _meta.Meta != null)
|
|
{
|
|
var meta = _meta.Meta;
|
|
|
|
// info
|
|
VRM.meta.version = meta.Version;
|
|
VRM.meta.author = meta.Author;
|
|
VRM.meta.contactInformation = meta.ContactInformation;
|
|
VRM.meta.reference = meta.Reference;
|
|
VRM.meta.title = meta.Title;
|
|
if (meta.Thumbnail != null)
|
|
{
|
|
VRM.meta.texture = TextureExporter.RegisterExportingAsSRgb(meta.Thumbnail, needsAlpha: true);
|
|
}
|
|
|
|
// ussage permission
|
|
VRM.meta.allowedUser = meta.AllowedUser;
|
|
VRM.meta.violentUssage = meta.ViolentUssage;
|
|
VRM.meta.sexualUssage = meta.SexualUssage;
|
|
VRM.meta.commercialUssage = meta.CommercialUssage;
|
|
VRM.meta.otherPermissionUrl = meta.OtherPermissionUrl;
|
|
|
|
// distribution license
|
|
VRM.meta.licenseType = meta.LicenseType;
|
|
if (meta.LicenseType == LicenseType.Other)
|
|
{
|
|
VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// firstPerson
|
|
if (Copy.TryGetComponent<VRMFirstPerson>(out var firstPerson))
|
|
{
|
|
if (firstPerson.FirstPersonBone != null)
|
|
{
|
|
VRM.firstPerson.firstPersonBone = Nodes.IndexOf(firstPerson.FirstPersonBone);
|
|
VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset;
|
|
VRM.firstPerson.meshAnnotations = firstPerson.Renderers
|
|
.Select(x => new glTF_VRM_MeshAnnotation
|
|
{
|
|
mesh = Meshes.IndexOf(x.SharedMesh),
|
|
firstPersonFlag = x.FirstPersonFlag.ToString(),
|
|
})
|
|
.Where(x => x.mesh != -1)
|
|
.ToList();
|
|
}
|
|
|
|
// lookAt
|
|
if (Copy.TryGetComponent<VRMLookAtHead>(out var lookAtHead))
|
|
{
|
|
if (Copy.TryGetComponent<VRMLookAtBoneApplyer>(out var boneApplyer))
|
|
{
|
|
VRM.firstPerson.lookAtType = LookAtType.Bone;
|
|
VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner);
|
|
VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter);
|
|
VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown);
|
|
VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp);
|
|
}
|
|
else if (Copy.TryGetComponent<VRMLookAtBlendShapeApplyer>(out var blendShapeApplyer))
|
|
{
|
|
VRM.firstPerson.lookAtType = LookAtType.BlendShape;
|
|
VRM.firstPerson.lookAtHorizontalOuter.Apply(blendShapeApplyer.Horizontal);
|
|
VRM.firstPerson.lookAtVerticalDown.Apply(blendShapeApplyer.VerticalDown);
|
|
VRM.firstPerson.lookAtVerticalUp.Apply(blendShapeApplyer.VerticalUp);
|
|
}
|
|
}
|
|
}
|
|
|
|
// materials
|
|
foreach (var m in Materials)
|
|
{
|
|
VRM.materialProperties.Add(BuiltInVrmExtensionMaterialPropertyExporter.ExportMaterial(m, TextureExporter));
|
|
}
|
|
|
|
// Serialize VRM
|
|
var f = new JsonFormatter();
|
|
VRMSerializer.Serialize(f, VRM);
|
|
var bytes = f.GetStoreBytes();
|
|
glTFExtensionExport.GetOrCreate(ref _gltf.extensions).Add("VRM", bytes);
|
|
}
|
|
}
|
|
}
|