public int getColorForPoint(double x, double y, int px, int py, int plane, double brightness, ChunkMapper chunkMapper)
	{
		x /= 8.d;
		y /= 8.d;

		int centerChunkData = chunkData(px / 8, py / 8, plane, chunkMapper);
		if (centerChunkData == -1)
		{
			// No data in the center chunk?
			return 0;
		}

		double t = 0;
		double ty = 0;
		double tco = 0;
		double tcg = 0;

		int xmin = (int) (x - BLEND_RADIUS);
		int xmax = (int) Math.ceil(x + BLEND_RADIUS);
		int ymin = (int) (y - BLEND_RADIUS);
		int ymax = (int) Math.ceil(y + BLEND_RADIUS);

		for (int ucx = xmin; ucx < xmax; ucx++)
		{
			for (int ucy = ymin; ucy <= ymax; ucy++)
			{
				int val = chunkData(ucx, ucy, plane, chunkMapper);
				if (val == -1)
				{
					continue;
				}

				// Get the blend value, add 1/8 tile to make sure we don't div/0, convert to chunks
				double sigma = ((val >>> 24) + .125) / 8.d;

				// Calculate how far we have to be away before we can discard this value without
				// becoming visibly discontinuous
				double minDist = 1 + (sigma * BLEND_DISTRIBUTION);

				// Try to fast-fail
				double dxl = ucx - x;
				double dxh = dxl + 1.d;
				if (dxl < -minDist || dxl > minDist)
				{
					continue;
				}

				double dyl = ucy - y;
				double dyh = dyl + 1.d;
				if (dyl < -minDist || dyh > minDist)
				{
					continue;
				}

				// Calculate integrate a gaussian distribution in each dimension for
				// this chunk relative to the requested point
				double erfdivc = sigma * SQRT2;
				double m = (erf(dxl / erfdivc) - erf(dxh / erfdivc)) * (erf(dyl / erfdivc) - erf(dyh / erfdivc));

				// Load our YCoCg24 values into floats
				double vy = (val >>> 16 & 0xFF) / 255.d;
				double vco = (byte) (val >>> 8) / 128.d;
				double vcg = (byte) val / 128.d;

				// And multiply by the weight
				ty += vy * m;
				tco += vco * m;
				tcg += vcg * m;
				t += m;
			}
		}

		// Convert back to int range values, and bounds check while we are at it
		byte ay = (byte) Math.min(Math.max(Math.round(ty / t * 255.d), 0), 255);
		byte aco = (byte) Math.min(Math.max(Math.round(tco * 128.d / t), -128), 127);
		byte acg = (byte) Math.min(Math.max(Math.round(tcg * 128.d / t), -128), 127);

		// convert back to rgb from YCoCg24
		int g = (ay - (acg >> 1)) & 0xFF;
		int tmp = (g + acg) & 0xFF;
		int r = (tmp - (aco >> 1)) & 0xFF;
		int b = (r + aco) & 0xFF;

		// increase brightness with HSB
		float[] hsb = Color.RGBtoHSB(r, g, b, null);
		hsb[2] = (float) Math.pow(hsb[2], brightness);

		return 0xFFFFFF & Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
	}
@Test
	public void testLoadSimple() throws IOException
	{
		Skybox skybox = new Skybox(CharSource.wrap("bounds 0 0 100 100 #00F // R 0 0 100 100\r\nr 99 99").openStream(), "simple");
		Assert.assertEquals(0, skybox.getColorForPoint(0, 0, 0, 0, 0, 1, null));
		int x = (99 * 64) + 32;
		int y = (99 * 64) + 32;
		Assert.assertEquals(0x0000FF, skybox.getColorForPoint(x, y, x, y, 0, 1, null));
	}