void RenderClusterOffMapV( S32 x, S32 z)
  {
    S32 xc = x / (S32) heightField.meterPerCell;
    S32 zc = z / (S32) heightField.meterPerCell;
    ASSERT(xc != 0 || zc != 0);
/*
    if (zc > 0 || xc < heightField.cellWidth)
    {
      return;
    }
*/
    F32 xs = F32(x) - OffsetX();
    F32 zs = F32(z) - OffsetZ();

    F32 xend = xs + (F32) meterPerClus;
    F32 zend = zs + (F32) meterPerClus;

    F32 xy[5], zy[5], dx, dxx, dz = 0, dzz = 0, ymin = F32_MAX, ymax = -F32_MAX;

    S32 zcc = zc;
    S32 xcc = xc;

    S32 corners = 0;

    if (xc < 0)
    {
      for (U32 i = 0; i < 5; i++, zcc++)
      {
        S32 tzc = zcc < 0 ? 0 : zcc > (S32) heightField.cellHeight ? heightField.cellHeight : zcc;

        xy[i] = heightField.cellList[ tzc * heightField.cellPitch].height;

        ymin = Min<F32>( ymin, xy[i]);
        ymax = Max<F32>( ymax, xy[i]);
      }
      dx = (F32) -xc * (F32) heightField.meterPerCell;
      dxx =  - (F32) heightField.meterPerCell;

      corners |= 1;
    }
    else if (xc >= (S32) heightField.cellWidth)
    {
      for (U32 i = 0; i < 5; i++, zcc++)
      {
        S32 tzc = zcc < 0 ? 0 : zcc > (S32) heightField.cellHeight ? heightField.cellHeight : zcc;

        xy[i] = heightField.cellList[ tzc * heightField.cellPitch + heightField.cellWidth].height;

        ymin = Min<F32>( ymin, xy[i]);
        ymax = Max<F32>( ymax, xy[i]);
      }
      dx = (F32(xc) - F32(heightField.cellWidth)) * (F32) heightField.meterPerCell;
      dxx = (F32) heightField.meterPerCell;

      corners |= 1;
    }
    else
    {
      for (U32 i = 0; i < 5; i++, zcc++)
      {
        S32 tzc = zcc < 0 ? 0 : zcc > (S32) heightField.cellHeight ? heightField.cellHeight : zcc;

        xy[i] = heightField.cellList[ tzc * heightField.cellPitch + xc].height;

        ymin = Min<F32>( ymin, xy[i]);
        ymax = Max<F32>( ymax, xy[i]);
      }
      dx = 0;
      dxx = (F32) heightField.meterPerCell;
    }

    if (zc < 0)
    {
      for (U32 i = 0; i < 5; i++, xcc++)
      {
        S32 txc = xcc < 0 ? 0 : xcc > (S32) heightField.cellWidth  ? heightField.cellWidth : xcc;

        zy[i] = heightField.cellList[ txc].height;

        ymin = Min<F32>( ymin, zy[i]);
        ymax = Max<F32>( ymax, zy[i]);
      }
      dz = (F32) -zc * (F32) heightField.meterPerCell;
      dzz = - (F32) heightField.meterPerCell;

      corners |= 2;
    }
    else if (zc >= (S32) heightField.cellHeight)
    {
      for (U32 i = 0; i < 5; i++, xcc++)
      {
        S32 txc = xcc < 0 ? 0 : xcc > (S32) heightField.cellWidth  ? heightField.cellWidth : xcc;

        zy[i] = heightField.cellList[ heightField.cellHeight * heightField.cellPitch + txc].height;
        
        ymin = Min<F32>( ymin, zy[i]);
        ymax = Max<F32>( ymax, zy[i]);
      }

      dz = F32(zc - heightField.cellHeight) * (F32) heightField.meterPerCell;
      dzz = (F32) heightField.meterPerCell;

      corners |= 2;
    }

//  DyDx = (dy12 * dz02 - dy02 * dz12) *  dx;
//	DyDz = (dy12 * dx02 - dy02 * dx12) * -dx;

    Vector offset( (xend + xs) * .5f, (ymin + ymax) * .5f, (zend + zs) * .5f); 
    Bounds bounds;
    bounds.Set( (F32) fabs( xend - xs), ymax - ymin, (F32) fabs( zend - zs)); 

    U32 clipFlags = Vid::CurCamera().BoundsTestBox( offset, bounds);
    if (clipFlags == clipOUTSIDE)
    {
      // cluster is completely outside the view frustrum
      return;
    }

    Vid::SetBucketFlags( RS_BLEND_DEF | DP_DONOTLIGHT | renderFlags | ((clipFlags & clipALL) ? 0 : DP_DONOTCLIP) );

    Vid::SetTranBucketZMax( Vid::sortTERRAIN0 + 1);
    Vid::SetBucketMaterial( Vid::defMaterial);
    Vid::SetBucketTexture( NULL, FALSE);

    F32 dxy[5], dzy[5];
	U32 iz = 0;
    for (; iz < 5; iz++)
    {
      dxy[iz] = (offMapHeight - xy[iz]) / 1000;
      dzy[iz] = (offMapHeight - zy[iz]) / 1000;
    }

    VertexC * vertmem;
    U16 *    indexmem;
    if (!Vid::LockIndexedPrimitiveMem( (void **)&vertmem, 25, &indexmem, 96))
    {
      LOG_WARN( ("Terrain::RenderCluster: can't lock bucket!") );
      return;
    }
    VertexC * v = vertmem;

    iz = 0;
    for ( zs; zs <= zend; zs += heightField.meterPerCell, iz++, dz += dzz, zc++)
    {
      U32 ix = 0;
      F32 ddx = dx;
      S32 xcc = xc;
      for (F32 x = xs; x <= xend; x += heightField.meterPerCell, ix++, v++, ddx += dxx, xcc++)
      {
        v->vv.x = x;
        v->vv.z = zs;
        v->nv.Zero();
        v->diffuse  = 0xff000000;

        switch (corners)
        {
        case 3:
        {
          v->vv.y = xy[iz] + dxy[iz] * ddx;

          F32 zz = zs < 0 ? -zs : zs >= (S32) heightField.meterHeight ? zs - heightField.meterHeight : zs;
          F32 xx = x  < 0 ? -x  : x  >= (S32) heightField.meterWidth  ? x  - heightField.meterWidth  : x;

          if (zz > xx)
          {
            F32 dy = zy[ix] + dzy[ix] * dz;
            dy = (dy - v->vv.y) / zz;

            v->vv.y += dy * (zz - xx);
          }
          break;
        }
        case 2:
          v->vv.y = zy[ix] + dzy[ix] * dz;
          break;
        case 1:
          v->vv.y = xy[iz] + dxy[iz] * ddx;
          break;
        }
      }
    }
    Utils::Memcpy( indexmem, clusterI, 96 << 1);

    Vid::UnlockIndexedPrimitiveMem( 25, 96);

#ifdef DOSTATISTICS
    if (clipFlags == clipNONE)
    {
      Statistics::noClipTris += 2;
    }
    else
    {
      Statistics::clipTris += 2;
    }
#endif

  }