All pastes #80998 Raw Edit

Stuff

public text v1 · immutable
·published 2006-07-07 00:57 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Text;
using Math2D;
using Microsoft.DirectX;

// Aliases
using PhysicsShapes = FRB.Physics.PhysicsManager.PhysicsShapes;

namespace FRB.Physics
{
    public class PhysicsObject : AttachablePoly
    {
        const int LEFT = 0;
        const int RIGHT = 1;
        const int TOP = 2;
        const int BOTTOM = 3;

        private int LastCollisionSide = -1;

        public Point mCenterOfMass = new Point(0,0);
        public Point mCenterPoint = new Point(0, 0);
        
        public float mMass = 1f;
        public float mElasticCoefficient = 1f;
        public float mStaticFriction = 0;
        public float mKineticFriction = 0;

        public bool mMoveable = false;
        public bool mCollidable = true;

        public PhysicsShapes mShape;

        public float sclX = 0;
        public float sclY = 0;

        public float mRadius = 1;

        public int Layer = 0;

        private Vector3 mOldPosition = new Vector3(0, 0, 0);
        private Vector3 mOldVelocity = new Vector3(0, 0, 0);
        private Vector3 mOldAcceleration = new Vector3(0, 0, 0);

        static double differenceX;
        static double differenceY;

        private List<PhysicsForce> mConstantForces = new List<PhysicsForce>();
        private List<PhysicsForce> mImpulseForces = new List<PhysicsForce>();


        public PhysicsObject()
            : base(0)
        {
            SetShape(PhysicsShapes.Point);
        }


        public PhysicsObject(PhysicsShapes NewShape) 
            : base(0)
        {
            SetShape(NewShape);
        }

        public PhysicsObject(Sprite newSprite)
            : base(0)
        {

            SetShape(PhysicsShapes.Square);
            
            Point[] SquarePoint = new Point[4];
                       
            // Point 1
            SquarePoint[0].x = -newSprite.sclX;
            SquarePoint[0].y = newSprite.sclY;

            // Point 2
            SquarePoint[1].x = newSprite.sclX;
            SquarePoint[1].y = newSprite.sclY;

            // Point 3
            SquarePoint[2].x = -newSprite.sclX;
            SquarePoint[2].y = -newSprite.sclY;

            // Point 4
            SquarePoint[3].x = newSprite.sclX;
            SquarePoint[3].y = -newSprite.sclY;
          
            // Create Our Square
            SetPointsForVertices(SquarePoint);

            sclX = newSprite.sclX;
            sclY = newSprite.sclY;
        }

        public void InitializeObject()
        {



        }

        private void SetPointsForVertices(Point[] NewPoints)
        {
            // Add New Points
            for (int i = 0; i < NewPoints.Length; i++)
                AddPoint(NewPoints[i].x, NewPoints[i].y);
        }


        public void SetShape(PhysicsShapes NewShape)
        {
            switch (NewShape)
            {
                case PhysicsShapes.Polygon:
                    mShape = PhysicsShapes.Polygon;
                    break;
                case PhysicsShapes.Square:

                    mShape = PhysicsShapes.Square;


                    break;
                case PhysicsShapes.Circle:

                    mShape = PhysicsShapes.Circle;

                    break;
                case PhysicsShapes.Point:

                    // Setup Default Properties of a Point

                    mShape = PhysicsShapes.Point;
                    mCollidable = false;


                    break;
            }
        }



        public void UpdateObject()
        {
            if (DependentOn == null)
            {
                for (int i = 0; i < vertices; i++)
                {
                    p[i].x = position.X + relP[i].x;
                    p[i].y = position.Y + relP[i].y;
                }

                UpdateScl();
            }

            ApplyConstantForces();
        }


        public void StopAllMovement()
        {
            mOldVelocity = velocity;
            mOldAcceleration = acceleration;

            xVelocity = 0;
            yVelocity = 0;

            xAcceleration = 0;
            yAcceleration = 0;
        }

        public void StartFromOldMovement()
        {
            velocity = mOldVelocity;
            acceleration = mOldAcceleration;
        }


