Home | History | Annotate | Download | only in textures
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 package com.jme3.scene.plugins.blender.textures;
     33 
     34 import com.jme3.math.FastMath;
     35 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
     36 import com.jme3.scene.plugins.blender.BlenderContext;
     37 import com.jme3.scene.plugins.blender.file.Structure;
     38 import com.jme3.scene.plugins.blender.textures.TextureGeneratorMusgrave.MusgraveData;
     39 import java.io.IOException;
     40 import java.io.InputStream;
     41 import java.io.ObjectInputStream;
     42 import java.util.HashMap;
     43 import java.util.Map;
     44 import java.util.logging.Level;
     45 import java.util.logging.Logger;
     46 
     47 /**
     48  * This generator is responsible for creating various noises used to create
     49  * generated textures loaded from blender.
     50  * It derives from AbstractBlenderHelper but is not stored in blender context.
     51  * It is only used by TextureHelper.
     52  * @author Marcin Roguski (Kaelthas)
     53  */
     54 /*package*/ class NoiseGenerator extends AbstractBlenderHelper {
     55     private static final Logger LOGGER = Logger.getLogger(NoiseGenerator.class.getName());
     56 
     57     // flag
     58     protected static final int TEX_COLORBAND = 1;
     59     protected static final int TEX_FLIPBLEND = 2;
     60     protected static final int TEX_NEGALPHA = 4;
     61     protected static final int TEX_CHECKER_ODD = 8;
     62     protected static final int TEX_CHECKER_EVEN = 16;
     63     protected static final int TEX_PRV_ALPHA = 32;
     64     protected static final int TEX_PRV_NOR = 64;
     65     protected static final int TEX_REPEAT_XMIR = 128;
     66     protected static final int TEX_REPEAT_YMIR = 256;
     67     protected static final int TEX_FLAG_MASK = TEX_COLORBAND | TEX_FLIPBLEND | TEX_NEGALPHA | TEX_CHECKER_ODD | TEX_CHECKER_EVEN | TEX_PRV_ALPHA | TEX_PRV_NOR | TEX_REPEAT_XMIR | TEX_REPEAT_YMIR;
     68 
     69     // tex->stype
     70     protected static final int TEX_PLASTIC = 0;
     71     protected static final int TEX_WALLIN = 1;
     72     protected static final int TEX_WALLOUT = 2;
     73 
     74     // musgrave stype
     75     protected static final int TEX_MFRACTAL = 0;
     76     protected static final int TEX_RIDGEDMF = 1;
     77     protected static final int TEX_HYBRIDMF = 2;
     78     protected static final int TEX_FBM = 3;
     79     protected static final int TEX_HTERRAIN = 4;
     80 
     81     // keyblock->type
     82     protected static final int KEY_LINEAR = 0;
     83     protected static final int KEY_CARDINAL = 1;
     84     protected static final int KEY_BSPLINE = 2;
     85 
     86     // CONSTANTS (read from file)
     87     protected static float[] hashpntf;
     88     protected static short[] hash;
     89     protected static float[] hashvectf;
     90     protected static short[] p;
     91     protected static float[][] g;
     92 
     93     /**
     94      * Constructor. Stores the blender version number and loads the constants needed for computations.
     95      * @param blenderVersion
     96      *        the number of blender version
     97      */
     98     public NoiseGenerator(String blenderVersion) {
     99         super(blenderVersion, false);
    100         this.loadConstants();
    101     }
    102 
    103     /**
    104      * This method loads the constants needed for computations. They are exactly like the ones the blender uses. Each
    105      * deriving class should override this method and load its own constraints. Be carefult with overriding though, if
    106      * an exception will be thrown the class will not be instantiated.
    107      */
    108     protected void loadConstants() {
    109         InputStream is = NoiseGenerator.class.getResourceAsStream("noiseconstants.dat");
    110         try {
    111             ObjectInputStream ois = new ObjectInputStream(is);
    112             hashpntf = (float[]) ois.readObject();
    113             hash = (short[]) ois.readObject();
    114             hashvectf = (float[]) ois.readObject();
    115             p = (short[]) ois.readObject();
    116             g = (float[][]) ois.readObject();
    117         } catch (IOException e) {
    118             LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
    119         } catch (ClassNotFoundException e) {
    120             assert false : "Constants' classes should be arrays of primitive types, so they are ALWAYS known!";
    121         } finally {
    122             if (is != null) {
    123                 try {
    124                     is.close();
    125                 } catch (IOException e) {
    126                     LOGGER.log(Level.WARNING, e.getLocalizedMessage());
    127                 }
    128             }
    129         }
    130     }
    131 
    132     protected static Map<Integer, NoiseFunction> noiseFunctions = new HashMap<Integer, NoiseFunction>();
    133     static {
    134         noiseFunctions.put(Integer.valueOf(0), new NoiseFunction() {
    135         	// originalBlenderNoise
    136             @Override
    137             public float execute(float x, float y, float z) {
    138                 return NoiseFunctions.originalBlenderNoise(x, y, z);
    139             }
    140 
    141             @Override
    142             public float executeSigned(float x, float y, float z) {
    143                 return 2.0f * NoiseFunctions.originalBlenderNoise(x, y, z) - 1.0f;
    144             }
    145         });
    146         noiseFunctions.put(Integer.valueOf(1), new NoiseFunction() {
    147         	// orgPerlinNoise
    148             @Override
    149             public float execute(float x, float y, float z) {
    150                 return 0.5f + 0.5f * NoiseFunctions.noise3Perlin(x, y, z);
    151             }
    152 
    153             @Override
    154             public float executeSigned(float x, float y, float z) {
    155                 return NoiseFunctions.noise3Perlin(x, y, z);
    156             }
    157         });
    158         noiseFunctions.put(Integer.valueOf(2), new NoiseFunction() {
    159         	// newPerlin
    160             @Override
    161             public float execute(float x, float y, float z) {
    162                 return 0.5f + 0.5f * NoiseFunctions.newPerlin(x, y, z);
    163             }
    164 
    165             @Override
    166             public float executeSigned(float x, float y, float z) {
    167                 return this.execute(x, y, z);
    168             }
    169         });
    170         noiseFunctions.put(Integer.valueOf(3), new NoiseFunction() {
    171         	// voronoi_F1
    172             @Override
    173             public float execute(float x, float y, float z) {
    174                 float[] da = new float[4], pa = new float[12];
    175                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    176                 return da[0];
    177             }
    178 
    179             @Override
    180             public float executeSigned(float x, float y, float z) {
    181                 float[] da = new float[4], pa = new float[12];
    182                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    183                 return 2.0f * da[0] - 1.0f;
    184             }
    185         });
    186         noiseFunctions.put(Integer.valueOf(4), new NoiseFunction() {
    187         	// voronoi_F2
    188             @Override
    189             public float execute(float x, float y, float z) {
    190                 float[] da = new float[4], pa = new float[12];
    191                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    192                 return da[1];
    193             }
    194 
    195             @Override
    196             public float executeSigned(float x, float y, float z) {
    197                 float[] da = new float[4], pa = new float[12];
    198                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    199                 return 2.0f * da[1] - 1.0f;
    200             }
    201         });
    202         noiseFunctions.put(Integer.valueOf(5), new NoiseFunction() {
    203         	// voronoi_F3
    204             @Override
    205             public float execute(float x, float y, float z) {
    206                 float[] da = new float[4], pa = new float[12];
    207                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    208                 return da[2];
    209             }
    210 
    211             @Override
    212             public float executeSigned(float x, float y, float z) {
    213                 float[] da = new float[4], pa = new float[12];
    214                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    215                 return 2.0f * da[2] - 1.0f;
    216             }
    217         });
    218         noiseFunctions.put(Integer.valueOf(6), new NoiseFunction() {
    219         	// voronoi_F4
    220             @Override
    221             public float execute(float x, float y, float z) {
    222                 float[] da = new float[4], pa = new float[12];
    223                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    224                 return da[3];
    225             }
    226 
    227             @Override
    228             public float executeSigned(float x, float y, float z) {
    229                 float[] da = new float[4], pa = new float[12];
    230                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    231                 return 2.0f * da[3] - 1.0f;
    232             }
    233         });
    234         noiseFunctions.put(Integer.valueOf(7), new NoiseFunction() {
    235         	// voronoi_F1F2
    236             @Override
    237             public float execute(float x, float y, float z) {
    238                 float[] da = new float[4], pa = new float[12];
    239                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    240                 return da[1] - da[0];
    241             }
    242 
    243             @Override
    244             public float executeSigned(float x, float y, float z) {
    245                 float[] da = new float[4], pa = new float[12];
    246                 NoiseFunctions.voronoi(x, y, z, da, pa, 1, 0);
    247                 return 2.0f * (da[1] - da[0]) - 1.0f;
    248             }
    249         });
    250         noiseFunctions.put(Integer.valueOf(8), new NoiseFunction() {
    251         	// voronoi_Cr
    252             @Override
    253             public float execute(float x, float y, float z) {
    254                 float t = 10 * noiseFunctions.get(Integer.valueOf(7)).execute(x, y, z);// voronoi_F1F2
    255                 return t > 1.0f ? 1.0f : t;
    256             }
    257 
    258             @Override
    259             public float executeSigned(float x, float y, float z) {
    260                 float t = 10.0f * noiseFunctions.get(Integer.valueOf(7)).execute(x, y, z);// voronoi_F1F2
    261                 return t > 1.0f ? 1.0f : 2.0f * t - 1.0f;
    262             }
    263         });
    264         noiseFunctions.put(Integer.valueOf(14), new NoiseFunction() {
    265         	// cellNoise
    266             @Override
    267             public float execute(float x, float y, float z) {
    268                 int xi = (int) Math.floor(x);
    269                 int yi = (int) Math.floor(y);
    270                 int zi = (int) Math.floor(z);
    271                 long n = xi + yi * 1301 + zi * 314159;
    272                 n ^= n << 13;
    273                 return (n * (n * n * 15731 + 789221) + 1376312589) / 4294967296.0f;
    274             }
    275 
    276             @Override
    277             public float executeSigned(float x, float y, float z) {
    278                 return 2.0f * this.execute(x, y, z) - 1.0f;
    279             }
    280         });
    281     }
    282     /** Distance metrics for voronoi. e parameter only used in Minkovsky. */
    283     protected static Map<Integer, DistanceFunction> distanceFunctions = new HashMap<Integer, NoiseGenerator.DistanceFunction>();
    284 
    285     static {
    286         distanceFunctions.put(Integer.valueOf(0), new DistanceFunction() {
    287         	// real distance
    288             @Override
    289             public float execute(float x, float y, float z, float e) {
    290                 return (float) Math.sqrt(x * x + y * y + z * z);
    291             }
    292         });
    293         distanceFunctions.put(Integer.valueOf(1), new DistanceFunction() {
    294         	// distance squared
    295             @Override
    296             public float execute(float x, float y, float z, float e) {
    297                 return x * x + y * y + z * z;
    298             }
    299         });
    300         distanceFunctions.put(Integer.valueOf(2), new DistanceFunction() {
    301         	// manhattan/taxicab/cityblock distance
    302             @Override
    303             public float execute(float x, float y, float z, float e) {
    304                 return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z);
    305             }
    306         });
    307         distanceFunctions.put(Integer.valueOf(3), new DistanceFunction() {
    308         	// Chebychev
    309             @Override
    310             public float execute(float x, float y, float z, float e) {
    311                 x = FastMath.abs(x);
    312                 y = FastMath.abs(y);
    313                 z = FastMath.abs(z);
    314                 float t = x > y ? x : y;
    315                 return z > t ? z : t;
    316             }
    317         });
    318         distanceFunctions.put(Integer.valueOf(4), new DistanceFunction() {
    319         	// Minkovsky, preset exponent 0.5 (MinkovskyH)
    320             @Override
    321             public float execute(float x, float y, float z, float e) {
    322                 float d = (float) (Math.sqrt(FastMath.abs(x)) + Math.sqrt(FastMath.abs(y)) + Math.sqrt(FastMath.abs(z)));
    323                 return d * d;
    324             }
    325         });
    326         distanceFunctions.put(Integer.valueOf(5), new DistanceFunction() {
    327         	// Minkovsky, preset exponent 0.25 (Minkovsky4)
    328             @Override
    329             public float execute(float x, float y, float z, float e) {
    330                 x *= x;
    331                 y *= y;
    332                 z *= z;
    333                 return (float) Math.sqrt(Math.sqrt(x * x + y * y + z * z));
    334             }
    335         });
    336         distanceFunctions.put(Integer.valueOf(6), new DistanceFunction() {
    337         	// Minkovsky, general case
    338             @Override
    339             public float execute(float x, float y, float z, float e) {
    340                 return (float) Math.pow(Math.pow(FastMath.abs(x), e) + Math.pow(FastMath.abs(y), e) + Math.pow(FastMath.abs(z), e), 1.0f / e);
    341             }
    342         });
    343     }
    344 
    345     protected static Map<Integer, MusgraveFunction> musgraveFunctions = new HashMap<Integer, NoiseGenerator.MusgraveFunction>();
    346     static {
    347         musgraveFunctions.put(Integer.valueOf(TEX_MFRACTAL), new MusgraveFunction() {
    348 
    349             @Override
    350             public float execute(MusgraveData musgraveData, float x, float y, float z) {
    351                 float rmd, value = 1.0f, pwr = 1.0f, pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
    352                 NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(musgraveData.noisebasis));
    353                 if (abstractNoiseFunc == null) {
    354                     abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(0));
    355                 }
    356 
    357                 for (int i = 0; i < (int) musgraveData.octaves; ++i) {
    358                     value *= pwr * abstractNoiseFunc.executeSigned(x, y, z) + 1.0f;
    359                     pwr *= pwHL;
    360                     x *= musgraveData.lacunarity;
    361                     y *= musgraveData.lacunarity;
    362                     z *= musgraveData.lacunarity;
    363                 }
    364                 rmd = (float) (musgraveData.octaves - Math.floor(musgraveData.octaves));
    365                 if (rmd != 0.0f) {
    366                     value *= rmd * abstractNoiseFunc.executeSigned(x, y, z) * pwr + 1.0f;
    367                 }
    368                 return value;
    369             }
    370         });
    371         musgraveFunctions.put(Integer.valueOf(TEX_RIDGEDMF), new MusgraveFunction() {
    372 
    373             @Override
    374             public float execute(MusgraveData musgraveData, float x, float y, float z) {
    375                 float result, signal, weight;
    376                 float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
    377                 float pwr = pwHL;
    378 
    379                 NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(musgraveData.noisebasis));
    380                 if (abstractNoiseFunc == null) {
    381                     abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(0));
    382                 }
    383 
    384                 signal = musgraveData.offset - FastMath.abs(abstractNoiseFunc.executeSigned(x, y, z));
    385                 signal *= signal;
    386                 result = signal;
    387                 weight = 1.0f;
    388 
    389                 for (int i = 1; i < (int) musgraveData.octaves; ++i) {
    390                     x *= musgraveData.lacunarity;
    391                     y *= musgraveData.lacunarity;
    392                     z *= musgraveData.lacunarity;
    393                     weight = signal * musgraveData.gain;
    394                     if (weight > 1.0f) {
    395                         weight = 1.0f;
    396                     } else if (weight < 0.0) {
    397                         weight = 0.0f;
    398                     }
    399                     signal = musgraveData.offset - FastMath.abs(abstractNoiseFunc.executeSigned(x, y, z));
    400                     signal *= signal;
    401                     signal *= weight;
    402                     result += signal * pwr;
    403                     pwr *= pwHL;
    404                 }
    405                 return result;
    406             }
    407         });
    408         musgraveFunctions.put(Integer.valueOf(TEX_HYBRIDMF), new MusgraveFunction() {
    409 
    410             @Override
    411             public float execute(MusgraveData musgraveData, float x, float y, float z) {
    412                 float result, signal, weight, rmd;
    413                 float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
    414                 float pwr = pwHL;
    415                 NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(musgraveData.noisebasis));
    416                 if (abstractNoiseFunc == null) {
    417                     abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(0));
    418                 }
    419 
    420                 result = abstractNoiseFunc.executeSigned(x, y, z) + musgraveData.offset;
    421                 weight = musgraveData.gain * result;
    422                 x *= musgraveData.lacunarity;
    423                 y *= musgraveData.lacunarity;
    424                 z *= musgraveData.lacunarity;
    425 
    426                 for (int i = 1; weight > 0.001f && i < (int) musgraveData.octaves; ++i) {
    427                     if (weight > 1.0f) {
    428                         weight = 1.0f;
    429                     }
    430                     signal = (abstractNoiseFunc.executeSigned(x, y, z) + musgraveData.offset) * pwr;
    431                     pwr *= pwHL;
    432                     result += weight * signal;
    433                     weight *= musgraveData.gain * signal;
    434                     x *= musgraveData.lacunarity;
    435                     y *= musgraveData.lacunarity;
    436                     z *= musgraveData.lacunarity;
    437                 }
    438 
    439                 rmd = musgraveData.octaves - (float) Math.floor(musgraveData.octaves);
    440                 if (rmd != 0.0f) {
    441                     result += rmd * (abstractNoiseFunc.executeSigned(x, y, z) + musgraveData.offset) * pwr;
    442                 }
    443                 return result;
    444             }
    445         });
    446         musgraveFunctions.put(Integer.valueOf(TEX_FBM), new MusgraveFunction() {
    447 
    448             @Override
    449             public float execute(MusgraveData musgraveData, float x, float y, float z) {
    450                 float rmd, value = 0.0f, pwr = 1.0f, pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
    451 
    452                 NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(musgraveData.noisebasis));
    453                 if (abstractNoiseFunc == null) {
    454                     abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(0));
    455                 }
    456 
    457                 for (int i = 0; i < (int) musgraveData.octaves; ++i) {
    458                     value += abstractNoiseFunc.executeSigned(x, y, z) * pwr;
    459                     pwr *= pwHL;
    460                     x *= musgraveData.lacunarity;
    461                     y *= musgraveData.lacunarity;
    462                     z *= musgraveData.lacunarity;
    463                 }
    464 
    465                 rmd = (float) (musgraveData.octaves - Math.floor(musgraveData.octaves));
    466                 if (rmd != 0.f) {
    467                     value += rmd * abstractNoiseFunc.executeSigned(x, y, z) * pwr;
    468                 }
    469                 return value;
    470             }
    471         });
    472         musgraveFunctions.put(Integer.valueOf(TEX_HTERRAIN), new MusgraveFunction() {
    473 
    474             @Override
    475             public float execute(MusgraveData musgraveData, float x, float y, float z) {
    476                 float value, increment, rmd;
    477                 float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
    478                 float pwr = pwHL;
    479                 NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(musgraveData.noisebasis));
    480                 if (abstractNoiseFunc == null) {
    481                     abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(0));
    482                 }
    483 
    484                 value = musgraveData.offset + abstractNoiseFunc.executeSigned(x, y, z);
    485                 x *= musgraveData.lacunarity;
    486                 y *= musgraveData.lacunarity;
    487                 z *= musgraveData.lacunarity;
    488 
    489                 for (int i = 1; i < (int) musgraveData.octaves; ++i) {
    490                     increment = (abstractNoiseFunc.executeSigned(x, y, z) + musgraveData.offset) * pwr * value;
    491                     value += increment;
    492                     pwr *= pwHL;
    493                     x *= musgraveData.lacunarity;
    494                     y *= musgraveData.lacunarity;
    495                     z *= musgraveData.lacunarity;
    496                 }
    497 
    498                 rmd = musgraveData.octaves - (float) Math.floor(musgraveData.octaves);
    499                 if (rmd != 0.0) {
    500                     increment = (abstractNoiseFunc.executeSigned(x, y, z) + musgraveData.offset) * pwr * value;
    501                     value += rmd * increment;
    502                 }
    503                 return value;
    504             }
    505         });
    506     }
    507 
    508     public static class NoiseFunctions {
    509     	public static float noise(float x, float y, float z, float noiseSize, int noiseDepth, int noiseBasis, boolean isHard) {
    510     		NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(noiseBasis));
    511     		if (abstractNoiseFunc == null) {
    512 	            abstractNoiseFunc = noiseFunctions.get(0);
    513 	            noiseBasis = 0;
    514 	        }
    515 
    516     		if (noiseBasis == 0) {
    517     			++x;
    518 	            ++y;
    519 	            ++z;
    520 	        }
    521 
    522 	        if (noiseSize != 0.0) {
    523 	            noiseSize = 1.0f / noiseSize;
    524 	            x *= noiseSize;
    525 	            y *= noiseSize;
    526 	            z *= noiseSize;
    527 	        }
    528 	        float result = abstractNoiseFunc.execute(x, y, z);
    529 	        return isHard ? Math.abs(2.0f * result - 1.0f) : result;
    530     	}
    531 
    532     	public static float turbulence(float x, float y, float z, float noiseSize, int noiseDepth, int noiseBasis, boolean isHard) {
    533     		NoiseFunction abstractNoiseFunc = noiseFunctions.get(Integer.valueOf(noiseBasis));
    534     		if (abstractNoiseFunc == null) {
    535 	            abstractNoiseFunc = noiseFunctions.get(0);
    536 	            noiseBasis = 0;
    537 	        }
    538 
    539     		if (noiseBasis == 0) {
    540 	            ++x;
    541 	            ++y;
    542 	            ++z;
    543 	        }
    544 	        if (noiseSize != 0.0) {
    545 	            noiseSize = 1.0f / noiseSize;
    546 	            x *= noiseSize;
    547 	            y *= noiseSize;
    548 	            z *= noiseSize;
    549 	        }
    550 
    551 	        float sum = 0, t, amp = 1, fscale = 1;
    552 	        for (int i = 0; i <= noiseDepth; ++i, amp *= 0.5, fscale *= 2) {
    553 	            t = abstractNoiseFunc.execute(fscale * x, fscale * y, fscale * z);
    554 	            if (isHard) {
    555 	                t = FastMath.abs(2.0f * t - 1.0f);
    556 	            }
    557 	            sum += t * amp;
    558 	        }
    559 
    560 	        sum *= (float) (1 << noiseDepth) / (float) ((1 << noiseDepth + 1) - 1);
    561 	        return sum;
    562     	}
    563 
    564     	/**
    565          * Not 'pure' Worley, but the results are virtually the same. Returns distances in da and point coords in pa
    566          */
    567         public static void voronoi(float x, float y, float z, float[] da, float[] pa, float distanceExponent, int distanceType) {
    568             float xd, yd, zd, d, p[] = new float[3];
    569 
    570             DistanceFunction distanceFunc = distanceFunctions.get(Integer.valueOf(distanceType));
    571             if (distanceFunc == null) {
    572                 distanceFunc = distanceFunctions.get(Integer.valueOf(0));
    573             }
    574 
    575             int xi = (int) FastMath.floor(x);
    576             int yi = (int) FastMath.floor(y);
    577             int zi = (int) FastMath.floor(z);
    578             da[0] = da[1] = da[2] = da[3] = 1e10f;
    579             for (int i = xi - 1; i <= xi + 1; ++i) {
    580                 for (int j = yi - 1; j <= yi + 1; ++j) {
    581                     for (int k = zi - 1; k <= zi + 1; ++k) {
    582                         NoiseMath.hash(i, j, k, p);
    583                         xd = x - (p[0] + i);
    584                         yd = y - (p[1] + j);
    585                         zd = z - (p[2] + k);
    586                         d = distanceFunc.execute(xd, yd, zd, distanceExponent);
    587                         if (d < da[0]) {
    588                             da[3] = da[2];
    589                             da[2] = da[1];
    590                             da[1] = da[0];
    591                             da[0] = d;
    592                             pa[9] = pa[6];
    593                             pa[10] = pa[7];
    594                             pa[11] = pa[8];
    595                             pa[6] = pa[3];
    596                             pa[7] = pa[4];
    597                             pa[8] = pa[5];
    598                             pa[3] = pa[0];
    599                             pa[4] = pa[1];
    600                             pa[5] = pa[2];
    601                             pa[0] = p[0] + i;
    602                             pa[1] = p[1] + j;
    603                             pa[2] = p[2] + k;
    604                         } else if (d < da[1]) {
    605                             da[3] = da[2];
    606                             da[2] = da[1];
    607                             da[1] = d;
    608                             pa[9] = pa[6];
    609                             pa[10] = pa[7];
    610                             pa[11] = pa[8];
    611                             pa[6] = pa[3];
    612                             pa[7] = pa[4];
    613                             pa[8] = pa[5];
    614                             pa[3] = p[0] + i;
    615                             pa[4] = p[1] + j;
    616                             pa[5] = p[2] + k;
    617                         } else if (d < da[2]) {
    618                             da[3] = da[2];
    619                             da[2] = d;
    620                             pa[9] = pa[6];
    621                             pa[10] = pa[7];
    622                             pa[11] = pa[8];
    623                             pa[6] = p[0] + i;
    624                             pa[7] = p[1] + j;
    625                             pa[8] = p[2] + k;
    626                         } else if (d < da[3]) {
    627                             da[3] = d;
    628                             pa[9] = p[0] + i;
    629                             pa[10] = p[1] + j;
    630                             pa[11] = p[2] + k;
    631                         }
    632                     }
    633                 }
    634             }
    635         }
    636 
    637         // instead of adding another permutation array, just use hash table defined above
    638         public static float newPerlin(float x, float y, float z) {
    639             int A, AA, AB, B, BA, BB;
    640             float floorX = (float) Math.floor(x), floorY = (float) Math.floor(y), floorZ = (float) Math.floor(z);
    641             int intX = (int) floorX & 0xFF, intY = (int) floorY & 0xFF, intZ = (int) floorZ & 0xFF;
    642             x -= floorX;
    643             y -= floorY;
    644             z -= floorZ;
    645             //computing fading curves
    646             floorX = NoiseMath.npfade(x);
    647             floorY = NoiseMath.npfade(y);
    648             floorZ = NoiseMath.npfade(z);
    649             A = hash[intX] + intY;
    650             AA = hash[A] + intZ;
    651             AB = hash[A + 1] + intZ;
    652             B = hash[intX + 1] + intY;
    653             BA = hash[B] + intZ;
    654             BB = hash[B + 1] + intZ;
    655             return  NoiseMath.lerp(floorZ, NoiseMath.lerp(floorY, NoiseMath.lerp(floorX, NoiseMath.grad(hash[AA], x, y, z),
    656             		NoiseMath.grad(hash[BA], x - 1, y, z)),
    657             		NoiseMath.lerp(floorX, NoiseMath.grad(hash[AB], x, y - 1, z),
    658             		NoiseMath.grad(hash[BB], x - 1, y - 1, z))),
    659             		NoiseMath.lerp(floorY, NoiseMath.lerp(floorX, NoiseMath.grad(hash[AA + 1], x, y, z - 1),
    660             		NoiseMath.grad(hash[BA + 1], x - 1, y, z - 1)),
    661             		NoiseMath.lerp(floorX, NoiseMath.grad(hash[AB + 1], x, y - 1, z - 1),
    662             		NoiseMath.grad(hash[BB + 1], x - 1, y - 1, z - 1))));
    663         }
    664 
    665         public static float noise3Perlin(float x, float y, float z) {
    666             float t = x + 10000.0f;
    667             int bx0 = (int) t & 0xFF;
    668             int bx1 = bx0 + 1 & 0xFF;
    669             float rx0 = t - (int) t;
    670             float rx1 = rx0 - 1.0f;
    671 
    672             t = y + 10000.0f;
    673             int by0 = (int) t & 0xFF;
    674             int by1 = by0 + 1 & 0xFF;
    675             float ry0 = t - (int) t;
    676             float ry1 = ry0 - 1.0f;
    677 
    678             t = z + 10000.0f;
    679             int bz0 = (int) t & 0xFF;
    680             int bz1 = bz0 + 1 & 0xFF;
    681             float rz0 = t - (int) t;
    682             float rz1 = rz0 - 1.0f;
    683 
    684             int i = p[bx0];
    685             int j = p[bx1];
    686 
    687             int b00 = p[i + by0];
    688             int b10 = p[j + by0];
    689             int b01 = p[i + by1];
    690             int b11 = p[j + by1];
    691 
    692             float sx = NoiseMath.surve(rx0);
    693             float sy = NoiseMath.surve(ry0);
    694             float sz = NoiseMath.surve(rz0);
    695 
    696             float[] q = g[b00 + bz0];
    697             float u = NoiseMath.at(rx0, ry0, rz0, q);
    698             q = g[b10 + bz0];
    699             float v = NoiseMath.at(rx1, ry0, rz0, q);
    700             float a = NoiseMath.lerp(sx, u, v);
    701 
    702             q = g[b01 + bz0];
    703             u = NoiseMath.at(rx0, ry1, rz0, q);
    704             q = g[b11 + bz0];
    705             v = NoiseMath.at(rx1, ry1, rz0, q);
    706             float b = NoiseMath.lerp(sx, u, v);
    707 
    708             float c = NoiseMath.lerp(sy, a, b);
    709 
    710             q = g[b00 + bz1];
    711             u = NoiseMath.at(rx0, ry0, rz1, q);
    712             q = g[b10 + bz1];
    713             v = NoiseMath.at(rx1, ry0, rz1, q);
    714             a = NoiseMath.lerp(sx, u, v);
    715 
    716             q = g[b01 + bz1];
    717             u = NoiseMath.at(rx0, ry1, rz1, q);
    718             q = g[b11 + bz1];
    719             v = NoiseMath.at(rx1, ry1, rz1, q);
    720             b = NoiseMath.lerp(sx, u, v);
    721 
    722             float d = NoiseMath.lerp(sy, a, b);
    723             return 1.5f * NoiseMath.lerp(sz, c, d);
    724         }
    725 
    726         public static float originalBlenderNoise(float x, float y, float z) {
    727             float n = 0.5f;
    728 
    729             int ix = (int) Math.floor(x);
    730             int iy = (int) Math.floor(y);
    731             int iz = (int) Math.floor(z);
    732 
    733             float ox = x - ix;
    734             float oy = y - iy;
    735             float oz = z - iz;
    736 
    737             float jx = ox - 1;
    738             float jy = oy - 1;
    739             float jz = oz - 1;
    740 
    741             float cn1 = ox * ox;
    742             float cn2 = oy * oy;
    743             float cn3 = oz * oz;
    744             float cn4 = jx * jx;
    745             float cn5 = jy * jy;
    746             float cn6 = jz * jz;
    747 
    748             cn1 = 1.0f - 3.0f * cn1 + 2.0f * cn1 * ox;
    749             cn2 = 1.0f - 3.0f * cn2 + 2.0f * cn2 * oy;
    750             cn3 = 1.0f - 3.0f * cn3 + 2.0f * cn3 * oz;
    751             cn4 = 1.0f - 3.0f * cn4 - 2.0f * cn4 * jx;
    752             cn5 = 1.0f - 3.0f * cn5 - 2.0f * cn5 * jy;
    753             cn6 = 1.0f - 3.0f * cn6 - 2.0f * cn6 * jz;
    754             float[] cn = new float[] {cn1 * cn2 * cn3, cn1 * cn2 * cn6, cn1 * cn5 * cn3, cn1 * cn5 * cn6,
    755 					  cn4 * cn2 * cn3, cn4 * cn2 * cn6, cn4 * cn5 * cn3, cn4 * cn5 * cn6,};
    756 
    757             int b00 = hash[hash[ix & 0xFF] + (iy & 0xFF)];
    758             int b01 = hash[hash[ix & 0xFF] + (iy + 1 & 0xFF)];
    759             int b10 = hash[hash[ix + 1 & 0xFF] + (iy & 0xFF)];
    760             int b11 = hash[hash[ix + 1 & 0xFF] + (iy + 1 & 0xFF)];
    761             int[] b1 = new int[] {b00, b00, b01, b01, b10, b10, b11, b11};
    762 
    763             int[] b2 = new int[] {iz & 0xFF, iz + 1 & 0xFF};
    764 
    765             float[] xFactor = new float[] {ox, ox, ox, ox, jx, jx, jx, jx};
    766             float[] yFactor = new float[] {oy, oy, jy, jy, oy, oy, jy, jy};
    767             float[] zFactor = new float[] {oz, jz, oz, jz, oz, jz, oz, jz};
    768 
    769             for(int i=0;i<8;++i) {
    770             	int hIndex = 3 * hash[b1[i] + b2[i%2]];
    771             	n += cn[i] * (hashvectf[hIndex] * xFactor[i] + hashvectf[hIndex + 1] * yFactor[i] + hashvectf[hIndex + 2] * zFactor[i]);
    772             }
    773 
    774             if (n < 0.0f) {
    775                 n = 0.0f;
    776             } else if (n > 1.0f) {
    777                 n = 1.0f;
    778             }
    779             return n;
    780         }
    781     }
    782 
    783     /**
    784      * This class is abstract to the noise functions computations. It has two methods. One calculates the Signed (with
    785      * 'S' at the end) and the other Unsigned value.
    786      * @author Marcin Roguski (Kaelthas)
    787      */
    788     interface NoiseFunction {
    789 
    790         /**
    791          * This method calculates the unsigned value of the noise.
    792          * @param x
    793          *        the x texture coordinate
    794          * @param y
    795          *        the y texture coordinate
    796          * @param z
    797          *        the z texture coordinate
    798          * @return value of the noise
    799          */
    800         float execute(float x, float y, float z);
    801 
    802         /**
    803          * This method calculates the signed value of the noise.
    804          * @param x
    805          *        the x texture coordinate
    806          * @param y
    807          *        the y texture coordinate
    808          * @param z
    809          *        the z texture coordinate
    810          * @return value of the noise
    811          */
    812         float executeSigned(float x, float y, float z);
    813     }
    814 
    815     public static class NoiseMath {
    816     	public static float lerp(float t, float a, float b) {
    817             return a + t * (b - a);
    818         }
    819 
    820     	public static float npfade(float t) {
    821             return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
    822         }
    823 
    824     	public static float grad(int hash, float x, float y, float z) {
    825             int h = hash & 0x0F;
    826             float u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
    827             return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
    828         }
    829 
    830     	public static float surve(float t) {
    831             return t * t * (3.0f - 2.0f * t);
    832         }
    833 
    834     	public static float at(float x, float y, float z, float[] q) {
    835             return x * q[0] + y * q[1] + z * q[2];
    836         }
    837 
    838     	public static void hash(int x, int y, int z, float[] result) {
    839             result[0] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF]];
    840             result[1] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF] + 1];
    841             result[2] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF] + 2];
    842         }
    843     }
    844 
    845     @Override
    846     public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) {
    847     	return true;
    848     }
    849 
    850     /**
    851      * This interface is used for distance calculation classes. Distance metrics for voronoi. e parameter only used in
    852      * Minkovsky.
    853      */
    854     interface DistanceFunction {
    855 
    856         /**
    857          * This method calculates the distance for voronoi algorithms.
    858          * @param x
    859          *        the x coordinate
    860          * @param y
    861          *        the y coordinate
    862          * @param z
    863          *        the z coordinate
    864          * @param e
    865          *        this parameter used in Monkovsky (no idea what it really is ;)
    866          * @return
    867          */
    868         float execute(float x, float y, float z, float e);
    869     }
    870 
    871     interface MusgraveFunction {
    872 
    873         float execute(MusgraveData musgraveData, float x, float y, float z);
    874     }
    875 }
    876