Пример #1
0
        void IJobParallelFor.Execute(int index)
        {
            var pRW = pRWPoints + index;

            if (IsEnableFloor)
            {
                if (pRW->Position.y <= FloorHeight)
                {
                    pRW->Position.y = FloorHeight;
                }
            }

            if (IsEnableCollider)
            {
                for (int i = 0; i < ColliderCount; ++i)
                {
                    Collider *  pCollider   = pColliders + i;
                    ColliderEx *pColliderEx = pColliderExs + i;

                    if (pCollider->Height <= 0.0f)
                    {
                        PushoutFromSphere(pCollider, pColliderEx, ref pRW->Position);
                    }
                    else
                    {
                        PushoutFromCapsule(pCollider, pColliderEx, ref pRW->Position);
                    }
                }
            }
        }
Пример #2
0
        void PushoutFromCapsule(Collider *pCollider, ColliderEx *pColliderEx, ref Vector3 point)
        {
            var capsuleVec       = pColliderEx->Direction;
            var capsuleVecNormal = capsuleVec.normalized;
            var capsulePos       = pColliderEx->Position;
            var targetVec        = point - capsulePos;
            var distanceOnVec    = Vector3.Dot(capsuleVecNormal, targetVec);

            if (distanceOnVec <= EPSILON)
            {
                PushoutFromSphere(capsulePos, pCollider->RadiusHead, ref point);
                return;
            }
            else if (distanceOnVec >= pCollider->Height)
            {
                PushoutFromSphere(capsulePos + capsuleVec, pCollider->RadiusTail, ref point);
                return;
            }
            else
            {
                var positionOnVec      = capsulePos + (capsuleVecNormal * distanceOnVec);
                var pushoutVec         = point - positionOnVec;
                var sqrPushoutDistance = pushoutVec.sqrMagnitude;
                if (sqrPushoutDistance > EPSILON)
                {
                    var Radius = pCollider->RadiusHead + (pCollider->RadiusTail - pCollider->RadiusHead) * distanceOnVec;
                    if (sqrPushoutDistance < Radius * Radius)
                    {
                        var pushoutDistance = Mathf.Sqrt(sqrPushoutDistance);
                        point = positionOnVec + pushoutVec * Radius / pushoutDistance;
                        return;
                    }
                }
            }
        }
Пример #3
0
        static void PushoutFromCapsule(Collider *pCollider, ColliderEx *pColliderEx, ref Vector3 point)
        {
            var capsuleVec    = pColliderEx->Direction;
            var capsulePos    = pColliderEx->Position;
            var targetVec     = point - capsulePos;
            var radius        = pCollider->Radius;
            var distanceOnVec = Vector3.Dot(capsuleVec, targetVec);

            if (distanceOnVec <= 0.0f)
            {
                PushoutFromSphere(capsulePos, radius, ref point);
            }
            else if (distanceOnVec >= pCollider->Height)
            {
                PushoutFromSphere(capsulePos + capsuleVec * distanceOnVec, radius, ref point);
            }
            else
            {
                var positionOnVec   = capsulePos + (capsuleVec * distanceOnVec);
                var pushoutVec      = point - positionOnVec;
                var distanceSquared = pushoutVec.sqrMagnitude;
                if (distanceSquared > Epsilon && distanceSquared < radius * radius)
                {
                    var distance = Mathf.Sqrt(distanceSquared);
                    point = positionOnVec + pushoutVec * radius / distance;
                }
            }
        }
