public float blendValAt(float x, float y, float stepFade) {
    x = Visit.clamp(x, 0.5f, size - 0.5f) ;
    y = Visit.clamp(y, 0.5f, size - 0.5f) ;
    if (stepFade < 0) stepFade = 0 ;
    float sum = 0, weight = 1, sumWeights = 0 ;
    int minX, minY, maxX, maxY, range ;
    float pX, pY, aX, aY ;
    
    for (int h = 0, s = 1 ; h <= high ; h++, s *= 2) {
      range = (this.size / s) - 1 ;
      pX = (x - 0.5f) / s ;
      pY = (y - 0.5f) / s ;
      minX = (int) pX ;
      minY = (int) pY ;
      maxX = (minX == range) ? minX : (minX + 1) ;
      maxY = (minY == range) ? minY : (minY + 1) ;
      aX = pX - minX ;
      aY = pY - minY ;
      //if (aX < 0 || aY < 0) I.complain("Negative relAlpha values! "+aX+" "+aY) ;
      final float blend =
        (getTotalAt(minX, minY, h) * (1 - aX) * (1 - aY)) +
        (getTotalAt(maxX, minY, h) *      aX  * (1 - aY)) +
        (getTotalAt(minX, maxY, h) * (1 - aX) *      aY ) +
        (getTotalAt(maxX, maxY, h) *      aX  *      aY ) ;
      //if (blend < 0) I.complain("Negative blend value: "+blend) ;
      sum += (blend * weight) / (s * s) ;
      sumWeights += weight ;
      weight *= stepFade ;
    }
    /*
    I.say(
      "Sum weights: "+sumWeights+", sum: "+sum+
      ", height: "+(quadLevels.length + 1)
    ) ;
    //*/
    //return sumWeights ;
    return sum / sumWeights ;
  }