static public RaycastTileResult RaycastTile(World.CubeWorld world, Vector3 from, Vector3 fwd, float maxDistance, bool ignoreNonSolid, bool ignoreNonClickable) { Vector3 pos = from; RaycastTileResult result = new RaycastTileResult(); TileManager tileManager = world.tileManager; while (true) { Vector3 near = pos; //Find near planes for (int d = 0; d < 3; d++) { near[d] = (float) Math.Round(near[d] / Graphics.TILE_SIZE) * Graphics.TILE_SIZE; near[d] += Graphics.HALF_TILE_SIZE * Math.Sign(fwd[d]); } //Calculate nearest plane float[] ns = new float[3]; for (int d = 0; d < 3; d++) { if (fwd[d] != 0.0f) ns[d] = (near[d] - pos[d]) / fwd[d]; else ns[d] = 1.0f; } float minN = ns[0]; int lockedAxis = 0; for (int d = 1; d < 3; d++) { if (ns[d] < minN) { minN = ns[d]; lockedAxis = d; } } //Advance until the border of the nearest plane pos += fwd * minN; if ((pos - from).magnitude >= maxDistance) break; //See what tile is there Vector3 d2 = new Vector3(); d2[lockedAxis] = Math.Sign(fwd[lockedAxis]) * Graphics.QUART_TILE_SIZE; TilePosition cursorPosition = Graphics.Vector3ToTilePosition(pos + d2); //Advance a little to stop the next loop from selecting the same tile / border pos += fwd * Graphics.TILE_SIZE * 0.0001f; //Now validate what to do :-) if (tileManager.IsValidTile(cursorPosition)) { byte tileType = tileManager.GetTileType(cursorPosition); if (tileType != TileDefinition.EMPTY_TILE_TYPE && ((ignoreNonSolid == false || tileManager.GetTileSolid(cursorPosition) == true) || (ignoreNonClickable == false && tileManager.GetTileDefinition(tileType).GetRulesForAction(TileActionRule.ActionType.CLICKED) != null))) { switch (lockedAxis) { case 0: if (Math.Sign(fwd[lockedAxis]) > 0) result.face = Faces.Left; else result.face = Faces.Right; break; case 1: if (Math.Sign(fwd[lockedAxis]) > 0) result.face = Faces.Bottom; else result.face = Faces.Top; break; case 2: if (Math.Sign(fwd[lockedAxis]) > 0) result.face = Faces.Front; else result.face = Faces.Back; break; } result.position = cursorPosition; result.hit = true; result.tile = tileManager.GetTile(cursorPosition); break; } } } return result; }
static public RaycastTileResult RaycastTile(World.CubeWorld world, Vector3 from, Vector3 fwd, float maxDistance, bool ignoreNonSolid, bool ignoreNonClickable) { Vector3 pos = from; RaycastTileResult result = new RaycastTileResult(); TileManager tileManager = world.tileManager; while (true) { Vector3 near = pos; //Find near planes for (int d = 0; d < 3; d++) { near[d] = (float)Math.Round(near[d] / Graphics.TILE_SIZE) * Graphics.TILE_SIZE; near[d] += Graphics.HALF_TILE_SIZE * Math.Sign(fwd[d]); } //Calculate nearest plane float[] ns = new float[3]; for (int d = 0; d < 3; d++) { if (fwd[d] != 0.0f) { ns[d] = (near[d] - pos[d]) / fwd[d]; } else { ns[d] = 1.0f; } } float minN = ns[0]; int lockedAxis = 0; for (int d = 1; d < 3; d++) { if (ns[d] < minN) { minN = ns[d]; lockedAxis = d; } } //Advance until the border of the nearest plane pos += fwd * minN; if ((pos - from).magnitude >= maxDistance) { break; } //See what tile is there Vector3 d2 = new Vector3(); d2[lockedAxis] = Math.Sign(fwd[lockedAxis]) * Graphics.QUART_TILE_SIZE; TilePosition cursorPosition = Graphics.Vector3ToTilePosition(pos + d2); //Advance a little to stop the next loop from selecting the same tile / border pos += fwd * Graphics.TILE_SIZE * 0.0001f; //Now validate what to do :-) if (tileManager.IsValidTile(cursorPosition)) { byte tileType = tileManager.GetTileType(cursorPosition); if (tileType != TileDefinition.EMPTY_TILE_TYPE && ((ignoreNonSolid == false || tileManager.GetTileSolid(cursorPosition) == true) || (ignoreNonClickable == false && tileManager.GetTileDefinition(tileType).GetRulesForAction(TileActionRule.ActionType.CLICKED) != null))) { switch (lockedAxis) { case 0: if (Math.Sign(fwd[lockedAxis]) > 0) { result.face = Faces.Left; } else { result.face = Faces.Right; } break; case 1: if (Math.Sign(fwd[lockedAxis]) > 0) { result.face = Faces.Bottom; } else { result.face = Faces.Top; } break; case 2: if (Math.Sign(fwd[lockedAxis]) > 0) { result.face = Faces.Front; } else { result.face = Faces.Back; } break; } result.position = cursorPosition; result.hit = true; result.tile = tileManager.GetTile(cursorPosition); break; } } } return(result); }