private void HandleCollision(MoveBall b1, MoveBall b2)
    {                                                              //collision detected: the collision has happened anytime between the previous frame and this one.
        //find how much time has past since the the collision
        MyVector3 relVelocity = MoveBall.RelativeVelocity(b2, b1); // V° rel velocity (const)
        MyVector3 relPosition = MoveBall.RelativePosition(b2, b1); // P° rel position at t=0
        //  relative position P(t) = P° - V° * t
        //  the collision happens when |P(t)| = 2 * radius
        //  <P(t)|P(t)> = <(P° - V° * t)|(P° - V° * t)> = 4 * radius^2
        //  solve the above quadratic eq. for t
        float term1       = MyVector3.Dot(relVelocity, relPosition);
        float term2       = MyVector3.Dot(relPosition, relPosition);
        float term3       = MyVector3.Dot(relVelocity, relVelocity);
        float rootSquared = term1 * term1 - term3 * (term2 - 4 * SnookerBall.radius * SnookerBall.radius);

        if (rootSquared < 0)
        {
            rootSquared = 0;
        }
        float timeAfterCollision = (term1 + Mathf.Sqrt(rootSquared)) / term3;

        b1.MoveByVector(b1.GetVelocity().Scale(-timeAfterCollision)); //minus sign because we are moving the ball back in time
        b2.MoveByVector(b2.GetVelocity().Scale(-timeAfterCollision)); //minus sign because we are moving the ball back in time
        relPosition = MoveBall.RelativePosition(b2, b1);              //vector joining the centers of the 2 balls
        MyVector3 b1_parallel      = b1.GetLinearMomentum().ParallelComponent(relPosition);
        MyVector3 b1_perpendicular = b1.GetLinearMomentum().NormalComponent(relPosition);
        MyVector3 b2_parallel      = b2.GetLinearMomentum().ParallelComponent(relPosition);
        MyVector3 b2_perpendicular = b2.GetLinearMomentum().NormalComponent(relPosition);

        //the two ball exchange the parallel components of their linear momenta
        //this is only valid in the case of the masses being the same
        b1.SetLinearMomentum(MyVector3.Add(b1_perpendicular, b2_parallel));
        b2.SetLinearMomentum(MyVector3.Add(b2_perpendicular, b1_parallel));
    }
Beispiel #2
0
    //calculate the x velocity resulting from the ball sliding on the floor for a time deltaTime
    private MyVector3 HorizontalVelocityAfterSliding(float deltaTime)
    {
        if (pureRolling)
        {
            return(velocityPreviousFrame);
        }
        MyVector3 afterSlidingVel;
        MyVector3 horizontal_velocityPreviousFrame =
            new MyVector3(velocityPreviousFrame.getX(), 0, velocityPreviousFrame.getZ());
        //calculate the variation in the angular momentum and x component of the linear momentum
        float     arbitraryConst1         = 5f;
        MyVector3 frictionDirection       = horizontal_velocityPreviousFrame.Scale(-1).UnitVector();
        MyVector3 linearMomentumVariation = frictionDirection.Scale(
            arbitraryConst1 * floorFriction * mass * deltaTime);
        MyVector3 angularMomentumVariation = MyVector3.Cross(
            new MyVector3(0, -radius, 0),
            linearMomentumVariation);

        afterSlidingVel             = MyVector3.Add(horizontal_velocityPreviousFrame, linearMomentumVariation.Scale(1 / mass));
        angularMomentumCurrentFrame = MyVector3.Add(angularMomentumCurrentFrame, angularMomentumVariation);
        MyVector3 contactPointTangentVel = MyVector3.Cross(AngularVelocity(angularMomentumCurrentFrame), new MyVector3(0, -radius, 0));

        if (contactPointTangentVel.Magnitude() > afterSlidingVel.Magnitude())
        {
            pureRolling = true;
            //calculate the rolling horizintal velocity
            //pure rolling law: speed = (radius) * (angular vel)
            float MRsquared_over_I = (mass * radius * radius) / momentOfInertia;
            afterSlidingVel =
                MyVector3.Subtract(afterSlidingVel.Scale(MRsquared_over_I), contactPointTangentVel).Scale(1 / (1 + MRsquared_over_I));
            angularMomentumCurrentFrame = MyVector3.Cross(afterSlidingVel, new MyVector3(0, -1, 0)).Scale(momentOfInertia / radius);
        }
        return(afterSlidingVel);
    }
