Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * @author David Olsen
- */
- public class OlsenNoise3D {
- int maxiterations = 5;
- //you can mess with maxiterations all you'd want.
- public double[][] olsennoise(int x, int y, int width, int height) {
- return normalized(olsennoise3d(maxiterations, 0, x, y, 2, x + width, y + height))[0];
- //this grabs a 2d slice of 3d noise.
- }
- public double[][][] olsennoise(int x, int y, int z, int width, int height, int depth) {
- return normalized(olsennoise3d(maxiterations, x, y, z, x + width, y + height, z + depth));
- //gets a 3d section of noise.
- }
- public double[][][] normalized(double[][][] arr) {
- double max = Double.NEGATIVE_INFINITY;
- double min = Double.POSITIVE_INFINITY;
- double mv;
- for (int k = 0, n = arr.length; k < n; k++) {
- for (int j = 0, m = arr[0].length; j < m; j++) {
- for (int q = 0, p = arr[0][0].length; q < p; q++) {
- mv = arr[k][j][q];
- if (mv > max) {
- max = mv;
- }
- if (mv < min) {
- min = mv;
- }
- }
- } //find max/min
- }
- double range = max - min;
- if (max != Integer.MIN_VALUE) {
- for (int k = 0, n = arr.length; k < n; k++) {
- for (int j = 0, m = arr[0].length; j < m; j++) {
- for (int q = 0, p = arr[0][0].length; q < p; q++) {
- arr[k][j][q] = (arr[k][j][q] - min) / range;
- }
- }
- }
- } //perform normalization.
- return arr;
- }
- private void upsample(double[][][] from, double[][][] to) {
- for (int j = 0, m = from.length; j < m; j++) {
- for (int k = 0, n = from[0].length; k < n; k++) {
- for (int q = 0, p = from[0][0].length; q < p; q++) {
- for (int h = 0, g = 2 * 2 * 2; h < g; h++) {
- to[(j * 2) + ((h >> 2) & 1)][(k * 2) + ((h >> 1) & 1)][(q * 2) + (h & 1)] = from[j][k][q];
- }
- }
- }
- }//copy over the reused sections of field. Upsample.
- }
- private void blur(double[][][] currentfield, double[][][] field) {
- for (int j = 0, m = field.length - 1; j < m; j++) {
- for (int k = 0, n = field[0].length - 1; k < n; k++) {
- for (int q = 0, p = field[0][0].length; q < p; q++) {
- int g = 3 * 3 * 3;
- for (int h = 0; h < g; h++) {
- field[j][k][q] += currentfield[j + (h % 3)][k + ((h / 3) % 3)][q + ((h / 9) % 3)];
- }
- field[j][k][q] /= g;
- }
- }//blursubset.
- }
- }
- private void noise(double[][][] field, int iterations, int x0, int y0, int z0) {
- for (int j = 0, m = field.length - 1; j < m; j++) {
- for (int k = 0, n = field[0].length - 1; k < n; k++) {
- for (int q = 0, p = field[0][0].length; q < p; q++) {
- field[j][k][q] += random(iterations, x0, y0, z0);
- }
- }//noise.
- }
- }
- private double[][][] olsennoise3d(int iterations, int x0, int y0, int z0, int x1, int y1, int z1) {
- double[][][] field = new double[x1 - x0][y1 - y0][z1 - z0];
- if (iterations == 0) {
- //if this is the last iteration, provide a true random field.
- for (int j = 0, m = field.length; j < m; j++) {
- for (int k = 0, n = field[0].length; k < n; k++) {
- for (int q = 0, p = field[0][0].length; q < p; q++) {
- field[j][k][q] = (random(iterations, j + x0, k + y0, q + z0));
- }
- }
- }
- } else {
- //if this is not yet the last iteration, call for the upperfield recursively.
- double[][][] upperfield = olsennoise3d(iterations - 1, (x0 / 2) - 1, (y0 / 2) - 1, (z0 / 2) - 1, (x1 / 2) + (x1 & 1) + 1, (y1 / 2) + (y1 & 1) + 1, (z1 / 2) + (z1 & 1) + 1);
- //(x1&1) makes it a ceiling operation.
- double[][][] currentfield = new double[upperfield.length * 2][upperfield[0].length * 2][upperfield[0][0].length * 2];
- upsample(upperfield, currentfield); //upsample the field
- blur(currentfield, field); //blur the field
- noise(field, iterations, x0, y0, z0); //add noise to the field.
- //Those three operations are all that's required, that and scoping the field recusively so any request for any slice of the infinte field is complete
- //in a reasonable amount of time.
- }
- return field;
- }
- public double random(int iterations, int x, int y, int z) {
- return (((hashrandom(x,y,z,iterations) - 0.5) * 2)) / (1<<iterations);
- //This function controls the drop off rate for the noise. The noise added to each iteration should be greater at every lower iteration,
- //down to iteration 0 which is basically pure random.
- }
- public double hashrandom(int... elements) {
- //To prevent repeating all that play a role in the request are hashed together.
- //This could be anything that gives a deterministic answer but seemingly random return value.
- long hash = 0;
- for (int i = 0; i < elements.length; i++) {
- hash ^= elements[i];
- hash = hash(hash);
- }
- return (double)(hash & 0xFFFFFFF) / (double)0xFFFFFFF;
- }
- //This is a hash I found on the internet. It's just a good effective hash.
- public long hash(long v) {
- long hash = v;
- long h = hash;
- switch ((int)hash & 3) {
- case 3:
- hash += h;
- hash ^= hash << 32;
- hash ^= h << 36;
- hash += hash >> 22;
- break;
- case 2:
- hash += h;
- hash ^= hash << 22;
- hash += hash >> 34;
- break;
- case 1:
- hash += h;
- hash ^= hash << 20;
- hash += hash >> 2;
- }
- hash ^= hash << 6;
- hash += hash >> 10;
- hash ^= hash << 8;
- hash += hash >> 34;
- hash ^= hash << 50;
- hash += hash >> 12;
- return hash;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement