Beispiel #1
0
        public void SetDisplacementMode(EntityDisplacementModes newValue, Vector3D WorldEyePosition)
        {
            // Moving from flight behavior to first person behavior.
            // Need to ignore camera roll, but retain existing pitch and heading.
            if (_displacementMode == EntityDisplacementModes.FreeFlying && newValue == EntityDisplacementModes.Walking)
            {
                InitRotation(WorldEyePosition.AsVector3(), WorldEyePosition.AsVector3() + _entityEyeZAxis, Vector3.UnitY);
            }

            _displacementMode = newValue;
        }
Beispiel #2
0
 //Get the initial value of _eyeOrientation/_moveOrientation quaternion based on Quaternion value
 //This will generation a rotation without any roll if the movement mode is not Flying
 public void SetOrientation(Quaternion rotationValue, Vector3D WorldEyePosition)
 {
     if (_displacementMode == EntityDisplacementModes.FreeFlying)
     {
         Matrix rotationMatrix;
         Matrix.RotationQuaternion(ref rotationValue, out rotationMatrix);
         _eyeOrientation    = rotationValue;
         _bodyOrientation   = rotationValue;
         _accumPitchDegrees = (float)MathHelper.ToDegrees(Math.Asin(rotationMatrix.M23));
     }
     else
     {
         InitRotation(WorldEyePosition.AsVector3(), WorldEyePosition.AsVector3() + _lookAt, Vector3.UnitY);
     }
 }
Beispiel #3
0
        private void RangeChanged() // Start it also if the World offset Change !!!
        {
            ChunkPositionBlockUnit = new Vector2I()
            {
                X = _cubeRange.Position.X, Y = _cubeRange.Position.Z
            };

            Position = new Vector3I()
            {
                X = _cubeRange.Position.X / AbstractChunk.ChunkSize.X, Y = 0, Z = _cubeRange.Position.Z / AbstractChunk.ChunkSize.Z
            };

            ChunkCenter = new Vector3D(_cubeRange.Position.X + (_cubeRange.Max.X - _cubeRange.Position.X) / 2.0,
                                       _cubeRange.Position.Y + (_cubeRange.Max.Y - _cubeRange.Position.Y) / 2.0,
                                       _cubeRange.Position.Z + (_cubeRange.Max.Z - _cubeRange.Position.Z) / 2.0);

#if DEBUG
            ChunkBoundingBoxDisplay = new BoundingBox3D(_d3DEngine, _worldFocusManager, new Vector3((float)(CubeRange.Max.X - CubeRange.Position.X), (float)(CubeRange.Max.Y - CubeRange.Position.Y), (float)(CubeRange.Max.Z - CubeRange.Position.Z)), _blockpickedUPEffect, Color.Tomato);
            ChunkBoundingBoxDisplay.Update(ChunkCenter.AsVector3(), Vector3.One, 0);
#endif

            RefreshWorldMatrix();

            OutOfChunkLightSourceStaticEntities.Clear();
            SoundStaticEntities.Clear();
            lock (_syncRoot)
                _visualVoxelEntities.Clear();
            EmitterStaticEntities.Clear();
        }
        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);
            }
        }
Beispiel #5
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());
            }
        }
        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 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 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;
            }
        }
        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;
        }
Beispiel #10
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;
        }
Beispiel #11
0
        /// <summary>
        /// "Simple" collision detection check against landscape, send back the cube being collided
        /// </summary>
        /// <param name="localEntityBoundingBox"></param>
        /// <param name="newPosition2Evaluate"></param>
        public byte IsCollidingWithTerrain(ref BoundingBox localEntityBoundingBox, ref Vector3D newPosition2Evaluate)
        {
            TerraCubeWithPosition _collidingCube;

            BoundingBox boundingBox2Evaluate = new BoundingBox(localEntityBoundingBox.Minimum + newPosition2Evaluate.AsVector3(), localEntityBoundingBox.Maximum + newPosition2Evaluate.AsVector3());

            if (IsSolidToPlayer(ref boundingBox2Evaluate, true, out _collidingCube))
            {
                return(_collidingCube.Cube.Id);
            }

            return(WorldConfiguration.CubeId.Air);
        }
