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; }
//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); } }
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); } }
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; }
/// <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; }
/// <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); }
/// <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); }
/// <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(); }
public void ComputeWorldBoundingBox(Vector3D worldPosition, out BoundingBox worldBB) { worldBB = new BoundingBox(LocalBBox.Minimum + worldPosition.AsVector3(), LocalBBox.Maximum + worldPosition.AsVector3()); }
/// <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())); }