aboutsummaryrefslogtreecommitdiff
path: root/engine/src/terrain/com/jme3/terrain/noise/filter
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/terrain/com/jme3/terrain/noise/filter')
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/AbstractFilter.java100
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/HydraulicErodeFilter.java154
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/IterativeFilter.java102
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/OptimizedErode.java113
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/PerturbFilter.java98
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/SmoothFilter.java80
-rw-r--r--engine/src/terrain/com/jme3/terrain/noise/filter/ThermalErodeFilter.java101
7 files changed, 748 insertions, 0 deletions
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/AbstractFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/AbstractFilter.java
new file mode 100644
index 0000000..4174ba9
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/AbstractFilter.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jme3.terrain.noise.Filter;
+
+public abstract class AbstractFilter implements Filter {
+
+ protected List<Filter> preFilters = new ArrayList<Filter>();
+ protected List<Filter> postFilters = new ArrayList<Filter>();
+
+ private boolean enabled = true;
+
+ @Override
+ public Filter addPreFilter(Filter filter) {
+ this.preFilters.add(filter);
+ return this;
+ }
+
+ @Override
+ public Filter addPostFilter(Filter filter) {
+ this.postFilters.add(filter);
+ return this;
+ }
+
+ @Override
+ public FloatBuffer doFilter(float sx, float sy, float base, FloatBuffer data, int size) {
+ if (!this.isEnabled()) {
+ return data;
+ }
+ FloatBuffer retval = data;
+ for (Filter f : this.preFilters) {
+ retval = f.doFilter(sx, sy, base, retval, size);
+ }
+ retval = this.filter(sx, sy, base, retval, size);
+ for (Filter f : this.postFilters) {
+ retval = f.doFilter(sx, sy, base, retval, size);
+ }
+ return retval;
+ }
+
+ public abstract FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int size);
+
+ @Override
+ public int getMargin(int size, int margin) {
+ // TODO sums up all the margins from filters... maybe there's a more
+ // efficient algorithm
+ if (!this.isEnabled()) {
+ return margin;
+ }
+ for (Filter f : this.preFilters) {
+ margin = f.getMargin(size, margin);
+ }
+ for (Filter f : this.postFilters) {
+ margin = f.getMargin(size, margin);
+ }
+ return margin;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/HydraulicErodeFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/HydraulicErodeFilter.java
new file mode 100644
index 0000000..13e2c5e
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/HydraulicErodeFilter.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+
+import com.jme3.terrain.noise.Basis;
+
+public class HydraulicErodeFilter extends AbstractFilter {
+
+ private Basis waterMap;
+ private Basis sedimentMap;
+ private float Kr;
+ private float Ks;
+ private float Ke;
+ private float Kc;
+ private float T;
+
+ public void setKc(float kc) {
+ this.Kc = kc;
+ }
+
+ public void setKe(float ke) {
+ this.Ke = ke;
+ }
+
+ public void setKr(float kr) {
+ this.Kr = kr;
+ }
+
+ public void setKs(float ks) {
+ this.Ks = ks;
+ }
+
+ public void setSedimentMap(Basis sedimentMap) {
+ this.sedimentMap = sedimentMap;
+ }
+
+ public void setT(float t) {
+ this.T = t;
+ }
+
+ public void setWaterMap(Basis waterMap) {
+ this.waterMap = waterMap;
+ }
+
+ @Override
+ public int getMargin(int size, int margin) {
+ return super.getMargin(size, margin) + 1;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int workSize) {
+ float[] ga = buffer.array();
+ // float[] wa = this.waterMap.getBuffer(sx, sy, base, workSize).array();
+ // float[] sa = this.sedimentMap.getBuffer(sx, sy, base,
+ // workSize).array();
+ float[] wt = new float[workSize * workSize];
+ float[] st = new float[workSize * workSize];
+
+ int[] idxrel = { -workSize - 1, -workSize + 1, workSize - 1, workSize + 1 };
+
+ // step 1. water arrives and step 2. captures material
+ for (int y = 0; y < workSize; y++) {
+ for (int x = 0; x < workSize; x++) {
+ int idx = y * workSize + x;
+ float wtemp = this.Kr; // * wa[idx];
+ float stemp = this.Ks; // * sa[idx];
+ if (wtemp > 0) {
+ wt[idx] += wtemp;
+ if (stemp > 0) {
+ ga[idx] -= stemp * wt[idx];
+ st[idx] += stemp * wt[idx];
+ }
+ }
+
+ // step 3. water is transported to it's neighbours
+ float a = ga[idx] + wt[idx];
+ // float[] aj = new float[idxrel.length];
+ float amax = 0;
+ int amaxidx = -1;
+ float ac = 0;
+ float dtotal = 0;
+
+ for (int j = 0; j < idxrel.length; j++) {
+ if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize) {
+ float at = ga[idx + idxrel[j]] + wt[idx + idxrel[j]];
+ if (a - at > a - amax) {
+ dtotal += at;
+ amax = at;
+ amaxidx = j;
+ ac++;
+ }
+ }
+ }
+
+ float aa = (dtotal + a) / (ac + 1);
+ // for (int j = 0; j < idxrel.length; j++) {
+ // if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize && a -
+ // aj[j] > 0) {
+ if (amaxidx > -1) {
+ float dwj = Math.min(wt[idx], a - aa) * (a - amax) / dtotal;
+ float dsj = st[idx] * dwj / wt[idx];
+ wt[idx] -= dwj;
+ st[idx] -= dsj;
+ wt[idx + idxrel[amaxidx]] += dwj;
+ st[idx + idxrel[amaxidx]] += dsj;
+ }
+ // }
+
+ // step 4. water evaporates and deposits material
+ wt[idx] = wt[idx] * (1 - this.Ke);
+ if (wt[idx] < this.T) {
+ wt[idx] = 0;
+ }
+ float smax = this.Kc * wt[idx];
+ if (st[idx] > smax) {
+ ga[idx] += st[idx] - smax;
+ st[idx] -= st[idx] - smax;
+ }
+ }
+ }
+
+ return buffer;
+ }
+
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/IterativeFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/IterativeFilter.java
new file mode 100644
index 0000000..3764256
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/IterativeFilter.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jme3.terrain.noise.Filter;
+
+public class IterativeFilter extends AbstractFilter {
+
+ private int iterations;
+
+ private List<Filter> preIterateFilters = new ArrayList<Filter>();
+ private List<Filter> postIterateFilters = new ArrayList<Filter>();
+ private Filter filter;
+
+ @Override
+ public int getMargin(int size, int margin) {
+ if (!this.isEnabled()) {
+ return margin;
+ }
+ for (Filter f : this.preIterateFilters) {
+ margin = f.getMargin(size, margin);
+ }
+ margin = this.filter.getMargin(size, margin);
+ for (Filter f : this.postIterateFilters) {
+ margin = f.getMargin(size, margin);
+ }
+ return this.iterations * margin + super.getMargin(size, margin);
+ }
+
+ public void setIterations(int iterations) {
+ this.iterations = iterations;
+ }
+
+ public int getIterations() {
+ return this.iterations;
+ }
+
+ public IterativeFilter addPostIterateFilter(Filter filter) {
+ this.postIterateFilters.add(filter);
+ return this;
+ }
+
+ public IterativeFilter addPreIterateFilter(Filter filter) {
+ this.preIterateFilters.add(filter);
+ return this;
+ }
+
+ public void setFilter(Filter filter) {
+ this.filter = filter;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer data, int size) {
+ if (!this.isEnabled()) {
+ return data;
+ }
+ FloatBuffer retval = data;
+
+ for (int i = 0; i < this.iterations; i++) {
+ for (Filter f : this.preIterateFilters) {
+ retval = f.doFilter(sx, sy, base, retval, size);
+ }
+ retval = this.filter.doFilter(sx, sy, base, retval, size);
+ for (Filter f : this.postIterateFilters) {
+ retval = f.doFilter(sx, sy, base, retval, size);
+ }
+ }
+
+ return retval;
+ }
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/OptimizedErode.java b/engine/src/terrain/com/jme3/terrain/noise/filter/OptimizedErode.java
new file mode 100644
index 0000000..fc20da6
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/OptimizedErode.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+
+public class OptimizedErode extends AbstractFilter {
+
+ private float talus;
+ private int radius;
+
+ public OptimizedErode setRadius(int radius) {
+ this.radius = radius;
+ return this;
+ }
+
+ public int getRadius() {
+ return this.radius;
+ }
+
+ public OptimizedErode setTalus(float talus) {
+ this.talus = talus;
+ return this;
+ }
+
+ public float getTalus() {
+ return this.talus;
+ }
+
+ @Override
+ public int getMargin(int size, int margin) {
+ return super.getMargin(size, margin) + this.radius;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int size) {
+ float[] tmp = buffer.array();
+ float[] retval = new float[tmp.length];
+
+ for (int y = this.radius + 1; y < size - this.radius; y++) {
+ for (int x = this.radius + 1; x < size - this.radius; x++) {
+ int idx = y * size + x;
+ float h = tmp[idx];
+
+ float horizAvg = 0;
+ int horizCount = 0;
+ float vertAvg = 0;
+ int vertCount = 0;
+
+ boolean horizT = false;
+ boolean vertT = false;
+
+ for (int i = 0; i >= -this.radius; i--) {
+ int idxV = (y + i) * size + x;
+ int idxVL = (y + i - 1) * size + x;
+ int idxH = y * size + x + i;
+ int idxHL = y * size + x + i - 1;
+ float hV = tmp[idxV];
+ float hH = tmp[idxH];
+
+ if (Math.abs(h - hV) > this.talus && Math.abs(h - tmp[idxVL]) > this.talus || vertT) {
+ vertT = true;
+ } else {
+ if (Math.abs(h - hV) <= this.talus) {
+ vertAvg += hV;
+ vertCount++;
+ }
+ }
+
+ if (Math.abs(h - hH) > this.talus && Math.abs(h - tmp[idxHL]) > this.talus || horizT) {
+ horizT = true;
+ } else {
+ if (Math.abs(h - hH) <= this.talus) {
+ horizAvg += hH;
+ horizCount++;
+ }
+ }
+ }
+
+ retval[idx] = 0.5f * (vertAvg / (vertCount > 0 ? vertCount : 1) + horizAvg / (horizCount > 0 ? horizCount : 1));
+ }
+ }
+ return FloatBuffer.wrap(retval);
+ }
+
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/PerturbFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/PerturbFilter.java
new file mode 100644
index 0000000..f510f90
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/PerturbFilter.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+import java.util.logging.Logger;
+
+import com.jme3.terrain.noise.ShaderUtils;
+import com.jme3.terrain.noise.fractal.FractalSum;
+
+public class PerturbFilter extends AbstractFilter {
+
+ private float magnitude;
+
+ @Override
+ public int getMargin(int size, int margin) {
+ margin = super.getMargin(size, margin);
+ return (int) Math.floor(this.magnitude * (margin + size) + margin);
+ }
+
+ public void setMagnitude(float magnitude) {
+ this.magnitude = magnitude;
+ }
+
+ public float getMagnitude() {
+ return this.magnitude;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer data, int workSize) {
+ float[] arr = data.array();
+ int origSize = (int) Math.ceil(workSize / (2 * this.magnitude + 1));
+ int offset = (workSize - origSize) / 2;
+ Logger.getLogger(PerturbFilter.class.getCanonicalName()).info(
+ "Found origSize : " + origSize + " and offset: " + offset + " for workSize : " + workSize + " and magnitude : "
+ + this.magnitude);
+ float[] retval = new float[workSize * workSize];
+ float[] perturbx = new FractalSum().setOctaves(8).setScale(5f).getBuffer(sx, sy, base, workSize).array();
+ float[] perturby = new FractalSum().setOctaves(8).setScale(5f).getBuffer(sx, sy, base + 1, workSize).array();
+ for (int y = 0; y < workSize; y++) {
+ for (int x = 0; x < workSize; x++) {
+ // Perturb our coordinates
+ float noisex = perturbx[y * workSize + x];
+ float noisey = perturby[y * workSize + x];
+
+ int px = (int) (origSize * noisex * this.magnitude);
+ int py = (int) (origSize * noisey * this.magnitude);
+
+ float c00 = arr[this.wrap(y - py, workSize) * workSize + this.wrap(x - px, workSize)];
+ float c01 = arr[this.wrap(y - py, workSize) * workSize + this.wrap(x + px, workSize)];
+ float c10 = arr[this.wrap(y + py, workSize) * workSize + this.wrap(x - px, workSize)];
+ float c11 = arr[this.wrap(y + py, workSize) * workSize + this.wrap(x + px, workSize)];
+
+ float c0 = ShaderUtils.mix(c00, c01, noisex);
+ float c1 = ShaderUtils.mix(c10, c11, noisex);
+ retval[y * workSize + x] = ShaderUtils.mix(c0, c1, noisey);
+ }
+ }
+ return FloatBuffer.wrap(retval);
+ }
+
+ private int wrap(int v, int size) {
+ if (v < 0) {
+ return v + size - 1;
+ } else if (v >= size) {
+ return v - size;
+ } else {
+ return v;
+ }
+ }
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/SmoothFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/SmoothFilter.java
new file mode 100644
index 0000000..1c20c24
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/SmoothFilter.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+
+public class SmoothFilter extends AbstractFilter {
+
+ private int radius;
+ private float effect;
+
+ public void setRadius(int radius) {
+ this.radius = radius;
+ }
+
+ public int getRadius() {
+ return this.radius;
+ }
+
+ public void setEffect(float effect) {
+ this.effect = effect;
+ }
+
+ public float getEffect() {
+ return this.effect;
+ }
+
+ @Override
+ public int getMargin(int size, int margin) {
+ return super.getMargin(size, margin) + this.radius;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int size) {
+ float[] data = buffer.array();
+ float[] retval = new float[data.length];
+
+ for (int y = this.radius; y < size - this.radius; y++) {
+ for (int x = this.radius; x < size - this.radius; x++) {
+ int idx = y * size + x;
+ float n = 0;
+ for (int i = -this.radius; i < this.radius + 1; i++) {
+ for (int j = -this.radius; j < this.radius + 1; j++) {
+ n += data[(y + i) * size + x + j];
+ }
+ }
+ retval[idx] = this.effect * n / (4 * this.radius * (this.radius + 1) + 1) + (1 - this.effect) * data[idx];
+ }
+ }
+
+ return FloatBuffer.wrap(retval);
+ }
+}
diff --git a/engine/src/terrain/com/jme3/terrain/noise/filter/ThermalErodeFilter.java b/engine/src/terrain/com/jme3/terrain/noise/filter/ThermalErodeFilter.java
new file mode 100644
index 0000000..2e49679
--- /dev/null
+++ b/engine/src/terrain/com/jme3/terrain/noise/filter/ThermalErodeFilter.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2011, Novyon Events
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Anthyon
+ */
+package com.jme3.terrain.noise.filter;
+
+import java.nio.FloatBuffer;
+
+public class ThermalErodeFilter extends AbstractFilter {
+
+ private float talus;
+ private float c;
+
+ public ThermalErodeFilter setC(float c) {
+ this.c = c;
+ return this;
+ }
+
+ public ThermalErodeFilter setTalus(float talus) {
+ this.talus = talus;
+ return this;
+ }
+
+ @Override
+ public int getMargin(int size, int margin) {
+ return super.getMargin(size, margin) + 1;
+ }
+
+ @Override
+ public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int workSize) {
+ float[] ga = buffer.array();
+ float[] sa = new float[workSize * workSize];
+
+ int[] idxrel = { -workSize - 1, -workSize + 1, workSize - 1, workSize + 1 };
+
+ for (int y = 0; y < workSize; y++) {
+ for (int x = 0; x < workSize; x++) {
+ int idx = y * workSize + x;
+ ga[idx] += sa[idx];
+ sa[idx] = 0;
+
+ float[] deltas = new float[idxrel.length];
+ float deltaMax = this.talus;
+ float deltaTotal = 0;
+
+ for (int j = 0; j < idxrel.length; j++) {
+ if (idx + idxrel[j] > 0 && idx + idxrel[j] < ga.length) {
+ float dj = ga[idx] - ga[idx + idxrel[j]];
+ if (dj > this.talus) {
+ deltas[j] = dj;
+ deltaTotal += dj;
+ if (dj > deltaMax) {
+ deltaMax = dj;
+ }
+ }
+ }
+ }
+
+ for (int j = 0; j < idxrel.length; j++) {
+ if (deltas[j] != 0) {
+ float d = this.c * (deltaMax - this.talus) * deltas[j] / deltaTotal;
+ if (d > ga[idx] + sa[idx]) {
+ d = ga[idx] + sa[idx];
+ }
+ sa[idx] -= d;
+ sa[idx + idxrel[j]] += d;
+ }
+ deltas[j] = 0;
+ }
+ }
+ }
+
+ return buffer;
+ }
+
+}