Beispiel #3
0
    private void Update()
    {
        Debug.DrawRay(Vector3.zero, A.transform.forward, Color.red);
        Debug.DrawRay(Vector3.zero, B.transform.forward, Color.green);

        Vector3 target = MyVector3.Add(A.transform.forward, B.transform.forward);

        Resultant.transform.LookAt(target, Vector3.up);
        Debug.DrawLine(Vector3.zero, MyVector3.Scale(Resultant.transform.forward, target.magnitude), Color.blue);
    }
Beispiel #4
0
        /// <summary>
        /// Constructs a <see cref="MyBoundingSphere" /> that fully contains the given points.
        /// </summary>
        /// <param name="points">The points that will be contained by the sphere.</param>
        /// <param name="start">The start index from points array to start compute the bounding sphere.</param>
        /// <param name="count">The count of points to process to compute the bounding sphere.</param>
        /// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
        /// <exception cref="System.ArgumentNullException">points</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// start
        /// or
        /// count
        /// </exception>
        public static void FromPoints(MyVector3[] points, int start, int count, out MyBoundingSphere result)
        {
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            // Check that start is in the correct range
            if (start < 0 || start >= points.Length)
            {
                throw new ArgumentOutOfRangeException("start", start, string.Format("Must be in the range [0, {0}]", points.Length - 1));
            }

            // Check that count is in the correct range
            if (count < 0 || (start + count) > points.Length)
            {
                throw new ArgumentOutOfRangeException("count", count, string.Format("Must be in the range <= {0}", points.Length));
            }

            var upperEnd = start + count;

            //Find the center of all points.
            MyVector3 center = MyVector3.Zero;

            for (int i = start; i < upperEnd; ++i)
            {
                MyVector3.Add(ref points[i], ref center, out center);
            }

            //This is the center of our sphere.
            center /= (float)count;

            //Find the radius of the sphere
            float radius = 0f;

            for (int i = start; i < upperEnd; ++i)
            {
                //We are doing a relative distance comparison to find the maximum distance
                //from the center of our sphere.
                float distance;
                MyVector3.DistanceSquared(ref center, ref points[i], out distance);

                if (distance > radius)
                {
                    radius = distance;
                }
            }

            //Find the real distance from the DistanceSquared.
            radius = (float)Math.Sqrt(radius);

            //Construct the sphere.
            result.Center = center;
            result.Radius = radius;
        }
Beispiel #5
0
    private void FixedUpdate()
    {
        //simulation starts upon pressing the spacebar
        if (Input.GetKeyDown(KeyCode.Space) == true)
        {
            startSimulation = true;
        }
        if (!startSimulation)
        {
            return;
        }

        float     t = Time.fixedDeltaTime;
        MyVector3 previousLinearMomentum  = linearMomentum;
        MyVector3 linearMomentumVariation = linearMomentum.UnitVector().Scale(
            -SnookerBall.NormalForce * SnookerBall.frictionCoeff * t);

        if (linearMomentumVariation.Magnitude() >= linearMomentum.Magnitude())
        {//the decrease in linear momentum is bigger than the linear momentum itself
            linearMomentum = MyVector3.Zero();
        }
        else
        {
            linearMomentum = MyVector3.Add(linearMomentum, linearMomentumVariation);
        }
        MyVector3 avgLinearMomentum = MyVector3.Add(linearMomentum, previousLinearMomentum).Scale(0.5f);
        MyVector3 avgVelocity       = avgLinearMomentum.Scale(1 / SnookerBall.mass);
        MyVector3 newPosition       = MyVector3.Add(position, avgVelocity.Scale(t));

        foreach (Plane plane in cushions)
        {
            float distanceFromPlane = newPosition.DistanceFromPlane(plane) - SnookerBall.radius;
            if (distanceFromPlane < 0)
            {//the ball has gone beyond the boundary
                //collision detected: the collision has happened anytime between the previous frame and this one.
                //find how much time has past since the collision
                float impactTime =
                    ImpactTime(
                        MyVector3.Dot(previousLinearMomentum, plane.Normal()),
                        -MyVector3.Dot(avgLinearMomentum.UnitVector(), plane.Normal()) * SnookerBall.NormalForce * SnookerBall.frictionCoeff,
                        position.DistanceFromPlane(plane) - SnookerBall.radius);
                linearMomentumVariation = previousLinearMomentum.UnitVector().Scale(
                    -SnookerBall.NormalForce * SnookerBall.frictionCoeff * impactTime);
                //reflect the linear momentum along the normal of the plane
                linearMomentum = MyVector3.Add(previousLinearMomentum, linearMomentumVariation).Reflect(plane.Normal());
                //position ball just within the boundaries
                newPosition = MyVector3.Add(newPosition, plane.Normal().Scale(-distanceFromPlane));
            }
        }
        position = newPosition;
        MoveGameObject();
    }
