* Terrain API changes to better support TG in SDK terrain editor

* Refactored TG slightly.
* Updated TG tests
* new TG alphamap test data

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8711 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
bre..ns 13 years ago
parent 47e393ba23
commit 4e34217111
  1. 2
      engine/src/terrain/Common/MatDefs/Terrain/TerrainLighting.frag
  2. 24
      engine/src/terrain/com/jme3/terrain/Terrain.java
  3. 61
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java
  4. 1
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java
  5. 11
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java
  6. 4
      engine/src/test/jme3test/terrain/TerrainFractalGridTest.java
  7. 122
      engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java
  8. 8
      engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java
  9. 8
      engine/src/test/jme3test/terrain/TerrainGridTest.java
  10. 12
      engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java
  11. 16
      sdk/JME3TestsTemplate/nbproject/genfiles.properties
  12. 2
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeTerrainGrid.java
  13. BIN
      sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip
  14. 48
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java
  15. 4
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java
  16. 6
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainToolAction.java

@ -163,6 +163,8 @@ float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
} }
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){ float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
// NOTE: check for shiny <= 1 removed since shininess is now
// 1.0 by default (uses matdefs default vals)
if (shiny <= 1.0){ if (shiny <= 1.0){
return 0.0; return 0.0;
} }

@ -154,10 +154,18 @@ public interface Terrain {
/** /**
* Returns the material that this terrain uses. * Returns the material that this terrain uses.
* This does not necessarily have to guarantee the material * Terrain can have different materials in different locations.
* return is the only material used in the whole terrain structure. * In general, the TerrainQuad will only have one material. But
* TerrainGrid will have a different material per tile.
*
* It could be possible to pass in null for the location, some Terrain
* implementations might just have the one material and not care where
* you are looking. So implementations must handle null being supplied.
*
* @param worldLocation the location, in world coordinates, of where
* we are interested in the underlying texture.
*/ */
public Material getMaterial(); public Material getMaterial(Vector3f worldLocation);
/** /**
* Used for painting to get the number of vertices along the edge of the * Used for painting to get the number of vertices along the edge of the
@ -180,6 +188,14 @@ public interface Terrain {
* 1/512 (or 0.00195) percent of the texture. * 1/512 (or 0.00195) percent of the texture.
* This is used for converting between tri-planar texture scales and regular * This is used for converting between tri-planar texture scales and regular
* texture scales. * texture scales.
*
* not needed
*/
//public float getTextureCoordinateScale();
/**
*
*
*/ */
public float getTextureCoordinateScale(); public int getNumMajorSubdivisions();
} }