        public void ApplyConstantForces()
        {
            for (int i = 0; i < mConstantForces.Count; i++)
            {
                mConstantForces[i].UpdateForce(this);
            }
        }

        public void ApplyImpulseForces()
        {
            // Apply Impulse Forces
            for (int i = 0; i < mImpulseForces.Count; i++)
            {
                mImpulseForces[i].UpdateForce(this);
            }

            // Delete the List now that we've applyed them
            mImpulseForces.Clear();
        }

        public void FindCollisionForce(PhysicsObject cObject)
        {
            Vector3 mVector1 = new Vector3();
            Vector3 mVector2 = new Vector3();
            
            Vector3 mVector3 = new Vector3();
            Vector3 mVector4 = new Vector3();

            switch (cObject.mShape)
            {
                case PhysicsShapes.Square:


                    switch (LastCollisionSide)
                    {
                        case LEFT: 
                            break;
                        case RIGHT: 
                            break;
                        case TOP: 
                            break;
                        case BOTTOM: 
                            break;
                    }




                    mVector1.X = cObject.rotationMatrix.M21;
                    mVector1.Y = cObject.rotationMatrix.M22;
                    mVector1.Z = cObject.rotationMatrix.M23;

                    mVector2.X = this.rotationMatrix.M21;
                    mVector2.Y = this.rotationMatrix.M22;
                    mVector2.Z = this.rotationMatrix.M23;

                    mVector1.Normalize();

                    mVector3 = mVector2 - 2 * mVector1 * (Vector3.Dot(mVector1, mVector2));

                    velocity = mVector3 * ((((mElasticCoefficient + 1) * cObject.mMass * cObject.mOldVelocity.Length()) + (mOldVelocity.Length() * (mMass - (mElasticCoefficient * cObject.mMass)))) / (mMass + cObject.mMass));

                    cObject.velocity = mVector3 * ((((cObject.mElasticCoefficient + 1) * mMass * mOldVelocity.Length()) + (cObject.mOldVelocity.Length() * (cObject.mMass - (cObject.mElasticCoefficient * mMass)))) / (mMass + cObject.mMass));


                    break;

                case PhysicsShapes.Circle:

                    Vector3 Norm = new Vector3();

                    Vector3 Norm1 = new Vector3();
                    Vector3 Norm2 = new Vector3();

                    Vector3 Tang1 = new Vector3();
                    Vector3 Tang2 = new Vector3();

                    Norm = this.position - cObject.position;
                    Norm.Normalize();

                    Norm1 = (Vector3.Dot(velocity, -Norm)) * -Norm;
                    Norm2 = (Vector3.Dot(cObject.velocity, Norm)) * Norm;


                    if (Norm1.X == 0 && Norm1.Y == 0)
                        Norm1 = Norm2;
                    else if (Norm2.X == 0 && Norm2.Y == 0)
                        Norm2 = Norm1;

                    Tang1 = Norm1 - velocity;
                    Tang2 = Norm2 - cObject.velocity;

                    mVector1 = Tang2 + Norm2;
                    mVector2 = Tang1 + Norm1;

                    mVector1.Normalize();
                    mVector2.Normalize();

                    float MyVel1 = ((((mElasticCoefficient + 1) * cObject.mMass * -cObject.velocity.Length()) + (velocity.Length() * (mMass - (mElasticCoefficient * cObject.mMass)))) / (mMass + cObject.mMass));
                    float MyVel2 = ((((cObject.mElasticCoefficient + 1) * mMass * velocity.Length()) + (-cObject.velocity.Length() * (cObject.mMass - (cObject.mElasticCoefficient * mMass)))) / (mMass + cObject.mMass));

                    velocity = mVector1 * MyVel1;
                    cObject.velocity = mVector2 * MyVel2;

                    break;

            }
        }


        public PhysicsForce EnvironmentGravitationalForce(Vector3 Direction, float Acceleration)
        {
            PhysicsForce newConstantForcesArray = new PhysicsForce(PhysicsForce.ForceType.EnvironmentConstantGravitational);

            mConstantForces.Add(newConstantForcesArray);

            newConstantForcesArray.DirectionV = Direction;
            newConstantForcesArray.Acceleration = Acceleration;

            return newConstantForcesArray;
        }