Beispiel #6
0
 private void SetLinearMovementVariables()
 {
     rotationPosition = new MyVector3_Cylindrical(
         rotationPosition.getRadius(),
         directionConcesutiveWaypoints.getAzmuthalRad(), //place ball exctly between the current and the next waypoint
         rotationPosition.getY());
     rotating = false;
     position = MyVector3.Add(rotationPosition.ToCartesian(), waypoints_position[target]);
     MakeRed(target);
     target = NextTarget();
     MakeGreen(target);
     MakeYellow(NextTarget());
     movementDirection = MyVector3.DirectionalUnitVector(position, waypoints_position[target]);
 }
Beispiel #7
0
 public void FixedUpdate()
 {
     if (rotating)
     {//the ball is rotating around a waypoint
         //angle ball->current waypoint->next waypoint at the end of the previous update (clockwise winding)
         float prevAngle = MyVector3_Cylindrical.DeltaAngleRadiants(rotationPosition, directionConcesutiveWaypoints);
         int   sign      = clockwise ? -1 : 1;
         float dAngle    = angularVelocity * Time.fixedDeltaTime * sign;
         rotationPosition.RotateByAngle(dAngle);
         //angle ball->current waypoint->next waypoint at the current update
         float angle = MyVector3_Cylindrical.DeltaAngleRadiants(rotationPosition, directionConcesutiveWaypoints);
         if ((!clockwise && prevAngle > Mathf.PI && angle < Mathf.PI) ||
             (clockwise && prevAngle < Mathf.PI && angle > Mathf.PI) ||
             dAngle > Mathf.PI)
         {//the ball has moved past the next movement direction on this frame
             SetLinearMovementVariables();
         }
         else
         {//the ball has NOT crossed the next movement direction on this frame
             position = MyVector3.Add(rotationPosition.ToCartesian(), waypoints_position[target]);
         }
     }
     else
     {
         if (MyVector3.CloserThanRadius(position, waypoints_position[target], rotationRadius))
         {//the ball is closer to the waypoint than the specified radius
             SetRotationVariables();
         }
         else
         {
             MyVector3 deltaPos             = movementDirection.Scale(Time.fixedDeltaTime * velocity);
             float     distanceFromWaypoint = MyVector3.Subtract(waypoints_position[target], position).Magnitude();
             if (distanceFromWaypoint - deltaPos.Magnitude() <= rotationRadius)
             {//the ball has moved closer than the specified radius on this frame
                 position = MyVector3.Subtract(waypoints_position[target], movementDirection.Scale(rotationRadius));
                 SetRotationVariables();
             }
             else
             {//the ball has NOT moved closer than the specified radius on this frame
                 position = MyVector3.Add(position, deltaPos);
             }
         }
     }
     //place object in the scene
     MoveGameObject();
 }
Beispiel #8
0
 public void Calculate()
 {
     try
     {//parse strings into floating point numbers
         float v1_x = Single.Parse(v1_inputs[0].text);
         float v1_y = Single.Parse(v1_inputs[1].text);
         float v1_z = Single.Parse(v1_inputs[2].text);
         float v2_x = Single.Parse(v2_inputs[0].text);
         float v2_y = Single.Parse(v2_inputs[1].text);
         float v2_z = Single.Parse(v2_inputs[2].text);
         float num  = Single.Parse(scalar_input.text);
         v1     = new MyVector3(v1_x, v1_y, v1_z);
         v2     = new MyVector3(v2_x, v2_y, v2_z);
         scalar = num;
     }
     catch (Exception e)
     {//parsing failed
         Debug.LogError(e.Message);
         v1_inputs[0].text = "";
         v1_inputs[1].text = "";
         v1_inputs[2].text = "";
         v2_inputs[0].text = "";
         v2_inputs[1].text = "";
         v2_inputs[2].text = "";
         scalar_input.text = "";
         return;
     }
     //print vectors in the scene
     add.text       = MyVector3.Add(v1, v2).Print();
     subtract.text  = MyVector3.Subtract(v1, v2).Print();
     scale.text     = v1.Scale(scalar).Print();
     dot.text       = MyVector3.Dot(v1, v2).ToString("0.00");
     magnitude.text = v1.Magnitude().ToString("0.00");
     unitVect.text  = v1.UnitVector().Print();
     reflectX.text  = v1.ReflectX().Print();
     reflectY.text  = v1.ReflectY().Print();
     reflectZ.text  = v1.ReflectZ().Print();
     zero.text      = MyVector3.Zero().Print();
 }
