/// <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); }
//NOTE: Will normally need to save before dispose public static void Dispose() { chunkManager = null; }