159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2011, Novyon Events
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - Redistributions of source code must retain the above copyright notice, this
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - Redistributions in binary form must reproduce the above copyright notice,
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this list of conditions and the following disclaimer in the documentation
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Anthyon
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.terrain.noise.filter;
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.terrain.noise.Basis;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class HydraulicErodeFilter extends AbstractFilter {
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private Basis waterMap;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private Basis sedimentMap;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private float Kr;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private float Ks;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private float Ke;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private float Kc;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private float T;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setKc(float kc) {
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.Kc = kc;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setKe(float ke) {
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.Ke = ke;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setKr(float kr) {
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.Kr = kr;
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setKs(float ks) {
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.Ks = ks;
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setSedimentMap(Basis sedimentMap) {
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.sedimentMap = sedimentMap;
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setT(float t) {
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.T = t;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public void setWaterMap(Basis waterMap) {
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.waterMap = waterMap;
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	@Override
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public int getMargin(int size, int margin) {
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		return super.getMargin(size, margin) + 1;
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	@Override
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int workSize) {
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float[] ga = buffer.array();
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		// float[] wa = this.waterMap.getBuffer(sx, sy, base, workSize).array();
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		// float[] sa = this.sedimentMap.getBuffer(sx, sy, base,
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		// workSize).array();
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float[] wt = new float[workSize * workSize];
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float[] st = new float[workSize * workSize];
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		int[] idxrel = { -workSize - 1, -workSize + 1, workSize - 1, workSize + 1 };
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		// step 1. water arrives and step 2. captures material
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		for (int y = 0; y < workSize; y++) {
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			for (int x = 0; x < workSize; x++) {
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				int idx = y * workSize + x;
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float wtemp = this.Kr; // * wa[idx];
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float stemp = this.Ks; // * sa[idx];
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				if (wtemp > 0) {
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					wt[idx] += wtemp;
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					if (stemp > 0) {
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						ga[idx] -= stemp * wt[idx];
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						st[idx] += stemp * wt[idx];
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					}
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// step 3. water is transported to it's neighbours
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float a = ga[idx] + wt[idx];
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// float[] aj = new float[idxrel.length];
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float amax = 0;
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				int amaxidx = -1;
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float ac = 0;
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float dtotal = 0;
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				for (int j = 0; j < idxrel.length; j++) {
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize) {
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						float at = ga[idx + idxrel[j]] + wt[idx + idxrel[j]];
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						if (a - at > a - amax) {
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							dtotal += at;
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							amax = at;
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							amaxidx = j;
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							ac++;
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					}
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float aa = (dtotal + a) / (ac + 1);
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// for (int j = 0; j < idxrel.length; j++) {
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize && a -
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// aj[j] > 0) {
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				if (amaxidx > -1) {
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					float dwj = Math.min(wt[idx], a - aa) * (a - amax) / dtotal;
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					float dsj = st[idx] * dwj / wt[idx];
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					wt[idx] -= dwj;
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					st[idx] -= dsj;
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					wt[idx + idxrel[amaxidx]] += dwj;
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					st[idx + idxrel[amaxidx]] += dsj;
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// }
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				// step 4. water evaporates and deposits material
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				wt[idx] = wt[idx] * (1 - this.Ke);
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				if (wt[idx] < this.T) {
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					wt[idx] = 0;
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				float smax = this.Kc * wt[idx];
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				if (st[idx] > smax) {
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					ga[idx] += st[idx] - smax;
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					st[idx] -= st[idx] - smax;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			}
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		return buffer;
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
155