mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-23 19:15:07 -05:00
Merge pull request #2722 from ousttrue/feature/springbonelimit_serializer
[SpringBoneLimit] Importer / Exporter
This commit is contained in:
@@ -86,6 +86,14 @@ namespace UniVRM10
|
||||
$"{Vrm10SpecDir}/VRMC_springBone_extended_collider-1.0/schema/VRMC_springBone_extended_collider.schema.json",
|
||||
$"{Vrm10FormatGeneratedDir}/SpringBoneExtendedCollider"
|
||||
),
|
||||
|
||||
// VRMC_springBone_limit-1.0
|
||||
// (experimental)
|
||||
// https://github.com/0b5vr/vrm-specification/tree/springBone-limit
|
||||
new GenerateInfo(
|
||||
$"{Vrm10SpecDir}/VRMC_springBone_limit-1.0/schema/VRMC_springBone_limit.schema.json",
|
||||
$"{Vrm10FormatGeneratedDir}/SpringBoneLimit"
|
||||
),
|
||||
};
|
||||
|
||||
foreach (var arg in args)
|
||||
|
||||
8
Assets/VRM10/Runtime/Format/SpringBoneLimit.meta
Normal file
8
Assets/VRM10/Runtime/Format/SpringBoneLimit.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b6c07a37ce7d2348beb488d3c2fad01
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
236
Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs
Normal file
236
Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
// This file is generated from JsonSchema. Don't modify this source code.
|
||||
using UniJSON;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.Extensions.VRMC_springBone_limit {
|
||||
|
||||
public static class GltfDeserializer
|
||||
{
|
||||
public static readonly Utf8String ExtensionNameUtf8 = Utf8String.From(VRMC_springBone_limit.ExtensionName);
|
||||
|
||||
public static bool TryGet(UniGLTF.glTFExtension src, out VRMC_springBone_limit extension)
|
||||
{
|
||||
if(src is UniGLTF.glTFExtensionImport extensions)
|
||||
{
|
||||
foreach(var kv in extensions.ObjectItems())
|
||||
{
|
||||
if(kv.Key.GetUtf8String() == ExtensionNameUtf8)
|
||||
{
|
||||
extension = Deserialize(kv.Value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static VRMC_springBone_limit Deserialize(JsonNode parsed)
|
||||
{
|
||||
var value = new VRMC_springBone_limit();
|
||||
|
||||
foreach(var kv in parsed.ObjectItems())
|
||||
{
|
||||
var key = kv.Key.GetString();
|
||||
|
||||
if(key=="extensions"){
|
||||
value.Extensions = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="extras"){
|
||||
value.Extras = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="specVersion"){
|
||||
value.SpecVersion = kv.Value.GetString();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="limit"){
|
||||
value.Limit = Deserialize_Limit(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Limit Deserialize_Limit(JsonNode parsed)
|
||||
{
|
||||
var value = new Limit();
|
||||
|
||||
foreach(var kv in parsed.ObjectItems())
|
||||
{
|
||||
var key = kv.Key.GetString();
|
||||
|
||||
if(key=="extensions"){
|
||||
value.Extensions = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="extras"){
|
||||
value.Extras = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="cone"){
|
||||
value.Cone = __limit_Deserialize_Cone(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="hinge"){
|
||||
value.Hinge = __limit_Deserialize_Hinge(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="spherical"){
|
||||
value.Spherical = __limit_Deserialize_Spherical(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static ConeLimit __limit_Deserialize_Cone(JsonNode parsed)
|
||||
{
|
||||
var value = new ConeLimit();
|
||||
|
||||
foreach(var kv in parsed.ObjectItems())
|
||||
{
|
||||
var key = kv.Key.GetString();
|
||||
|
||||
if(key=="extensions"){
|
||||
value.Extensions = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="extras"){
|
||||
value.Extras = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="angle"){
|
||||
value.Angle = kv.Value.GetSingle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="rotation"){
|
||||
value.Rotation = __limit__cone_Deserialize_Rotation(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float[] __limit__cone_Deserialize_Rotation(JsonNode parsed)
|
||||
{
|
||||
var value = new float[parsed.GetArrayCount()];
|
||||
int i=0;
|
||||
foreach(var x in parsed.ArrayItems())
|
||||
{
|
||||
value[i++] = x.GetSingle();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HingeLimit __limit_Deserialize_Hinge(JsonNode parsed)
|
||||
{
|
||||
var value = new HingeLimit();
|
||||
|
||||
foreach(var kv in parsed.ObjectItems())
|
||||
{
|
||||
var key = kv.Key.GetString();
|
||||
|
||||
if(key=="extensions"){
|
||||
value.Extensions = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="extras"){
|
||||
value.Extras = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="angle"){
|
||||
value.Angle = kv.Value.GetSingle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="rotation"){
|
||||
value.Rotation = __limit__hinge_Deserialize_Rotation(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float[] __limit__hinge_Deserialize_Rotation(JsonNode parsed)
|
||||
{
|
||||
var value = new float[parsed.GetArrayCount()];
|
||||
int i=0;
|
||||
foreach(var x in parsed.ArrayItems())
|
||||
{
|
||||
value[i++] = x.GetSingle();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static SphericalLimit __limit_Deserialize_Spherical(JsonNode parsed)
|
||||
{
|
||||
var value = new SphericalLimit();
|
||||
|
||||
foreach(var kv in parsed.ObjectItems())
|
||||
{
|
||||
var key = kv.Key.GetString();
|
||||
|
||||
if(key=="extensions"){
|
||||
value.Extensions = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="extras"){
|
||||
value.Extras = new glTFExtensionImport(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="phi"){
|
||||
value.Phi = kv.Value.GetSingle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="theta"){
|
||||
value.Theta = kv.Value.GetSingle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key=="rotation"){
|
||||
value.Rotation = __limit__spherical_Deserialize_Rotation(kv.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float[] __limit__spherical_Deserialize_Rotation(JsonNode parsed)
|
||||
{
|
||||
var value = new float[parsed.GetArrayCount()];
|
||||
int i=0;
|
||||
foreach(var x in parsed.ArrayItems())
|
||||
{
|
||||
value[i++] = x.GetSingle();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} // GltfDeserializer
|
||||
} // UniGLTF
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91feea663efc32c40bc07c67bdc8b868
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
91
Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs
Normal file
91
Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
// This file is generated from JsonSchema. Don't modify this source code.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace UniGLTF.Extensions.VRMC_springBone_limit
|
||||
{
|
||||
|
||||
public class ConeLimit
|
||||
{
|
||||
// Dictionary object with extension-specific objects.
|
||||
public object Extensions;
|
||||
|
||||
// Application-specific data.
|
||||
public object Extras;
|
||||
|
||||
// The angle of the cone limit in radians. If the angle is set to π or greater, the angle will be interpreted as π by the implementation. When the angle is set to π, the cone shape becomes a sphere.
|
||||
public float? Angle;
|
||||
|
||||
// The rotation from the default orientation of the cone limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar.
|
||||
public float[] Rotation;
|
||||
}
|
||||
|
||||
public class HingeLimit
|
||||
{
|
||||
// Dictionary object with extension-specific objects.
|
||||
public object Extensions;
|
||||
|
||||
// Application-specific data.
|
||||
public object Extras;
|
||||
|
||||
// The angle of the hinge limit in radians. If the angle is set to π or greater, the angle will be interpreted as π by the implementation. When the angle is set to π, the hinge shape becomes a full disc.
|
||||
public float? Angle;
|
||||
|
||||
// The rotation from the default orientation of the hinge limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar.
|
||||
public float[] Rotation;
|
||||
}
|
||||
|
||||
public class SphericalLimit
|
||||
{
|
||||
// Dictionary object with extension-specific objects.
|
||||
public object Extensions;
|
||||
|
||||
// Application-specific data.
|
||||
public object Extras;
|
||||
|
||||
// The phi angle of the spherical limit in radians. If the phi angle is set to π or greater, the angle will be interpreted as π by the implementation.
|
||||
public float? Phi;
|
||||
|
||||
// The theta angle of the spherical limit in radians. If the theta angle is set to π/2 or greater, the angle will be interpreted as π/2 by the implementation.
|
||||
public float? Theta;
|
||||
|
||||
// The rotation from the default orientation of the spherical limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar.
|
||||
public float[] Rotation;
|
||||
}
|
||||
|
||||
public class Limit
|
||||
{
|
||||
// Dictionary object with extension-specific objects.
|
||||
public object Extensions;
|
||||
|
||||
// Application-specific data.
|
||||
public object Extras;
|
||||
|
||||
// A limit that restricts the orientation of the spring in a cone shape.
|
||||
public ConeLimit Cone;
|
||||
|
||||
// A limit that restricts the orientation of the spring in a hinge shape.
|
||||
public HingeLimit Hinge;
|
||||
|
||||
// A limit that restricts the orientation of the spring in a spherical coordinate shape.
|
||||
public SphericalLimit Spherical;
|
||||
}
|
||||
|
||||
public class VRMC_springBone_limit
|
||||
{
|
||||
public const string ExtensionName = "VRMC_springBone_limit";
|
||||
|
||||
// Dictionary object with extension-specific objects.
|
||||
public object Extensions;
|
||||
|
||||
// Application-specific data.
|
||||
public object Extras;
|
||||
|
||||
// Specification version of VRMC_springBone_limit.
|
||||
public string SpecVersion;
|
||||
|
||||
// Describes a limit apply to the spring. Either cone, hinge, or spherical must be present.
|
||||
public Limit Limit;
|
||||
}
|
||||
}
|
||||
11
Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta
Normal file
11
Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40be47ec456e1cb46a3ce8a3ecb70910
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
218
Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs
Normal file
218
Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
// This file is generated from JsonSchema. Don't modify this source code.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UniJSON;
|
||||
|
||||
namespace UniGLTF.Extensions.VRMC_springBone_limit {
|
||||
|
||||
static public class GltfSerializer
|
||||
{
|
||||
|
||||
public static void SerializeTo(ref UniGLTF.glTFExtension dst, VRMC_springBone_limit extension)
|
||||
{
|
||||
if (dst is glTFExtensionImport)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
if (!(dst is glTFExtensionExport extensions))
|
||||
{
|
||||
extensions = new glTFExtensionExport();
|
||||
dst = extensions;
|
||||
}
|
||||
|
||||
var f = new JsonFormatter();
|
||||
Serialize(f, extension);
|
||||
extensions.Add(VRMC_springBone_limit.ExtensionName, f.GetStoreBytes());
|
||||
}
|
||||
|
||||
|
||||
public static void Serialize(JsonFormatter f, VRMC_springBone_limit value)
|
||||
{
|
||||
f.BeginMap();
|
||||
|
||||
|
||||
if(value.Extensions!=null){
|
||||
f.Key("extensions");
|
||||
(value.Extensions as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Extras!=null){
|
||||
f.Key("extras");
|
||||
(value.Extras as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(value.SpecVersion)){
|
||||
f.Key("specVersion");
|
||||
f.Value(value.SpecVersion);
|
||||
}
|
||||
|
||||
if(value.Limit!=null){
|
||||
f.Key("limit");
|
||||
Serialize_Limit(f, value.Limit);
|
||||
}
|
||||
|
||||
f.EndMap();
|
||||
}
|
||||
|
||||
public static void Serialize_Limit(JsonFormatter f, Limit value)
|
||||
{
|
||||
f.BeginMap();
|
||||
|
||||
|
||||
if(value.Extensions!=null){
|
||||
f.Key("extensions");
|
||||
(value.Extensions as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Extras!=null){
|
||||
f.Key("extras");
|
||||
(value.Extras as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Cone!=null){
|
||||
f.Key("cone");
|
||||
__limit_Serialize_Cone(f, value.Cone);
|
||||
}
|
||||
|
||||
if(value.Hinge!=null){
|
||||
f.Key("hinge");
|
||||
__limit_Serialize_Hinge(f, value.Hinge);
|
||||
}
|
||||
|
||||
if(value.Spherical!=null){
|
||||
f.Key("spherical");
|
||||
__limit_Serialize_Spherical(f, value.Spherical);
|
||||
}
|
||||
|
||||
f.EndMap();
|
||||
}
|
||||
|
||||
public static void __limit_Serialize_Cone(JsonFormatter f, ConeLimit value)
|
||||
{
|
||||
f.BeginMap();
|
||||
|
||||
|
||||
if(value.Extensions!=null){
|
||||
f.Key("extensions");
|
||||
(value.Extensions as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Extras!=null){
|
||||
f.Key("extras");
|
||||
(value.Extras as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Angle.HasValue){
|
||||
f.Key("angle");
|
||||
f.Value(value.Angle.GetValueOrDefault());
|
||||
}
|
||||
|
||||
if(value.Rotation!=null&&value.Rotation.Count()>=4){
|
||||
f.Key("rotation");
|
||||
__limit__cone_Serialize_Rotation(f, value.Rotation);
|
||||
}
|
||||
|
||||
f.EndMap();
|
||||
}
|
||||
|
||||
public static void __limit__cone_Serialize_Rotation(JsonFormatter f, float[] value)
|
||||
{
|
||||
f.BeginList();
|
||||
|
||||
foreach(var item in value)
|
||||
{
|
||||
f.Value(item);
|
||||
|
||||
}
|
||||
f.EndList();
|
||||
}
|
||||
|
||||
public static void __limit_Serialize_Hinge(JsonFormatter f, HingeLimit value)
|
||||
{
|
||||
f.BeginMap();
|
||||
|
||||
|
||||
if(value.Extensions!=null){
|
||||
f.Key("extensions");
|
||||
(value.Extensions as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Extras!=null){
|
||||
f.Key("extras");
|
||||
(value.Extras as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Angle.HasValue){
|
||||
f.Key("angle");
|
||||
f.Value(value.Angle.GetValueOrDefault());
|
||||
}
|
||||
|
||||
if(value.Rotation!=null&&value.Rotation.Count()>=4){
|
||||
f.Key("rotation");
|
||||
__limit__hinge_Serialize_Rotation(f, value.Rotation);
|
||||
}
|
||||
|
||||
f.EndMap();
|
||||
}
|
||||
|
||||
public static void __limit__hinge_Serialize_Rotation(JsonFormatter f, float[] value)
|
||||
{
|
||||
f.BeginList();
|
||||
|
||||
foreach(var item in value)
|
||||
{
|
||||
f.Value(item);
|
||||
|
||||
}
|
||||
f.EndList();
|
||||
}
|
||||
|
||||
public static void __limit_Serialize_Spherical(JsonFormatter f, SphericalLimit value)
|
||||
{
|
||||
f.BeginMap();
|
||||
|
||||
|
||||
if(value.Extensions!=null){
|
||||
f.Key("extensions");
|
||||
(value.Extensions as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Extras!=null){
|
||||
f.Key("extras");
|
||||
(value.Extras as glTFExtension).Serialize(f);
|
||||
}
|
||||
|
||||
if(value.Phi.HasValue){
|
||||
f.Key("phi");
|
||||
f.Value(value.Phi.GetValueOrDefault());
|
||||
}
|
||||
|
||||
if(value.Theta.HasValue){
|
||||
f.Key("theta");
|
||||
f.Value(value.Theta.GetValueOrDefault());
|
||||
}
|
||||
|
||||
if(value.Rotation!=null&&value.Rotation.Count()>=4){
|
||||
f.Key("rotation");
|
||||
__limit__spherical_Serialize_Rotation(f, value.Rotation);
|
||||
}
|
||||
|
||||
f.EndMap();
|
||||
}
|
||||
|
||||
public static void __limit__spherical_Serialize_Rotation(JsonFormatter f, float[] value)
|
||||
{
|
||||
f.BeginList();
|
||||
|
||||
foreach(var item in value)
|
||||
{
|
||||
f.Value(item);
|
||||
|
||||
}
|
||||
f.EndList();
|
||||
}
|
||||
|
||||
} // class
|
||||
} // namespace
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02602b2f45f722f47a872ca0d1d8262d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -140,6 +140,12 @@ namespace UniVRM10
|
||||
return new float[] { -v.x, v.y, v.z };
|
||||
}
|
||||
|
||||
static float[] ReverseX(Quaternion q)
|
||||
{
|
||||
q = UniGLTF.Axes.X.Create().InvertQuaternion(q);
|
||||
return new float[] { q.x, q.y, q.z, q.w };
|
||||
}
|
||||
|
||||
///
|
||||
/// 必要な容量を計算
|
||||
/// (sparseは考慮してないので大きめ)
|
||||
@@ -444,6 +450,65 @@ namespace UniVRM10
|
||||
GravityDir = ReverseX(y.m_gravityDir),
|
||||
GravityPower = y.m_gravityPower,
|
||||
};
|
||||
|
||||
switch (y.m_anglelimitType)
|
||||
{
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone:
|
||||
{
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Cone = new UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit
|
||||
{
|
||||
Rotation = ReverseX(y.m_angleLimitRotation),
|
||||
Angle = y.m_angleLimitAngle1,
|
||||
}
|
||||
}
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge:
|
||||
{
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Hinge = new UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit
|
||||
{
|
||||
Rotation = ReverseX(y.m_angleLimitRotation),
|
||||
Angle = y.m_angleLimitAngle1,
|
||||
}
|
||||
}
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical:
|
||||
{
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Spherical = new UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit
|
||||
{
|
||||
Rotation = ReverseX(y.m_angleLimitRotation),
|
||||
Theta = y.m_angleLimitAngle1,
|
||||
Phi = y.m_angleLimitAngle2,
|
||||
}
|
||||
}
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return joint;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.Extensions.VRMC_springBone_limit;
|
||||
using UniGLTF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -626,6 +628,31 @@ namespace UniVRM10
|
||||
joint.m_gravityDir = gltfJoint.GravityDir != null ? Vector3InvertX(gltfJoint.GravityDir) : Vector3.down;
|
||||
joint.m_gravityPower = gltfJoint.GravityPower.GetValueOrDefault(0.0f);
|
||||
joint.m_stiffnessForce = gltfJoint.Stiffness.GetValueOrDefault(1.0f);
|
||||
|
||||
if (UniGLTF.Extensions.VRMC_springBone_limit.GltfDeserializer.TryGet(gltfJoint.Extensions as glTFExtension,
|
||||
out var extensionSpringBoneLimit))
|
||||
{
|
||||
if (extensionSpringBoneLimit.Limit.Cone is UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit cone)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone;
|
||||
joint.m_angleLimitRotation = QuaternionFromFloat4(cone.Rotation);
|
||||
joint.m_angleLimitAngle1 = cone.Angle.GetValueOrDefault(Mathf.PI * 0.5f);
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Hinge is UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit hinge)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge;
|
||||
joint.m_angleLimitRotation = QuaternionFromFloat4(hinge.Rotation);
|
||||
joint.m_angleLimitAngle1 = hinge.Angle.GetValueOrDefault(Mathf.PI * 0.5f);
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Spherical is UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit spherical)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical;
|
||||
joint.m_angleLimitRotation = QuaternionFromFloat4(spherical.Rotation);
|
||||
joint.m_angleLimitAngle1 = spherical.Theta.GetValueOrDefault(Mathf.PI * 0.5f);
|
||||
joint.m_angleLimitAngle2 = spherical.Phi.GetValueOrDefault(Mathf.PI * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
spring.Joints.Add(joint);
|
||||
}
|
||||
}
|
||||
@@ -633,6 +660,16 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
private static Quaternion QuaternionFromFloat4(float[] xyzw)
|
||||
{
|
||||
var q = (xyzw != null && xyzw.Length == 4)
|
||||
? new Quaternion(xyzw[0], xyzw[1], xyzw[2], xyzw[3])
|
||||
: Quaternion.identity
|
||||
;
|
||||
// vrm-1.0 is x inverted
|
||||
return Axes.X.Create().InvertQuaternion(q);
|
||||
}
|
||||
|
||||
static AxisMask ConstraintAxes(bool[] flags)
|
||||
{
|
||||
var mask = default(AxisMask);
|
||||
|
||||
Reference in New Issue
Block a user