Пример #4
0
        bool CollisionDetection(Collider *pCollider, ColliderEx *pColliderEx, Vector3 point1, Vector3 point2, out Vector3 pointOnLine, out Vector3 pointOnCollider, out float Radius)
        {
            if (pCollider->Height <= EPSILON)
            {
                var direction       = point2 - point1;
                var directionLength = direction.magnitude;
                direction /= directionLength;

                var toCenter         = pColliderEx->Position - point1;
                var dot              = Vector3.Dot(direction, toCenter);
                var pointOnDirection = direction * Mathf.Clamp(dot, 0.0f, directionLength);

                pointOnCollider = pColliderEx->Position;
                pointOnLine     = pointOnDirection + point1;
                Radius          = pCollider->RadiusHead;

                if ((pointOnCollider - pointOnLine).sqrMagnitude > pCollider->RadiusHead * pCollider->RadiusHead)
                {
                    return(false);
                }

                return(true);
            }
            else
            {
                var capsuleDir = pColliderEx->Direction;
                var capsulePos = pColliderEx->Position;
                var pointDir   = point2 - point1;

                float t1, t2;
                var   sqrDistance = ComputeNearestPoints(capsulePos, capsuleDir, point1, pointDir, out t1, out t2, out pointOnCollider, out pointOnLine);
                t1     = Mathf.Clamp01(t1);
                Radius = pCollider->RadiusHead + (pCollider->RadiusTail - pCollider->RadiusHead) * t1;

                if (sqrDistance > Radius * Radius)
                {
                    pointOnCollider = Vector3.zero;
                    pointOnLine     = Vector3.zero;
                    return(false);
                }

                t2 = Mathf.Clamp01(t2);

                pointOnCollider = capsulePos + capsuleDir * t1;
                pointOnLine     = point1 + pointDir * t2;

                return((pointOnCollider - pointOnLine).sqrMagnitude <= Radius * Radius);
            }
        }
Пример #5
0
        static bool HitTest(Collider *pCollider, ColliderEx *pColliderEx, Vector3 point1, Vector3 point2, out Vector3 pointOnLine, out Vector3 pointOnCollider)
        {
            if (pCollider->IsSphere)
            {
                var direction       = point2 - point1;
                var directionLength = direction.magnitude;
                direction /= directionLength;

                var toCenter         = pColliderEx->Position - point1;
                var dot              = Vector3.Dot(direction, toCenter);
                var pointOnDirection = direction * Mathf.Clamp(dot, 0.0f, directionLength);

                pointOnCollider = pColliderEx->Position;
                pointOnLine     = pointOnDirection + point1;

                return(!((pointOnCollider - pointOnLine).sqrMagnitude > pCollider->Radius * pCollider->Radius));
            }
            else
            {
                var capsuleDir = pColliderEx->Direction;
                var capsulePos = pColliderEx->Position;
                var pointDir   = point2 - point1;

                var sqrDistance = ComputeNearestPoints(capsulePos, capsuleDir, point1, pointDir, out float t1, out float t2, out pointOnCollider, out pointOnLine);
                if (sqrDistance > pCollider->Radius * pCollider->Radius)
                {
                    pointOnCollider = Vector3.zero;
                    pointOnLine     = Vector3.zero;
                    return(false);
                }

                t1 = Mathf.Clamp01(t1);
                t2 = Mathf.Clamp01(t2);

                pointOnCollider = capsulePos + capsuleDir * t1;
                pointOnLine     = point1 + pointDir * t2;

                return((pointOnCollider - pointOnLine).sqrMagnitude <= pCollider->Radius * pCollider->Radius);
            }
        }
Пример #6
0
 void PushoutFromSphere(Collider *pCollider, ColliderEx *pColliderEx, ref Vector3 point)
 {
     PushoutFromSphere(pColliderEx->Position, pCollider->RadiusHead, ref point);
 }