        public PhysicsForce PositionalGravitationalForce(Vector3 Position, Vector3 Direction, float Acceleration)
        {
            PhysicsForce newConstantForcesArray = new PhysicsForce(PhysicsForce.ForceType.PositionalConstantGravitational);

            mConstantForces.Add(newConstantForcesArray);

            newConstantForcesArray.PositionV = Position;
            newConstantForcesArray.DirectionV = Direction;
            newConstantForcesArray.Acceleration = Acceleration;

            return newConstantForcesArray;
        }


        public bool PollygonCollisionAgainst(PhysicsObject cPoly)
        {
            // make sure that the two are touching or else you don't want to move this instance
            if (this.isTouching(cPoly))
            {
                Point[] pointsInside = this.GetPointsInside(cPoly);

                double longestDistanceSquared = double.NegativeInfinity;

                Point tempVector;
                Point vectorTo = new Point(0, 0);

                for (int i = 0; i < pointsInside.Length; i++)
                {
                    tempVector = pointsInside[i].VectorTo(cPoly);
                    if (tempVector.x * tempVector.x + tempVector.y * tempVector.y > longestDistanceSquared)
                    {
                        vectorTo = tempVector;
                        longestDistanceSquared = vectorTo.x * vectorTo.x + vectorTo.y * vectorTo.y;

                    }
                }

                pointsInside = cPoly.GetPointsInside(this);
                for (int i = 0; i < pointsInside.Length; i++)
                {
                    tempVector = pointsInside[i].VectorTo(this);
                    if (tempVector.x * tempVector.x + tempVector.y * tempVector.y > longestDistanceSquared)
                    {
                        vectorTo = tempVector;
                        longestDistanceSquared = vectorTo.x * vectorTo.x + vectorTo.y * vectorTo.y;

                        // We want to reverse the vector here because this instance is going to be moved.
                        vectorTo.x = -vectorTo.x;
                        vectorTo.y = -vectorTo.y;
                    }
                }

                topParent.x += (float)vectorTo.x;
                topParent.y += (float)vectorTo.y;

                return true;
            }

            return false;                      
            
        }

        public bool rectCollisionMoveRotation(PhysicsObject PhyObj1, PhysicsObject PhyObj2)
        {
            float tempX = PhyObj1.x;
            float tempY = PhyObj1.y;

            FRB.CommonFunctions.RotatePointAroundPoint(PhyObj2.x, PhyObj2.y, ref tempX, ref tempY, -PhyObj2.rotZ);


            if (tempX - PhyObj1.sclX < PhyObj2.x + PhyObj2.sclX &&
                tempX + PhyObj1.sclX > PhyObj2.x - PhyObj2.sclX &&
                tempY - PhyObj1.sclY < PhyObj2.y + PhyObj2.sclY &&
                tempY + PhyObj1.sclY > PhyObj2.y - PhyObj2.sclY )
            {// looks like we have a collision.  So let's move the object to the edge
                int sideOn = LEFT; // set it to this.  We'll change this if we need to
                double smallest = tempX + PhyObj1.sclX - (PhyObj2.x - PhyObj2.sclX);
                if (smallest < 0) smallest *= -1; // this gets us the absolute distance from the left

                double currentDistance = tempX - PhyObj1.sclX - (PhyObj2.x + PhyObj2.sclX);
                if (currentDistance < 0) currentDistance *= -1;
                if (currentDistance < smallest) { smallest = currentDistance; sideOn = RIGHT; }

                currentDistance = tempY - PhyObj1.sclY - (PhyObj2.y + PhyObj2.sclY);
                if (currentDistance < 0) currentDistance *= -1;
                if (currentDistance < smallest) { smallest = currentDistance; sideOn = TOP; }

                currentDistance = tempY + PhyObj1.sclY - (PhyObj2.y - PhyObj2.sclY);
                if (currentDistance < 0) currentDistance *= -1;
                if (currentDistance < smallest) { smallest = currentDistance; sideOn = BOTTOM; }

                LastCollisionSide = sideOn;

                switch (sideOn)
                {
                    case LEFT: tempX = PhyObj2.x - PhyObj1.sclX - PhyObj2.sclX ; break;
                    case RIGHT: tempX = PhyObj2.x + PhyObj1.sclX + PhyObj2.sclX; break;
                    case TOP: tempY = PhyObj2.y + PhyObj1.sclY + PhyObj2.sclY; break;
                    case BOTTOM: tempY = PhyObj2.y - PhyObj1.sclY - PhyObj2.sclY; break;
                }
                FRB.CommonFunctions.RotatePointAroundPoint(PhyObj2.x, PhyObj2.y, ref tempX, ref tempY, PhyObj2.rotZ);
                PhyObj1.x = tempX;
                PhyObj1.y = tempY;

                return true;
            }
            return false;
        }


