public override void Initialize()
        {
            // Compute the Eye position into the entity
            _entityEyeOffset = new Vector3(0, Player.DefaultSize.Y / 100 * 80, 0);

            // Set Position
            // Set the entity world position following the position received from server
            _worldPosition = Player.Position;

            // Compute the initial Player world bounding box
            VisualVoxelEntity.RefreshWorldBoundingBox(ref _worldPosition);

            // Init Velret physic simulator
            _physicSimu = new VerletSimulator(ref VisualVoxelEntity.LocalBBox)
            {
                WithCollisionBouncing = false
            };
            _physicSimu.ConstraintFct += _entityCollisionManager.IsCollidingWithEntity;       //Check against entities first
            _physicSimu.ConstraintFct += _landscapeManager.IsCollidingWithTerrain;            //Landscape checking after

            _entityRotations = new EntityRotations(_inputsManager, _physicSimu);
            _entityRotations.EntityRotationSpeed = Player.RotationSpeed;
            _entityRotations.SetOrientation(Player.HeadRotation, _worldPosition + _entityEyeOffset);

            // Set displacement mode
            _playerCharacter.DisplacementMode = Player.DisplacementMode;
        }
    public void Start()
    {
        switch (simulationMode)
        {
        case SimulationMode.Verlet:
            verletSimulator = new VerletSimulator(ref verletConstants)
            {
                simulationManager = this,
                targetManager     = TargetManager,
                particleDisplayer = Displayer
            };
            verletSimulator.Start();
            break;

        case SimulationMode.Euler:
            eulerSimulator = new EulerSimulator(ref eulerConstants)
            {
                simulationManager = this,
                targetManager     = TargetManager,
                particleDisplayer = Displayer
            };
            eulerSimulator.Start();
            break;
        }

        // Call this from here to make sure all the required variables are set
        Displayer.SpawnParticles();
    }
示例#3
0
        void Start()
        {
            debuggers = new List <GameObject>();
            particles = new List <VParticle>();
            for (int i = 0; i < count; i++)
            {
                var p = new VParticle(Vector3.right * i);
                particles.Add(p);

                var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.localScale = Vector3.one * 0.25f;
                debuggers.Add(sphere);
            }
            ;

            for (int i = 0; i < count; i++)
            {
                if (i != count - 1)
                {
                    var a = particles[i];
                    var b = particles[i + 1];
                    var e = new VEdge(a, b);
                    a.Connect(e);
                    b.Connect(e);
                }
            }

            simulator = new VerletSimulator(particles);
        }
        private static bool IsSlopeCollisionDetection(VerletSimulator physicSimu, VisualEntity entityTesting, ref BoundingBox playerBoundingBox, ref BoundingBox playerBoundingBox2Evaluate, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ItemOrientation slopeOrientation, bool onSlidingSlope, out bool isSliding)
        {
            isSliding = false;

            Vector3 entityPosition = newPosition2Evaluate.AsVector3();
            float   posi           = 0.0f;

            float L = 0.0f;
            float H = entityTesting.WorldBBox.Maximum.Y - entityTesting.WorldBBox.Minimum.Y;

            switch (slopeOrientation)
            {
            case ItemOrientation.North:
                L    = entityTesting.WorldBBox.Maximum.Z - entityTesting.WorldBBox.Minimum.Z;
                posi = (entityPosition.Z + playerBoundingBox.Maximum.Z) - entityTesting.WorldBBox.Minimum.Z;
                break;

            case ItemOrientation.South:
                L    = entityTesting.WorldBBox.Maximum.Z - entityTesting.WorldBBox.Minimum.Z;
                posi = entityTesting.WorldBBox.Maximum.Z - (entityPosition.Z + playerBoundingBox.Minimum.Z);
                break;

            case ItemOrientation.East:
                L    = entityTesting.WorldBBox.Maximum.X - entityTesting.WorldBBox.Minimum.X;
                posi = entityTesting.WorldBBox.Maximum.X - (entityPosition.X + playerBoundingBox.Minimum.X);
                break;

            case ItemOrientation.West:
                L    = entityTesting.WorldBBox.Maximum.X - entityTesting.WorldBBox.Minimum.X;
                posi = (entityPosition.X + playerBoundingBox.Maximum.X) - entityTesting.WorldBBox.Minimum.X;
                break;

            default:
                break;
            }

            float posiOriginal = posi;

            posi = posi / L;
            float Y = posi * H;

            Y = Math.Min(Math.Max(Y, 0), 1);

            if (onSlidingSlope)
            {
                return(SlidingSlope(physicSimu, entityTesting, Y, ref newPosition2Evaluate, ref previousPosition, slopeOrientation, out isSliding));
            }

            //Apply only if new Y is >= Current Y
            if (entityTesting.WorldBBox.Minimum.Y + Y > newPosition2Evaluate.Y)
            {
                return(NormalSlope(physicSimu, entityTesting, Y, ref newPosition2Evaluate, ref previousPosition));
            }
            else
            {
                physicSimu.AllowJumping = true;
                return(false);
            }
        }
        //Entity vs Player Collision detection
        //Used by physics engine
        public void IsCollidingWithEntity(VerletSimulator physicSimu, ref BoundingBox playerBoundingBox, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ref Vector3D originalPosition)
        {
            if (IsDirty)
            {
                _timer_OnTimerRaised();
            }

            IsCollidingWithEntity(physicSimu, AroundEntities(), ref playerBoundingBox, ref newPosition2Evaluate, ref previousPosition, ref originalPosition);
        }
