Exemplo n.º 1
0
        // Add a Physic Plane to the world
        public void AddPlane(PhysicWorldModel worldModel, OnPlaneModelChanged callback, object context, params FixedVector3[] paramPoints)
        {
            PhysicPlaneModel planeModel = new PhysicPlaneModel(paramPoints);

            addPlaneCallbacks[planeModel] = new Eppy.Tuple <OnPlaneModelChanged, object>(callback, context);
            StateManager.state.AddModel(planeModel, OnPlaneAdded, worldModel);
        }
Exemplo n.º 2
0
        // Delegate for when a plane is removed, it redirects to the caller delegate
        private void OnPlaneRemoved(Model model, object context)
        {
            Eppy.Tuple <OnPlaneModelChanged, object> callbackTuple;
            PhysicPlaneModel planeModel = model as PhysicPlaneModel;
            PhysicWorldModel worldModel = context as PhysicWorldModel;

            if (planeModel == null || worldModel == null)
            {
                // Something went wrong!
                return;
            }
            if (removePlaneCallbacks.TryGetValue(planeModel, out callbackTuple))
            {
                if (callbackTuple.Item1 != null)
                {
                    callbackTuple.Item1(planeModel, callbackTuple.Item2);
                }
                removePlaneCallbacks.Remove(planeModel);
                worldModel.planeModels.Remove(model.Index);
            }
        }
Exemplo n.º 3
0
 // Remove a Physic Plane from the world
 public void RemovePlane(PhysicWorldModel worldModel, PhysicPlaneModel planeModel, OnPlaneModelChanged callback = null, object context = null)
 {
     removePlaneCallbacks[planeModel] = new Eppy.Tuple <OnPlaneModelChanged, object>(callback, context);
     StateManager.state.RemoveModel(planeModel, OnPlaneRemoved, worldModel);
 }
        // Collision reaction.
        // Return true if collision is considered stable (no position modifications occured)
        public virtual bool OnCollision(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection)
        {
            //		if (pointModel.position == intersection){
            //			// Nothing to change
            //			return true;
            //		}

            // Pick one of two methods depending on the plane's normal angle against up vector
            FixedFloat planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Up);

            // If it's too much inclined, use natural reaction
            if (planeAngle > FixedFloat.PI * 0.4)
            {
                // check direction against 4 walls
                FixedFloat maxDelta = FixedFloat.PI * 0.4;
                planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Left);
                if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta)
                {
                    // collision in the X axis
                    FixedFloat inpactX = pointModel.GetVelocity().X - planeModel.GetVelocity().X;
                    if (FixedFloat.Abs(inpactX) > FixedFloat.Abs(newCollisionInpact.X))
                    {
                        newCollisionInpact.X = inpactX;
                    }
                }
                planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Forward);
                if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta)
                {
                    // collision in the Z axis
                    FixedFloat inpactZ = pointModel.GetVelocity().Z - planeModel.GetVelocity().Z;
                    if (FixedFloat.Abs(inpactZ) > FixedFloat.Abs(newCollisionInpact.Z))
                    {
                        newCollisionInpact.Z = inpactZ;
                    }
                }
                return(CollisionNaturalReaction(world, pointModel, planeModel, intersection));
            }
            else
            {
                // Otherwise we're hitting the ground, do not slide
                FixedFloat inpactY = pointModel.GetVelocity().Y - planeModel.GetVelocity().Y;
                if (FixedFloat.Abs(inpactY) > FixedFloat.Abs(newCollisionInpact.Y))
                {
                    newCollisionInpact.Y = inpactY;
                }
                // We use a lot of arguments here just to avoid recalculating them
                return(CollisionGroundReaction(world, pointModel, planeModel, intersection));
            }
        }
        // Natural reaction: slide along the plane
        protected bool CollisionNaturalReaction(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection)
        {
            bool intersectionChanged = false;

            if (pointModel.position != intersection)
            {
                // Project remaining velocity against the plane
                FixedVector3 normal            = planeModel.normal;
                FixedVector3 pos1              = pointModel.position;
                FixedVector3 pos2              = pointModel.position + normal;
                FixedVector3 pointDeltaPos     = pos2 - pos1;
                FixedVector3 pos1ToOrigin      = planeModel.origin - pos1;
                FixedFloat   dotDeltaPosNormal = FixedVector3.Dot(pointDeltaPos, normal);
                FixedFloat   t = FixedVector3.Dot(pos1ToOrigin, normal) / dotDeltaPosNormal;
                FixedVector3 newIntersection = pos1 + t * pointDeltaPos;
                if (newIntersection != intersection)
                {
                    intersection        = newIntersection;
                    intersectionChanged = true;
                }

                // finally, our new position is the intersection point
                pointModel.position = intersection;
            }

            // in the end, also sum the plane velocity, essential for platforms
            GainPlaneVelocity(world, pointModel, planeModel);

            return(!intersectionChanged);            // if intersection didn't change, it's considered stable
        }
        // Note: objects over elevators may behave in a weird way if gravity isn't enough to keep them grounded
        // with increased gravity or slower elevators everything seems smoother
        protected void KillGravityEffectAgainstPlane(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel)
        {
            FixedVector3 normal     = planeModel.normal;
            FixedVector3 defaultVel = pointModel.GetDefaultVelocityAffector();

            //FixedVector3 velToAdd = FixedVector3.Zero;
            if ((world.gravity.X < 0 && defaultVel.X < world.gravity.X && normal.X > 0) || (world.gravity.X > 0 && defaultVel.X > world.gravity.X && normal.X < 0))
            {
                defaultVel.X = world.gravity.X;
                //velToAdd.X = world.gravity.X - defaultVel.X;
            }

            if ((world.gravity.Y < 0 && defaultVel.Y < world.gravity.X && normal.Y > 0) || (world.gravity.Y > 0 && defaultVel.Y > world.gravity.Y && normal.Y < 0))
            {
                defaultVel.Y = world.gravity.Y;
                //velToAdd.Y = world.gravity.Y - defaultVel.Y;
            }

            if ((world.gravity.Z < 0 && defaultVel.Z < world.gravity.Z && normal.Z > 0) || (world.gravity.Z > 0 && defaultVel.Z > world.gravity.Z && normal.Z < 0))
            {
                defaultVel.Z = world.gravity.Z;
                //velToAdd.Z = world.gravity.Z - defaultVel.Z;
            }

            //UnityEngine.Debug.Log("Setting default velocity affector: " + defaultVel);
            pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] = defaultVel;
            //SetDefaultVelocityAffector(defaultVel);
            //AddDefaultVelocityAffector(velToAdd);
        }
        protected void GainPlaneVelocity(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel)
        {
            FixedVector3 velocityToAdd = planeModel.GetVelocity();

            // Only add velocity that doesn't conflict with gravity, otherwise it starts flickering
            if (velocityToAdd.X > 0 && world.gravity.X < 0 || velocityToAdd.X < 0 && world.gravity.X > 0)
            {
                velocityToAdd.X = 0;
            }
            if (velocityToAdd.Y > 0 && world.gravity.Y < 0 || velocityToAdd.Y < 0 && world.gravity.Y > 0)
            {
                velocityToAdd.Y = 0;
            }
            if (velocityToAdd.Z > 0 && world.gravity.Z < 0 || velocityToAdd.Z < 0 && world.gravity.Z > 0)
            {
                velocityToAdd.Z = 0;
            }

            AddVelocityAffector(pointModel, collisionVelocityAffectorName, velocityToAdd);
        }