        public bool circleCollisionMove(PhysicsObject PhyObj1, PhysicsObject PhyObj2)
        {
            differenceX = PhyObj2.x - PhyObj1.x;
            differenceY = PhyObj2.y - PhyObj1.y;

            double differenceSquared = differenceX * differenceX + differenceY * differenceY;
            double difference = Math.Pow(differenceSquared, .5);

            if (difference - PhyObj1.mRadius - PhyObj2.mRadius < 0)
            {
                double angle = (float)Math.Atan2(PhyObj1.y - PhyObj2.y, PhyObj1.x - PhyObj2.x);

                float distanceToMove = PhyObj1.mRadius + PhyObj2.mRadius;

                PhyObj1.x = PhyObj2.x + (float)Math.Cos(angle) * distanceToMove;
                PhyObj1.y = PhyObj2.y + (float)Math.Sin(angle) * distanceToMove;
                return true;
            }
            else
                return false;


        }



        public static char GetClosestSide(PhysicsObject ObjectToTest, PhysicsObject referenceObject)
        {
            char sideOn = 'l'; // set it to this.  We'll change this if we need to

            double smallest = Math.Abs(
                  ObjectToTest.x + ObjectToTest.sclX - (referenceObject.x - referenceObject.sclX));

            double currentDistance = Math.Abs(
                  ObjectToTest.x - ObjectToTest.sclX - (referenceObject.x + referenceObject.sclX));
           
            if (currentDistance < smallest) { smallest = currentDistance; sideOn = 'r'; }
           
            currentDistance = Math.Abs(
                ObjectToTest.y - ObjectToTest.sclY - (referenceObject.y + referenceObject.sclY));
            
            if (currentDistance < smallest) { smallest = currentDistance; sideOn = 't'; }
            
            currentDistance = Math.Abs(
                ObjectToTest.y + ObjectToTest.sclY - (referenceObject.y - referenceObject.sclY));
            
            if (currentDistance < smallest) { smallest = currentDistance; sideOn = 'b'; }

            return sideOn;
        }


        public bool CollisionCheck(PhysicsObject cObject)
        {
            switch (this.mShape)
            {
                case PhysicsShapes.Polygon:
                    break;
                case PhysicsShapes.Square:

                    switch (cObject.mShape)
                    {
                        case PhysicsShapes.Polygon:
                            break;
                        case PhysicsShapes.Square:

                            return rectCollisionMoveRotation(this, cObject);

                            break;
                        case PhysicsShapes.Circle:
                            break;
                        case PhysicsShapes.Point:
                            break;
                    }

                    break;
                case PhysicsShapes.Circle:

                    switch (cObject.mShape)
                    {
                        case PhysicsShapes.Polygon:
                            break;
                        case PhysicsShapes.Square:
                            break;
                        case PhysicsShapes.Circle:

                            return circleCollisionMove(this, cObject);

                            break;
                        case PhysicsShapes.Point:
                            break;
                    }



                    break;
                case PhysicsShapes.Point:
                    break;
            }
            
            return false;
        }

            

        



    }
}