/** Trace ray, based on "Voxel Tranversal along a 3D line" */
    private void raytrace(
        MapChunkCache cache,
        MapIterator mapiter,
        HDShaderState[] shaderstate,
        boolean[] shaderdone) {
      /* Initialize raytrace state variables */
      raytrace_init();

      mapiter.initialize(x, y, z);

      for (; n > 0; --n) {
        if (visit_block(mapiter, shaderstate, shaderdone)) {
          return;
        }
        /* If X step is next best */
        if ((t_next_x <= t_next_y) && (t_next_x <= t_next_z)) {
          x += x_inc;
          t = t_next_x;
          t_next_x += dt_dx;
          laststep = stepx;
          mapiter.stepPosition(laststep);
        }
        /* If Y step is next best */
        else if ((t_next_y <= t_next_x) && (t_next_y <= t_next_z)) {
          y += y_inc;
          t = t_next_y;
          t_next_y += dt_dy;
          laststep = stepy;
          mapiter.stepPosition(laststep);
          /* If outside 0-127 range */
          if ((y & (~0x7F)) != 0) return;
        }
        /* Else, Z step is next best */
        else {
          z += z_inc;
          t = t_next_z;
          t_next_z += dt_dz;
          laststep = stepz;
          mapiter.stepPosition(laststep);
        }
      }
    }
  public boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile) {
    DynmapWorld world = tile.getDynmapWorld();
    boolean isnether = world.isNether();
    DynmapBufferedImage im =
        DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth, KzedMap.tileHeight);
    DynmapBufferedImage zim =
        DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth / 2, KzedMap.tileHeight / 2);

    DynmapBufferedImage im_day = null;
    DynmapBufferedImage zim_day = null;
    if (night_and_day) {
      im_day = DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth, KzedMap.tileHeight);
      zim_day =
          DynmapBufferedImage.allocateBufferedImage(KzedMap.tileWidth / 2, KzedMap.tileHeight / 2);
    }

    if (cache.getWorld().worldheight > 128) {
      if (maximumHeight == 127) maximumHeight = cache.getWorld().worldheight - 1;
    }
    int ix = tile.px / 2 + tile.py / 2 - ((127 - maximumHeight) / 2);
    int iy = maximumHeight;
    int iz = tile.px / 2 - tile.py / 2 + ((127 - maximumHeight) / 2);

    /* Don't mess with existing height-clipped renders */
    if (maximumHeight < 127) isnether = false;

    int jx, jz;

    int x, y;

    MapIterator mapiter = cache.getIterator(ix, iy, iz);

    Color c1 = new Color();
    Color c2 = new Color();
    int[] argb = im.argb_buf;
    int[] zargb = zim.argb_buf;
    Color c1_day = null;
    Color c2_day = null;
    int[] argb_day = null;
    int[] zargb_day = null;
    if (night_and_day) {
      c1_day = new Color();
      c2_day = new Color();
      argb_day = im_day.argb_buf;
      zargb_day = zim_day.argb_buf;
    }
    int rowoff = 0;
    /* draw the map */
    for (y = 0; y < KzedMap.tileHeight; ) {
      jx = ix;
      jz = iz;

      for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
        mapiter.initialize(jx, iy, jz);
        scan(world, 0, isnether, c1, c1_day, mapiter);
        mapiter.initialize(jx, iy, jz);
        scan(world, 2, isnether, c2, c2_day, mapiter);

        argb[rowoff + x] = c1.getARGB();
        argb[rowoff + x - 1] = c2.getARGB();

        if (night_and_day) {
          argb_day[rowoff + x] = c1_day.getARGB();
          argb_day[rowoff + x - 1] = c2_day.getARGB();
        }

        jx++;
        jz++;
      }

      y++;
      rowoff += KzedMap.tileWidth;

      jx = ix;
      jz = iz - 1;

      for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) {
        mapiter.initialize(jx, iy, jz);
        scan(world, 2, isnether, c1, c1_day, mapiter);
        jx++;
        jz++;
        mapiter.initialize(jx, iy, jz);
        scan(world, 0, isnether, c2, c2_day, mapiter);

        argb[rowoff + x] = c1.getARGB();
        argb[rowoff + x - 1] = c2.getARGB();

        if (night_and_day) {
          argb_day[rowoff + x] = c1_day.getARGB();
          argb_day[rowoff + x - 1] = c2_day.getARGB();
        }
      }
      y++;
      rowoff += KzedMap.tileWidth;

      ix++;
      iz--;
    }
    /* Now, compute zoomed tile - bilinear filter 2x2 -> 1x1 */
    doScaleWithBilinear(argb, zargb, KzedMap.tileWidth, KzedMap.tileHeight);
    if (night_and_day) {
      doScaleWithBilinear(argb_day, zargb_day, KzedMap.tileWidth, KzedMap.tileHeight);
    }

    /* Hand encoding and writing file off to MapManager */
    KzedZoomedMapTile zmtile = new KzedZoomedMapTile(tile.getDynmapWorld(), tile);
    File zoomFile = MapManager.mapman.getTileFile(zmtile);

    return doFileWrites(outputFile, tile, im, im_day, zmtile, zoomFile, zim, zim_day);
  }