Beispiel #1
0
    //calculate the vertical velocity at the moment of impact
    private float Y_ImpactVelocity()
    {// (V)^2 = (V°)^2  - 2 * g * X°
        float Y_impactVelSquared = velocityPreviousFrame.getY() * velocityPreviousFrame.getY() -
                                   2 * gravity.getY() * (position.DistanceFromPlane(ground) - radius);

        if (Y_impactVelSquared < 0)
        {
            Y_impactVelSquared = 0;
        }
        return(Mathf.Sqrt(Y_impactVelSquared));
    }
Beispiel #2
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();
    }
    //draw rays in the scene
    private void Update()
    {
        int       lines  = 36;
        MyVector3 normal = plane.Normal();
        MyVector3 p      = MyVector3.Subtract(vector, normal.Scale(vector.DistanceFromPlane(plane)));

        for (int i = 0; i < lines; i++)
        {
            Vector3 v = new Vector3((float)Math.Cos(Math.PI * 2 * i / lines), 0, (float)Math.Sin(Math.PI * 2 * i / lines));
            v = Quaternion.FromToRotation(Vector3.up, new Vector3(normal.getX(), normal.getY(), normal.getZ())) * v;
            Debug.DrawRay(new Vector3(p.getX(), p.getY(), p.getZ()), 1000 * v, Color.magenta);
        }
        Debug.DrawRay(Vector3.zero, new Vector3(vector.getX(), vector.getY(), vector.getZ()), Color.black);
    }
 public void Calculate()
 {
     try
     {//parse strings into floating point numbers
         float v_x     = Single.Parse(vect_inputs[0].text);
         float v_y     = Single.Parse(vect_inputs[1].text);
         float v_z     = Single.Parse(vect_inputs[2].text);
         float plane_a = Single.Parse(plane_inputs[0].text);
         float plane_b = Single.Parse(plane_inputs[1].text);
         float plane_c = Single.Parse(plane_inputs[2].text);
         float plane_d = Single.Parse(plane_inputs[3].text);
         if (plane_a == 0 && plane_b == 0 && plane_c == 0)
         {
             throw new Exception("Coefficients cannot all be zero!");
         }
         float num = Single.Parse(scalar_input.text);
         if (num < 0)
         {
             throw new Exception("Only positive tolerance allowed!");
         }
         vector    = new MyVector3(v_x, v_y, v_z);
         plane     = new Plane(plane_a, plane_b, plane_c, plane_d);
         tolerance = num;
     }
     catch (Exception e)
     {//parsing failed
         Debug.LogError(e.Message);
         vect_inputs[0].text  = "";
         vect_inputs[1].text  = "";
         vect_inputs[2].text  = "";
         plane_inputs[0].text = "";
         plane_inputs[1].text = "";
         plane_inputs[2].text = "";
         plane_inputs[3].text = "";
         scalar_input.text    = "";
         return;
     }
     //printe vectors to the scene
     distanceFromPlane.text = vector.DistanceFromPlane(plane).ToString("0.000");
     isOnPlane.text         = vector.IsOnPlane(plane, tolerance).ToString();
 }
Beispiel #5
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);
            }
        }
    }