A fast implementation of fractional Brownian motion. - Java java.lang

Java examples for java.lang:Math Algorithm

Description

A fast implementation of fractional Brownian motion.

Demo Code

/*/*from  w  ww  .  j a  v a  2 s. c o  m*/
 * A Java Utility Library
 * 
 * Copyright (C) 2010-2012 Jan Graichen <jg@altimos.de>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * See the NOTICE file distributed along with this work for further
 * information.
 */
//package com.java2s;

public class Main {
    public static int p[] = new int[512];

    /** 
     * A fast implementation of fractional Brownian motion.
     * This implementation assumes an integer number of octaves and
     * a lacunarity of two.  This simplification is done for speed.
     */
    public static double fBm(double x, double y, double z, int H,
            int octaves) {
        double sum = 0;
        for (int i = 0; i < octaves; i++) {
            sum += noise(x, y, z) / (1 << H * i);
            x *= 2;
            y *= 2;
            z *= 2;
        }
        return sum;
    }

    public static float fBm(float x, float y, float z, int octaves,
            float lacunarity, float gain) {
        float sum = 0;
        float amp = 1;
        for (int i = 0; i < octaves; i++) {
            sum += amp * noiseF(x, y, z);
            x *= lacunarity;
            y *= lacunarity;
            z *= lacunarity;
            amp *= gain;
        }
        return sum;
    }

    public static double noise(double x, double y, double z) {
        double a = Math.floor(x);
        double b = Math.floor(y);
        double c = Math.floor(z);

        int X = (int) a & 255;
        int Y = (int) b & 255;
        int Z = (int) c & 255;
        x -= a;
        y -= b;
        z -= c;
        int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z;
        int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;

        double u = fade(x);
        double v = fade(y);
        double w = fade(z);
        return mix(
                w,
                mix(v,
                        mix(u, grad(p[AA], x, y, z),
                                grad(p[BA], x - 1, y, z)),
                        mix(u, grad(p[AB], x, y - 1, z),
                                grad(p[BB], x - 1, y - 1, z))),
                mix(v,
                        mix(u, grad(p[AA + 1], x, y, z - 1),
                                grad(p[BA + 1], x - 1, y, z - 1)),
                        mix(u, grad(p[AB + 1], x, y - 1, z - 1),
                                grad(p[BB + 1], x - 1, y - 1, z - 1))));
    }

    public static float noiseF(float x, float y, float z) {
        // Sourced this computation out to gain performance:
        double a = Math.floor(x);
        double b = Math.floor(y);
        double c = Math.floor(z);

        int X = (int) a & 255;
        int Y = (int) b & 255;
        int Z = (int) c & 255;
        x -= a;
        y -= b;
        z -= c;
        int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z;
        int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;

        float u = fadeF(x);
        float v = fadeF(y);
        float w = fadeF(z);
        return mixF(
                w,
                mixF(v,
                        mixF(u, gradF(p[AA], x, y, z),
                                gradF(p[BA], x - 1, y, z)),
                        mixF(u, gradF(p[AB], x, y - 1, z),
                                gradF(p[BB], x - 1, y - 1, z))),
                mixF(v,
                        mixF(u, gradF(p[AA + 1], x, y, z - 1),
                                gradF(p[BA + 1], x - 1, y, z - 1)),
                        mixF(u, gradF(p[AB + 1], x, y - 1, z - 1),
                                gradF(p[BB + 1], x - 1, y - 1, z - 1))));
    }

    /**
     * Uses a fifth order polynom to avoid the second order discontinuity
     */
    private static double fade(double x) {
        return x * x * x * (x * (x * 6 - 15) + 10);
    }

    /**
     * Performs a linear blend operation of a and b based on t
     */
    public static double mix(double x, double a, double b) {
        return a + x * (b - a);
    }

    /**
     * This function are using a hard-coded switch-statement-table
     * to determine the result only based on corners hash value.
     *
     * This is up to 3 times faster the Ken Perlins original approach!
     */
    private static double grad(int hash, double x, double y, double z) {
        switch (hash & 15) {
        case 0:
            return x + y;
        case 1:
            return -x + y;
        case 2:
            return x - y;
        case 3:
            return -x - y;

        case 4:
            return x + z;
        case 5:
            return -x + z;
        case 6:
            return x - z;
        case 7:
            return -x - z;

        case 8:
            return y + z;
        case 9:
            return -y + z;
        case 10:
            return y - z;
        case 11:
            return -y - z;

        case 12:
            return x + y;
        case 13:
            return -y + z;
        case 14:
            return -x + y;
        case 15:
            return -y - z;
        }

        throw new IllegalArgumentException("Should never reach here!");
    }

    private static float fadeF(float x) {
        return x * x * x * (x * (x * 6 - 15) + 10);
    }

    public static float mixF(float x, float a, float b) {
        return a + x * (b - a);
    }

    /**
     * This function are using a hard-coded switch-statement-table
     * to determine the result only based on corners hash value.
     *
     * This is up to 3 times faster the Ken Perlins original approach!
     */
    private static float gradF(int hash, float x, float y, float z) {
        switch (hash & 15) {
        case 0:
            return x + y;
        case 1:
            return -x + y;
        case 2:
            return x - y;
        case 3:
            return -x - y;

        case 4:
            return x + z;
        case 5:
            return -x + z;
        case 6:
            return x - z;
        case 7:
            return -x - z;

        case 8:
            return y + z;
        case 9:
            return -y + z;
        case 10:
            return y - z;
        case 11:
            return -y - z;

        case 12:
            return x + y;
        case 13:
            return -y + z;
        case 14:
            return -x + y;
        case 15:
            return -y - z;
        }

        throw new IllegalArgumentException("Should never reach here!");
    }
}

Related Tutorials