Пример #7
0
        void IJobParallelFor.Execute(int index)
        {
            var constraint = pConstraints + index;
            var RptA       = pRPoints + constraint->IndexA;
            var RptB       = pRPoints + constraint->IndexB;

            float WeightA = RptA->Weight;
            float WeightB = RptB->Weight;

            if ((WeightA <= EPSILON) && (WeightB <= EPSILON))
            {
                return;
            }

            var RWptA = pRWPoints + constraint->IndexA;
            var RWptB = pRWPoints + constraint->IndexB;

            var Direction = RWptB->Position - RWptA->Position;

            float Distance = Direction.magnitude;
            float Force    = (Distance - constraint->Length) * SpringK;

            bool  IsShrink = Force >= 0.0f;
            float ConstraintPower;

            switch (constraint->Type)
            {
            case SPCRJointDynamicsController.ConstraintType.Structural_Vertical:
                ConstraintPower = IsShrink
                    ? constraint->Shrink * (RptA->StructuralShrinkVertical + RptB->StructuralShrinkVertical)
                    : constraint->Stretch * (RptA->StructuralStretchVertical + RptB->StructuralStretchVertical);
                break;

            case SPCRJointDynamicsController.ConstraintType.Structural_Horizontal:
                ConstraintPower = IsShrink
                    ? constraint->Shrink * (RptA->StructuralShrinkHorizontal + RptB->StructuralShrinkHorizontal)
                    : constraint->Stretch * (RptA->StructuralStretchHorizontal + RptB->StructuralStretchHorizontal);
                break;

            case SPCRJointDynamicsController.ConstraintType.Shear:
                ConstraintPower = IsShrink
                    ? constraint->Shrink * (RptA->ShearShrink + RptB->ShearShrink)
                    : constraint->Stretch * (RptA->ShearStretch + RptB->ShearStretch);
                break;

            case SPCRJointDynamicsController.ConstraintType.Bending_Vertical:
                ConstraintPower = IsShrink
                    ? constraint->Shrink * (RptA->BendingShrinkVertical + RptB->BendingShrinkVertical)
                    : constraint->Stretch * (RptA->BendingStretchVertical + RptB->BendingStretchVertical);
                break;

            case SPCRJointDynamicsController.ConstraintType.Bending_Horizontal:
                ConstraintPower = IsShrink
                    ? constraint->Shrink * (RptA->BendingShrinkHorizontal + RptB->BendingShrinkHorizontal)
                    : constraint->Stretch * (RptA->BendingStretchHorizontal + RptB->BendingStretchHorizontal);
                break;

            default:
                ConstraintPower = 0.0f;
                break;
            }

            if (ConstraintPower > 0.0f)
            {
                var Displacement = Direction.normalized * (Force * ConstraintPower);

                float WightAB = WeightA + WeightB;
                RWptA->Position += Displacement * WeightA / WightAB;
                RWptB->Position -= Displacement * WeightB / WightAB;
            }

            if (constraint->IsCollision == 0)
            {
                return;
            }

            float Friction = 0.0f;

            for (int i = 0; i < ColliderCount; ++i)
            {
                Collider *  pCollider   = pColliders + i;
                ColliderEx *pColliderEx = pColliderExs + i;

                float   Radius;
                Vector3 pointOnLine, pointOnCollider;
                if (CollisionDetection(pCollider, pColliderEx, RWptA->Position, RWptB->Position, out pointOnLine, out pointOnCollider, out Radius))
                {
                    var Pushout         = pointOnLine - pointOnCollider;
                    var PushoutDistance = Pushout.magnitude;

                    var pointDistance = (RWptB->Position - RWptA->Position).magnitude * 0.5f;
                    var rateP1        = Mathf.Clamp01((pointOnLine - RWptA->Position).magnitude / pointDistance);
                    var rateP2        = Mathf.Clamp01((pointOnLine - RWptB->Position).magnitude / pointDistance);

                    Pushout         /= PushoutDistance;
                    Pushout         *= Mathf.Max(Radius - PushoutDistance, 0.0f);
                    RWptA->Position += Pushout * rateP2;
                    RWptB->Position += Pushout * rateP1;

                    var Dot = Vector3.Dot(Vector3.up, (pointOnLine - pointOnCollider).normalized);
                    Friction = Mathf.Max(Friction, pCollider->Friction * Mathf.Clamp01(Dot));
                }
            }

            RWptA->Friction = Mathf.Max(Friction, RWptA->Friction);
            RWptB->Friction = Mathf.Max(Friction, RWptB->Friction);
        }