示例#6
0
        public void Update(DynamicUpdateState gameTime)
        {
            var elapsedS = (float)gameTime.RealTime.TotalSeconds;

            Vector3D newPos;

            VerletSimulator.Simulate(elapsedS, out newPos);
            Npc.DynamicEntity.Position = newPos;

            VerletSimulator.CurPosition = Npc.DynamicEntity.Position;

            if (IsMoving)
            {
                if (Vector3D.DistanceSquared(_pathTargetPoint, Npc.DynamicEntity.Position) < 0.1d)
                {
                    FollowNextPoint();
                }

                _moveDirection = _pathTargetPoint - Npc.DynamicEntity.Position;

                _jump            = _moveDirection.Y > 0;
                _moveDirection.Y = 0;

                //if (Vector3D.DistanceSquared(VerletSimulator.PrevPosition, VerletSimulator.CurPosition) < 0.01f)
                //{
                //    if (Math.Abs(_moveDirection.X) < Math.Abs(_moveDirection.Z))
                //        _moveDirection.Z = 0.1f * Math.Sign(_moveDirection.Z);
                //    else
                //        _moveDirection.X = 0.1f * Math.Sign(_moveDirection.X);
                //}

                _moveDirection.Normalize();

                VerletSimulator.Impulses.Add(new Impulse(elapsedS)
                {
                    ForceApplied = _moveDirection.AsVector3() * Npc.DynamicEntity.MoveSpeed * (_runAway ? 2f : 1f)
                });

                if (_jump && VerletSimulator.OnGround)
                {
                    VerletSimulator.Impulses.Add(new Impulse(elapsedS)
                    {
                        ForceApplied = Vector3.UnitY * 22
                    });
                }
            }

            if (_leader != null && Vector3D.Distance(_leader.Position, Npc.DynamicEntity.Position) > FollowStayDistance)
            {
                if (IsMoving && Vector3D.Distance(new Vector3D(_path.Goal) + CubeCenter, _leader.Position) < FollowStayDistance)
                {
                    return;
                }

                MoveTo(_leader.Position.ToCubePosition());
            }
        }
