vrm-c / vrm-specification

vrm specification
244 stars 37 forks source link

VRM1.0のlookAtのrangeMapのinputMaxValueが0指定の場合にゼロ除算が発生する #489

Closed tsgcpp closed 1 month ago

tsgcpp commented 2 months ago

概要

VRM1.0のlookAtの仕様に従うとゼロ除算が発生するパターンがあるのではと思ったので報告します。

経緯

まず、VRMC_vrm.lookAt.rangeMap.schema.json を確認すると、inputMaxValueのminimumとして0が明記されているため、0は有効な値であると認識しております。

  "properties": {
    "inputMaxValue": {
      "type": "number",
      "minimum": 0.0,
      "maximum": 180.0,
      "description": "Yaw and pitch angles  ( degrees )  between the head bone forward vector and the eye gaze LookAt vector"
    },

一方で、lookAt.md#interpretation-when-type-is-boneに記載されている以下の数式をinputMaxValueが0の場合に実施するとゼロ除算が発生するのではないかと思います。

const boneLocalEulerAngle = min(fabs(value), rangeMap.inputMaxValue)/rangeMap.inputMaxValue * rangeMap.outputScale;

参考としてlookAtの項目が以下のように設定されているVRM1.0を、UniVRM v0.126.0のVRM10Viewerでロードするとエラーが発生します。

      "lookAt": {
        "type": "bone",
        "rangeMapHorizontalInner": {
          "inputMaxValue": 0,
          "outputScale": 0
        },
        "rangeMapHorizontalOuter": {
          "inputMaxValue": 0,
          "outputScale": 0
        },
        "rangeMapVerticalDown": {
          "inputMaxValue": 0,
          "outputScale": 0
        },
        "rangeMapVerticalUp": {
          "inputMaxValue": 0,
          "outputScale": 0
        }

発生するエラーログは以下となります。

Assertion failed on expression: 'CompareApproximately(SqrMagnitude(result), 1.0F)'
UnityEngine.Quaternion: Internal_FromEulerRad(UnityEngine.Vector3)
UniVRM10.LookAtEyeDirectionApplicableToBone: SetYawPitchToBones(UniVRM10.LookAtEyeDirection)(at Assets / VRM10 / Runtime / Components / LookAt / LookAtEyeDirectionApplicableToBone.cs: 79)
UniVRM10.LookAtEyeDirectionApplicableToBone: Apply(UniVRM10.LookAtEyeDirection, System.Collections.Generic.Dictionary`2<UniVRM10.ExpressionKey, single>) (at Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs:45)
UniVRM10.Vrm10RuntimeExpression:Apply (UniVRM10.LookAtEyeDirection) (at Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs:126)
UniVRM10.Vrm10RuntimeExpression:Process (UniVRM10.LookAtEyeDirection) (at Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs:66)
UniVRM10.Vrm10Runtime:Process () (at Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs:130)
UniVRM10.Vrm10Instance:LateUpdate () (at Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs:138)
transform.localRotation assign attempt for 'J_Adj_L_FaceEye' is not valid. Input rotation is { NaN, NaN, NaN, NaN }.
UnityEngine.Transform:set_localRotation (UnityEngine.Quaternion)
UniVRM10.LookAtEyeDirectionApplicableToBone:SetYawPitchToBones (UniVRM10.LookAtEyeDirection) (at Assets/VRM10/Runtime/Components/LookAt/LookAtEyeDirectionApplicableToBone.cs:79)
UniVRM10.LookAtEyeDirectionApplicableToBone:Apply (UniVRM10.LookAtEyeDirection,System.Collections.Generic.Dictionary`2 < UniVRM10.ExpressionKey, single >)(at Assets / VRM10 / Runtime / Components / LookAt / LookAtEyeDirectionApplicableToBone.cs: 45)
UniVRM10.Vrm10RuntimeExpression: Apply(UniVRM10.LookAtEyeDirection)(at Assets / VRM10 / Runtime / Components / Vrm10Runtime / Vrm10RuntimeExpression.cs: 126)
UniVRM10.Vrm10RuntimeExpression: Process(UniVRM10.LookAtEyeDirection)(at Assets / VRM10 / Runtime / Components / Vrm10Runtime / Vrm10RuntimeExpression.cs: 66)
UniVRM10.Vrm10Runtime: Process()(at Assets / VRM10 / Runtime / Components / Vrm10Runtime / Vrm10Runtime.cs: 130)
UniVRM10.Vrm10Instance: LateUpdate()(at Assets / VRM10 / Runtime / Components / Vrm10Instance / Vrm10Instance.cs: 138)

要望

VRM1.0のlookAtのrangeMapのinputMaxValueが0指定の場合の扱いを定義していただければと考えております。

0b5vr commented 2 months ago

報告ありがとうございます!

inputMaxValue が0の場合の挙動を仕様内で定義し、実装をそのように変更する方針で対応を検討します。 具体的には、blenderの実装が max(0.001, inputMaxValue) を取るような実装になっているようですので、それに準じた方針で仕様を追記予定です。

tsgcpp commented 2 months ago

ご回答ありがとうございました。

inputMaxValue が0の場合の挙動を仕様内で定義し、実装をそのように変更する方針で対応を検討します。 具体的には、blenderの実装が max(0.001, inputMaxValue) を取るような実装になっているようですので、それに準じた方針で仕様を追記予定です。

こちらの方針で対応されるとのこと、承知しました!

よろしくお願いします。

(#488 の件については別途質問をさせていただきます。)

tsgcpp commented 2 months ago

@0b5vr #488 の件も併せて質問をさせていただければと思います (必要であれば別途Issueを発行します)。

もともと必須パラメータでなかったプロパティ

上記とのことなので、lookAt.rangeMapの outputScale も任意パラメータのため指定されていないパターンが考えられますが、もし outputScale がVRMのJSON部分で指定されていない場合はどのような対応をするのが好ましいでしょうか? inputMaxValueと異なりoutputScale にはminimumやdefaultの指定されていないため、もし推奨される対応があればご教授をお願いできればと思います。

0b5vr commented 2 months ago

lookAt.rangeMapの outputScale も任意パラメータのため指定されていないパターンが考えられますが、もし outputScale がVRMのJSON部分で指定されていない場合はどのような対応をするのが好ましいでしょうか? inputMaxValueと異なりoutputScale にはminimumやdefaultの指定されていないため、もし推奨される対応があればご教授をお願いできればと思います。

すいません、こちらの観点拾い忘れておりました!outputScaleについて、何かしらデフォルト値を設けるのが自然とは思いますが、具体的な値が自明でないため、対応方針について一度コンソーシアムに持ち帰らせてください。