コード例 #1
0
        //sphere move to collide capsule
        static bool sweepSphereCapsule(SphereShape sphere, VIntTransform sphereTransform, VInt3 end,
                                       CapsuleShape capsule, VIntTransform capsuleTransform, ref VInt3 normal, ref VFixedPoint t)
        {
            VInt3       move           = end - sphereTransform.position;
            VFixedPoint radiusSum      = sphere.getRadius() + capsule.getRadius();
            VInt3       capsuleP0      = capsuleTransform.TransformPoint(capsule.getUpAxis() * capsule.getHalfHeight());
            VInt3       capsuleP1      = capsuleTransform.TransformPoint(capsule.getUpAxis() * -capsule.getHalfHeight());
            VInt3       spherePosition = sphereTransform.position;
            VFixedPoint tmp            = VFixedPoint.Zero;

            if (Distance.distancePointSegmentSquared(capsuleP0, capsuleP1, spherePosition, ref tmp) < radiusSum * radiusSum)
            {
                t      = VFixedPoint.Zero;
                normal = -move.Normalize();
                return(true);
            }

            VFixedPoint u0        = VFixedPoint.Zero;
            VInt3       tmpNormal = VInt3.zero;

            if (capsuleP0 == capsuleP1)
            {
                VInt3 ToPos = spherePosition + move;
                if (SphereSphereSweepAlgorithm.sphereSphereSweep(sphere.getRadius(), spherePosition, ToPos, capsule.getRadius(), capsuleTransform.position, ref u0, ref tmp, ref tmpNormal))
                {
                    t      = u0;
                    normal = tmpNormal;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else if (CapsuleRaytestAlgorithm.raycastCapsule(spherePosition, end, capsuleP0, capsuleP1, radiusSum, ref normal, ref u0))
            {
                t = u0;
                VFixedPoint param             = VFixedPoint.Zero;
                VInt3       movedSphereCenter = spherePosition + (end - spherePosition) * u0;
                Distance.distancePointSegmentSquared(capsuleP0, capsuleP1, movedSphereCenter, ref param);
                normal = movedSphereCenter - (capsuleP0 * (VFixedPoint.One - param) + capsuleP1 * param);
                normal = normal.Normalize();
                return(true);
            }

            return(false);
        }
コード例 #2
0
        static bool testRayVsSphereOrCapsule(ref VFixedPoint impactDistance, bool testSphere, VInt3 center, VFixedPoint radius, VInt3 dir, VFixedPoint length, VInt3[] verts, int e0, int e1)
        {
            if (testSphere)
            {
                VFixedPoint t = VFixedPoint.Zero; VInt3 tmp = VInt3.zero;
                if (SphereRaytestAlgorithm.rayTestSphere(center, dir * length + center, verts[e0], radius, ref tmp, ref t))
                {
                    impactDistance = t;
                    return(true);
                }
            }
            else
            {
                VFixedPoint t = VFixedPoint.Zero; VInt3 tmp = VInt3.zero;
                if (CapsuleRaytestAlgorithm.raycastCapsule(center, dir * length + center, verts[e0], verts[e1], radius, ref tmp, ref t))
                {
                    impactDistance = t;
                    return(true);
                }
            }

            return(false);
        }
コード例 #3
0
        public static bool sweepCapsuleCapsule(CapsuleShape lss0, VIntTransform transform0, VInt3 toPos, CapsuleShape lss1, VIntTransform transform1, ref VFixedPoint dist, ref VInt3 hitNormal)
        {
            VInt3       FromPos   = transform0.position;
            VFixedPoint radiusSun = lss0.getRadius() + lss1.getRadius();
            VFixedPoint length    = (toPos - FromPos).magnitude;
            VInt3       dir       = (toPos - FromPos) / length;

            VInt3 lss0p0 = transform0.TransformPoint(lss0.getUpAxis() * lss0.getHalfHeight()), lss0p1 = transform0.TransformPoint(lss0.getUpAxis() * -lss0.getHalfHeight());
            VInt3 lss1p0 = transform1.TransformPoint(lss1.getUpAxis() * lss1.getHalfHeight()), lss1p1 = transform1.TransformPoint(lss1.getUpAxis() * -lss1.getHalfHeight());

            bool        initialOverlapStatus = false;
            VFixedPoint tmp = VFixedPoint.Zero;

            if (lss0.getHalfHeight() < Globals.EPS)
            {
                initialOverlapStatus = Distance.distancePointSegmentSquared(lss1p0, lss1p1, lss0p0, ref tmp) < radiusSun * radiusSun;
            }
            else if (lss1.getHalfHeight() < Globals.EPS)
            {
                initialOverlapStatus = Distance.distancePointSegmentSquared(lss0p0, lss0p1, lss1p0, ref tmp) < radiusSun * radiusSun;
            }
            else
            {
                VInt3 x, y;
                initialOverlapStatus = Distance.SegmentSegmentDist2(lss0p0, lss0p1 - lss0p0, lss1p0, lss1p1 - lss1p0, out x, out y) < radiusSun * radiusSun;
            }

            if (initialOverlapStatus)
            {
                dist      = VFixedPoint.Zero;
                hitNormal = (FromPos - toPos).Normalize();
                return(true);
            }

            // 1. Extrude lss0 by lss1's length
            // 2. Inflate extruded shape by lss1's radius
            // 3. Raycast against resulting quad
            VInt3 D = (lss0p1 - lss0p0) * VFixedPoint.Half;
            VInt3 p0 = lss1p0 - D, p1 = lss1p1 - D, p0b = lss1p0 + D, p1b = lss1p1 + D;
            VInt3 normal = VInt3.Cross(p1b - p0b, p1 - p0b); normal = normal.Normalize();

            dist = VFixedPoint.One; bool status = false;

            VInt3 pa, pb, pc;

            if (VInt3.Dot(normal, dir) >= VFixedPoint.Zero)
            {
                pc = p0 - normal * radiusSun;
                pa = p1 - normal * radiusSun;
                pb = p1b - normal * radiusSun;
            }
            else
            {
                pc = p0 + normal * radiusSun;
                pa = p1 + normal * radiusSun;
                pb = p1b + normal * radiusSun;
            }
            VFixedPoint t = VFixedPoint.Zero, u = VFixedPoint.Zero, v = VFixedPoint.Zero;

            if (rayQuad(transform1.position, dir, pa, pb, pc, ref t, ref u, ref v, true) && t >= VFixedPoint.Zero && t < length)
            {
                dist   = t / length;
                status = true;
            }

            if (!status)
            {
                VInt3[] caps = new VInt3[]
                {
                    p0, p1, p1, p1b, p1b, p0b, p0b, p0
                };
                VInt3 tmpNormal = VInt3.zero;
                for (int i = 0; i < 4; i++)
                {
                    VFixedPoint s = VFixedPoint.Zero;
                    if (CapsuleRaytestAlgorithm.raycastCapsule(FromPos, toPos, caps[i * 2], caps[i * 2 + 1], radiusSun, ref tmpNormal, ref s))
                    {
                        if (s > VFixedPoint.Zero && s < dist)
                        {
                            dist   = s;
                            status = true;
                        }
                    }
                }
            }

            if (status)
            {
                VInt3 x, y;
                Distance.SegmentSegmentDist2(lss0p0 + dir * length * dist, lss0p1 - lss0p0, lss1p0, lss1p1 - lss1p0, out x, out y);
                hitNormal = (x - y).Normalize();
            }
            return(status);
        }