159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.terrain.heightmap; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>ParticleDepositionHeightMap</code> creates a heightmap based on the 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Particle Deposition algorithm based on Jason Shankel's paper from 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "Game Programming Gems". A heightmap is created using a Molecular beam 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * epitaxy, or MBE, for depositing thin layers of atoms on a substrate. 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * We drop a sequence of particles and simulate their flow across a surface 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * of previously dropped particles. This creates a few high peaks, for further 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * realism we can define a caldera. Similar to the way volcano's form 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * islands, rock is deposited via lava, when the lava cools, it recedes 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * into the volcano, creating the caldera. 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @version $Id$ 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class ParticleDepositionHeightMap extends AbstractHeightMap { 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger logger = Logger.getLogger(ParticleDepositionHeightMap.class.getName()); 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //Attributes. 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int jumps; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int peakWalk; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int minParticles; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int maxParticles; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float caldera; 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Constructor sets the attributes of the Particle Deposition 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Height Map and then generates the map. 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param size the size of the terrain where the area is size x size. 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param jumps number of areas to drop particles. Can also think 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * of it as the number of peaks. 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param peakWalk determines how much to agitate the drop point 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * during a creation of a single peak. The lower the number 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the more the drop point will be agitated. 1 will insure 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * agitation every round. 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param minParticles defines the minimum number of particles to 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * drop during a single jump. 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param maxParticles defines the maximum number of particles to 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * drop during a single jump. 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param caldera defines the altitude to invert a peak. This is 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * represented as a percentage, where 0.0 will not invert 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * anything, and 1.0 will invert all. 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if any value is less than zero, and 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * if caldera is not between 0 and 1. If minParticles is greater than 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * max particles as well. 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public ParticleDepositionHeightMap( 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int size, 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int jumps, 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int peakWalk, 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int minParticles, 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int maxParticles, 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float caldera) throws Exception { 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (size <= 0 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || jumps < 0 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || peakWalk < 0 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || minParticles > maxParticles 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || minParticles < 0 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta || maxParticles < 0) { 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception( 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "values must be greater than zero, " 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "and minParticles must be greater than maxParticles"); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (caldera < 0.0f || caldera > 1.0f) { 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception( 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Caldera level must be " + "between 0 and 1"); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.size = size; 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.jumps = jumps; 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.peakWalk = peakWalk; 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.minParticles = minParticles; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.maxParticles = maxParticles; 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.caldera = caldera; 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta load(); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>load</code> generates the heightfield using the Particle Deposition 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * algorithm. <code>load</code> uses the latest attributes, so a call 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * to <code>load</code> is recommended if attributes have changed using 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the set methods. 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean load() { 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int x, y; 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int calderaX, calderaY; 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int sx, sy; 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int tx, ty; 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int m; 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float calderaStartPoint; 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float cutoff; 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dx[] = {0, 1, 0, size - 1, 1, 1, size - 1, size - 1}; 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dy[] = {1, 0, size - 1, 0, size - 1, 1, size - 1, 1}; 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[][] tempBuffer = new float[size][size]; 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //map 0 unmarked, unvisited, 1 marked, unvisited, 2 marked visited. 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[][] calderaMap = new int[size][size]; 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean done; 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int minx, maxx; 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int miny, maxy; 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (null != heightData) { 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta unloadHeightMap(); 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta heightData = new float[size * size]; 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //create peaks. 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < jumps; i++) { 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //pick a random point. 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta x = (int) (Math.rint(Math.random() * (size - 1))); 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta y = (int) (Math.rint(Math.random() * (size - 1))); 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //set the caldera point. 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = x; 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaY = y; 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int numberParticles = 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta (int) (Math.rint( 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta (Math.random() * (maxParticles - minParticles)) 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + minParticles)); 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //drop particles. 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < numberParticles; j++) { 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //check to see if we should aggitate the drop point. 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (peakWalk != 0 && j % peakWalk == 0) { 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m = (int) (Math.rint(Math.random() * 7)); 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta x = (x + dx[m] + size) % size; 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta y = (y + dy[m] + size) % size; 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //add the particle to the piont. 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempBuffer[x][y] += 1; 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sx = x; 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sy = y; 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = false; 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //cause the particle to "slide" down the slope and settle at 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //a low point. 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!done) { 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = true; 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //check neighbors to see if we are higher. 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m = (int) (Math.rint((Math.random() * 8))); 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int jj = 0; jj < 8; jj++) { 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tx = (sx + dx[(jj + m) % 8]) % (size); 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ty = (sy + dy[(jj + m) % 8]) % (size); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //move to the neighbor. 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tempBuffer[tx][ty] + 1.0f < tempBuffer[sx][sy]) { 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempBuffer[tx][ty] += 1.0f; 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempBuffer[sx][sy] -= 1.0f; 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sx = tx; 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sy = ty; 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = false; 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //This point is higher than the current caldera point, 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //so move the caldera here. 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tempBuffer[sx][sy] > tempBuffer[calderaX][calderaY]) { 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = sx; 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaY = sy; 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //apply the caldera. 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaStartPoint = tempBuffer[calderaX][calderaY]; 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cutoff = calderaStartPoint * (1.0f - caldera); 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta minx = calderaX; 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxx = calderaX; 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta miny = calderaY; 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxy = calderaY; 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 1; 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = false; 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!done) { 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = true; 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sx = minx; 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sy = miny; 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tx = maxx; 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ty = maxy; 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (x = sx; x <= tx; x++) { 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (y = sy; y <= ty; y++) { 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = (x + size) % size; 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaY = (y + size) % size; 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (calderaMap[calderaX][calderaY] == 1) { 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 2; 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tempBuffer[calderaX][calderaY] > cutoff 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta && tempBuffer[calderaX][calderaY] 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta <= calderaStartPoint) { 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta done = false; 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempBuffer[calderaX][calderaY] = 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2 * cutoff - tempBuffer[calderaX][calderaY]; 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //check the left and right neighbors 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = (calderaX + 1) % size; 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (calderaMap[calderaX][calderaY] == 0) { 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (x + 1 > maxx) { 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxx = x + 1; 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 1; 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = (calderaX + size - 2) % size; 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (calderaMap[calderaX][calderaY] == 0) { 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (x - 1 < minx) { 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta minx = x - 1; 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 1; 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //check the upper and lower neighbors. 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaX = (x + size) % size; 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaY = (calderaY + 1) % size; 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (calderaMap[calderaX][calderaY] == 0) { 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (y + 1 > maxy) { 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta maxy = y + 1; 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 1; 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaY = (calderaY + size - 2) % size; 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (calderaMap[calderaX][calderaY] == 0) { 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (y - 1 < miny) { 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta miny = y - 1; 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta calderaMap[calderaX][calderaY] = 1; 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //transfer the new terrain into the height map. 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < size; i++) { 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < size; j++) { 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setHeightAtPoint((float) tempBuffer[i][j], j, i); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta erodeTerrain(); 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalizeTerrain(NORMALIZE_RANGE); 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.info("Created heightmap using Particle Deposition"); 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setJumps</code> sets the number of jumps or peaks that will 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * be created during the next call to <code>load</code>. 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param jumps the number of jumps to use for next load. 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if jumps is less than zero. 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setJumps(int jumps) throws Exception { 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (jumps < 0) { 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception("jumps must be positive"); 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.jumps = jumps; 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setPeakWalk</code> sets how often the jump point will be 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * aggitated. The lower the peakWalk, the more often the point will 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * be aggitated. 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param peakWalk the amount to aggitate the jump point. 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if peakWalk is negative or zero. 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setPeakWalk(int peakWalk) throws Exception { 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (peakWalk <= 0) { 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception( 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "peakWalk must be greater than " + "zero"); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.peakWalk = peakWalk; 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setCaldera</code> sets the level at which a peak will be 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * inverted. 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param caldera the level at which a peak will be inverted. This must be 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * between 0 and 1, as it is represented as a percentage. 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if caldera is not between 0 and 1. 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setCaldera(float caldera) throws Exception { 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (caldera < 0.0f || caldera > 1.0f) { 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception( 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Caldera level must be " + "between 0 and 1"); 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.caldera = caldera; 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setMaxParticles</code> sets the maximum number of particles 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * for a single jump. 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param maxParticles the maximum number of particles for a single jump. 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if maxParticles is negative or less than 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the current number of minParticles. 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMaxParticles(int maxParticles) { 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.maxParticles = maxParticles; 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setMinParticles</code> sets the minimum number of particles 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * for a single jump. 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param minParticles the minimum number of particles for a single jump. 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws JmeException if minParticles are greater than 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the current maxParticles; 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMinParticles(int minParticles) throws Exception { 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (minParticles > maxParticles) { 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new Exception( 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "minParticles must be less " + "than the current maxParticles"); 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.minParticles = minParticles; 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 398