public ThreeDeeView(
      Dimension dimension,
      ColourScheme colourScheme,
      BiomeScheme biomeScheme,
      CustomBiomeManager customBiomeManager,
      int rotation,
      int zoom) {
    this.dimension = dimension;
    this.colourScheme = colourScheme;
    this.biomeScheme = biomeScheme;
    this.customBiomeManager = customBiomeManager;
    this.rotation = rotation;
    this.zoom = zoom;
    scale = (int) Math.pow(2.0, Math.abs(zoom - 1));
    //        System.out.println("Zoom " + zoom + " -> scale " + scale);
    maxHeight = dimension.getMaxHeight();
    if (dimension.getTileFactory() instanceof HeightMapTileFactory) {
      waterLevel = ((HeightMapTileFactory) dimension.getTileFactory()).getWaterHeight();
    } else {
      waterLevel = maxHeight / 2;
    }
    upsideDown = dimension.getDim() < 0; // Ceiling dimension
    switch (rotation) {
      case 0:
        zSortedTiles =
            new TreeSet<>(
                (t1, t2) -> {
                  if (t1.getY() != t2.getY()) {
                    return t1.getY() - t2.getY();
                  } else {
                    return t1.getX() - t2.getX();
                  }
                });
        break;
      case 1:
        zSortedTiles =
            new TreeSet<>(
                (t1, t2) -> {
                  if (t1.getX() != t2.getX()) {
                    return t1.getX() - t2.getX();
                  } else {
                    return t2.getY() - t1.getY();
                  }
                });
        break;
      case 2:
        zSortedTiles =
            new TreeSet<>(
                (t1, t2) -> {
                  if (t1.getY() != t2.getY()) {
                    return t2.getY() - t1.getY();
                  } else {
                    return t2.getX() - t1.getX();
                  }
                });
        break;
      case 3:
        zSortedTiles =
            new TreeSet<>(
                (t1, t2) -> {
                  if (t1.getX() != t2.getX()) {
                    return t2.getX() - t1.getX();
                  } else {
                    return t1.getY() - t2.getY();
                  }
                });
        break;
      default:
        throw new IllegalArgumentException();
    }
    zSortedTiles.addAll(dimension.getTiles());
    threeDeeRenderManager =
        new ThreeDeeRenderManager(
            dimension, colourScheme, biomeScheme, customBiomeManager, rotation);

    dimension.addDimensionListener(this);
    for (Tile tile : dimension.getTiles()) {
      tile.addListener(this);
    }

    int width = dimension.getWidth() * TILE_SIZE + dimension.getHeight() * TILE_SIZE;
    int height = width / 2 + maxHeight - 1;
    //        maxX = dimension.getHighestX();
    //        maxY = dimension.getHighestY();
    maxX = maxY = 0;
    //        xOffset = 512;
    //        yOffset = 256;
    //        xOffset = yOffset = 0;
    switch (rotation) {
      case 0:
        xOffset = -getTileBounds(dimension.getLowestX(), dimension.getHighestY()).x;
        yOffset = -getTileBounds(dimension.getLowestX(), dimension.getLowestY()).y;
        break;
      case 1:
        xOffset = -getTileBounds(dimension.getHighestX(), dimension.getHighestY()).x;
        yOffset = -getTileBounds(dimension.getLowestX(), dimension.getHighestY()).y;
        break;
      case 2:
        xOffset = -getTileBounds(dimension.getHighestX(), dimension.getLowestY()).x;
        yOffset = -getTileBounds(dimension.getHighestX(), dimension.getHighestY()).y;
        break;
      case 3:
        xOffset = -getTileBounds(dimension.getLowestX(), dimension.getLowestY()).x;
        yOffset = -getTileBounds(dimension.getHighestX(), dimension.getLowestY()).y;
        break;
      default:
        throw new IllegalArgumentException();
    }
    //        System.out.println("xOffset: " + xOffset + ", yOffset: " + yOffset);
    java.awt.Dimension preferredSize = zoom(new java.awt.Dimension(width, height));
    setPreferredSize(preferredSize);
    setMinimumSize(preferredSize);
    setMaximumSize(preferredSize);
    setSize(preferredSize);

    addHierarchyListener(this);
  }