/** * 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); } }