mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-25 20:32:32 -05:00
Merge pull request #2833 from ousttrue/fix/spring_limit_specversion
[VRMC_springBone_limit] specVersion and validation
This commit is contained in:
@@ -14,6 +14,7 @@ namespace UniVRM10
|
||||
public const string SPRINGBONE_EXTENDED_COLLIDER_SPEC_VERSION = "1.0";
|
||||
public const string NODE_CONSTRAINT_SPEC_VERSION = "1.0";
|
||||
public const string MTOON_SPEC_VERSION = "1.0";
|
||||
public const string VRMC_springBone_limit_SPEC_VERSION = "1.0-draft";
|
||||
|
||||
public const string LICENSE_URL_JA = "https://vrm.dev/licenses/1.0/";
|
||||
public const string LICENSE_URL_EN = "https://vrm.dev/licenses/1.0/en/";
|
||||
@@ -451,63 +452,70 @@ namespace UniVRM10
|
||||
GravityPower = y.m_gravityPower,
|
||||
};
|
||||
|
||||
switch (y.m_anglelimitType)
|
||||
if (y.transform.childCount > 0)
|
||||
{
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone:
|
||||
{
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
// childが存在する => 末端でない
|
||||
switch (y.m_anglelimitType)
|
||||
{
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone:
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Cone = new UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit
|
||||
SpecVersion = VRMC_springBone_limit_SPEC_VERSION,
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Angle = y.m_pitch,
|
||||
Cone = new UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Angle = y.m_pitch,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
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
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge:
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Hinge = new UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit
|
||||
SpecVersion = VRMC_springBone_limit_SPEC_VERSION,
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Angle = y.m_pitch,
|
||||
Hinge = new UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Angle = y.m_pitch,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
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
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical:
|
||||
{
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit
|
||||
{
|
||||
Spherical = new UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit
|
||||
SpecVersion = VRMC_springBone_limit_SPEC_VERSION,
|
||||
Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Pitch = y.m_pitch,
|
||||
Yaw = y.m_yaw,
|
||||
Spherical = new UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit
|
||||
{
|
||||
Rotation = ReverseXToFloat4(y.m_limitSpaceOffset),
|
||||
Pitch = y.m_pitch,
|
||||
Yaw = y.m_yaw,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
};
|
||||
glTFExtension extensions = default;
|
||||
UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit);
|
||||
joint.Extensions = extensions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return joint;
|
||||
}
|
||||
|
||||
@@ -650,24 +650,27 @@ namespace UniVRM10
|
||||
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)
|
||||
if (VRMC_springBone_limit_Validate(go.transform, extensionSpringBoneLimit))
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(cone.Rotation);
|
||||
joint.m_pitch = math.clamp(cone.Angle.GetValueOrDefault(), 0.0f, math.PI);
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Hinge is UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit hinge)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(hinge.Rotation);
|
||||
joint.m_pitch = math.clamp(hinge.Angle.GetValueOrDefault(), 0.0f, math.PI);
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Spherical is UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit spherical)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(spherical.Rotation);
|
||||
joint.m_pitch = math.clamp(spherical.Pitch.GetValueOrDefault(), 0.0f, math.PI);
|
||||
joint.m_yaw = math.clamp(spherical.Yaw.GetValueOrDefault(), 0.0f, math.PI / 2);
|
||||
if (extensionSpringBoneLimit.Limit.Cone is UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit cone)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(cone.Rotation);
|
||||
joint.m_pitch = cone.Angle.GetValueOrDefault();
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Hinge is UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit hinge)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(hinge.Rotation);
|
||||
joint.m_pitch = hinge.Angle.GetValueOrDefault();
|
||||
}
|
||||
else if (extensionSpringBoneLimit.Limit.Spherical is UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit spherical)
|
||||
{
|
||||
joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical;
|
||||
joint.m_limitSpaceOffset = QuaternionFromFloat4(spherical.Rotation);
|
||||
joint.m_pitch = spherical.Pitch.GetValueOrDefault();
|
||||
joint.m_yaw = spherical.Yaw.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,6 +681,60 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
private static bool VRMC_springBone_limit_Validate(Transform node, VRMC_springBone_limit extensionSpringBoneLimit)
|
||||
{
|
||||
var validate = true;
|
||||
if (extensionSpringBoneLimit.SpecVersion != Vrm10Exporter.VRMC_springBone_limit_SPEC_VERSION)
|
||||
{
|
||||
validate = false;
|
||||
UniGLTFLogger.Warning($"Unknown VRMC_springBone_limit specVersion: {extensionSpringBoneLimit.SpecVersion}");
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
if (extensionSpringBoneLimit.Limit != null)
|
||||
{
|
||||
if (extensionSpringBoneLimit.Limit.Cone is UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit cone)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
if (extensionSpringBoneLimit.Limit.Hinge is UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit hinge)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
if (extensionSpringBoneLimit.Limit.Spherical is UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit spherical)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
// Limit 欠落
|
||||
validate = false;
|
||||
UniGLTFLogger.Warning($"No VRMC_springBone_limit.Limit: skip");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// ok
|
||||
break;
|
||||
|
||||
default:
|
||||
validate = false;
|
||||
UniGLTFLogger.Warning($"Multiple VRMC_springBone_limit.Limit: skip");
|
||||
break;
|
||||
}
|
||||
|
||||
if (node.childCount == 0)
|
||||
{
|
||||
// leaf
|
||||
UniGLTFLogger.Warning($"VRMC_springBone_limit: leaf node '{node.name}' must not have limit. skip");
|
||||
validate = false;
|
||||
}
|
||||
|
||||
return validate;
|
||||
}
|
||||
|
||||
private static Quaternion QuaternionFromFloat4(float[] xyzw)
|
||||
{
|
||||
var q = (xyzw != null && xyzw.Length == 4)
|
||||
|
||||
Reference in New Issue
Block a user