@ -50,8 +50,11 @@ import com.jme3.material.Material;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.terrain.Terrain;
import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
import com.jme3.terrain.heightmap.HeightMapGrid; import com.jme3.terrain.heightmap.HeightMapGrid;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
/** /**
@ -108,7 +111,7 @@ public class TerrainGrid extends TerrainQuad {
protected HeightMapGrid heightMapGrid; protected HeightMapGrid heightMapGrid;
private TerrainGridTileLoader gridTileLoader; private TerrainGridTileLoader gridTileLoader;
protected Vector3f[] quadIndex; protected Vector3f[] quadIndex;
protected Map<String, TerrainGridListener> listeners = new HashMap<String, TerrainGridListener>(); protected Set<TerrainGridListener> listeners = new HashSet<TerrainGridListener>();
protected Material material; protected Material material;
protected LRUCache<Vector3f, TerrainQuad> cache = new LRUCache<Vector3f, TerrainQuad>(16); protected LRUCache<Vector3f, TerrainQuad> cache = new LRUCache<Vector3f, TerrainQuad>(16);
protected RigidBodyControl[] quadControls; protected RigidBodyControl[] quadControls;
@ -137,22 +140,22 @@ public class TerrainGrid extends TerrainQuad {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
int quadIdx = i * 4 + j; int quadIdx = i * 4 + j;
final Vector3f temp = location.add(quadIndex[quadIdx]); final Vector3f quadCell = location.add(quadIndex[quadIdx]);
TerrainQuad q = cache.get(temp); TerrainQuad q = cache.get(quadCell);
if (q == null) { if (q == null) {
if (heightMapGrid != null) { if (heightMapGrid != null) {
// create the new Quad since it doesn't exist // create the new Quad since it doesn't exist
HeightMap heightMapAt = heightMapGrid.getHeightMapAt(temp); HeightMap heightMapAt = heightMapGrid.getHeightMapAt(quadCell);
q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap()); q = new TerrainQuad(getName() + "Quad" + quadCell, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap());
q.setMaterial(material.clone()); q.setMaterial(material.clone());
log.log(Level.FINE, "Loaded TerrainQuad {0} from HeightMapGrid", q.getName()); log.log(Level.FINE, "Loaded TerrainQuad {0} from HeightMapGrid", q.getName());
} else if (gridTileLoader != null) { } else if (gridTileLoader != null) {
q = gridTileLoader.getTerrainQuadAt(temp); q = gridTileLoader.getTerrainQuadAt(quadCell);
q.setMaterial(material); q.setMaterial(material.clone());
log.log(Level.FINE, "Loaded TerrainQuad {0} from TerrainQuadGrid", q.getName()); log.log(Level.FINE, "Loaded TerrainQuad {0} from TerrainQuadGrid", q.getName());
} }
} }
cache.put(temp, q); cache.put(quadCell, q);
if (isCenter(quadIdx)) { if (isCenter(quadIdx)) {
// if it should be attached as a child right now, attach it // if it should be attached as a child right now, attach it
@ -162,7 +165,7 @@ public class TerrainGrid extends TerrainQuad {
getControl(UpdateControl.class).enqueue(new Callable() { getControl(UpdateControl.class).enqueue(new Callable() {
public Object call() throws Exception { public Object call() throws Exception {
attachQuadAt(newQuad, quadrant, temp); attachQuadAt(newQuad, quadrant, quadCell);
newQuad.resetCachedNeighbours(); newQuad.resetCachedNeighbours();
return null; return null;
} }
@ -272,7 +275,7 @@ public class TerrainGrid extends TerrainQuad {
} }
Vector3f camCell = this.getCamCell(location); Vector3f camCell = this.getCamCell(location);
this.updateChildren(camCell); this.updateChildren(camCell);
for (TerrainGridListener l : this.listeners.values()) { for (TerrainGridListener l : this.listeners) {
l.gridMoved(camCell); l.gridMoved(camCell);
} }
} }
@ -283,7 +286,7 @@ public class TerrainGrid extends TerrainQuad {
// to accept more, there are two ways: // to accept more, there are two ways:
// 1: every camera has an associated grid, then the location is not enough to identify which camera location has changed // 1: every camera has an associated grid, then the location is not enough to identify which camera location has changed
// 2: grids are associated with locations, and no incremental update is done, we load new grids for new locations, and unload those that are not needed anymore // 2: grids are associated with locations, and no incremental update is done, we load new grids for new locations, and unload those that are not needed anymore
Vector3f cam = locations.size() == 0 ? Vector3f.ZERO.clone() : locations.get(0); Vector3f cam = locations.isEmpty() ? Vector3f.ZERO.clone() : locations.get(0);
Vector3f camCell = this.getCamCell(cam); // get the grid index value of where the camera is (ie. 2,1) Vector3f camCell = this.getCamCell(cam); // get the grid index value of where the camera is (ie. 2,1)
if (cellsLoaded > 1) { // Check if cells are updated before updating gridoffset. if (cellsLoaded > 1) { // Check if cells are updated before updating gridoffset.
gridOffset[0] = Math.round(camCell.x * (size / 2)); gridOffset[0] = Math.round(camCell.x * (size / 2));
@ -293,7 +296,7 @@ public class TerrainGrid extends TerrainQuad {
if (camCell.x != this.currentCamCell.x || camCell.z != currentCamCell.z) { if (camCell.x != this.currentCamCell.x || camCell.z != currentCamCell.z) {
// if the camera has moved into a new cell, load new terrain into the visible 4 center quads // if the camera has moved into a new cell, load new terrain into the visible 4 center quads
this.updateChildren(camCell); this.updateChildren(camCell);
for (TerrainGridListener l : this.listeners.values()) { for (TerrainGridListener l : this.listeners) {
l.gridMoved(camCell); l.gridMoved(camCell);
} }
} }
@ -326,7 +329,7 @@ public class TerrainGrid extends TerrainQuad {
if (quadControls != null) { if (quadControls != null) {
this.getQuad(idx).removeControl(RigidBodyControl.class); this.getQuad(idx).removeControl(RigidBodyControl.class);
} }
for (TerrainGridListener l : listeners.values()) { for (TerrainGridListener l : listeners) {
l.tileDetached(getTileCell(this.getQuad(idx).getWorldTranslation()), this.getQuad(idx)); l.tileDetached(getTileCell(this.getQuad(idx).getWorldTranslation()), this.getQuad(idx));
} }
this.detachChild(this.getQuad(idx)); this.detachChild(this.getQuad(idx));
@ -337,17 +340,17 @@ public class TerrainGrid extends TerrainQuad {
/** /**
* Runs on the rendering thread * Runs on the rendering thread
*/ */
protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f cam) { protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f quadCell) {
this.removeQuad(quadrant); this.removeQuad(quadrant);
q.setQuadrant((short) quadrant); q.setQuadrant((short) quadrant);
this.attachChild(q); this.attachChild(q);
Vector3f loc = cam.mult(this.quadSize - 1).subtract(quarterSize, 0, quarterSize);// quadrant location handled TerrainQuad automatically now Vector3f loc = quadCell.mult(this.quadSize - 1).subtract(quarterSize, 0, quarterSize);// quadrant location handled TerrainQuad automatically now
q.setLocalTranslation(loc); q.setLocalTranslation(loc);
for (TerrainGridListener l : listeners.values()) { for (TerrainGridListener l : listeners) {
l.tileAttached(cam, q); l.tileAttached(quadCell, q);
} }
updateModelBound(); updateModelBound();
} }
@ -418,16 +421,16 @@ public class TerrainGrid extends TerrainQuad {
this.currentCamCell = camCell; this.currentCamCell = camCell;
} }
public void addListener(String id, TerrainGridListener listener) { public void addListener(TerrainGridListener listener) {
this.listeners.put(id, listener); this.listeners.add(listener);
} }
public Vector3f getCurrentCell() { public Vector3f getCurrentCell() {
return this.currentCamCell; return this.currentCamCell;
} }
public void removeListener(String id) { public void removeListener(TerrainGridListener listener) {
this.listeners.remove(id); this.listeners.remove(listener);
} }
@Override @Override
@ -454,6 +457,22 @@ public class TerrainGrid extends TerrainQuad {
protected float getHeightmapHeight(int x, int z) { protected float getHeightmapHeight(int x, int z) {
return super.getHeightmapHeight(x - gridOffset[0], z - gridOffset[1]); return super.getHeightmapHeight(x - gridOffset[0], z - gridOffset[1]);
} }
@Override
public int getNumMajorSubdivisions() {
return 2;
}
@Override
public Material getMaterial(Vector3f worldLocation) {
if (worldLocation == null)
return null;
Vector3f tileCell = getTileCell(worldLocation);
Terrain terrain = cache.get(tileCell);
if (terrain == null)
return null; // terrain not loaded for that cell yet!
return terrain.getMaterial(worldLocation);
}
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {

@ -31,7 +31,6 @@
*/ */
package com.jme3.terrain.geomipmap; package com.jme3.terrain.geomipmap;
import com.jme3.material.Material;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
/** /**

@ -378,13 +378,13 @@ public class TerrainQuad extends Node implements Terrain {
return (getParent() != null && !(getParent() instanceof TerrainQuad) ); return (getParent() != null && !(getParent() instanceof TerrainQuad) );
} }
public Material getMaterial() { public Material getMaterial(Vector3f worldLocation) {
// get the material from one of the children. They all share the same material // get the material from one of the children. They all share the same material
if (children != null) { if (children != null) {
for (int i = children.size(); --i >= 0;) { for (int i = children.size(); --i >= 0;) {
Spatial child = children.get(i); Spatial child = children.get(i);
if (child instanceof TerrainQuad) { if (child instanceof TerrainQuad) {
return ((TerrainQuad)child).getMaterial(); return ((TerrainQuad)child).getMaterial(worldLocation);
} else if (child instanceof TerrainPatch) { } else if (child instanceof TerrainPatch) {
return ((TerrainPatch)child).getMaterial(); return ((TerrainPatch)child).getMaterial();
} }
@ -393,8 +393,11 @@ public class TerrainQuad extends Node implements Terrain {
return null; return null;
} }
public float getTextureCoordinateScale() { //public float getTextureCoordinateScale() {
return 1f/(float)totalSize; // return 1f/(float)totalSize;
//}
public int getNumMajorSubdivisions() {
return 1;
} }
/** /**

@ -38,7 +38,7 @@ public class TerrainFractalGridTest extends SimpleApplication {
private float grassScale = 64; private float grassScale = 64;
private float dirtScale = 16; private float dirtScale = 16;
private float rockScale = 128; private float rockScale = 128;
private boolean usePhysics = true; private boolean usePhysics = false;
public static void main(final String[] args) { public static void main(final String[] args) {
TerrainFractalGridTest app = new TerrainFractalGridTest(); TerrainFractalGridTest app = new TerrainFractalGridTest();
@ -162,7 +162,7 @@ public class TerrainFractalGridTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().add(player3); bulletAppState.getPhysicsSpace().add(player3);
terrain.addListener("physicsStartListener", new TerrainGridListener() { terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) { public void gridMoved(Vector3f newCenter) {
} }

@ -7,6 +7,7 @@ import com.jme3.app.SimpleApplication;
import com.jme3.app.state.ScreenshotAppState; import com.jme3.app.state.ScreenshotAppState;
import com.jme3.asset.plugins.HttpZipLocator; import com.jme3.asset.plugins.HttpZipLocator;
import com.jme3.asset.plugins.ZipLocator; import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.BulletAppState; import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape; import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
@ -19,8 +20,13 @@ import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.Arrow;
import com.jme3.terrain.geomipmap.TerrainGrid; import com.jme3.terrain.geomipmap.TerrainGrid;
import com.jme3.terrain.geomipmap.TerrainGridListener; import com.jme3.terrain.geomipmap.TerrainGridListener;
import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl;
@ -45,7 +51,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
private float grassScale = 64; private float grassScale = 64;
private float dirtScale = 16; private float dirtScale = 16;
private float rockScale = 128; private float rockScale = 128;
private boolean usePhysics = true; private boolean usePhysics = false;
public static void main(final String[] args) { public static void main(final String[] args) {
TerrainGridAlphaMapTest app = new TerrainGridAlphaMapTest(); TerrainGridAlphaMapTest app = new TerrainGridAlphaMapTest();
@ -57,7 +63,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
private OptimizedErode therm; private OptimizedErode therm;
private SmoothFilter smooth; private SmoothFilter smooth;
private IterativeFilter iterate; private IterativeFilter iterate;
private Material matRock; private Material material;
private Material matWire; private Material matWire;
@Override @Override
@ -71,11 +77,11 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
al.setColor(ColorRGBA.White.mult(1.3f)); al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al); rootNode.addLight(al);
File file = new File("mountains.zip"); File file = new File("TerrainGridTestData.zip");
if (!file.exists()) { if (!file.exists()) {
assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/mountains.zip", HttpZipLocator.class); assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
} else { } else {
assetManager.registerLocator("mountains.zip", ZipLocator.class); assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
} }
this.flyCam.setMoveSpeed(100f); this.flyCam.setMoveSpeed(100f);
@ -83,27 +89,27 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
this.stateManager.attach(state); this.stateManager.attach(state);
// TERRAIN TEXTURE material // TERRAIN TEXTURE material
matRock = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); material = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
matRock.setBoolean("useTriPlanarMapping", false); material.setBoolean("useTriPlanarMapping", false);
matRock.setBoolean("isTerrainGrid", true); //material.setBoolean("isTerrainGrid", true);
// GRASS texture // GRASS texture
Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"); Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat); grass.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap", grass); material.setTexture("DiffuseMap", grass);
matRock.setFloat("DiffuseMap_0_scale", grassScale); material.setFloat("DiffuseMap_0_scale", grassScale);
// DIRT texture // DIRT texture
Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg"); Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat); dirt.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_1", dirt); material.setTexture("DiffuseMap_1", dirt);
matRock.setFloat("DiffuseMap_1_scale", dirtScale); material.setFloat("DiffuseMap_1_scale", dirtScale);
// ROCK texture // ROCK texture
Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg"); Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
rock.setWrap(WrapMode.Repeat); rock.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_2", rock); material.setTexture("DiffuseMap_2", rock);
matRock.setFloat("DiffuseMap_2_scale", rockScale); material.setFloat("DiffuseMap_2_scale", rockScale);
// WIREFRAME material // WIREFRAME material
matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
@ -147,7 +153,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
ground.addPreFilter(this.iterate); ground.addPreFilter(this.iterate);
this.terrain = new TerrainGrid("terrain", 33, 257, new FractalTileLoader(ground, null, 256)); this.terrain = new TerrainGrid("terrain", 33, 257, new FractalTileLoader(ground, null, 256));
this.terrain.setMaterial(this.matRock); this.terrain.setMaterial(this.material);
this.terrain.setLocalTranslation(0, 0, 0); this.terrain.setLocalTranslation(0, 0, 0);
this.terrain.setLocalScale(2f, 1f, 2f); this.terrain.setLocalScale(2f, 1f, 2f);
@ -165,7 +171,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
this.getCamera().setLocation(new Vector3f(0, 256, 0)); this.getCamera().setLocation(new Vector3f(0, 256, 0));
this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f)); //this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
if (usePhysics) { if (usePhysics) {
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1); CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
@ -179,22 +185,24 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().add(player3); bulletAppState.getPhysicsSpace().add(player3);
} }
terrain.addListener("physicsStartListener", new TerrainGridListener() { terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) { public void gridMoved(Vector3f newCenter) {
} }
public Material tileLoaded(Material material, Vector3f cell) {
return material;
}
public void tileAttached(Vector3f cell, TerrainQuad quad) { public void tileAttached(Vector3f cell, TerrainQuad quad) {
Texture alpha = assetManager.loadTexture("Scenes/TerrainAlphaTest/alphamap_" + Math.abs((int) (cell.x % 2)) * 512 + "_" + Math.abs((int) (cell.z % 2) * 512) + ".png"); Texture alpha = null;
quad.getMaterial().setTexture("AlphaMap", alpha); try {
alpha = assetManager.loadTexture("TerrainAlphaTest/alpha_" + (int)cell.x+ "_" + (int)cell.z + ".png");
} catch (Exception e) {
alpha = assetManager.loadTexture("TerrainAlphaTest/alpha_default.png");
}
quad.getMaterial(null).setTexture("AlphaMap", alpha);
if (usePhysics) { if (usePhysics) {
quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0)); quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
bulletAppState.getPhysicsSpace().add(quad); bulletAppState.getPhysicsSpace().add(quad);
} }
updateMarkerElevations();
} }
public void tileDetached(Vector3f cell, TerrainQuad quad) { public void tileDetached(Vector3f cell, TerrainQuad quad) {
@ -202,12 +210,47 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().remove(quad); bulletAppState.getPhysicsSpace().remove(quad);
quad.removeControl(RigidBodyControl.class); quad.removeControl(RigidBodyControl.class);
} }
updateMarkerElevations();
} }
}); });
this.terrain.initialize(cam.getLocation()); this.terrain.initialize(cam.getLocation());
this.initKeys(); this.initKeys();
markers = new Node();
rootNode.attachChild(markers);
createMarkerPoints(1);
} }
Node markers;
private void createMarkerPoints(float count) {
Node center = createAxisMarker(10);
markers.attachChild(center);
float xS = (count-1)*terrain.getTerrainSize() - (terrain.getTerrainSize()/2);
float zS = (count-1)*terrain.getTerrainSize() - (terrain.getTerrainSize()/2);
float xSi = xS;
float zSi = zS;
for (int x=0; x<count*2; x++) {
for (int z=0; z<count*2; z++) {
Node m = createAxisMarker(5);
m.setLocalTranslation(xSi, 0, zSi);
markers.attachChild(m);
zSi += terrain.getTerrainSize();
}
zSi = zS;
xSi += terrain.getTerrainSize();
}
}
private void updateMarkerElevations() {
for (Spatial s : markers.getChildren()) {
float h = terrain.getHeight(new Vector2f(s.getLocalTranslation().x, s.getLocalTranslation().z));
s.setLocalTranslation(s.getLocalTranslation().x, h+1, s.getLocalTranslation().z);
}
}
private void initKeys() { private void initKeys() {
// You can map one or several inputs to one named action // You can map one or several inputs to one named action
this.inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A)); this.inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
@ -283,4 +326,35 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
this.cam.setLocation(this.player3.getPhysicsLocation()); this.cam.setLocation(this.player3.getPhysicsLocation());
} }
} }
protected Node createAxisMarker(float arrowSize) {
Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
redMat.getAdditionalRenderState().setWireframe(true);
redMat.setColor("Color", ColorRGBA.Red);
Material greenMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
greenMat.getAdditionalRenderState().setWireframe(true);
greenMat.setColor("Color", ColorRGBA.Green);
Material blueMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
blueMat.getAdditionalRenderState().setWireframe(true);
blueMat.setColor("Color", ColorRGBA.Blue);
Node axis = new Node();
// create arrows
Geometry arrowX = new Geometry("arrowX", new Arrow(new Vector3f(arrowSize, 0, 0)));
arrowX.setMaterial(redMat);
Geometry arrowY = new Geometry("arrowY", new Arrow(new Vector3f(0, arrowSize, 0)));
arrowY.setMaterial(greenMat);
Geometry arrowZ = new Geometry("arrowZ", new Arrow(new Vector3f(0, 0, arrowSize)));
arrowZ.setMaterial(blueMat);
axis.attachChild(arrowX);
axis.attachChild(arrowY);
axis.attachChild(arrowZ);
//axis.setModelBound(new BoundingBox());
return axis;
}
} }

@ -35,11 +35,11 @@ public class TerrainGridSerializationTest extends SimpleApplication {
@Override @Override
public void simpleInitApp() { public void simpleInitApp() {
File file = new File("mountains.zip"); File file = new File("TerrainGridTestData.zip");
if (!file.exists()) { if (!file.exists()) {
assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/mountains.zip", HttpZipLocator.class); assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
} else { } else {
assetManager.registerLocator("mountains.zip", ZipLocator.class); assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
} }
this.flyCam.setMoveSpeed(100f); this.flyCam.setMoveSpeed(100f);
@ -72,7 +72,7 @@ public class TerrainGridSerializationTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().add(player3); bulletAppState.getPhysicsSpace().add(player3);
terrain.addListener("physicsStartListener", new TerrainGridListener() { terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) { public void gridMoved(Vector3f newCenter) {
} }

@ -44,11 +44,11 @@ public class TerrainGridTest extends SimpleApplication {
@Override @Override
public void simpleInitApp() { public void simpleInitApp() {
File file = new File("mountains.zip"); File file = new File("TerrainGridTestData.zip");
if (!file.exists()) { if (!file.exists()) {
assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/mountains.zip", HttpZipLocator.class); assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
} else { } else {
assetManager.registerLocator("mountains.zip", ZipLocator.class); assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
} }
this.flyCam.setMoveSpeed(100f); this.flyCam.setMoveSpeed(100f);
@ -128,7 +128,7 @@ public class TerrainGridTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().add(player3); bulletAppState.getPhysicsSpace().add(player3);
terrain.addListener("physicsStartListener", new TerrainGridListener() { terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) { public void gridMoved(Vector3f newCenter) {
} }

@ -9,7 +9,6 @@ import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape; import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
import com.jme3.bullet.control.CharacterControl; import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl; import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.export.binary.BinaryExporter;
import com.jme3.input.KeyInput; import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.KeyTrigger;
@ -25,9 +24,6 @@ import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture.WrapMode;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TerrainGridTileLoaderTest extends SimpleApplication { public class TerrainGridTileLoaderTest extends SimpleApplication {
@ -47,11 +43,11 @@ public class TerrainGridTileLoaderTest extends SimpleApplication {
@Override @Override
public void simpleInitApp() { public void simpleInitApp() {
File file = new File("mountains.zip"); File file = new File("TerrainGridTestData.zip");
if (!file.exists()) { if (!file.exists()) {
assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/mountains.zip", HttpZipLocator.class); assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
} else { } else {
assetManager.registerLocator("mountains.zip", ZipLocator.class); assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
} }
this.flyCam.setMoveSpeed(100f); this.flyCam.setMoveSpeed(100f);
@ -134,7 +130,7 @@ public class TerrainGridTileLoaderTest extends SimpleApplication {
bulletAppState.getPhysicsSpace().add(player3); bulletAppState.getPhysicsSpace().add(player3);
terrain.addListener("physicsStartListener", new TerrainGridListener() { terrain.addListener(new TerrainGridListener() {
public void gridMoved(Vector3f newCenter) { public void gridMoved(Vector3f newCenter) {
} }

@ -1,8 +1,8 @@
build.xml.data.CRC32=0f706f4a build.xml.data.CRC32=0f706f4a
build.xml.script.CRC32=0b0b23c4 build.xml.script.CRC32=0b0b23c4
build.xml.stylesheet.CRC32=28e38971@1.38.1.45 build.xml.stylesheet.CRC32=28e38971@1.38.1.45
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=0f706f4a nbproject/build-impl.xml.data.CRC32=0f706f4a
nbproject/build-impl.xml.script.CRC32=7c2e5d21 nbproject/build-impl.xml.script.CRC32=46d1a69a
nbproject/build-impl.xml.stylesheet.CRC32=f33e10ff@1.38.2.45 nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45

@ -63,7 +63,7 @@ public class JmeTerrainGrid extends JmeTerrainQuad implements TerrainGridListene
getLookupContents().add(spatial); getLookupContents().add(spatial);
this.geom = spatial; this.geom = spatial;
setName(spatial.getName()); setName(spatial.getName());
geom.addListener("GuiListener", this); geom.addListener(this);
SceneApplication.getApplication().enqueue(new Callable<Void>() { SceneApplication.getApplication().enqueue(new Callable<Void>() {
public Void call() throws Exception { public Void call() throws Exception {

@ -335,7 +335,7 @@ public class TerrainEditorController implements NodeListener {
if (terrain == null) if (terrain == null)
return 1f; return 1f;
MatParam matParam = null; MatParam matParam = null;
matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer+"_scale"); matParam = terrain.getMaterial(null).getParam("DiffuseMap_"+layer+"_scale");
if (matParam == null) if (matParam == null)
return -1f; return -1f;
return (Float) matParam.getValue(); return (Float) matParam.getValue();
@ -367,7 +367,7 @@ public class TerrainEditorController implements NodeListener {
Terrain terrain = (Terrain) getTerrain(null); Terrain terrain = (Terrain) getTerrain(null);
if (terrain == null) if (terrain == null)
return; return;
terrain.getMaterial().setFloat("DiffuseMap_"+layer+"_scale", scale); terrain.getMaterial(null).setFloat("DiffuseMap_"+layer+"_scale", scale);
setNeedsSave(true); setNeedsSave(true);
} else { } else {
try { try {
@ -397,9 +397,9 @@ public class TerrainEditorController implements NodeListener {
return null; return null;
MatParam matParam = null; MatParam matParam = null;
if (layer == 0) if (layer == 0)
matParam = terrain.getMaterial().getParam("DiffuseMap"); matParam = terrain.getMaterial(null).getParam("DiffuseMap");
else else
matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer); matParam = terrain.getMaterial(null).getParam("DiffuseMap_"+layer);
if (matParam == null || matParam.getValue() == null) { if (matParam == null || matParam.getValue() == null) {
return null; return null;
@ -430,11 +430,11 @@ public class TerrainEditorController implements NodeListener {
return null; return null;
MatParam matParam = null; MatParam matParam = null;
if (alphaLayer == 0) if (alphaLayer == 0)
matParam = terrain.getMaterial().getParam("AlphaMap"); matParam = terrain.getMaterial(null).getParam("AlphaMap");
else if(alphaLayer == 1) else if(alphaLayer == 1)
matParam = terrain.getMaterial().getParam("AlphaMap_1"); matParam = terrain.getMaterial(null).getParam("AlphaMap_1");
else if(alphaLayer == 2) else if(alphaLayer == 2)
matParam = terrain.getMaterial().getParam("AlphaMap_2"); matParam = terrain.getMaterial(null).getParam("AlphaMap_2");
if (matParam == null || matParam.getValue() == null) { if (matParam == null || matParam.getValue() == null) {
return null; return null;
@ -471,9 +471,9 @@ public class TerrainEditorController implements NodeListener {
if (terrain == null) if (terrain == null)
return; return;
if (layer == 0) if (layer == 0)
terrain.getMaterial().setTexture("DiffuseMap", texture); terrain.getMaterial(null).setTexture("DiffuseMap", texture);
else else
terrain.getMaterial().setTexture("DiffuseMap_"+layer, texture); terrain.getMaterial(null).setTexture("DiffuseMap_"+layer, texture);
setNeedsSave(true); setNeedsSave(true);
} else { } else {
@ -522,9 +522,9 @@ public class TerrainEditorController implements NodeListener {
if (terrain == null) if (terrain == null)
return; return;
if (layer == 0) if (layer == 0)
terrain.getMaterial().clearParam("DiffuseMap"); terrain.getMaterial(null).clearParam("DiffuseMap");
else else
terrain.getMaterial().clearParam("DiffuseMap_"+layer); terrain.getMaterial(null).clearParam("DiffuseMap_"+layer);
setNeedsSave(true); setNeedsSave(true);
} }
@ -535,9 +535,9 @@ public class TerrainEditorController implements NodeListener {
if (terrain == null) if (terrain == null)
return; return;
if (layer == 0) if (layer == 0)
terrain.getMaterial().clearParam("NormalMap"); terrain.getMaterial(null).clearParam("NormalMap");
else else
terrain.getMaterial().clearParam("NormalMap_"+layer); terrain.getMaterial(null).clearParam("NormalMap_"+layer);
setNeedsSave(true); setNeedsSave(true);
} }
@ -553,9 +553,9 @@ public class TerrainEditorController implements NodeListener {
return null; return null;
MatParam matParam = null; MatParam matParam = null;
if (layer == 0) if (layer == 0)
matParam = terrain.getMaterial().getParam("NormalMap"); matParam = terrain.getMaterial(null).getParam("NormalMap");
else else
matParam = terrain.getMaterial().getParam("NormalMap_"+layer); matParam = terrain.getMaterial(null).getParam("NormalMap_"+layer);
if (matParam == null || matParam.getValue() == null) { if (matParam == null || matParam.getValue() == null) {
return null; return null;
@ -616,18 +616,18 @@ public class TerrainEditorController implements NodeListener {
if (texture == null) { if (texture == null) {
// remove the texture if it is null // remove the texture if it is null
if (layer == 0) if (layer == 0)
terrain.getMaterial().clearParam("NormalMap"); terrain.getMaterial(null).clearParam("NormalMap");
else else
terrain.getMaterial().clearParam("NormalMap_"+layer); terrain.getMaterial(null).clearParam("NormalMap_"+layer);
return; return;
} }
texture.setWrap(WrapMode.Repeat); texture.setWrap(WrapMode.Repeat);
if (layer == 0) if (layer == 0)
terrain.getMaterial().setTexture("NormalMap", texture); terrain.getMaterial(null).setTexture("NormalMap", texture);
else else
terrain.getMaterial().setTexture("NormalMap_"+layer, texture); terrain.getMaterial(null).setTexture("NormalMap_"+layer, texture);
setNeedsSave(true); setNeedsSave(true);
} else { } else {
@ -957,7 +957,7 @@ public class TerrainEditorController implements NodeListener {
Terrain terrain = (Terrain) getTerrain(null); Terrain terrain = (Terrain) getTerrain(null);
if (terrain == null) if (terrain == null)
return false; return false;
MatParam param = terrain.getMaterial().getParam("useTriPlanarMapping"); MatParam param = terrain.getMaterial(null).getParam("useTriPlanarMapping");
if (param != null) if (param != null)
return (Boolean)param.getValue(); return (Boolean)param.getValue();
@ -992,18 +992,18 @@ public class TerrainEditorController implements NodeListener {
Terrain terrain = (Terrain) getTerrain(null); Terrain terrain = (Terrain) getTerrain(null);
if (terrain == null) if (terrain == null)
return; return;
terrain.getMaterial().setBoolean("useTriPlanarMapping", enabled); terrain.getMaterial(null).setBoolean("useTriPlanarMapping", enabled);
float texCoordSize = 1/terrain.getTextureCoordinateScale(); float size = terrain.getTerrainSize();
if (enabled) { if (enabled) {
for (int i=0; i<getNumUsedTextures(); i++) { for (int i=0; i<getNumUsedTextures(); i++) {
float scale = 1f/(float)(texCoordSize/getTextureScale(i)); float scale = 1f/(float)(size/getTextureScale(i));
setTextureScale(i, scale); setTextureScale(i, scale);
} }
} else { } else {
for (int i=0; i<getNumUsedTextures(); i++) { for (int i=0; i<getNumUsedTextures(); i++) {
float scale = (float)(texCoordSize*getTextureScale(i)); float scale = (float)(size*getTextureScale(i));
setTextureScale(i, scale); setTextureScale(i, scale);
} }
} }

@ -1020,7 +1020,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
// runs on AWT thread now // runs on AWT thread now
public void sceneOpened(SceneRequest request) { public void sceneOpened(SceneRequest request) {
if (request.equals(sentRequest)) { if (request.equals(sentRequest) && editorController != null) {
currentRequest = request; currentRequest = request;
//Logger.getLogger(TerrainEditorTopComponent.class.getName()).finer("Terrain sceneRequested " + request.getWindowTitle()); //Logger.getLogger(TerrainEditorTopComponent.class.getName()).finer("Terrain sceneRequested " + request.getWindowTitle());
@ -1033,7 +1033,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
if (terrain != null) { if (terrain != null) {
// add the terrain root save node // add the terrain root save node
((Node) terrain).setMaterial(terrain.getMaterial()); ((Node) terrain).setMaterial(terrain.getMaterial(null));
// it appears when loading the actual applied material on the terrain // it appears when loading the actual applied material on the terrain
// does not reflect the material that we get from the terrain. // does not reflect the material that we get from the terrain.

@ -118,11 +118,11 @@ public class PaintTerrainToolAction extends AbstractTerrainToolAction {
return null; return null;
MatParam matParam = null; MatParam matParam = null;
if (alphaLayer == 0) if (alphaLayer == 0)
matParam = terrain.getMaterial().getParam("AlphaMap"); matParam = terrain.getMaterial(null).getParam("AlphaMap");
else if(alphaLayer == 1) else if(alphaLayer == 1)
matParam = terrain.getMaterial().getParam("AlphaMap_1"); matParam = terrain.getMaterial(null).getParam("AlphaMap_1");
else if(alphaLayer == 2) else if(alphaLayer == 2)
matParam = terrain.getMaterial().getParam("AlphaMap_2"); matParam = terrain.getMaterial(null).getParam("AlphaMap_2");
if (matParam == null || matParam.getValue() == null) { if (matParam == null || matParam.getValue() == null) {
return null; return null;

Loading…
Cancel
Save