diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java index 81fa12266..ccbdeedd2 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java @@ -31,10 +31,15 @@ */ package com.jme3.terrain.geomipmap; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; import com.jme3.scene.control.UpdateControl; import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.export.InputCapsule; +import com.jme3.export.OutputCapsule; import com.jme3.terrain.heightmap.HeightMap; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -101,6 +106,7 @@ public class TerrainGrid extends TerrainQuad { protected int quarterSize; protected int quadSize; protected HeightMapGrid heightMapGrid; + protected TerrainQuadGrid terrainQuadGrid; protected Vector3f[] quadIndex; protected Map listeners = new HashMap(); protected Material material; @@ -134,11 +140,17 @@ public class TerrainGrid extends TerrainQuad { final Vector3f temp = location.add(quadIndex[quadIdx]); TerrainQuad q = cache.get(temp); if (q == 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()); - q.setMaterial(material.clone()); - log.log(Level.FINE, "Loaded TerrainQuad {0}", q.getName()); + 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()); + q.setMaterial(material.clone()); + log.log(Level.FINE, "Loaded TerrainQuad {0} from HeightMapGrid", q.getName()); + } else if (terrainQuadGrid != null) { + q = terrainQuadGrid.getTerrainQuadAt(location); + q.setMaterial(material); + log.log(Level.FINE, "Loaded TerrainQuad {0} from TerrainQuadGrid", q.getName()); + } } cache.put(temp, q); @@ -179,6 +191,50 @@ public class TerrainGrid extends TerrainQuad { return 0; // error } + //TODO: unify constructors + public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, TerrainQuadGrid terrainQuadGrid, + Vector2f offset, float offsetAmount) { + this.name = name; + this.patchSize = patchSize; + this.size = maxVisibleSize; + this.quarterSize = maxVisibleSize >> 2; + this.quadSize = (maxVisibleSize + 1) >> 1; + this.stepScale = scale; + this.terrainQuadGrid = terrainQuadGrid; + terrainQuadGrid.setSize(this.size); + terrainQuadGrid.setPatchSize(this.patchSize); + terrainQuadGrid.setQuadSize(this.quadSize); + this.totalSize = maxVisibleSize; + this.offset = offset; + this.offsetAmount = offsetAmount; + this.gridOffset = new int[]{0, 0}; + + /* + * -z + * | + * 1|3 + * -x ----+---- x + * 2|4 + * | + * z + */ + this.quadIndex = new Vector3f[]{ + new Vector3f(-1, 0, -1), new Vector3f(0, 0, -1), new Vector3f(1, 0, -1), new Vector3f(2, 0, -1), + new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(2, 0, 0), + new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1), + new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)}; + + addControl(new UpdateControl()); + } + + public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, TerrainQuadGrid terrainQuadGrid) { + this(name, patchSize, maxVisibleSize, scale, terrainQuadGrid, new Vector2f(), 0); + } + + public TerrainGrid(String name, int patchSize, int maxVisibleSize, TerrainQuadGrid terrainQuadGrid) { + this(name, patchSize, maxVisibleSize, Vector3f.UNIT_XYZ, terrainQuadGrid); + } + public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, HeightMapGrid heightMapGrid, Vector2f offset, float offsetAmount) { this.name = name; @@ -192,8 +248,8 @@ public class TerrainGrid extends TerrainQuad { this.totalSize = maxVisibleSize; this.offset = offset; this.offsetAmount = offsetAmount; - this.gridOffset = new int[]{0,0}; - + this.gridOffset = new int[]{0, 0}; + /* * -z * | @@ -204,10 +260,10 @@ public class TerrainGrid extends TerrainQuad { * z */ this.quadIndex = new Vector3f[]{ - new Vector3f(-1, 0, -1), new Vector3f(0, 0, -1), new Vector3f(1, 0, -1), new Vector3f(2, 0, -1), - new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(2, 0, 0), - new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1), - new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)}; + new Vector3f(-1, 0, -1), new Vector3f(0, 0, -1), new Vector3f(1, 0, -1), new Vector3f(2, 0, -1), + new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(2, 0, 0), + new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1), + new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)}; addControl(new UpdateControl()); } @@ -242,10 +298,10 @@ public class TerrainGrid extends TerrainQuad { // 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.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)); - gridOffset[1] = Math.round(camCell.z*(size/2)); - cellsLoaded=0; + if (cellsLoaded > 1) { // Check if cells are updated before updating gridoffset. + gridOffset[0] = Math.round(camCell.x * (size / 2)); + gridOffset[1] = Math.round(camCell.z * (size / 2)); + cellsLoaded = 0; } 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 @@ -263,7 +319,7 @@ public class TerrainGrid extends TerrainQuad { Vector3f shifted = tile.subtract(offsetHalf); return new Vector3f(FastMath.floor(shifted.x), 0, FastMath.floor(shifted.z)); } - + /** * Centered at 0,0. * Get the tile index location in integer form: @@ -292,7 +348,7 @@ public class TerrainGrid extends TerrainQuad { */ protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f cam) { this.removeQuad(quadrant); - + q.setQuadrant((short) quadrant); this.attachChild(q); @@ -318,7 +374,7 @@ public class TerrainGrid extends TerrainQuad { * @param camCell the cell the camera is in */ protected void updateChildrens(Vector3f camCell) { - + int dx = 0; int dy = 0; if (currentCamCell != null) { @@ -394,10 +450,61 @@ public class TerrainGrid extends TerrainQuad { } super.adjustHeight(xz, height); } - + @Override 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 void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule c = im.getCapsule(this); + name = c.readString("name", null); + size = c.readInt("size", 0); + patchSize = c.readInt("patchSize", 0); + stepScale = (Vector3f) c.readSavable("stepScale", null); + offset = (Vector2f) c.readSavable("offset", null); + offsetAmount = c.readFloat("offsetAmount", 0); + terrainQuadGrid = (TerrainQuadGrid) c.readSavable("terrainQuadGrid", null); +// terrainQuadGrid.setSize(this.size); +// terrainQuadGrid.setPatchSize(this.patchSize); +// terrainQuadGrid.setQuadSize(this.quadSize); + + int maxVisibleSize = size; + this.quarterSize = maxVisibleSize >> 2; + this.quadSize = (maxVisibleSize + 1) >> 1; + this.totalSize = maxVisibleSize; + + this.gridOffset = new int[]{0, 0}; + + /* + * -z + * | + * 1|3 + * -x ----+---- x + * 2|4 + * | + * z + */ + this.quadIndex = new Vector3f[]{ + new Vector3f(-1, 0, -1), new Vector3f(0, 0, -1), new Vector3f(1, 0, -1), new Vector3f(2, 0, -1), + new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(2, 0, 0), + new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1), + new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)}; + + addControl(new UpdateControl()); } + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule c = ex.getCapsule(this); + c.write(terrainQuadGrid, "terrainQuadGrid", null); + c.write(size, "size", 0); + c.write(patchSize, "patchSize", 0); + c.write(stepScale, "stepScale", null); + c.write(offset, "offset", null); + c.write(offsetAmount, "offsetAmount", 0); + } } diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuadGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuadGrid.java new file mode 100644 index 000000000..9117bf0b8 --- /dev/null +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuadGrid.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.terrain.geomipmap; + +import com.jme3.export.Savable; +import com.jme3.math.Vector3f; + +/** + * + * @author normenhansen + */ +public interface TerrainQuadGrid extends Savable { + + public TerrainQuad getTerrainQuadAt(Vector3f location); + + public void setSize(int size); + + public void setPatchSize(int patchSize); + + public void setQuadSize(int quadSize); +} diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/grid/AssetQuadGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/grid/AssetQuadGrid.java new file mode 100644 index 000000000..16ca942bb --- /dev/null +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/grid/AssetQuadGrid.java @@ -0,0 +1,85 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.terrain.geomipmap.grid; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.math.Vector3f; +import com.jme3.terrain.geomipmap.TerrainQuad; +import com.jme3.terrain.geomipmap.TerrainQuadGrid; +import java.io.IOException; + +/** + * + * @author normenhansen + */ +public class AssetQuadGrid implements TerrainQuadGrid { + + private AssetManager manager; + private String assetPath; + private String name; + private int size; + private int patchSize; + private int quadSize; + + public AssetQuadGrid() { + } + + public AssetQuadGrid(AssetManager manager, String name, String assetPath, int size, int patchSize, int quadSize) { + this.manager = manager; + this.name = name; + this.assetPath = assetPath; + this.size = size; + this.patchSize = patchSize; + this.quadSize = quadSize; + } + + public TerrainQuad getTerrainQuadAt(Vector3f location) { + TerrainQuad quad = (TerrainQuad) manager.loadModel(assetPath + "/" + name + "-" + Math.round(location.x) + "/" + Math.round(location.y) + "/" + Math.round(location.z)); + if (quad == null) { + createNewQuad(location); + } + return quad; + } + + public void setSize(int size) { + this.size = size; + } + + public void setPatchSize(int patchSize) { + this.patchSize = patchSize; + } + + public void setQuadSize(int quadSize) { + this.quadSize = quadSize; + } + + private TerrainQuad createNewQuad(Vector3f location) { + TerrainQuad q = new TerrainQuad("Quad" + location, patchSize, quadSize, null); + return q; + } + + public void write(JmeExporter ex) throws IOException { + OutputCapsule c = ex.getCapsule(this); + c.write(assetPath, "assetPath", null); + c.write(size, "size", 0); + c.write(name, "name", null); + c.write(patchSize, "patchSize", 0); + c.write(quadSize, "quadSize", 0); + } + + public void read(JmeImporter im) throws IOException { + InputCapsule c = im.getCapsule(this); + manager = im.getAssetManager(); + assetPath = c.readString("assetPath", null); + name = c.readString("name", null); + size = c.readInt("size", 0); + patchSize = c.readInt("patchSize", 0); + quadSize = c.readInt("quadSize", 0); + } +} \ No newline at end of file