//Collision detection for perception squares //public void SweepAndPrune() //{ // List<AbstractEntity> xAxisList = new List<AbstractEntity>(); // List<AbstractEntity> activeList = new List<AbstractEntity>(); // //1. Sort entitys' list based on X coordinate // //Order objects in increasing order along the (2D, not global) X-axis // //NOTE: OrderBy may be a O(N log N) quicksort // xAxisList = gameComponentEntities.OrderBy(o => o.PhysicsObject.PerceptionBounds.BottomX).ToList<AbstractEntity>(); // Queue<AbstractEntity> xAxisQueue = new Queue<AbstractEntity>(); // foreach (AbstractEntity e in xAxisList) // { // xAxisQueue.Enqueue(e); // } // //3. Add first object to active list // // activeList.Add(xAxisQueue.Dequeue()); // while (xAxisQueue.Count > 0) // { // List<AbstractEntity> toRemove = new List<AbstractEntity>(); // AbstractEntity current = xAxisQueue.Dequeue(); // current.PhysicsObject.ClearPerceivedEntities();//Clear the perception of the object before updating // for (int i = 0; i < activeList.Count; i++) // { // //Check if current overlaps with activeList elements on XAxis // if (current.PhysicsObject.PerceptionBounds.BottomX <= activeList[i].PhysicsObject.PerceptionBounds.TopX) // { // //if overlap, check for full collision between perception squares // if (activeList[i].PhysicsObject.PerceptionBounds.IsColliding(current.PhysicsObject.PerceptionBounds)) // { // //collision // //Check if each perceives the other, if so report to object // if(current.PhysicsObject.PerceptionBounds.IsColliding(activeList[i].PhysicsObject.CollisionBounds)) // { // current.PhysicsObject.AddPerceivedObject(activeList[i].PhysicsObject); // } // if (activeList[i].PhysicsObject.PerceptionBounds.IsColliding(current.PhysicsObject.CollisionBounds)) // { // activeList[i].PhysicsObject.AddPerceivedObject(current.PhysicsObject); // } // } // } // //Else, remove activeList element // else // { // toRemove.Add(activeList[i]); // } // } // foreach (AbstractEntity e in toRemove) // { // activeList.Remove(e); // } // //Add current to activeList // activeList.Add(current); // } //} //public void SweepAndPruneStaticObjects(AbstractEntity entity) //{ // List<AbstractEntity> xAxisList = new List<AbstractEntity>(); // List<AbstractEntity> activeList = new List<AbstractEntity>(); // foreach (AbstractEntity e in gameComponentEntities) // { // xAxisList.Add(e); // } // xAxisList.Add(entity); // //1. Sort entitys' list based on X coordinate // //Order objects in increasing order along the (2D, not global) X-axis // //NOTE: OrderBy may be a O(N log N) quicksort // xAxisList = xAxisList.OrderBy(o => o.PhysicsObject.PerceptionBounds.BottomX).ToList<AbstractEntity>(); // Queue<AbstractEntity> xAxisQueue = new Queue<AbstractEntity>(); // foreach (AbstractEntity e in xAxisList) // { // xAxisQueue.Enqueue(e); // } // //3. Add first object to active list // // activeList.Add(xAxisQueue.Dequeue()); // while (xAxisQueue.Count > 0) // { // List<AbstractEntity> toRemove = new List<AbstractEntity>(); // AbstractEntity current = xAxisQueue.Dequeue(); // current.PhysicsObject.ClearPerceivedEntities();//Clear the perception of the object before updating // for (int i = 0; i < activeList.Count; i++) // { // //Check if current overlaps with activeList elements on XAxis // if (current.PhysicsObject.PerceptionBounds.BottomX <= activeList[i].PhysicsObject.PerceptionBounds.TopX) // { // //if overlap, check for full collision between perception squares // if (activeList[i].PhysicsObject.PerceptionBounds.IsColliding(current.PhysicsObject.PerceptionBounds)) // { // //collision // current.PhysicsObject.AddPerceivedObject(activeList[i].PhysicsObject); // activeList[i].PhysicsObject.AddPerceivedObject(current.PhysicsObject); // } // } // //Else, remove activeList element // else // { // toRemove.Add(activeList[i]); // } // } // foreach (AbstractEntity e in toRemove) // { // activeList.Remove(e); // } // //Add current to activeList // activeList.Add(current); // } //} #region Loading public bool Load3DModel(AbstractWorldObject gameObject) { Boolean result = false; if (gameObject.ModelFileLocation != null) { try { gameObject.Model = ScreenManager.GetInstance().ContentManager.Load <Model>(gameObject.ModelFileLocation); result = true; } catch (ContentLoadException e) { result = false; } } if (gameObject.TextureLocation != null) { try { gameObject.Texture = ScreenManager.GetInstance().ContentManager.Load <Texture2D>(gameObject.TextureLocation); result = true; } catch (ContentLoadException e) { result = false; } } return(result); }
public void DisconnectSoftLock(AbstractWorldObject target) { if (TargetObject == target) { cameraTarget = TargetObject.Position; isSoftLocked = false; TargetObject = null; } }
/// <summary> /// Gets the nearest world object bounded by the voxel box centred at the input coordinates /// </summary> /// <param name="globalCoordinates"></param> /// <returns></returns> public AbstractWorldObject GetNearestWorldObjectAt(Vector3 globalCoordinates, Ray ray) { AbstractWorldObject result = null; AbstractBlock block = GetBlockAt(globalCoordinates); float?nearestDist = float.MaxValue; if (block != null) { CollisionFace face = VoxelRaycastUtility.GetNearestCollisionFace(block.GetCollisionFaces(), ray); if (face != null) { nearestDist = face.Intersects(ray); result = block; } } List <Wall> wallsInBlock = new List <Wall>(); Vector3 blockLowerLeft = globalCoordinates + new Vector3(-0.5f, -0.5f, -0.5f); Vector3 blockUpperLeft = globalCoordinates + new Vector3(0.5f, -0.5f, -0.5f); Vector3 blockLowerRight = globalCoordinates + new Vector3(-0.5f, -0.5f, 0.5f); Vector3 blockUpperRight = globalCoordinates + new Vector3(0.5f, -0.5f, 0.5f); //Get walls wallsInBlock.Add(GetWallAt(blockLowerLeft, blockUpperLeft)); wallsInBlock.Add(GetWallAt(blockLowerLeft, blockLowerRight)); wallsInBlock.Add(GetWallAt(blockLowerLeft, blockUpperRight)); wallsInBlock.Add(GetWallAt(blockUpperLeft, blockLowerRight)); foreach (Wall w in wallsInBlock) { if (w != null) { //Check if ray crosses wall and get nearest point CollisionFace face = VoxelRaycastUtility.GetNearestCollisionFace(w.GetCollisionFaces(), ray); if (face != null) { float?dist = face.Intersects(ray); if (dist != null && nearestDist != null && ((float)dist) < ((float)nearestDist)) { nearestDist = dist; result = w; } } } } return(result); }
public override void OnClick(InputState input) { //Attempt to remove wall at clicked position Ray?mouseRay = input.GetMouseRay(); if (mouseRay != null) { AbstractWorldObject selectedObject = VoxelRaycastUtility.GetNearestIntersectingWorldObject((Ray)mouseRay); if (selectedObject != null && selectedObject is Wall) { BuildTools.RemoveWall(selectedObject as Wall); } } }
public override void OnClick(InputState input) { //Attempt to place the first point of the wall Ray?mouseRay = input.GetMouseRay(); if (mouseRay != null) { AbstractWorldObject selectedObject = VoxelRaycastUtility.GetNearestIntersectingWorldObject((Ray)mouseRay); if (selectedObject != null) { Vector3?wallAnchor = VoxelRaycastUtility.GetNearestWallAnchor(VoxelRaycastUtility.GetNearestCollisionFace(selectedObject.GetCollisionFaces(), (Ray)mouseRay), (Ray)mouseRay); if (wallAnchor != null) { Vector3 anchor = (Vector3)wallAnchor; //Add anchor to start of collection of wall points... } } } }
public override void OnClick(InputState input) { //Attempt to add block at clicked position Ray?mouseRay = input.GetMouseRay(); if (mouseRay != null) { AbstractWorldObject selectedObject = VoxelRaycastUtility.GetNearestIntersectingWorldObject((Ray)mouseRay); if (selectedObject != null) { //Need a way to determine what type of block to create based on BlockType bool blockAdded = BuildTools.AddBlock((Ray)mouseRay, selectedObject as AbstractBlock); if (blockAdded) { RemoveQuantity(1); } } } //If successful, decrement _quantity and _numUses }
public BlockCollisionFace(Direction facing, AbstractWorldObject owningObject, Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Vector3 faceNormal) : base(owningObject, point1, point2, point3, point4, faceNormal) { _facing = facing; }
public override void HandleInput(Microsoft.Xna.Framework.GameTime gameTime, InputState input) { /* if (input.CurrentKeyboardState.IsKeyDown(Keys.D1) && input.PreviousKeyboardState.IsKeyUp(Keys.D1)) * { * tools = TEMP_Tools.AddBlock; * } * if (input.CurrentKeyboardState.IsKeyDown(Keys.D2) && input.PreviousKeyboardState.IsKeyUp(Keys.D2)) * { * tools = TEMP_Tools.RemoveBlock; * } * if (input.CurrentKeyboardState.IsKeyDown(Keys.D3) && input.PreviousKeyboardState.IsKeyUp(Keys.D3)) * { * tools = TEMP_Tools.AddWall; * } * if (input.CurrentKeyboardState.IsKeyDown(Keys.D4) && input.PreviousKeyboardState.IsKeyUp(Keys.D4)) * { * tools = TEMP_Tools.RemoveWall; * } * if (input.CurrentKeyboardState.IsKeyDown(Keys.D5) && input.PreviousKeyboardState.IsKeyUp(Keys.D5)) * { * tools = TEMP_Tools.PaintFace; * } * if (input.CurrentKeyboardState.IsKeyDown(Keys.D6) && input.PreviousKeyboardState.IsKeyUp(Keys.D6)) * { * tools = TEMP_Tools.PaintHalfFace; * }*/ TEMP_MouseClick = null; TEMP_MouseClick = new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y); if (camera != null && tools != TEMP_Tools.NULL) { TEMP_MouseRay = GetPointRay((Vector2)TEMP_MouseClick, camera); TEMP_selectedObject = VoxelRaycastUtility.GetNearestIntersectingWorldObject(TEMP_MouseRay); } switch (tools) { case TEMP_Tools.AddBlock: { if (input.CurrentMouseState.LeftButton == ButtonState.Pressed && input.PreviousMouseState.LeftButton == ButtonState.Released) { if (TEMP_selectedObject != null && TEMP_selectedObject is AbstractBlock) { BuildTools.AddBlock(TEMP_MouseRay, TEMP_selectedObject as AbstractBlock); } } break; } case TEMP_Tools.RemoveBlock: { if (input.CurrentMouseState.LeftButton == ButtonState.Pressed && input.PreviousMouseState.LeftButton == ButtonState.Released) { if (TEMP_selectedObject != null && TEMP_selectedObject is AbstractBlock) { BuildTools.RemoveBlock(TEMP_selectedObject as AbstractBlock); } } break; } case TEMP_Tools.AddWall: { if (input.CurrentMouseState.LeftButton == ButtonState.Pressed) { BuildTools.AddWall((AbstractTerrainObject)TEMP_selectedObject, TEMP_MouseRay); } if (input.CurrentMouseState.LeftButton == ButtonState.Released) { //Clear wall, build wall BuildTools.BuildWalls_Released(); } break; } case TEMP_Tools.RemoveWall: { if (input.CurrentMouseState.LeftButton == ButtonState.Pressed && input.PreviousMouseState.LeftButton == ButtonState.Released) { if (TEMP_selectedObject != null && TEMP_selectedObject is Wall) { BuildTools.RemoveWall(TEMP_selectedObject as Wall); } } break; } case TEMP_Tools.PaintFace: { if (input.CurrentMouseState.LeftButton == ButtonState.Pressed && input.PreviousMouseState.LeftButton == ButtonState.Released) { BuildTools.PaintFullFace((AbstractTerrainObject)TEMP_selectedObject, TEMP_MouseRay); } break; } case TEMP_Tools.PaintHalfFace: { break; } } if (input.CurrentMouseState.LeftButton == ButtonState.Pressed && input.PreviousMouseState.LeftButton == ButtonState.Released) { TEMP_selectedObjects = null; /* TEMP_selectedObjects = VoxelRaycastUtility.VoxelIntersectionGrid(TEMP_MouseRay); * * mouseRayLine = new List<VertexPositionColor>(); * mouseRayLine.Add(new VertexPositionColor(TEMP_MouseRay.Position, Color.White)); * mouseRayLine.Add(new VertexPositionColor(TEMP_MouseRay.Position + TEMP_MouseRay.Direction * 1000, Color.White)); * */ if (TEMP_selectedObject != null && TEMP_selectedObject is AbstractBlock) { // ((AbstractBlock)TEMP_selectedObject).OnHit(); } } if (input.CurrentKeyboardState.IsKeyDown(Keys.Tab) && input.PreviousKeyboardState.IsKeyUp(Keys.Tab)) { BuildTools.ToggleWallHeight(); } if (input.CurrentMouseState.LeftButton == ButtonState.Released) { } if (input.CurrentMouseState.LeftButton == ButtonState.Pressed /*&& input.PreviousMouseState.LeftButton == ButtonState.Released*/) { /* if(input.CurrentKeyboardState.IsKeyDown(Keys.LeftControl)) * { * TEMP_removeBlock=false; * } * else * { * TEMP_removeBlock = true; * } * * if (input.CurrentKeyboardState.IsKeyDown(Keys.LeftShift)) * { * TEMP_ColourBlock = true; * } * else * { * TEMP_ColourBlock = false; * }*/ if (camera != null) { Ray mouseRay = GetPointRay((Vector2)TEMP_MouseClick, camera); Vector3 point = GetWorldSpacePoint(new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y), camera); Vector3 rotVec = position - point; rotVec = new Vector3((float)Math.Round(rotVec.X, 2), (float)Math.Round(rotVec.Y, 2), (float)Math.Round(rotVec.Z, 2)); if (rotVec != Vector3.Zero) { rotVec.Normalize(); } //Default rotation is along x axis Vector3 defRotVec = new Vector3(1, 0, 0); float dot = Vector3.Dot(rotVec, defRotVec); int sign = 1; //If angle is greater than 180 degrees (i.e. on the negative side of the default rotation vector), give it //a negative angle if (point.Z < position.Z) { sign = -1; } double angle = sign * Math.Acos(dot) * (180 / Math.PI); rotation.Y = MathHelper.ToRadians((float)angle); } } /* if (input.CurrentMouseState.MiddleButton == ButtonState.Pressed) * { * ScreenManager.GetInstance().Game.IsMouseVisible = false; * //Only record position on click * if (input.PreviousMouseState.MiddleButton == ButtonState.Released) * { * TEMP_mouseClickPosition = new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y); * } * * TEMP_mouseDelta = input.CurrentMouseState.X - TEMP_mouseClickPosition.X; * RotateY(TEMP_mouseDelta); * Mouse.SetPosition((int)TEMP_mouseClickPosition.X, (int)TEMP_mouseClickPosition.Y); * } * else * { * ScreenManager.GetInstance().Game.IsMouseVisible = true; * }*/ // Vector3 positiveCameraDirection = cameraTarget - CameraPosition; velocity = Vector3.Zero; float slow = 1; if (input.CurrentKeyboardState.IsKeyDown(Keys.LeftShift)) { slow = 5; } else { slow = 1; } if (input.CurrentKeyboardState.IsKeyDown(Keys.W)) { velocity.X -= moveSpeed / slow; } if (input.CurrentKeyboardState.IsKeyDown(Keys.D)) { velocity.Z -= moveSpeed / slow; } if (input.CurrentKeyboardState.IsKeyDown(Keys.S)) { velocity.X += moveSpeed / slow; } if (input.CurrentKeyboardState.IsKeyDown(Keys.A)) { velocity.Z += moveSpeed / slow; } if (input.CurrentKeyboardState.IsKeyDown(Keys.Space) /* && input.PreviousKeyboardState.IsKeyUp(Keys.Space)*/) { // if (OnGround) { // position = new Vector3(0, 2, 0); TEMP_velJump = 0.4f; // velocity.Y = -4; } } }
/// <summary> /// For Debugging, returns all grid positions that the ray passes through /// /// </summary> /// <param name="ray"></param> /// <returns></returns> public static List <AbstractWorldObject> /*AbstractWorldObject*/ VoxelIntersectionGrid(Ray ray) { List <AbstractWorldObject> result = new List <AbstractWorldObject>(); Vector3?gridLowerBound = ChunkManager.GetInstance().GetMinimumBounds(); Vector3?gridUpperBound = ChunkManager.GetInstance().GetMaximumBounds(); if (gridLowerBound == null || gridUpperBound == null)//Will be null if chunk manager has no chunks { return(null); } float gridLowerX = ((Vector3)gridLowerBound).X, gridUpperX = ((Vector3)gridUpperBound).X; float gridLowerY = ((Vector3)gridLowerBound).Y, gridUpperY = ((Vector3)gridUpperBound).Y; float gridLowerZ = ((Vector3)gridLowerBound).Z, gridUpperZ = ((Vector3)gridUpperBound).Z; float gridWidth = gridUpperX - gridLowerX; float gridHeight = gridUpperY - gridLowerY; float gridBreadth = gridUpperZ - gridLowerZ; Vector3?gridIntersectionPoint = GetNearestGridIntersectionPoint(ray, (Vector3)gridLowerBound, gridWidth, gridHeight, gridBreadth); Vector3 rayPosition = ray.Position; //Direction vector. float dx = ray.Direction.X; float dy = ray.Direction.Y; float dz = ray.Direction.Z; /* if (gridIntersectionPoint != null) * { * rayPosition = ((Vector3)gridIntersectionPoint) + new Vector3(-dx, -dy, -dz); * }*/ //Lower position of block containing origin point. float x = GetVoxelCoordinates(rayPosition.X); // GetVoxelLowerCorner(rayPosition.X);// GetVoxelCoordinates(rayPosition.X, 1); float y = GetVoxelCoordinates(rayPosition.Y); // GetVoxelLowerCorner(rayPosition.Y);//(float)Math.Floor(rayPosition.Y) - 0.5f;// GetVoxelCoordinates(rayPosition.Y,1); float z = GetVoxelCoordinates(rayPosition.Z); //GetVoxelLowerCorner(rayPosition.Z);//(float)Math.Floor(rayPosition.Z) - 0.5f;// GetVoxelCoordinates(rayPosition.Z,1); float stepX = 1 * signNum(dx); float stepY = 1 * signNum(dy); float stepZ = 1 * signNum(dz); float tMaxX = initMaxT(ray.Position.X, dx);//stepX > 0 ? (x+stepX)-rayPosition.X :x-rayPosition.X;// float tMaxY = initMaxT(ray.Position.Y, dy); float tMaxZ = initMaxT(ray.Position.Z, dz); // The change in t when taking a step (always positive). float tDeltaX = stepX / dx; float tDeltaY = stepY / dy; float tDeltaZ = stepZ / dz; // Avoids an infinite loop. if (dx == 0 && dy == 0 && dz == 0) { throw new Exception("Raycast in zero direction!"); } // Vector3 voxelCoords = new Vector3(blockX, blockY, blockZ); // DirtBlock TEMP = new DirtBlock(BlockShape.Cube, Direction.North); // TEMP.Position = voxelCoords; // result.Add(TEMP); while ( (stepX > 0 ? x < gridUpperX : x >= gridLowerX) && (stepY > 0 ? y < gridUpperY : y >= gridLowerY) && (stepZ > 0 ? z < gridUpperZ : z >= gridLowerZ)) { float blockX = x + 0.5f; float blockY = y + 0.5f; float blockZ = z + 0.5f; Vector3 voxelCoords = new Vector3(blockX, blockY, blockZ); DirtBlock TEMP = new DirtBlock(BlockShape.Cube, Direction.North); TEMP.Position = voxelCoords; result.Add(TEMP); if (!(x < gridLowerX || y < gridLowerY || z < gridLowerZ || x >= gridUpperX || y >= gridUpperY || z >= gridUpperZ)) { //Blocks are stored by centre, but x,y and z are bottom corners of blocks Vector2 chunkKey = ChunkManager.GetInstance().GetChunkCoordinates(voxelCoords); //Get nearest object in block if (ChunkManager.GetInstance().ContainsChunk(chunkKey)) { DirtBlock TEMPblock = new DirtBlock(BlockShape.Cube, Direction.North); TEMPblock.Position = voxelCoords; AbstractWorldObject obj = ChunkManager.GetInstance().GetChunk(chunkKey).GetNearestWorldObjectAt(voxelCoords, ray); if (obj != null) { //result = obj; result.Add(obj); break; } //TEMP ChunkManager.GetInstance().GetChunk(chunkKey).wireFrameColour = Color.LimeGreen; ChunkManager.GetInstance().GetChunk(chunkKey).GetCubeWireframe(); // break; } } // tMaxX stores the t-value at which we cross a cube boundary along the // X axis, and similarly for Y and Z. Therefore, choosing the least tMax // chooses the closest cube boundary. Only the first case of the four // has been commented in detail. if (tMaxX < tMaxY) { if (tMaxX < tMaxZ) { // Update which cube we are now in. x += stepX; //if (x > gridUpperX) // break;//Outside grid // Adjust tMaxX to the next X-oriented boundary crossing. tMaxX += tDeltaX; // Record the normal vector of the cube face we entered. } else { z += stepZ; // if (z > gridUpperZ) // break;//Outside grid tMaxZ += tDeltaZ; } } else { if (tMaxY < tMaxZ) { y += stepY; // if (y > gridUpperY) // break;//Outside grid tMaxY += tDeltaY; } else { // Identical to the second case, repeated for simplicity in // the conditionals. z += stepZ; tMaxZ += tDeltaZ; } } } return(result); }
public CollisionFace(AbstractWorldObject owningObject, Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Vector3 faceNormal) : this(point1, point2, point3, point4, faceNormal) { owner = owningObject; }
public void SnapToCamera(AbstractWorldObject cameraFocusObject) { _camera.SoftLockToObject(cameraFocusObject); }
public void RemoveWorldObject(AbstractWorldObject obj) { worldObjects.Remove(obj); }
public void AddWorldObject(AbstractWorldObject obj) { worldObjects.Add(obj); }
public void SoftLockToObject(AbstractWorldObject target) { TargetObject = target; isSoftLocked = true; }