diff --git a/engine/src/terrain/Common/MatDefs/Terrain/TerrainLighting.frag b/engine/src/terrain/Common/MatDefs/Terrain/TerrainLighting.frag index 0dc9276fd..a60a3ac8e 100644 --- a/engine/src/terrain/Common/MatDefs/Terrain/TerrainLighting.frag +++ b/engine/src/terrain/Common/MatDefs/Terrain/TerrainLighting.frag @@ -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){ + // NOTE: check for shiny <= 1 removed since shininess is now + // 1.0 by default (uses matdefs default vals) if (shiny <= 1.0){ return 0.0; } diff --git a/engine/src/terrain/com/jme3/terrain/Terrain.java b/engine/src/terrain/com/jme3/terrain/Terrain.java index 1fdbd7818..9b7fbbb69 100644 --- a/engine/src/terrain/com/jme3/terrain/Terrain.java +++ b/engine/src/terrain/com/jme3/terrain/Terrain.java @@ -154,10 +154,18 @@ public interface Terrain { /** * Returns the material that this terrain uses. - * This does not necessarily have to guarantee the material - * return is the only material used in the whole terrain structure. + * Terrain can have different materials in different locations. + * 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 @@ -180,6 +188,14 @@ public interface Terrain { * 1/512 (or 0.00195) percent of the texture. * This is used for converting between tri-planar texture scales and regular * texture scales. + * + * not needed + */ + //public float getTextureCoordinateScale(); + + /** + * + * */ - public float getTextureCoordinateScale(); + public int getNumMajorSubdivisions(); } diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java index 7cceda290..b891a9782 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java @@ -50,8 +50,11 @@ import com.jme3.material.Material; import com.jme3.math.FastMath; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; +import com.jme3.terrain.Terrain; import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; import com.jme3.terrain.heightmap.HeightMapGrid; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.Callable; /** @@ -108,7 +111,7 @@ public class TerrainGrid extends TerrainQuad { protected HeightMapGrid heightMapGrid; private TerrainGridTileLoader gridTileLoader; protected Vector3f[] quadIndex; - protected Map listeners = new HashMap(); + protected Set listeners = new HashSet(); protected Material material; protected LRUCache cache = new LRUCache(16); protected RigidBodyControl[] quadControls; @@ -137,22 +140,22 @@ public class TerrainGrid extends TerrainQuad { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int quadIdx = i * 4 + j; - final Vector3f temp = location.add(quadIndex[quadIdx]); - TerrainQuad q = cache.get(temp); + final Vector3f quadCell = location.add(quadIndex[quadIdx]); + TerrainQuad q = cache.get(quadCell); if (q == null) { if (heightMapGrid != null) { // create the new Quad since it doesn't exist - HeightMap heightMapAt = heightMapGrid.getHeightMapAt(temp); - q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap()); + HeightMap heightMapAt = heightMapGrid.getHeightMapAt(quadCell); + q = new TerrainQuad(getName() + "Quad" + quadCell, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap()); q.setMaterial(material.clone()); log.log(Level.FINE, "Loaded TerrainQuad {0} from HeightMapGrid", q.getName()); } else if (gridTileLoader != null) { - q = gridTileLoader.getTerrainQuadAt(temp); - q.setMaterial(material); + q = gridTileLoader.getTerrainQuadAt(quadCell); + q.setMaterial(material.clone()); log.log(Level.FINE, "Loaded TerrainQuad {0} from TerrainQuadGrid", q.getName()); } } - cache.put(temp, q); + cache.put(quadCell, q); if (isCenter(quadIdx)) { // 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() { public Object call() throws Exception { - attachQuadAt(newQuad, quadrant, temp); + attachQuadAt(newQuad, quadrant, quadCell); newQuad.resetCachedNeighbours(); return null; } @@ -272,7 +275,7 @@ public class TerrainGrid extends TerrainQuad { } Vector3f camCell = this.getCamCell(location); this.updateChildren(camCell); - for (TerrainGridListener l : this.listeners.values()) { + for (TerrainGridListener l : this.listeners) { l.gridMoved(camCell); } } @@ -283,7 +286,7 @@ public class TerrainGrid extends TerrainQuad { // 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 // 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) if (cellsLoaded > 1) { // Check if cells are updated before updating gridoffset. 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 the camera has moved into a new cell, load new terrain into the visible 4 center quads this.updateChildren(camCell); - for (TerrainGridListener l : this.listeners.values()) { + for (TerrainGridListener l : this.listeners) { l.gridMoved(camCell); } } @@ -326,7 +329,7 @@ public class TerrainGrid extends TerrainQuad { if (quadControls != null) { 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)); } this.detachChild(this.getQuad(idx)); @@ -337,17 +340,17 @@ public class TerrainGrid extends TerrainQuad { /** * 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); q.setQuadrant((short) quadrant); 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); - for (TerrainGridListener l : listeners.values()) { - l.tileAttached(cam, q); + for (TerrainGridListener l : listeners) { + l.tileAttached(quadCell, q); } updateModelBound(); } @@ -418,16 +421,16 @@ public class TerrainGrid extends TerrainQuad { this.currentCamCell = camCell; } - public void addListener(String id, TerrainGridListener listener) { - this.listeners.put(id, listener); + public void addListener(TerrainGridListener listener) { + this.listeners.add(listener); } public Vector3f getCurrentCell() { return this.currentCamCell; } - public void removeListener(String id) { - this.listeners.remove(id); + public void removeListener(TerrainGridListener listener) { + this.listeners.remove(listener); } @Override @@ -454,6 +457,22 @@ public class TerrainGrid extends TerrainQuad { protected float getHeightmapHeight(int x, int z) { 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 public void read(JmeImporter im) throws IOException { diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java index 38e0001fd..e972ee0b4 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java @@ -31,7 +31,6 @@ */ package com.jme3.terrain.geomipmap; -import com.jme3.material.Material; import com.jme3.math.Vector3f; /** diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java index 7eb29ae56..6973c4e9a 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java @@ -378,13 +378,13 @@ public class TerrainQuad extends Node implements Terrain { 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 if (children != null) { for (int i = children.size(); --i >= 0;) { Spatial child = children.get(i); if (child instanceof TerrainQuad) { - return ((TerrainQuad)child).getMaterial(); + return ((TerrainQuad)child).getMaterial(worldLocation); } else if (child instanceof TerrainPatch) { return ((TerrainPatch)child).getMaterial(); } @@ -393,8 +393,11 @@ public class TerrainQuad extends Node implements Terrain { return null; } - public float getTextureCoordinateScale() { - return 1f/(float)totalSize; + //public float getTextureCoordinateScale() { + // return 1f/(float)totalSize; + //} + public int getNumMajorSubdivisions() { + return 1; } /** diff --git a/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java b/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java index 78d6d4fae..09a3e8614 100644 --- a/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java +++ b/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java @@ -38,7 +38,7 @@ public class TerrainFractalGridTest extends SimpleApplication { private float grassScale = 64; private float dirtScale = 16; private float rockScale = 128; - private boolean usePhysics = true; + private boolean usePhysics = false; public static void main(final String[] args) { TerrainFractalGridTest app = new TerrainFractalGridTest(); @@ -162,7 +162,7 @@ public class TerrainFractalGridTest extends SimpleApplication { bulletAppState.getPhysicsSpace().add(player3); - terrain.addListener("physicsStartListener", new TerrainGridListener() { + terrain.addListener(new TerrainGridListener() { public void gridMoved(Vector3f newCenter) { } diff --git a/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java b/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java index 5bcd004ee..db4397ffc 100644 --- a/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java +++ b/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java @@ -7,6 +7,7 @@ import com.jme3.app.SimpleApplication; import com.jme3.app.state.ScreenshotAppState; import com.jme3.asset.plugins.HttpZipLocator; import com.jme3.asset.plugins.ZipLocator; +import com.jme3.bounding.BoundingBox; import com.jme3.bullet.BulletAppState; import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape; @@ -19,8 +20,13 @@ import com.jme3.light.AmbientLight; import com.jme3.light.DirectionalLight; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; 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.TerrainGridListener; import com.jme3.terrain.geomipmap.TerrainLodControl; @@ -45,7 +51,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { private float grassScale = 64; private float dirtScale = 16; private float rockScale = 128; - private boolean usePhysics = true; + private boolean usePhysics = false; public static void main(final String[] args) { TerrainGridAlphaMapTest app = new TerrainGridAlphaMapTest(); @@ -57,7 +63,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { private OptimizedErode therm; private SmoothFilter smooth; private IterativeFilter iterate; - private Material matRock; + private Material material; private Material matWire; @Override @@ -71,11 +77,11 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { al.setColor(ColorRGBA.White.mult(1.3f)); rootNode.addLight(al); - File file = new File("mountains.zip"); + File file = new File("TerrainGridTestData.zip"); 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 { - assetManager.registerLocator("mountains.zip", ZipLocator.class); + assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class); } this.flyCam.setMoveSpeed(100f); @@ -83,27 +89,27 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { this.stateManager.attach(state); // TERRAIN TEXTURE material - matRock = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); - matRock.setBoolean("useTriPlanarMapping", false); - matRock.setBoolean("isTerrainGrid", true); + material = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); + material.setBoolean("useTriPlanarMapping", false); + //material.setBoolean("isTerrainGrid", true); // GRASS texture Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"); grass.setWrap(WrapMode.Repeat); - matRock.setTexture("DiffuseMap", grass); - matRock.setFloat("DiffuseMap_0_scale", grassScale); + material.setTexture("DiffuseMap", grass); + material.setFloat("DiffuseMap_0_scale", grassScale); // DIRT texture Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg"); dirt.setWrap(WrapMode.Repeat); - matRock.setTexture("DiffuseMap_1", dirt); - matRock.setFloat("DiffuseMap_1_scale", dirtScale); + material.setTexture("DiffuseMap_1", dirt); + material.setFloat("DiffuseMap_1_scale", dirtScale); // ROCK texture Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg"); rock.setWrap(WrapMode.Repeat); - matRock.setTexture("DiffuseMap_2", rock); - matRock.setFloat("DiffuseMap_2_scale", rockScale); + material.setTexture("DiffuseMap_2", rock); + material.setFloat("DiffuseMap_2_scale", rockScale); // WIREFRAME material matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); @@ -147,7 +153,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { ground.addPreFilter(this.iterate); 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.setLocalScale(2f, 1f, 2f); @@ -165,7 +171,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { 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) { CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1); @@ -179,22 +185,24 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { bulletAppState.getPhysicsSpace().add(player3); } - terrain.addListener("physicsStartListener", new TerrainGridListener() { + terrain.addListener(new TerrainGridListener() { public void gridMoved(Vector3f newCenter) { } - public Material tileLoaded(Material material, Vector3f cell) { - return material; - } - 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"); - quad.getMaterial().setTexture("AlphaMap", alpha); + Texture alpha = null; + 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) { quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0)); bulletAppState.getPhysicsSpace().add(quad); } + updateMarkerElevations(); } public void tileDetached(Vector3f cell, TerrainQuad quad) { @@ -202,12 +210,47 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { bulletAppState.getPhysicsSpace().remove(quad); quad.removeControl(RigidBodyControl.class); } + updateMarkerElevations(); } }); this.terrain.initialize(cam.getLocation()); 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() { public Void call() throws Exception { diff --git a/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip b/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip index 15285646c..a57484b68 100644 Binary files a/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip and b/sdk/jme3-templates/src/com/jme3/gde/templates/BasicGameProject.zip differ diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java index 3abe28615..6523adaa4 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java @@ -335,7 +335,7 @@ public class TerrainEditorController implements NodeListener { if (terrain == null) return 1f; MatParam matParam = null; - matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer+"_scale"); + matParam = terrain.getMaterial(null).getParam("DiffuseMap_"+layer+"_scale"); if (matParam == null) return -1f; return (Float) matParam.getValue(); @@ -367,7 +367,7 @@ public class TerrainEditorController implements NodeListener { Terrain terrain = (Terrain) getTerrain(null); if (terrain == null) return; - terrain.getMaterial().setFloat("DiffuseMap_"+layer+"_scale", scale); + terrain.getMaterial(null).setFloat("DiffuseMap_"+layer+"_scale", scale); setNeedsSave(true); } else { try { @@ -397,9 +397,9 @@ public class TerrainEditorController implements NodeListener { return null; MatParam matParam = null; if (layer == 0) - matParam = terrain.getMaterial().getParam("DiffuseMap"); + matParam = terrain.getMaterial(null).getParam("DiffuseMap"); else - matParam = terrain.getMaterial().getParam("DiffuseMap_"+layer); + matParam = terrain.getMaterial(null).getParam("DiffuseMap_"+layer); if (matParam == null || matParam.getValue() == null) { return null; @@ -430,11 +430,11 @@ public class TerrainEditorController implements NodeListener { return null; MatParam matParam = null; if (alphaLayer == 0) - matParam = terrain.getMaterial().getParam("AlphaMap"); + matParam = terrain.getMaterial(null).getParam("AlphaMap"); else if(alphaLayer == 1) - matParam = terrain.getMaterial().getParam("AlphaMap_1"); + matParam = terrain.getMaterial(null).getParam("AlphaMap_1"); else if(alphaLayer == 2) - matParam = terrain.getMaterial().getParam("AlphaMap_2"); + matParam = terrain.getMaterial(null).getParam("AlphaMap_2"); if (matParam == null || matParam.getValue() == null) { return null; @@ -471,9 +471,9 @@ public class TerrainEditorController implements NodeListener { if (terrain == null) return; if (layer == 0) - terrain.getMaterial().setTexture("DiffuseMap", texture); + terrain.getMaterial(null).setTexture("DiffuseMap", texture); else - terrain.getMaterial().setTexture("DiffuseMap_"+layer, texture); + terrain.getMaterial(null).setTexture("DiffuseMap_"+layer, texture); setNeedsSave(true); } else { @@ -522,9 +522,9 @@ public class TerrainEditorController implements NodeListener { if (terrain == null) return; if (layer == 0) - terrain.getMaterial().clearParam("DiffuseMap"); + terrain.getMaterial(null).clearParam("DiffuseMap"); else - terrain.getMaterial().clearParam("DiffuseMap_"+layer); + terrain.getMaterial(null).clearParam("DiffuseMap_"+layer); setNeedsSave(true); } @@ -535,9 +535,9 @@ public class TerrainEditorController implements NodeListener { if (terrain == null) return; if (layer == 0) - terrain.getMaterial().clearParam("NormalMap"); + terrain.getMaterial(null).clearParam("NormalMap"); else - terrain.getMaterial().clearParam("NormalMap_"+layer); + terrain.getMaterial(null).clearParam("NormalMap_"+layer); setNeedsSave(true); } @@ -553,9 +553,9 @@ public class TerrainEditorController implements NodeListener { return null; MatParam matParam = null; if (layer == 0) - matParam = terrain.getMaterial().getParam("NormalMap"); + matParam = terrain.getMaterial(null).getParam("NormalMap"); else - matParam = terrain.getMaterial().getParam("NormalMap_"+layer); + matParam = terrain.getMaterial(null).getParam("NormalMap_"+layer); if (matParam == null || matParam.getValue() == null) { return null; @@ -616,18 +616,18 @@ public class TerrainEditorController implements NodeListener { if (texture == null) { // remove the texture if it is null if (layer == 0) - terrain.getMaterial().clearParam("NormalMap"); + terrain.getMaterial(null).clearParam("NormalMap"); else - terrain.getMaterial().clearParam("NormalMap_"+layer); + terrain.getMaterial(null).clearParam("NormalMap_"+layer); return; } texture.setWrap(WrapMode.Repeat); if (layer == 0) - terrain.getMaterial().setTexture("NormalMap", texture); + terrain.getMaterial(null).setTexture("NormalMap", texture); else - terrain.getMaterial().setTexture("NormalMap_"+layer, texture); + terrain.getMaterial(null).setTexture("NormalMap_"+layer, texture); setNeedsSave(true); } else { @@ -957,7 +957,7 @@ public class TerrainEditorController implements NodeListener { Terrain terrain = (Terrain) getTerrain(null); if (terrain == null) return false; - MatParam param = terrain.getMaterial().getParam("useTriPlanarMapping"); + MatParam param = terrain.getMaterial(null).getParam("useTriPlanarMapping"); if (param != null) return (Boolean)param.getValue(); @@ -992,18 +992,18 @@ public class TerrainEditorController implements NodeListener { Terrain terrain = (Terrain) getTerrain(null); if (terrain == null) return; - terrain.getMaterial().setBoolean("useTriPlanarMapping", enabled); + terrain.getMaterial(null).setBoolean("useTriPlanarMapping", enabled); - float texCoordSize = 1/terrain.getTextureCoordinateScale(); + float size = terrain.getTerrainSize(); if (enabled) { for (int i=0; i