- add abstraction layer for TerrainGrid that allows serving in full TerrainQuads

- add serialization to TerrainGrid
- add AssetQuadGrid loading TerrainQuads from j3o files (WIP)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8677 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 13 years ago
parent b53c8737c0
commit fc23b0173e
  1. 147
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java
  2. 23
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuadGrid.java
  3. 85
      engine/src/terrain/com/jme3/terrain/geomipmap/grid/AssetQuadGrid.java

@ -31,10 +31,15 @@
*/ */
package com.jme3.terrain.geomipmap; package com.jme3.terrain.geomipmap;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.scene.control.UpdateControl; import com.jme3.scene.control.UpdateControl;
import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.control.RigidBodyControl; import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.export.InputCapsule;
import com.jme3.export.OutputCapsule;
import com.jme3.terrain.heightmap.HeightMap; import com.jme3.terrain.heightmap.HeightMap;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -101,6 +106,7 @@ public class TerrainGrid extends TerrainQuad {
protected int quarterSize; protected int quarterSize;
protected int quadSize; protected int quadSize;
protected HeightMapGrid heightMapGrid; protected HeightMapGrid heightMapGrid;
protected TerrainQuadGrid terrainQuadGrid;
protected Vector3f[] quadIndex; protected Vector3f[] quadIndex;
protected Map<String, TerrainGridListener> listeners = new HashMap<String, TerrainGridListener>(); protected Map<String, TerrainGridListener> listeners = new HashMap<String, TerrainGridListener>();
protected Material material; protected Material material;
@ -134,11 +140,17 @@ public class TerrainGrid extends TerrainQuad {
final Vector3f temp = location.add(quadIndex[quadIdx]); final Vector3f temp = location.add(quadIndex[quadIdx]);
TerrainQuad q = cache.get(temp); TerrainQuad q = cache.get(temp);
if (q == null) { if (q == null) {
// create the new Quad since it doesn't exist if (heightMapGrid != null) {
HeightMap heightMapAt = heightMapGrid.getHeightMapAt(temp); // create the new Quad since it doesn't exist
q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap()); HeightMap heightMapAt = heightMapGrid.getHeightMapAt(temp);
q.setMaterial(material.clone()); q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, heightMapAt == null ? null : heightMapAt.getHeightMap());
log.log(Level.FINE, "Loaded TerrainQuad {0}", q.getName()); 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); cache.put(temp, q);
@ -179,6 +191,50 @@ public class TerrainGrid extends TerrainQuad {
return 0; // error 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, public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, HeightMapGrid heightMapGrid,
Vector2f offset, float offsetAmount) { Vector2f offset, float offsetAmount) {
this.name = name; this.name = name;
@ -192,8 +248,8 @@ public class TerrainGrid extends TerrainQuad {
this.totalSize = maxVisibleSize; this.totalSize = maxVisibleSize;
this.offset = offset; this.offset = offset;
this.offsetAmount = offsetAmount; this.offsetAmount = offsetAmount;
this.gridOffset = new int[]{0,0}; this.gridOffset = new int[]{0, 0};
/* /*
* -z * -z
* | * |
@ -204,10 +260,10 @@ public class TerrainGrid extends TerrainQuad {
* z * z
*/ */
this.quadIndex = new Vector3f[]{ 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, -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, 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, 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, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)};
addControl(new UpdateControl()); 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 // 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 cam = 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));
gridOffset[1] = Math.round(camCell.z*(size/2)); gridOffset[1] = Math.round(camCell.z * (size / 2));
cellsLoaded=0; cellsLoaded = 0;
} }
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
@ -263,7 +319,7 @@ public class TerrainGrid extends TerrainQuad {
Vector3f shifted = tile.subtract(offsetHalf); Vector3f shifted = tile.subtract(offsetHalf);
return new Vector3f(FastMath.floor(shifted.x), 0, FastMath.floor(shifted.z)); return new Vector3f(FastMath.floor(shifted.x), 0, FastMath.floor(shifted.z));
} }
/** /**
* Centered at 0,0. * Centered at 0,0.
* Get the tile index location in integer form: * 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) { protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f cam) {
this.removeQuad(quadrant); this.removeQuad(quadrant);
q.setQuadrant((short) quadrant); q.setQuadrant((short) quadrant);
this.attachChild(q); this.attachChild(q);
@ -318,7 +374,7 @@ public class TerrainGrid extends TerrainQuad {
* @param camCell the cell the camera is in * @param camCell the cell the camera is in
*/ */
protected void updateChildrens(Vector3f camCell) { protected void updateChildrens(Vector3f camCell) {
int dx = 0; int dx = 0;
int dy = 0; int dy = 0;
if (currentCamCell != null) { if (currentCamCell != null) {
@ -394,10 +450,61 @@ public class TerrainGrid extends TerrainQuad {
} }
super.adjustHeight(xz, height); super.adjustHeight(xz, height);
} }
@Override @Override
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 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);
}
} }

@ -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);
}

@ -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);
}
}
Loading…
Cancel
Save