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