ひつじTips

技術系いろいろつまみ食います。

VRM モデルのスケールを変更すると,髪揺れがおかしくなる件の対策②

ちょう恥ずかしい.....
VRM モデルのスケールを変更すると,髪揺れがおかしくなる件の対策 - ひつじTips で全然問題解決できてなかったっす.....

なんかなーーーーここで確かにGizmoの球の位置おかしーな~と思ってたんよなぁーーーーー

f:id:mu-777:20190104045115p:plain

しかもまさかのTypo的なミスもしてるんよなぁーーーーーーーーーー

だめだ..深夜テンションで書くと絶対ミスってるので,一晩寝かせないといかんすな
(と言いつつ本記事も寝かさずにお気軽にUPしちゃうけど)

解決方法②

前記事と同じく,VRM/UniVRM/Scripts/SpringBone/VRMSpringBone.cs287行目あたりからを,

今回は以下のように修正します.

                foreach (var group in ColliderGroups)
                {
+                   var groupGlobalScale = Mathf.Max(Mathf.Max(group.transform.lossyScale.x,
+                                                              group.transform.lossyScale.y),
+                                                    group.transform.lossyScale.z);

                    if (group != null)
                    {
                        foreach (var collider in group.Colliders)
                        {
                            m_colliderList.Add(new SphereCollider
                            {
                                Position = group.transform.TransformPoint(collider.Offset),
-                               Radius = collider.Radius,
+                               Radius = collider.Radius * groupGlobalScale,
                            });
                        }
                    }
                }
            }

            var stiffness = m_stiffnessForce * Time.deltaTime;
            var external = m_gravityDir * (m_gravityPower * Time.deltaTime);
+           var globalScale = Mathf.Max(Mathf.Max(transform.lossyScale.x,
+                                                 transform.lossyScale.y),
+                                       transform.lossyScale.z);
            foreach (var verlet in m_verlet)
            {
-               verlet.Radius = m_hitRadius;
+               verlet.Radius = m_hitRadius * globalScale;
                verlet.Update(m_center,
                    stiffness,
                    m_dragForce,
                    external,
                    m_colliderList
                    );
            }
        }


前記事ではまさかのGlobalScaleの計算のところでTypoして,thisのtransform.lossyScale.zを持ってきちゃってたというね. やっちまったね.

さらに加えて,HitRadius側にも修正入れてます. これしないと,デフォルトのm_hitRadiusの大きさ(0.02f)が影響してくるぐらいモデルを小さくしたときに影響出ます(日本語不自由)

あとGizmo側も変更.

VRM/UniVRM/Scripts/SpringBone/VRMSpringBoneColliderGroup.cs33行目あたりからを,今回は以下のように修正.

            Matrix4x4 mat = transform.localToWorldMatrix;
            Gizmos.matrix = mat;
-           Gizmos.matrix = mat * Matrix4x4.Scale(new Vector3(
-               1.0f / transform.lossyScale.x,
-               1.0f / transform.lossyScale.y,
-               1.0f / transform.lossyScale.z
-               ));
+           //Gizmos.matrix = mat * Matrix4x4.Scale(new Vector3(
+           //    1.0f / transform.lossyScale.x,
+           //    1.0f / transform.lossyScale.y,
+           //    1.0f / transform.lossyScale.z
+           //    ));
            foreach (var y in Colliders)
            {
                Gizmos.DrawWireSphere(y.Offset, y.Radius);
           }


ここコメントアウトするだけでよかった!!!!!

てかわざわざスケールの逆数をかけてるのだからこれはある意味仕様っぽい...でも変えたいんすけど...

個人的にはGizmoもロジック側と合わせて,以下のように書きたい...

-           Matrix4x4 mat = transform.localToWorldMatrix;
-           Gizmos.matrix = mat;
-           Gizmos.matrix = mat * Matrix4x4.Scale(new Vector3(
-               1.0f / transform.lossyScale.x,
-               1.0f / transform.lossyScale.y,
-               1.0f / transform.lossyScale.z
-               ));
+           //Matrix4x4 mat = transform.localToWorldMatrix;
+           //Gizmos.matrix = mat;
+           //Gizmos.matrix = mat * Matrix4x4.Scale(new Vector3(
+           //    1.0f / transform.lossyScale.x,
+           //    1.0f / transform.lossyScale.y,
+           //    1.0f / transform.lossyScale.z
+           //    ));

+           var globalScale = Mathf.Max(Mathf.Max(transform.lossyScale.x,
+                                                 transform.lossyScale.y),
+                                       transform.lossyScale.z);
            foreach (var y in Colliders)
            {
-               Gizmos.DrawWireSphere(y.Offset, y.Radius);
+               Gizmos.DrawWireSphere(this.transform.TransformPoint(y.Offset), y.Radius* globalScale);
            }
        }

最後に

まだミスあったらどうしようかな...他人のコードむずいね...