• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 import com.jme3.terrain.noise.Basis;
35 
36 public class HydraulicErodeFilter extends AbstractFilter {
37 
38 	private Basis waterMap;
39 	private Basis sedimentMap;
40 	private float Kr;
41 	private float Ks;
42 	private float Ke;
43 	private float Kc;
44 	private float T;
45 
setKc(float kc)46 	public void setKc(float kc) {
47 		this.Kc = kc;
48 	}
49 
setKe(float ke)50 	public void setKe(float ke) {
51 		this.Ke = ke;
52 	}
53 
setKr(float kr)54 	public void setKr(float kr) {
55 		this.Kr = kr;
56 	}
57 
setKs(float ks)58 	public void setKs(float ks) {
59 		this.Ks = ks;
60 	}
61 
setSedimentMap(Basis sedimentMap)62 	public void setSedimentMap(Basis sedimentMap) {
63 		this.sedimentMap = sedimentMap;
64 	}
65 
setT(float t)66 	public void setT(float t) {
67 		this.T = t;
68 	}
69 
setWaterMap(Basis waterMap)70 	public void setWaterMap(Basis waterMap) {
71 		this.waterMap = waterMap;
72 	}
73 
74 	@Override
getMargin(int size, int margin)75 	public int getMargin(int size, int margin) {
76 		return super.getMargin(size, margin) + 1;
77 	}
78 
79 	@Override
filter(float sx, float sy, float base, FloatBuffer buffer, int workSize)80 	public FloatBuffer filter(float sx, float sy, float base, FloatBuffer buffer, int workSize) {
81 		float[] ga = buffer.array();
82 		// float[] wa = this.waterMap.getBuffer(sx, sy, base, workSize).array();
83 		// float[] sa = this.sedimentMap.getBuffer(sx, sy, base,
84 		// workSize).array();
85 		float[] wt = new float[workSize * workSize];
86 		float[] st = new float[workSize * workSize];
87 
88 		int[] idxrel = { -workSize - 1, -workSize + 1, workSize - 1, workSize + 1 };
89 
90 		// step 1. water arrives and step 2. captures material
91 		for (int y = 0; y < workSize; y++) {
92 			for (int x = 0; x < workSize; x++) {
93 				int idx = y * workSize + x;
94 				float wtemp = this.Kr; // * wa[idx];
95 				float stemp = this.Ks; // * sa[idx];
96 				if (wtemp > 0) {
97 					wt[idx] += wtemp;
98 					if (stemp > 0) {
99 						ga[idx] -= stemp * wt[idx];
100 						st[idx] += stemp * wt[idx];
101 					}
102 				}
103 
104 				// step 3. water is transported to it's neighbours
105 				float a = ga[idx] + wt[idx];
106 				// float[] aj = new float[idxrel.length];
107 				float amax = 0;
108 				int amaxidx = -1;
109 				float ac = 0;
110 				float dtotal = 0;
111 
112 				for (int j = 0; j < idxrel.length; j++) {
113 					if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize) {
114 						float at = ga[idx + idxrel[j]] + wt[idx + idxrel[j]];
115 						if (a - at > a - amax) {
116 							dtotal += at;
117 							amax = at;
118 							amaxidx = j;
119 							ac++;
120 						}
121 					}
122 				}
123 
124 				float aa = (dtotal + a) / (ac + 1);
125 				// for (int j = 0; j < idxrel.length; j++) {
126 				// if (idx + idxrel[j] > 0 && idx + idxrel[j] < workSize && a -
127 				// aj[j] > 0) {
128 				if (amaxidx > -1) {
129 					float dwj = Math.min(wt[idx], a - aa) * (a - amax) / dtotal;
130 					float dsj = st[idx] * dwj / wt[idx];
131 					wt[idx] -= dwj;
132 					st[idx] -= dsj;
133 					wt[idx + idxrel[amaxidx]] += dwj;
134 					st[idx + idxrel[amaxidx]] += dsj;
135 				}
136 				// }
137 
138 				// step 4. water evaporates and deposits material
139 				wt[idx] = wt[idx] * (1 - this.Ke);
140 				if (wt[idx] < this.T) {
141 					wt[idx] = 0;
142 				}
143 				float smax = this.Kc * wt[idx];
144 				if (st[idx] > smax) {
145 					ga[idx] += st[idx] - smax;
146 					st[idx] -= st[idx] - smax;
147 				}
148 			}
149 		}
150 
151 		return buffer;
152 	}
153 
154 }
155