Home | History | Annotate | Download | only in filter
      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 
     46 	public void setKc(float kc) {
     47 		this.Kc = kc;
     48 	}
     49 
     50 	public void setKe(float ke) {
     51 		this.Ke = ke;
     52 	}
     53 
     54 	public void setKr(float kr) {
     55 		this.Kr = kr;
     56 	}
     57 
     58 	public void setKs(float ks) {
     59 		this.Ks = ks;
     60 	}
     61 
     62 	public void setSedimentMap(Basis sedimentMap) {
     63 		this.sedimentMap = sedimentMap;
     64 	}
     65 
     66 	public void setT(float t) {
     67 		this.T = t;
     68 	}
     69 
     70 	public void setWaterMap(Basis waterMap) {
     71 		this.waterMap = waterMap;
     72 	}
     73 
     74 	@Override
     75 	public int getMargin(int size, int margin) {
     76 		return super.getMargin(size, margin) + 1;
     77 	}
     78 
     79 	@Override
     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