using UnityEngine;
using System.Collections;

public class Noise {
	static float[,] rawData;

	const int a = 106;
	const int b = 1283;
	const int m = 6075;

	static Noise() {
		rawData = new float[256, 256];
		int x = 2;
		for (int i = 0; i < 256; i++) {
			for (int j = 0; j < 256; j++) {
			//	rawData[i, j] = Random.Range(0f, 1f); // TODO stable alhorithm implement
				x = (x * a + b) % m;
				rawData[i, j] = (float)x / (float)m - 0.5f;
			}
		}
	}
	public static float Perlin(Vector3 point, float multiplier = 1f) {
		return GetPerlinNoise(point.x * multiplier, point.y * multiplier, point.z * multiplier);
	}
	static float GetPerlinNoise(float x, float y, float z) {
		x += 1000;
		y += 1000;
		z += 1000;
		int xS = (int)x;
		int yS = (int)y;
		int zS = (int)z;
		float xP = x - xS;
		float yP = y - yS;
		float zP = z - zS;
		byte zShift = (byte)(rawData [0, zS % 256] * 255f);
		float y1 = rawData[xS % 256, (yS + zShift) % 256] * (1f - xP) + rawData[(xS + 1) % 256, (yS + zShift) % 256] * xP;
		float y2 = rawData[xS % 256, (yS + zShift + 1) % 256] * (1f - xP) + rawData[(xS + 1) % 256, (yS + zShift + 1) % 256] * xP;
		float z1 = y1 * (1f - yP) + y2 * yP;
		zShift = (byte)(rawData [0, (zS + 1) % 256] * 255f);
		y1 = rawData[xS % 256, (yS + zShift) % 256] * (1f - xP) + rawData[(xS + 1) % 256, (yS + zShift) % 256] * xP;
		y2 = rawData[xS % 256, (yS + zShift + 1) % 256] * (1f - xP) + rawData[(xS + 1) % 256, (yS + zShift + 1) % 256] * xP;
		float z2 = y1 * (1f - yP) + y2 * yP;
		return z1 * (1f - zP) + z2 * zP;
	}
}