示例#7
0
        void Start()
        {
            debuggers = new List <GameObject>();
            particles = new List <Node>();

            var offset = -count * 0.5f;

            for (int y = 0; y < count; y++)
            {
                for (int x = 0; x < count; x++)
                {
                    var p = new Node(y * Vector3.forward + (Vector3.right * (x - offset)));
                    particles.Add(p);

                    var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    sphere.transform.localScale = Vector3.one * 0.25f;
                    debuggers.Add(sphere);
                }
            }

            for (int y = 0; y < count; y++)
            {
                if (y != count - 1)
                {
                    for (int x = 0; x < count; x++)
                    {
                        var index = y * count + x;
                        var c     = particles[index];

                        if (x != count - 1)
                        {
                            var right = particles[index + 1];
                            var re    = new Edge(c, right);
                            c.Connect(re); right.Connect(re);
                        }
                        var down = particles[index + count];
                        var de   = new Edge(c, down);
                        c.Connect(de); down.Connect(de);
                    }
                }
                else
                {
                    for (int x = 0; x < count - 1; x++)
                    {
                        var index = y * count + x;
                        var c     = particles[index];
                        var right = particles[index + 1];
                        var re    = new Edge(c, right);
                        c.Connect(re); right.Connect(re);
                    }
                }
            }

            simulator = new VerletSimulator(particles);
        }
        private static bool NormalSlope(VerletSimulator physicSimu, VisualEntity entityTesting, float Y, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition)
        {
            if (((entityTesting.WorldBBox.Minimum.Y + Y) - newPosition2Evaluate.Y) < 0.3f)
            {
                //Push up the player, and stabilize its physic simulation
                newPosition2Evaluate.Y = entityTesting.WorldBBox.Minimum.Y + Y;
                previousPosition.Y     = newPosition2Evaluate.Y;

                physicSimu.OnGround     = true;
                physicSimu.AllowJumping = true;
                return(false);
            }
            else
            {
                return(true);
            }
        }
示例#9
0
        public MoveAI(ServerNpc parentNpc)
        {
            _parentNpc = parentNpc;

            var size = parentNpc.DynamicEntity.DefaultSize;
            var bb   = new BoundingBox(Vector3.Zero, size);

            size.Y = 0;
            bb     = bb.Offset(-size / 2);

            VerletSimulator = new VerletSimulator(ref bb);
            VerletSimulator.ConstraintFct += Npc.Server.LandscapeManager.IsCollidingWithTerrain;
            VerletSimulator.StartSimulation(parentNpc.DynamicEntity.Position);

            FollowKeepDistance = 3;
            FollowStayDistance = 5;
        }
        public static void IsCollidingWithEntity(VerletSimulator physicSimu, IEnumerable <VisualEntity> aroundEntities, ref BoundingBox playerBoundingBox, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ref Vector3D originalPosition)
        {
            bool isSliding = false;

            foreach (var entityTesting in aroundEntities)
            {
                if (!entityTesting.Entity.IsPlayerCollidable)
                {
                    continue;
                }

                //Compute the New world located player bounding box, that will be use for collision detection
                var  playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPosition2Evaluate.AsVector3(), playerBoundingBox.Maximum + newPosition2Evaluate.AsVector3());
                bool isEntityOnSliding;
                CollisionCheck(physicSimu, entityTesting, ref playerBoundingBox, ref playerBoundingBox2Evaluate, ref newPosition2Evaluate, ref previousPosition, out isEntityOnSliding);
                isSliding |= isEntityOnSliding;
            }

            physicSimu.IsSliding = isSliding;
        }
