1 /** 2 * Copyright (c) 2011, Novyon Events 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * @author Anthyon 29 */ 30 package com.jme3.terrain.noise.filter; 31 32 import java.nio.FloatBuffer; 33 import java.util.logging.Logger; 34 35 import com.jme3.terrain.noise.ShaderUtils; 36 import com.jme3.terrain.noise.fractal.FractalSum; 37 38 public class PerturbFilter extends AbstractFilter { 39 40 private float magnitude; 41 42 @Override 43 public int getMargin(int size, int margin) { 44 margin = super.getMargin(size, margin); 45 return (int) Math.floor(this.magnitude * (margin + size) + margin); 46 } 47 48 public void setMagnitude(float magnitude) { 49 this.magnitude = magnitude; 50 } 51 52 public float getMagnitude() { 53 return this.magnitude; 54 } 55 56 @Override 57 public FloatBuffer filter(float sx, float sy, float base, FloatBuffer data, int workSize) { 58 float[] arr = data.array(); 59 int origSize = (int) Math.ceil(workSize / (2 * this.magnitude + 1)); 60 int offset = (workSize - origSize) / 2; 61 Logger.getLogger(PerturbFilter.class.getCanonicalName()).info( 62 "Found origSize : " + origSize + " and offset: " + offset + " for workSize : " + workSize + " and magnitude : " 63 + this.magnitude); 64 float[] retval = new float[workSize * workSize]; 65 float[] perturbx = new FractalSum().setOctaves(8).setScale(5f).getBuffer(sx, sy, base, workSize).array(); 66 float[] perturby = new FractalSum().setOctaves(8).setScale(5f).getBuffer(sx, sy, base + 1, workSize).array(); 67 for (int y = 0; y < workSize; y++) { 68 for (int x = 0; x < workSize; x++) { 69 // Perturb our coordinates 70 float noisex = perturbx[y * workSize + x]; 71 float noisey = perturby[y * workSize + x]; 72 73 int px = (int) (origSize * noisex * this.magnitude); 74 int py = (int) (origSize * noisey * this.magnitude); 75 76 float c00 = arr[this.wrap(y - py, workSize) * workSize + this.wrap(x - px, workSize)]; 77 float c01 = arr[this.wrap(y - py, workSize) * workSize + this.wrap(x + px, workSize)]; 78 float c10 = arr[this.wrap(y + py, workSize) * workSize + this.wrap(x - px, workSize)]; 79 float c11 = arr[this.wrap(y + py, workSize) * workSize + this.wrap(x + px, workSize)]; 80 81 float c0 = ShaderUtils.mix(c00, c01, noisex); 82 float c1 = ShaderUtils.mix(c10, c11, noisex); 83 retval[y * workSize + x] = ShaderUtils.mix(c0, c1, noisey); 84 } 85 } 86 return FloatBuffer.wrap(retval); 87 } 88 89 private int wrap(int v, int size) { 90 if (v < 0) { 91 return v + size - 1; 92 } else if (v >= size) { 93 return v - size; 94 } else { 95 return v; 96 } 97 } 98 } 99