예제 #1
0
        /// <summary>
        /// 指定座標に最も近い衝突点pと、中心軸からのpへの方向dirを返す。
        /// ※エディタ計算用
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="p"></param>
        /// <param name="dir"></param>
        public override bool CalcNearPoint(Vector3 pos, out Vector3 p, out Vector3 dir, out Vector3 d)
        {
            dir = Vector3.zero;

            var ldir = GetLocalDir();
            var l    = ldir * Length;
            var tpos = transform.position;
            var trot = transform.rotation;
            var spos = trot * -l + tpos; // スケールは含めない
            var epos = trot * l + tpos;  // スケールは含めない

            float t  = MathUtility.ClosestPtPointSegmentRatio(pos, spos, epos);
            float cr = Mathf.Lerp(StartRadius, EndRadius, t);

            d = spos + (epos - spos) * t; // 中心軸位置
            var   v    = pos - d;
            float vlen = v.magnitude;

            if (vlen < cr)
            {
                // 衝突している
                p = pos;
                if (vlen > 0.0f)
                {
                    dir = v.normalized;
                }
                return(true);
            }
            else
            {
                dir = v.normalized;
                p   = d + dir * cr;
                return(false);
            }
        }
예제 #2
0
            void CapsuleColliderDetection(ref float3 nextpos, float3 oldpos, float radius, int cindex, float3 dir)
            {
                var cpos = nextPosList[cindex];
                var crot = nextRotList[cindex];

                // x = 長さ(片側)
                // y = 始点半径
                // z = 終点半径
                //var lpos = localPosList[cindex];
                var cradius = radiusList[cindex];

                // スケール
                var   tindex = transformIndexList[cindex];
                var   cscl   = boneSclList[tindex];
                float scl    = math.dot(cscl, dir); // dirの軸のスケールを使用する

                cradius *= scl;

                // カプセル始点と終点
                float3 l    = math.mul(crot, dir * cradius.x);
                float3 spos = cpos - l;
                float3 epos = cpos + l;
                float  sr   = cradius.y;
                float  er   = cradius.z;

                // 移動前のパーティクル位置から押し出し平面を求める
                //float3 c = 0, n = 0;
                float  t   = MathUtility.ClosestPtPointSegmentRatio(oldpos, spos, epos);
                float  r   = math.lerp(sr, er, t);
                float3 d   = math.lerp(spos, epos, t);
                float3 v   = oldpos - d;
                var    len = math.length(v);
                float3 n   = math.normalize(v);

                len  = math.min(len, r + radius);
                len *= 0.999f;
                //float3 c = d + n * (r + radius);
                float3 c = d + n * len;

                // 平面衝突判定
                float3 opos;

                if (MathUtility.IntersectSegmentPlane(oldpos, nextpos, c, n, out opos))
                {
                    nextpos = opos;
                }


                // c = 平面位置
                // n = 平面方向
                // 平面衝突判定と押し出し
                //return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos);
            }
            /// <summary>
            /// カプセル衝突判定
            /// </summary>
            /// <param name="nextpos"></param>
            /// <param name="pos"></param>
            /// <param name="radius"></param>
            /// <param name="cindex"></param>
            /// <param name="dir"></param>
            /// <param name="friction"></param>
            /// <returns></returns>
            float CapsuleColliderDetection(ref float3 nextpos, float3 basepos, float radius, int cindex, float3 dir)
            {
                var cpos = nextPosList[cindex];
                var crot = nextRotList[cindex];

                // x = 長さ(片側)
                // y = 始点半径
                // z = 終点半径
                //var lpos = localPosList[cindex];
                var cradius = radiusList[cindex];

                // スケール
                var   tindex = transformIndexList[cindex];
                var   cscl   = boneSclList[tindex];
                float scl    = math.dot(math.abs(cscl), dir); // dirの軸のスケールを使用する

                cradius *= scl;

                float3 c = 0, n = 0;

                //if (keep)
                //{
                //    // 形状キープ
                //    // 物理OFFの基本状態から拘束を決定
                //    var cbasepos = basePosList[cindex];
                //    var cbaserot = baseRotList[cindex];

                //    // カプセル始点と終点
                //    float3 l = math.mul(cbaserot, dir * cradius.x);
                //    float3 spos = cbasepos - l;
                //    float3 epos = cbasepos + l;
                //    float sr = cradius.y;
                //    float er = cradius.z;

                //    // 移動前のコライダー位置から押し出し平面を割り出す
                //    float t = MathUtility.ClosestPtPointSegmentRatio(basepos, spos, epos);
                //    float r = math.lerp(sr, er, t);
                //    float3 d = math.lerp(spos, epos, t);
                //    float3 v = basepos - d;

                //    // 移動前コライダーのローカルベクトル
                //    var iq = math.inverse(cbaserot);
                //    float3 lv = math.mul(iq, v);

                //    // 移動後コライダーに変換
                //    l = math.mul(crot, dir * cradius.x);
                //    spos = cpos - l;
                //    epos = cpos + l;
                //    d = math.lerp(spos, epos, t);
                //    v = math.mul(crot, lv);
                //    n = math.normalize(v);
                //    c = d + n * (r + radius);
                //}
                //else
                {
                    var coldpos = posList[cindex];
                    var coldrot = rotList[cindex];

                    // カプセル始点と終点
                    float3 l    = math.mul(coldrot, dir * cradius.x);
                    float3 spos = coldpos - l;
                    float3 epos = coldpos + l;
                    float  sr   = cradius.y;
                    float  er   = cradius.z;

                    // 移動前のコライダー位置から押し出し平面を割り出す
                    float  t = MathUtility.ClosestPtPointSegmentRatio(nextpos, spos, epos);
                    float  r = math.lerp(sr, er, t);
                    float3 d = math.lerp(spos, epos, t);
                    float3 v = nextpos - d;

                    // 移動前コライダーのローカルベクトル
                    var    iq = math.inverse(coldrot);
                    float3 lv = math.mul(iq, v);

                    // 移動後コライダーに変換
                    l    = math.mul(crot, dir * cradius.x);
                    spos = cpos - l;
                    epos = cpos + l;
                    d    = math.lerp(spos, epos, t);
                    v    = math.mul(crot, lv);
                    n    = math.normalize(v);
                    c    = d + n * (r + radius);
                }


                // c = 平面位置
                // n = 平面方向
                // 平面衝突判定と押し出し
                return(MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos));
            }
        /// <summary>
        /// 指定座標に最も近い衝突点pと、中心軸からのpへの方向dirを返す。
        /// ※エディタ計算用
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="p"></param>
        /// <param name="dir"></param>
        public override bool CalcNearPoint(Vector3 pos, out Vector3 p, out Vector3 dir, out Vector3 d, bool skinning)
        {
            dir = Vector3.zero;

            var ldir = GetLocalDir();
            var l    = ldir * Length;

            //var tpos = transform.position;
            var   tpos = transform.TransformPoint(Center);
            var   trot = transform.rotation;
            float scl  = GetScale();

            l *= scl;

            var spos = trot * -l + tpos;
            var epos = trot * l + tpos;

#if true
            // 半径分長さ拡張
            if (skinning == false)
            {
                const float ratio = 0.5f;
                spos = trot * (-l - ldir * StartRadius * scl * ratio) + tpos;
                epos = trot * (l + ldir * EndRadius * scl * ratio) + tpos;
            }
#endif

            float t = MathUtility.ClosestPtPointSegmentRatio(pos, spos, epos);

#if true
            // 蓋の部分は無効とする
            if (skinning == false)
            {
                if (t < 0.0001f || t > 0.9999f)
                {
                    p = Vector3.zero;
                    d = Vector3.zero;
                    return(false);
                }
            }
#endif

            float cr = Mathf.Lerp(StartRadius * scl, EndRadius * scl, t);
            d = spos + (epos - spos) * t; // 中心軸位置
            var   v    = pos - d;
            float vlen = v.magnitude;
            if (vlen < cr)
            {
                // 衝突している
                p = pos;
                if (vlen > 0.0f)
                {
                    dir = v.normalized;
                }
            }
            else
            {
                dir = v.normalized;
                p   = d + dir * cr;
            }

            return(true);
        }