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 */ NoiseGenerator(String blenderVersion)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 */ loadConstants()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 { NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 }); NoiseFunction()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 { DistanceFunction()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 }); DistanceFunction()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 }); DistanceFunction()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 }); DistanceFunction()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 }); DistanceFunction()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 }); DistanceFunction()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 }); DistanceFunction()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 { MusgraveFunction()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 }); MusgraveFunction()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 }); MusgraveFunction()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 }); MusgraveFunction()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 }); MusgraveFunction()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 { noise(float x, float y, float z, float noiseSize, int noiseDepth, int noiseBasis, boolean isHard)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 turbulence(float x, float y, float z, float noiseSize, int noiseDepth, int noiseBasis, boolean isHard)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 */ voronoi(float x, float y, float z, float[] da, float[] pa, float distanceExponent, int distanceType)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 newPerlin(float x, float y, float z)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 noise3Perlin(float x, float y, float z)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 originalBlenderNoise(float x, float y, float z)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 */ execute(float x, float y, float z)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 */ executeSigned(float x, float y, float z)812 float executeSigned(float x, float y, float z); 813 } 814 815 public static class NoiseMath { lerp(float t, float a, float b)816 public static float lerp(float t, float a, float b) { 817 return a + t * (b - a); 818 } 819 npfade(float t)820 public static float npfade(float t) { 821 return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); 822 } 823 grad(int hash, float x, float y, float z)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