示例#11
0
 void Start()
 {
     vcam      = FindObjectOfType <CinemachineVirtualCamera>();
     particles = new List <Node>();
     for (int i = 0; i < 10; i++)
     {
         var p = new Node(Vector3.down * i, Joints[i]);
         particles.Add(p);
         Joints[i].SetLimb(i);
     }
     ;
     particles[(int)LimbsEnum.Hips].lockInGrip   = true;
     particles[(int)LimbsEnum.Hips].lockPosition = particles[(int)LimbsEnum.Hips].model.transform.position;
     ConnectHumanJoints();
     startPoint = Joints[(int)LimbsEnum.Hips].transform.position.y;
     SetHeight();
     simulator         = new VerletSimulator(particles);
     simulator.freezeZ = FreezZ;
     PreviewEnergy();
     InfoMessageText = "Go Up";
     StartCoroutine(InfoMessageDisplay());
 }
        private static void CollisionCheck(VerletSimulator physicSimu, VisualEntity entityTesting, ref BoundingBox entityBoundingBox, ref BoundingBox boundingBox2Evaluate, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, out bool isSliding)
        {
            isSliding = false;

            if (entityTesting.WorldBBox.Intersects(ref boundingBox2Evaluate))
            {
                if (entityTesting.Entity is Ladder)
                {
                    physicSimu.isInContactWithLadder = true;
                    return;
                }

                //Special treatment in case of an IOrientedSlope entity
                if (entityTesting.Entity is IOrientedSlope)
                {
                    IOrientedSlope entity = (IOrientedSlope)entityTesting.Entity;
                    if (entity.IsOrientedSlope)
                    {
                        SlopeCollisionDetection(physicSimu, entityTesting, ref entityBoundingBox, ref boundingBox2Evaluate, ref newPosition2Evaluate, ref previousPosition, entity.Orientation, entity.IsSlidingSlope, out isSliding);
                        return;
                    }
                }

                switch (entityTesting.Entity.CollisionType)
                {
                case Utopia.Shared.Entities.Entity.EntityCollisionType.BoundingBox:
                    BoundingBoxCollision(physicSimu, entityTesting, ref entityBoundingBox, ref boundingBox2Evaluate, ref newPosition2Evaluate, ref previousPosition);
                    break;

                case Utopia.Shared.Entities.Entity.EntityCollisionType.Model:
                    ModelCollisionDetection(physicSimu, entityTesting, ref entityBoundingBox, ref boundingBox2Evaluate, ref newPosition2Evaluate, ref previousPosition);
                    break;

                default:
                    break;
                }
            }
        }
        private static void SlopeCollisionDetection(VerletSimulator physicSimu, VisualEntity entityTesting, ref BoundingBox playerBoundingBox, ref BoundingBox playerBoundingBox2Evaluate, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ItemOrientation slopeOrientation, bool OnSlidingSlope, out bool isSliding)
        {
            if (IsSlopeCollisionDetection(physicSimu, entityTesting, ref playerBoundingBox, ref playerBoundingBox2Evaluate, ref newPosition2Evaluate, ref previousPosition, slopeOrientation, OnSlidingSlope, out isSliding))
            {
                Vector3D newPositionWithColliding = previousPosition;

                newPositionWithColliding.X = newPosition2Evaluate.X;
                playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
                if (entityTesting.WorldBBox.Intersects(ref playerBoundingBox2Evaluate))
                {
                    newPositionWithColliding.X = previousPosition.X;
                }

                newPositionWithColliding.Z = newPosition2Evaluate.Z;
                playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
                if (entityTesting.WorldBBox.Intersects(ref playerBoundingBox2Evaluate))
                {
                    newPositionWithColliding.Z = previousPosition.Z;
                }

                newPosition2Evaluate = newPositionWithColliding;
            }
        }
        private static void BoundingBoxCollision(VerletSimulator physicSimu, VisualEntity entityTesting, ref BoundingBox entityBoundingBox, ref BoundingBox boundingBox2Evaluate, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition)
        {
            Vector3D newPositionWithColliding = previousPosition;

            newPositionWithColliding.Y = newPosition2Evaluate.Y;
            boundingBox2Evaluate       = new BoundingBox(entityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), entityBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (entityTesting.WorldBBox.Intersects(ref boundingBox2Evaluate))
            {
                //If falling
                if (newPositionWithColliding.Y <= previousPosition.Y)
                {
                    newPositionWithColliding.Y = entityTesting.WorldBBox.Maximum.Y; //previousPosition.Y;
                }
                else
                {
                    newPositionWithColliding.Y = previousPosition.Y;
                }
                previousPosition.Y = newPositionWithColliding.Y;
                _onEntityTop       = true;
            }

            newPositionWithColliding.X = newPosition2Evaluate.X;
            boundingBox2Evaluate       = new BoundingBox(entityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), entityBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (entityTesting.WorldBBox.Intersects(ref boundingBox2Evaluate, 0.001f))
            {
                newPositionWithColliding.X = previousPosition.X;
                _onEntityTop = false;
            }

            newPositionWithColliding.Z = newPosition2Evaluate.Z;
            boundingBox2Evaluate       = new BoundingBox(entityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), entityBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (entityTesting.WorldBBox.Intersects(ref boundingBox2Evaluate, 0.001f))
            {
                newPositionWithColliding.Z = previousPosition.Z;
                _onEntityTop = false;
            }

            //Set the NEW player position after collision tests
            newPosition2Evaluate = newPositionWithColliding;

            // ? Am I on "TOP" of an object ???
            if (_onEntityTop == true)
            {
                physicSimu.OnGround = true;
            }

            if (entityTesting.Entity is IDynamicEntity)
            {
                //Send an impulse message to the Entity, following my "LookAtVector" !
                float impulsePower = 1;
                if (_input.ActionsManager.isTriggered(UtopiaActions.Move_Run))
                {
                    impulsePower = 2;
                }

                _server.ServerConnection.Send(new EntityImpulseMessage
                {
                    DynamicEntityId = (entityTesting.Entity as IDynamicEntity).DynamicId,
                    Vector3         = MQuaternion.GetLookAtFromQuaternion(_player.Player.HeadRotation) * impulsePower
                }
                                              );
            }
        }
        private static bool SlidingSlope(VerletSimulator physicSimu, VisualEntity entityTesting, float Y, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ItemOrientation slopeOrientation, out bool isSliding)
        {
            isSliding = false;

            if (entityTesting.WorldBBox.Minimum.Y + Y >= newPosition2Evaluate.Y)
            {
                if (((entityTesting.WorldBBox.Minimum.Y + Y) - newPosition2Evaluate.Y) < 0.3f)
                {
                    Y = Y - (float)(newPosition2Evaluate.Y - Math.Floor(newPosition2Evaluate.Y));

                    if (Y < 0.001 || Y >= 0.999)
                    {
                        Y = 0.02f;
                    }

                    newPosition2Evaluate.Y += entityTesting.Entity.Friction;

                    isSliding = true;

                    switch (slopeOrientation)
                    {
                    case ItemOrientation.North:
                        newPosition2Evaluate.Z = newPosition2Evaluate.Z - Y;
                        if (physicSimu.IsSliding == false)
                        {
                            physicSimu.SliddingForce = new Vector3(0, 0, -1);
                        }
                        break;

                    case ItemOrientation.South:

                        newPosition2Evaluate.Z = newPosition2Evaluate.Z + Y;

                        if (physicSimu.IsSliding == false)
                        {
                            physicSimu.SliddingForce = new Vector3(0, 0, 1);
                        }

                        break;

                    case ItemOrientation.East:
                        newPosition2Evaluate.X = newPosition2Evaluate.X + Y;

                        if (physicSimu.IsSliding == false)
                        {
                            physicSimu.SliddingForce = new Vector3(1, 0, 0);
                        }

                        break;

                    case ItemOrientation.West:
                        newPosition2Evaluate.X = newPosition2Evaluate.X - Y;

                        if (physicSimu.IsSliding == false)
                        {
                            physicSimu.SliddingForce = new Vector3(-1, 0, 0);
                        }

                        break;

                    default:
                        break;
                    }

                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                physicSimu.AllowJumping = true;
                return(false);
            }
        }
        private static void ModelCollisionDetection(VerletSimulator physicSimu, VisualEntity entityTesting, ref BoundingBox playerBoundingBox, ref BoundingBox playerBoundingBox2Evaluate, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition)
        {
            if (entityTesting.SkipOneCollisionTest)
            {
                entityTesting.SkipOneCollisionTest = false;
                return;
            }

            Vector3D newPositionWithColliding = previousPosition;

            _onEntityTop = null;

            newPositionWithColliding.X = newPosition2Evaluate.X;
            playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (IsCollidingWithModel(entityTesting, playerBoundingBox2Evaluate))
            {
                //logger.Debug("ModelCollisionDetection X detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.X, previousPosition.X);

                newPositionWithColliding.X = previousPosition.X;
                _onEntityTop          = false;
                Player.YForceApplying = entityTesting.Entity.YForceOnSideHit;
            }

            newPositionWithColliding.Z = newPosition2Evaluate.Z;
            playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (IsCollidingWithModel(entityTesting, playerBoundingBox2Evaluate))
            {
                //logger.Debug("ModelCollisionDetection Z detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.Z, previousPosition.Z);

                newPositionWithColliding.Z = previousPosition.Z;
                _onEntityTop          = false;
                Player.YForceApplying = entityTesting.Entity.YForceOnSideHit;
            }

            newPositionWithColliding.Y = newPosition2Evaluate.Y;
            playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (IsCollidingWithModel(entityTesting, playerBoundingBox2Evaluate))
            {
                //logger.Debug("ModelCollisionDetection Y detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.Y, previousPosition.Y);

                newPositionWithColliding.Y = previousPosition.Y;
                if (_onEntityTop == null)
                {
                    _onEntityTop = true;
                }
            }
            else
            {
                if (_isOnGround)
                {
                    playerBoundingBox2Evaluate.Minimum.Y -= 0.01f;
                    if (IsCollidingWithModel(entityTesting, playerBoundingBox2Evaluate))
                    {
                        _onEntityTop = true;
                    }
                }
            }

            //Set the NEW player position after collision tests
            newPosition2Evaluate = newPositionWithColliding;

            if (_onEntityTop == true)
            {
                physicSimu.OnGround     = true;
                _isOnGround             = true;
                physicSimu.AllowJumping = true;
            }
            else
            {
                _isOnGround = false;
            }

            playerBoundingBox2Evaluate = new BoundingBox(playerBoundingBox.Minimum + newPositionWithColliding.AsVector3(), playerBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (_onEntityTop != true && IsCollidingWithModel(entityTesting, playerBoundingBox2Evaluate))
            {
                //I'm "Blocked" by this entity !
                //Testing, inject Force to unblock myself !

                var forceDirection = playerBoundingBox2Evaluate.GetCenter() - entityTesting.WorldBBox.GetCenter();
                forceDirection.Normalize();

                physicSimu.Impulses.Add(new Impulse {
                    ForceApplied = forceDirection * 3
                });
                entityTesting.SkipOneCollisionTest = true;
            }
        }
示例#17
0
        /// <summary>
        /// Validate player move against surrounding landscape, if move not possible, it will be "rollbacked"
        /// It's used by the physic engine
        /// </summary>
        /// <param name="physicSimu"></param>
        /// <param name="localEntityBoundingBox"></param>
        /// <param name="newPosition2Evaluate"></param>
        /// <param name="previousPosition"></param>
        /// <param name="originalPosition"></param>
        public void IsCollidingWithTerrain(VerletSimulator physicSimu, ref BoundingBox localEntityBoundingBox, ref Vector3D newPosition2Evaluate, ref Vector3D previousPosition, ref Vector3D originalPosition)
        {
            Vector3D newPositionWithColliding = previousPosition;
            TerraCubeWithPosition collidingCube;

            //Create a Bounding box with my new suggested position, taking only the X that has been changed !
            //X Testing =====================================================
            newPositionWithColliding.X = newPosition2Evaluate.X;
            BoundingBox boundingBox2Evaluate = new BoundingBox(localEntityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), localEntityBoundingBox.Maximum + newPositionWithColliding.AsVector3());

            //If my new X position, make me placed "inside" a block, then invalid the new position
            if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out collidingCube))
            {
                //logger.Debug("ModelCollisionDetection X detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.X, previousPosition.X);

                newPositionWithColliding.X = previousPosition.X;
                if (collidingCube.BlockProfile.YBlockOffset > 0 || physicSimu.OnOffsettedBlock > 0)
                {
                    float offsetValue = (float)((1 - collidingCube.BlockProfile.YBlockOffset));
                    if (physicSimu.OnOffsettedBlock > 0)
                    {
                        offsetValue -= (1 - physicSimu.OnOffsettedBlock);
                    }
                    if (offsetValue <= 0.5)
                    {
                        if (collidingCube.BlockProfile.YBlockOffset == 0 && collidingCube.Position.Y + 1 < AbstractChunk.ChunkSize.Y)
                        {
                            //Check if an other block is place over the hitted one
                            var overcube = GetCubeAt(new Vector3I(collidingCube.Position.X, collidingCube.Position.Y + 1, collidingCube.Position.Z));
                            if (overcube.Id == WorldConfiguration.CubeId.Air)
                            {
                                physicSimu.OffsetBlockHitted = offsetValue;
                            }
                        }
                        else
                        {
                            physicSimu.OffsetBlockHitted = offsetValue;
                        }
                    }
                }
            }

            //Z Testing =========================================================
            newPositionWithColliding.Z = newPosition2Evaluate.Z;
            boundingBox2Evaluate       = new BoundingBox(localEntityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), localEntityBoundingBox.Maximum + newPositionWithColliding.AsVector3());

            //If my new Z position, make me placed "inside" a block, then invalid the new position
            if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out collidingCube))
            {
                //logger.Debug("ModelCollisionDetection Z detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.Z, previousPosition.Z);

                newPositionWithColliding.Z = previousPosition.Z;
                if (collidingCube.BlockProfile.YBlockOffset > 0 || physicSimu.OnOffsettedBlock > 0)
                {
                    float offsetValue = (float)((1 - collidingCube.BlockProfile.YBlockOffset));
                    if (physicSimu.OnOffsettedBlock > 0)
                    {
                        offsetValue -= (1 - physicSimu.OnOffsettedBlock);
                    }
                    if (offsetValue <= 0.5)
                    {
                        if (collidingCube.BlockProfile.YBlockOffset == 0 && collidingCube.Position.Y + 1 < AbstractChunk.ChunkSize.Y)
                        {
                            //Check if an other block is place over the hitted one
                            var overcube = GetCubeAt(new Vector3I(collidingCube.Position.X, collidingCube.Position.Y + 1, collidingCube.Position.Z));
                            if (overcube.Id == WorldConfiguration.CubeId.Air)
                            {
                                physicSimu.OffsetBlockHitted = offsetValue;
                            }
                        }
                        else
                        {
                            physicSimu.OffsetBlockHitted = offsetValue;
                        }
                    }
                }
            }

            //Y Testing ======================================================
            newPositionWithColliding.Y = newPosition2Evaluate.Y;
            boundingBox2Evaluate       = new BoundingBox(localEntityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), localEntityBoundingBox.Maximum + newPositionWithColliding.AsVector3());

            //If my new Y position, make me placed "inside" a block, then invalid the new position
            if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out collidingCube))
            {
                //If was Jummping "before" entering inside the cube
                if (previousPosition.Y >= newPositionWithColliding.Y)
                {
                    //If the movement between 2 Y is too large, use the GroundBelowEntity value
                    if (Math.Abs(newPositionWithColliding.Y - previousPosition.Y) > 1 || physicSimu.isInContactWithLadder)
                    {
                        previousPosition.Y = physicSimu.GroundBelowEntity;
                    }
                    else
                    {
                        //Raise Up until the Ground, next the previous position
                        if (collidingCube.BlockProfile.YBlockOffset > 0)
                        {
                            previousPosition.Y = MathHelper.Floor(previousPosition.Y + 1) - collidingCube.BlockProfile.YBlockOffset;
                        }
                        else
                        {
                            previousPosition.Y = MathHelper.Floor(originalPosition.Y);
                        }
                    }

                    physicSimu.OffsetBlockHitted = 0;
                    physicSimu.OnGround          = true; // On ground ==> Activite the force that will counter the gravity !!
                }

                //logger.Debug("ModelCollisionDetection Y detected tested {0}, assigned (= previous) {1}", newPositionWithColliding.Y, previousPosition.Y);

                newPositionWithColliding.Y = previousPosition.Y;
            }
            else
            {
                //No collision with Y, is the block below me solid to entity ?
                boundingBox2Evaluate.Minimum.Y -= 0.01f;
                if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out collidingCube))
                {
                    physicSimu.OnGround = true; // On ground ==> Activite the force that will counter the gravity !!
                }
            }

            //Check to see if new destination is not blocking me
            boundingBox2Evaluate = new BoundingBox(localEntityBoundingBox.Minimum + newPositionWithColliding.AsVector3(), localEntityBoundingBox.Maximum + newPositionWithColliding.AsVector3());
            if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out collidingCube))
            {
                //logger.Debug("Block STUCK tested {0}, assigned {1}", newPositionWithColliding, previousPosition);
                newPositionWithColliding    = originalPosition;
                newPositionWithColliding.Y += 0.1;
            }

            newPosition2Evaluate = newPositionWithColliding;
        }
示例#18
0
 public EntityRotations(InputsManager inputManager, VerletSimulator physicSimu)
 {
     _inputsManager = inputManager;
     _physicSimu    = physicSimu;
 }