Beispiel #12
0
        /// <summary>
        /// Update player picking
        /// </summary>
        /// <param name="pickingWorldPosition"></param>
        /// <param name="pickingLookAt"></param>
        /// <param name="blockPickingDistance"></param>
        /// <returns>return true if a new Item has been picked up !</returns>
        private bool RefreshPicking(ref Vector3D pickingWorldPosition, Vector3 pickingLookAt, float blockPickingDistance)
        {
            // first we will check entities
            // after that we will check blocks because they can be closer than the entity

            PlayerManager.Player.EntityState.IsEntityPicked = false;
            PlayerManager.Player.EntityState.IsBlockPicked  = false;

            //Check the Ray against all entity first
            var pickingRay = new Ray(pickingWorldPosition.AsVector3(), pickingLookAt);

            var epr = CheckEntityPicking(pickingRay);

            if (epr.Found && epr.Distance > blockPickingDistance)
            {
                epr.Found = false;
            }

            var tool = PlayerManager.ActiveTool;

            if (tool.PickRange != 0f)
            {
                blockPickingDistance = Math.Min(tool.PickRange, blockPickingDistance);
            }

            var nbrPointToSample = (int)(Math.Min(blockPickingDistance, epr.Distance) / 0.02);

            float sliceLimitSquared = float.PositiveInfinity;

            if (_worldChunks.SliceValue != -1)
            {
                var topPlane    = new Plane(new Vector3(0, _worldChunks.SliceValue, 0), Vector3.UnitY);
                var bottomPlane = new Plane(new Vector3(0, _worldChunks.SliceValue - 5, 0), Vector3.UnitY);

                Vector3 topIntersectionPoint;
                Vector3 bottomIntersectionPoint;

                var topIntersection    = pickingRay.Intersects(ref topPlane, out topIntersectionPoint);
                var bottomIntersection = pickingRay.Intersects(ref bottomPlane, out bottomIntersectionPoint);

                if (!topIntersection && !bottomIntersection)
                {
                    return(false);
                }

                if (topIntersection && bottomIntersection)
                {
                    // find the closest one to the camera

                    var topIsCloser = Vector3D.DistanceSquared(pickingWorldPosition, new Vector3D(topIntersectionPoint)) < Vector3D.DistanceSquared(pickingWorldPosition, new Vector3D(bottomIntersectionPoint));

                    if (topIsCloser)
                    {
                        pickingWorldPosition = new Vector3D(topIntersectionPoint);
                    }
                    else
                    {
                        pickingWorldPosition = new Vector3D(bottomIntersectionPoint);
                    }

                    sliceLimitSquared = Vector3.DistanceSquared(topIntersectionPoint, bottomIntersectionPoint);
                }
                else if (topIntersection)
                {
                    sliceLimitSquared = (float)Vector3D.DistanceSquared(pickingWorldPosition, new Vector3D(topIntersectionPoint));
                }
                else
                {
                    sliceLimitSquared = (float)Vector3D.DistanceSquared(pickingWorldPosition, new Vector3D(bottomIntersectionPoint));
                }

                if (epr.Found)
                {
                    sliceLimitSquared = (float)Vector3D.DistanceSquared(pickingWorldPosition, new Vector3D(epr.PickPoint));
                    if (epr.PickPoint.Y > topIntersectionPoint.Y)
                    {
                        nbrPointToSample = 0;
                    }
                }

                //if (Vector3D.DistanceSquared(prevPosition, prevPosition) > Vector3D.DistanceSquared(prevPosition, new Vector3D(bottomPoint)))
                //    pickingWorldPosition = new Vector3D(intersectPoint);
            }

            var startPos = pickingWorldPosition;

            //Check for Cube Picking
            //Sample points in the view direction vector
            for (var ptNbr = 0; ptNbr < nbrPointToSample; ptNbr++)
            {
                pickingWorldPosition += new Vector3D(pickingLookAt * 0.02f);

                if (Vector3D.DistanceSquared(pickingWorldPosition, startPos) >= sliceLimitSquared)
                {
                    break;
                }

                //Check if a block is picked up !
                var result = _cubesHolder.GetCube(pickingWorldPosition);
                if (!result.IsValid)
                {
                    break;
                }

                var blockProfile = _cubesHolder.Config.BlockProfiles[result.Cube.Id];
                var yOffset      = blockProfile.YBlockOffset;

                var pickType = tool.CanPickBlock(blockProfile);

                if (pickType == PickType.Stop)
                {
                    // we found a block that is closer than entity (if any)
                    // don't allow to pick the entity in this case
                    epr.Found = false;
                    break;
                }

                if (pickType == PickType.Pick)
                {
                    var blockPos = pickingWorldPosition.ToCubePosition();
                    PlayerManager.Player.EntityState.PickedBlockPosition = blockPos;

                    var     cubeBB = new BoundingBox(blockPos, blockPos + new Vector3(1, 1f - (float)yOffset, 1));
                    Vector3 faceInteresection;
                    if (cubeBB.Intersects(ref pickingRay, out faceInteresection))
                    {
                        _prevCube   = _pickedCube;
                        _pickedCube = new TerraCubeWithPosition {
                            Position = blockPos, BlockProfile = blockProfile, Cube = result.Cube
                        };

                        PlayerManager.Player.EntityState.PickedBlockFaceOffset = Vector3.One - (_pickedCube.Position - faceInteresection);
                        PlayerManager.Player.EntityState.PickPoint             = faceInteresection;
                        PlayerManager.Player.EntityState.PickPointNormal       = cubeBB.GetPointNormal(faceInteresection);
                    }

                    bool newPlacechanged = false;

                    //Find the potential new block place, by rolling back !
                    while (ptNbr > 0)
                    {
                        pickingWorldPosition -= new Vector3D(pickingLookAt * 0.02f);

                        if (_cubesHolder.isPickable(ref pickingWorldPosition, out _newCube) == false)
                        {
                            PlayerManager.Player.EntityState.NewBlockPosition = _newCube.Position;
                            newPlacechanged = true;
                            break;
                        }
                        ptNbr--;
                    }

                    PlayerManager.Player.EntityState.IsEntityPicked = false;
                    PlayerManager.Player.EntityState.IsBlockPicked  = true;
                    if (_prevCube.Position == PlayerManager.Player.EntityState.PickedBlockPosition)
                    {
                        if (!newPlacechanged)
                        {
                            return(false);
                        }
                    }

                    break;
                }
            }

            // we need to decide what we have picked (block or entity)
            // if we found the block this means that it is closer than entity
            // (because we used limit as the closest picked entity)

            if (!PlayerManager.Player.EntityState.IsBlockPicked && epr.Found)
            {
                _pickedUpEntity         = epr.PickedEntity;
                _pickedUpEntityPosition = _pickedUpEntity.Entity.Position;

                PlayerManager.Player.EntityState.PickedEntityPosition = _pickedUpEntity.Entity.Position;
                PlayerManager.Player.EntityState.PickedEntityLink     = _pickedUpEntity.Entity.GetLink();
                PlayerManager.Player.EntityState.PickPoint            = epr.PickPoint;
                PlayerManager.Player.EntityState.PickPointNormal      = epr.PickNormal;
                PlayerManager.Player.EntityState.IsEntityPicked       = true;
                PlayerManager.Player.EntityState.IsBlockPicked        = false;
            }

            return(PlayerManager.Player.EntityState.IsBlockPicked || PlayerManager.Player.EntityState.IsEntityPicked);
        }
Beispiel #13
0
 /// <summary>
 /// Compute player bounding box in World coordinate
 /// </summary>
 /// <param name="worldPosition"></param>
 public void RefreshWorldBoundingBox(Vector3D worldPosition)
 {
     WorldBBox.Minimum = LocalBBox.Minimum + worldPosition.AsVector3();
     WorldBBox.Maximum = LocalBBox.Maximum + worldPosition.AsVector3();
 }
Beispiel #14
0
 public void ComputeWorldBoundingBox(Vector3D worldPosition, out BoundingBox worldBB)
 {
     worldBB = new BoundingBox(LocalBBox.Minimum + worldPosition.AsVector3(),
                               LocalBBox.Maximum + worldPosition.AsVector3());
 }
Beispiel #15
0
 /// <summary>
 /// Compute player bounding box in World coordinate
 /// </summary>
 /// <param name="worldPosition"></param>
 public BoundingBox ComputeWorldBoundingBox(ref Vector3D worldPosition)
 {
     return(new BoundingBox(LocalBBox.Minimum + worldPosition.AsVector3(),
                            LocalBBox.Maximum + worldPosition.AsVector3()));
 }