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 */
32package com.jme3.scene.plugins.blender.textures;
33
34import com.jme3.math.FastMath;
35import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
36import com.jme3.scene.plugins.blender.BlenderContext;
37import com.jme3.scene.plugins.blender.file.Structure;
38import com.jme3.scene.plugins.blender.textures.TextureGeneratorMusgrave.MusgraveData;
39import java.io.IOException;
40import java.io.InputStream;
41import java.io.ObjectInputStream;
42import java.util.HashMap;
43import java.util.Map;
44import java.util.logging.Level;
45import 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