Beispiel #9
0
 //move the ball by the specified vector
 public void MoveByVector(MyVector3 v)
 {
     position = MyVector3.Add(v, position);
 }
Beispiel #10
0
    private void FixedUpdate()
    {
        //simulation start upon press of the spacebar
        if (Input.GetKeyDown(KeyCode.Space) == true)
        {
            startSimulation = true;
        }
        if (!startSimulation)
        {
            return;
        }

        if (fullStop)
        {
            return; //simulation ended
        }
        float t = Time.fixedDeltaTime;

        if (stopBouncing)
        {
            if (pureRolling)
            {//case 1: the ball is rolling on the floor without sliding
                float dumping = 1 -
                                (5 - 4 / (1 + mass)) *
                                (floorFriction / (4 * floorFriction + 6)) *
                                (1 + 49 / (1 + 10 * Mathf.Abs(velocityPreviousFrame.Magnitude()))) *
                                t; //arbitrary dumping factor. No real physical meaning.
                velocityCurrentFrame = velocityPreviousFrame.Scale(dumping);
                if (velocityCurrentFrame.Magnitude() < 0.01f)
                {//the velocity is low enough to be neglectable
                    velocityCurrentFrame = MyVector3.Zero();
                    fullStop             = true;
                }
                //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
                MyVector3 avgVelocity  = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
                MyVector3 displacement = avgVelocity.Scale(t);
                position = MyVector3.Add(position, displacement);
                MoveGameObject();
                angularMomentumCurrentFrame = MyVector3.Cross(velocityCurrentFrame, new MyVector3(0, -1, 0)).Scale(momentOfInertia / radius);
                RotateGameObject(t);
                velocityPreviousFrame        = velocityCurrentFrame;
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
            }
            else
            {//case 2: the ball is rolling on the floor with sliding
                velocityCurrentFrame = HorizontalVelocityAfterSliding(t);
                //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
                MyVector3 avgVelocity  = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
                MyVector3 displacement = avgVelocity.Scale(t);
                position = MyVector3.Add(position, displacement);
                MoveGameObject();
                //angularMomentumCurrentFrame set in the X_VelocityAfterSliding() function
                RotateGameObject(t);
                velocityPreviousFrame        = velocityCurrentFrame;
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
            }
        }
        else
        {//the ball is still bouncing
            MyVector3 deltaVel = gravity.Scale(t);
            velocityCurrentFrame = MyVector3.Add(velocityPreviousFrame, deltaVel);
            //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
            MyVector3 avgVelocity        = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
            MyVector3 displacement       = avgVelocity.Scale(t);
            MyVector3 newPosition        = MyVector3.Add(position, displacement);
            float     distanceFromGround = newPosition.DistanceFromPlane(ground) - radius;
            if (distanceFromGround < 0)
            {                                                             //case 3: the ball is bouncing and has partially fallen balow the plane of the ground
                float impactVel_y            = Y_ImpactVelocity();
                float velocityCurrentFrame_y = impactVel_y * restitution; //upwards speed after bounce
                if (velocityCurrentFrame_y < tresholdStopBouncing)
                {                                                         //the speed after the bounce is small enough to be ignored
                    stopBouncing           = true;
                    velocityCurrentFrame_y = 0;
                }
                MyVector3 horzVelocityCurrentFrame = HorizontalVelocityAfterSliding(t + 0.001f * impactVel_y + 8 * t * (1 - 1 / Mathf.Sqrt(1 + mass)));
                //position ball on top of the ground
                position = MyVector3.Add(newPosition, ground.Normal().Scale(-distanceFromGround));
                MoveGameObject();
                //angularMomentumCurrentFrame set in the X_VelocityAfterSliding() function
                RotateGameObject(t);
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
                velocityPreviousFrame        = new MyVector3(horzVelocityCurrentFrame.getX(), velocityCurrentFrame_y, horzVelocityCurrentFrame.getZ());
            }
            else
            {//case 4: the ball is bouncing and is in mid-air
                velocityPreviousFrame = velocityCurrentFrame;
                position = newPosition;
                MoveGameObject();
                RotateGameObject(t);
            }
        }
    }