コード例 #1
0
        // =====
        #region Update

        // Update
        public void Update()
        {
            // Entry logging
      #if IS_LOGGING_METHODS
            Log.Write(String.Format("Entering method for {0}", this.Name));
      #endif

            // Skip if paused
            if (this.IsPaused)
            {
                return;
            }

            /* // Test spool
             * if (Globals.TestBool)
             * {
             * RigidBody rb = (RigidBody)Globals.Scene.Bodies[0];
             * ConvexPolygon cp = (ConvexPolygon)Globals.Scene.Bodies[0].Geometry;
             * Vector2 p = cp.Vertices[2];
             * Vector2 v = rb.Velocity;
             * float w = rb.AngularVelocity;
             * Vector2 vp = cp.GetVelocityAtPoint(p, v, w);
             * Globals.TextFile.Write(String.Format("{0}\t{1}\t{2}", Globals.MathHelper.ToDegrees(cp.Angle), vp.X, vp.Y));
             * } */

            // Reset elapsedSceneTime
            this.elapsedSceneTime = 0.0f;

            // Update targetTotalTime
            this.targetTotalTime += Globals.Clock.ElapsedGameTime;

            // Declare minCollisionTime
            float minCollisionTime;
            // Initialize minCollisions
            List <CollisionResult> minCollisions = new List <CollisionResult>();
            // Initialize restingContacts
            List <CollisionResult> restingContacts = new List <CollisionResult>();
            // Reset substep count
            this.Substep = 0;
            // Initialize substep stopping criteria as false
            bool stop = false;

            // Begin simulation loop
            while (!stop)
            {
                // Increment substep count
                this.Substep++;
                // Initialize minCollisionTime as targetElapsedTime
                minCollisionTime = this.TargetElapsedTime;
                // Clear contact manager
                this.ContactManager.Clear();
                // Clear minCollisions
                minCollisions.Clear();
                // Clear restingContacts
                restingContacts.Clear();

                #region [1]  Find earliest time of impact

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("this.TotalSceneTime = {0}, this.Substep = {1}", this.TotalSceneTime, this.Substep));
                Log.Write(String.Format("Now finding earliest time of impact"));
        #endif

                // Loop through all bodies in scene
                for (int i = 0; i < this.Bodies.Count; i++)
                {
                    // Loop through all other bodies in scene
                    for (int j = i + 1; j < this.Bodies.Count; j++)
                    {
                        // Perform a collision check
                        CollisionResult collisionResult = new CollisionResult(this.Bodies[i], this.Bodies[j], minCollisionTime);

                        // Check if this is a resting contact
                        if (collisionResult.IsResting)
                        {
                            // If so, create contact
                            // Contact contact = new Contact(collisionResult);
                            // Add to manager
                            // this.ContactManager.Add(contact);

                            // If so, add to restingContacts
                            restingContacts.Add(collisionResult);
                        }

                        // Update minCollisionTime
                        else if (collisionResult.Time < minCollisionTime)
                        {
                            #region Case 1:  Strictly first

                            // Reset minCollision list
                            minCollisions.Clear();
                            minCollisions.Add(collisionResult);

                            // Update minCollisionTime
                            minCollisionTime = collisionResult.Time;

                            // Physics logging
              #if IS_LOGGING_PHYSICS
                            if (Log.Subject1 == null || (this.Name == Log.Subject1 && (Log.Subject2 == null || this.Bodies[j].Name == Log.Subject2)))
                            {
                                Log.Write(String.Format("This collision occurs strictly first with t = {0}", collisionResult.Time));
                            }
              #endif

                            #endregion
                        }
                        else if (collisionResult.Time == minCollisionTime)
                        {
                            #region Case 2:  Strictly first

                            // Add to minCollision list
                            minCollisions.Add(collisionResult);

                            // Physics logging
              #if IS_LOGGING_PHYSICS
                            if (Log.Subject1 == null || (this.Name == Log.Subject1 && (Log.Subject2 == null || this.Bodies[j].Name == Log.Subject2)))
                            {
                                Log.Write(String.Format("This collision is tied for first with t = {0}", collisionResult.Time));
                            }
              #endif

                            #endregion
                        }
                        else
                        {
                            #region Case 3:  Not first

                            // Physics logging
              #if IS_LOGGING_PHYSICS
                            if (Log.Subject1 == null || (this.Name == Log.Subject1 && (Log.Subject2 == null || this.Bodies[j].Name == Log.Subject2)))
                            {
                                Log.Write(String.Format("This collision does not occur first with t = {0} > {1}", collisionResult.Time, minCollisionTime));
                            }
              #endif

                            #endregion
                        }
                    }

                    // Clear sweep object
                    this.Bodies[i].Sweep.Clear();
                }

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("The earliest time of impact is {0}", minCollisionTime));
        #endif

                #endregion

                #region [2]  Perform a time step

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("Now performing a time step of minCollisionTime = {0} seconds", minCollisionTime));
        #endif

                // Loop through all bodies in scene
                for (int i = 0; i < this.Bodies.Count; i++)
                {
                    // Move body
                    this.Bodies[i].Move(minCollisionTime);
                }

                #endregion

                #region [3]  Find contact points

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("minCollisions.Count = {0}", minCollisions.Count));
                Log.Write(String.Format("restingContacts.Count = {0}", restingContacts.Count));
                Log.Write(String.Format("Now finding collision contact points"));
        #endif

                // Loop through minCollisions
                for (int i = 0; i < minCollisions.Count; i++)
                {
                    // Get contact
                    Contact contact = new Contact(minCollisions[i]);
                    // Add to contact manager
                    this.ContactManager.AddContact(contact);
                }

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("Now finding resting contact points"));
        #endif

                // Loop through restingContacts
                for (int i = 0; i < restingContacts.Count; i++)
                {
                    // Get contact
                    Contact contact = new Contact(restingContacts[i]);
                    // Add to contact manager
                    this.ContactManager.AddContact(contact);
                }

                #endregion

                #region [4]  Update velocity due to external forces

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("Now updating velocity due to external forces"));
        #endif

                // Loop through all bodies in scene
                for (int i = 0; i < this.Bodies.Count; i++)
                {
                    // Point to body
                    RigidBody body = (RigidBody)this.Bodies[i];
                    // Add field impulses to queue
                    body.GetFieldImpulses(minCollisionTime);
                    // Process and drain applied impulse queue
                    body.FeelImpulses();
                }

                #endregion

                #region [5]  Resolve all contacts

                // Physics logging
        #if IS_LOGGING_PHYSICS
                Log.Write(String.Format("Now resolving contacts"));
        #endif

                // Resolve all contacts
                this.ContactManager.Resolve();

                // Loop through all bodies in scene
                for (int i = 0; i < this.Bodies.Count; i++)
                {
                    // Point to body
                    RigidBody body = (RigidBody)this.Bodies[i];
                    // Process and drain applied impulse queue
                    body.FeelImpulses();
                }

                #endregion

                /* // Dampening
                 * for (int i = 0; i < this.Bodies.Count; i++)
                 * {
                 * this.Bodies[i].Velocity *= 0.99f;
                 * this.Bodies[i].AngularVelocity *= 0.99f;
                 * } */

                // Update elapsed scene time
                this.elapsedSceneTime += minCollisionTime;
                this.totalSceneTime   += minCollisionTime;

                // Check stopping criteria
                if (this.totalSceneTime >= this.targetTotalTime)
                {
                    stop = true;
                }

                // Substep override
                if (this.Substep >= 10)
                {
                    stop = true;
                }
            }

            // Exit logging
      #if IS_LOGGING_METHODS
            Log.Write(String.Format("Exiting method for {0}", this.Name));
      #endif
        }
