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