Beispiel #1
0
        public NearestPointResolver(Animator avatarRoot, ShapeKey key, bool isGenericMode)
        {
            this.avatarRoot = avatarRoot;
            this.key        = key;
            groups          = new BoneGroup[key.bodyLines.Count];
            for (var i = 0; i < key.bodyLines.Count; i++)
            {
                var b = key.bodyLines[i];
                switch (b.bones.Count)
                {
                case 2:
                {
                    var b0 = b.GetBoneTransform(0, avatarRoot, isGenericMode).position;
                    var b1 = b.GetBoneTransform(1, avatarRoot, isGenericMode).position;
                    groups[i] = new BoneGroup2(
                        Vector3.Lerp(b0, b1, key.startMargin),
                        Vector3.Lerp(b0, b1, 1f - key.endMargin),
                        key.isLeaf
                        );
                    break;
                }

                case 3:
                {
                    var b0 = b.GetBoneTransform(0, avatarRoot, isGenericMode).position;
                    var b1 = b.GetBoneTransform(1, avatarRoot, isGenericMode).position;
                    var b2 = b.GetBoneTransform(2, avatarRoot, isGenericMode).position;
                    groups[i] = new BoneGroup3(
                        Vector3.Lerp(b0, b1, key.startMargin * 2f),
                        b1,
                        Vector3.Lerp(b1, b2, 1f - key.endMargin * 2f)
                        );
                    break;
                }

                default:
                    Debug.Log("Body line must have 2 or 3 bones");
                    break;
                }
            }
        }
Beispiel #2
0
            public BoneGroup3(Vector3 pB0, Vector3 pB1, Vector3 pB2)
            {
                this.pB0 = pB0;
                this.pB1 = pB1;
                this.pB2 = pB2;

                // 1. 平面 B₀B₁B₂ の法線 N を、外積 B₁B₀×B₁B₂ から求める。
                vB1B0 = pB0 - pB1;
                vB1B2 = pB2 - pB1;
                N     = Vector3.Cross(vB1B0, vB1B2).normalized; // Issueの図では手前向き(左手座標系)

                // 2. 平面上の座標空間を以下のように定義する。
                //    - B₁ を原点 O とする
                //    - B₁B₀ の単位ベクトルを取り、その方向を𝓍軸とする
                //    - 𝓍軸を N の周りに反時計回り90度回転した方向を𝓎軸とする
                vX = vB1B0.normalized;
                vY = Vector3.Cross(vX, N).normalized;

                // 4. 平面上の𝓍・𝓎軸単位ベクトルとの内積から、平面上での B₀, B₂, Pₚ の座標を求める。
                qB0 = new Vector2(Vector3.Dot(vB1B0, vX), Vector3.Dot(vB1B0, vY));
                qB2 = new Vector2(Vector3.Dot(vB1B2, vX), Vector3.Dot(vB1B2, vY));

                if (Mathf.Abs(qB2.y) < 1e-5f)
                {
                    // 3ボーンが一直線上に並ぶときは2ボーン処理で代替
                    altForLinear = new BoneGroup2(pB0, pB2, false);
                    return;
                }

                // 5. 次の2直線の交点を C とする。
                //    - B₀ を通り B₀O と垂直な直線:𝓍 = B₀x
                //    - B₂ を通り B₂O と垂直な直線:𝓎-B₂y = (-B₂x/B₂y)(𝓍-B₂x)
                // 6. 上記2直線の式を連立方程式として解き、C の座標を求める。
                //    - Cx = B₀x
                //    - Cy = (-B₂x/B₂y)(B₀x-B₂x) + B₂y
                qC = new Vector2(qB0.x, -qB2.x * (qB0.x - qB2.x) / qB2.y + qB2.y);
            }