コード例 #2
0
        // =====
        #region Update

        // Update
        public override void Update()
        {
            // Entry logging
      #if IS_LOGGING_METHODS
            Log.Write(String.Format("Entering method for {0}", this.Name));
      #endif

            // Physics logging
      #if IS_LOGGING_PHYSICS
            if (this.Name == Log.Subject1)
            {
                Log.Write(this.Name + " now starting update");
                Log.Write(String.Format("Pre-update state:  centroid = {0}, angle = {1:0.0000}",
                                        this.Geometry.Centroid, this.Geometry.Angle));
                Log.Write(String.Format("Pre-update state:  bottom = {0:0.0000}, v = {1}, w = {2}",
                                        this.Geometry.MinBoundingBox.Bottom, this.Velocity, this.AngularVelocity));
                Log.Write("this.Contacts.Count = " + this.Contacts.Count);
            }
      #endif

            // If at rest, go to exit
            if (this.IsSleeping)
            {
                goto exit;
            }

            // If neither translatable nor rotatable, go to exit
            if (!this.IsRotatable && !this.IsTranslatable)
            {
                goto exit;
            }

            // [Test]  Dampen
            this.angularVelocity *= 0.99f;
            this.velocity        *= 0.99f;


            // ===
            #region [1]  Drain applied impulse queue

            // Add force field impulses to queue
            //this.GetFieldImpulses();
            // Update velocities
            //this.FeelImpulses();
            // Add contact impulses to queue
            //this.GetContactImpulses();
            // Update velocities again
            //this.FeelImpulses();

            #endregion


            // ===
            #region [3]  Check for collisions

            // Physics logging
      #if IS_LOGGING_PHYSICS
            if (this.Name == Log.Subject1)
            {
                Log.Write(this.Name + " now checking for collisions");
            }
      #endif

            // Get elapsed scene time
            float dt = (float)this.Scene.ElapsedSceneTime;
            // Initialize overall minCollisionTime as elapsedSceneTime
            float minCollisionTime = dt;
            // Initialize list of earliest collisions
            List <CollisionResult> collisions = new List <CollisionResult>();

            // Loop through nearby objects
            for (int i = 0; i < Globals.Scene.Bodies.Count; i++)
            {
                // If object is self, skip this iteration
                if (Globals.Scene.Bodies[i].Equals(this))
                {
                    continue;
                }

                // Perform a collision test
                CollisionResult collisionResult = new CollisionResult(this, Globals.Scene.Bodies[i], this.Scene.TargetElapsedTime);

                // Check if this collision occurs first
                if (collisionResult.Time < minCollisionTime)
                {
                    #region Case 1:  Strictly first

                    // If so, update minCollisionTime and reset the list
                    minCollisionTime = collisionResult.Time;
                    collisions.Clear();
                    collisions.Add(collisionResult);

                    // Physics logging
          #if IS_LOGGING_PHYSICS
                    if (this.Name == Log.Subject1)
                    {
                        Log.Write(String.Format("This collision occurs first with t = {0:0.0000}, which is {1:00.00%} of dt", collisionResult.Time, collisionResult.Time / dt));
                    }
          #endif

                    #endregion
                }
                // Otherwise, check if this collision is tied for first
                else if (collisionResult.Time == minCollisionTime)
                {
                    #region Case 2:  Tied for first

                    // If so, add to list
                    collisions.Add(collisionResult);

                    // Physics logging
          #if IS_LOGGING_PHYSICS
                    if (this.Name == Log.Subject1)
                    {
                        Log.Write(String.Format("This collision is tied for first with t = {0:0.0000}", collisionResult.Time));
                    }
          #endif

                    #endregion
                }
                // Otherwise, forget this collision
                else
                {
                    #region Case 3:  Not first

                    // Physics logging
          #if IS_LOGGING_PHYSICS
                    if (this.Name == Log.Subject1)
                    {
                        Log.Write(String.Format("This collision does not occur first with t = {0:0.0000} > {1:0.0000}", collisionResult.Time, minCollisionTime));
                    }
          #endif

                    #endregion
                }
            }

            // Physics logging
      #if IS_LOGGING_PHYSICS
            if (this.Name == Log.Subject1)
            {
                Log.Write(String.Format("{0} finished checking for collisions:  count = {1}, minCollisionTime = {2:0.0000}, ", this.Name, collisions.Count, minCollisionTime));
            }
      #endif

            #endregion


            // ===
            #region [4]  Rotate and translate

            // Translate and rotate shape
            this.Geometry.RotateAndTranslateBy(
                this.AngularVelocity * minCollisionTime,
                this.RotationalAxis,
                this.Velocity * minCollisionTime);

            // Update rotational axis
            this.RotationalAxis = this.Geometry.Centroid;

            #endregion


            // ===
            #region [5]  Get contact points

            // Clear old contacts
            this.Contacts.Clear();

            // Loop through earliest collisions
            for (int i = 0; i < collisions.Count; i++)
            {
                // Get contact points
                Contact contact = new Contact(collisions[i]);
                // Add to list
                this.Contacts.Add(contact);
            }

            #endregion

            // Add force field impulses to queue
            this.GetFieldImpulses(this.Scene.ElapsedSceneTime);
            // Update velocities
            this.FeelImpulses();
            // Add contact impulses to queue
            // this.GetContactImpulses(this.Scene.ElapsedSceneTime);
            // Update velocities again
            this.FeelImpulses();


            // ===
            #region [*]  Exit trap
exit:

            // Null op
            this.RotationalAxis = this.Geometry.Centroid;

            // Physics logging
      #if IS_LOGGING_PHYSICS
            if (this.Name == Log.Subject1)
            {
                Log.Write(this.Name + " finished update");
                Log.Write("==========");
            }
      #endif

            // [*]  Exit logging
      #if IS_LOGGING_METHODS
            Log.Write(String.Format("Exiting method for {0}", this.Name));
      #endif

            #endregion
        }