added terrain.getNormal(x,z)
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8200 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
7036ce194a
commit
69fe43f079
@ -54,6 +54,15 @@ public interface Terrain {
|
|||||||
* @return the height at the given point
|
* @return the height at the given point
|
||||||
*/
|
*/
|
||||||
public float getHeight(Vector2f xz);
|
public float getHeight(Vector2f xz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the normal vector for the surface of the terrain at the specified
|
||||||
|
* X-Z coordinate. This normal vector can be a close approximation. It does not
|
||||||
|
* take into account any normal maps on the material.
|
||||||
|
* @param xz the X-Z world coordinate
|
||||||
|
* @return the normal vector at the given point
|
||||||
|
*/
|
||||||
|
public Vector3f getNormal(Vector2f xz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the heightmap height at the specified X-Z coordinate. This does not
|
* Get the heightmap height at the specified X-Z coordinate. This does not
|
||||||
|
@ -691,19 +691,19 @@ public class TerrainPatch extends Geometry {
|
|||||||
|
|
||||||
Vector3f n1 = Vector3f.ZERO;
|
Vector3f n1 = Vector3f.ZERO;
|
||||||
if (topPoint != null && leftPoint != null) {
|
if (topPoint != null && leftPoint != null) {
|
||||||
n1 = getNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale));
|
n1 = calculateNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale));
|
||||||
}
|
}
|
||||||
Vector3f n2 = Vector3f.ZERO;
|
Vector3f n2 = Vector3f.ZERO;
|
||||||
if (leftPoint != null && bottomPoint != null) {
|
if (leftPoint != null && bottomPoint != null) {
|
||||||
n2 = getNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale));
|
n2 = calculateNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale));
|
||||||
}
|
}
|
||||||
Vector3f n3 = Vector3f.ZERO;
|
Vector3f n3 = Vector3f.ZERO;
|
||||||
if (rightPoint != null && bottomPoint != null) {
|
if (rightPoint != null && bottomPoint != null) {
|
||||||
n3 = getNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale));
|
n3 = calculateNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale));
|
||||||
}
|
}
|
||||||
Vector3f n4 = Vector3f.ZERO;
|
Vector3f n4 = Vector3f.ZERO;
|
||||||
if (rightPoint != null && topPoint != null) {
|
if (rightPoint != null && topPoint != null) {
|
||||||
n4 = getNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale));
|
n4 = calculateNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f binormal = new Vector3f();
|
Vector3f binormal = new Vector3f();
|
||||||
@ -713,12 +713,25 @@ public class TerrainPatch extends Geometry {
|
|||||||
normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal());
|
normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3f getNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) {
|
private Vector3f calculateNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) {
|
||||||
Vector3f normal = new Vector3f();
|
Vector3f normal = new Vector3f();
|
||||||
normal.set(firstPoint).subtractLocal(rootPoint)
|
normal.set(firstPoint).subtractLocal(rootPoint)
|
||||||
.crossLocal(secondPoint.subtract(rootPoint)).normalizeLocal();
|
.crossLocal(secondPoint.subtract(rootPoint)).normalizeLocal();
|
||||||
return normal;
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Vector3f getMeshNormal(int x, int z) {
|
||||||
|
if (x >= size || z >= size)
|
||||||
|
return null; // out of range
|
||||||
|
|
||||||
|
int index = (z*size+x)*3;
|
||||||
|
FloatBuffer nb = (FloatBuffer)this.getMesh().getBuffer(Type.Normal).getData();
|
||||||
|
Vector3f normal = new Vector3f();
|
||||||
|
normal.x = nb.get(index);
|
||||||
|
normal.y = nb.get(index+1);
|
||||||
|
normal.z = nb.get(index+2);
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the mesh (sets it static) to improve performance.
|
* Locks the mesh (sets it static) to improve performance.
|
||||||
|
@ -959,12 +959,56 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
return Float.NaN;
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Vector3f getMeshNormal(int x, int z) {
|
||||||
|
int quad = findQuadrant(x, z);
|
||||||
|
int split = (size + 1) >> 1;
|
||||||
|
if (children != null) {
|
||||||
|
for (int i = children.size(); --i >= 0;) {
|
||||||
|
Spatial spat = children.get(i);
|
||||||
|
int col = x;
|
||||||
|
int row = z;
|
||||||
|
boolean match = false;
|
||||||
|
|
||||||
|
// get the childs quadrant
|
||||||
|
int childQuadrant = 0;
|
||||||
|
if (spat instanceof TerrainQuad) {
|
||||||
|
childQuadrant = ((TerrainQuad) spat).getQuadrant();
|
||||||
|
} else if (spat instanceof TerrainPatch) {
|
||||||
|
childQuadrant = ((TerrainPatch) spat).getQuadrant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childQuadrant == 1 && (quad & 1) != 0) {
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 2 && (quad & 2) != 0) {
|
||||||
|
row = z - split + 1;
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 3 && (quad & 4) != 0) {
|
||||||
|
col = x - split + 1;
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 4 && (quad & 8) != 0) {
|
||||||
|
col = x - split + 1;
|
||||||
|
row = z - split + 1;
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
if (spat instanceof TerrainQuad) {
|
||||||
|
return ((TerrainQuad) spat).getMeshNormal(col, row);
|
||||||
|
} else if (spat instanceof TerrainPatch) {
|
||||||
|
return ((TerrainPatch) spat).getMeshNormal(col, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public float getHeight(Vector2f xz) {
|
public float getHeight(Vector2f xz) {
|
||||||
// offset
|
// offset
|
||||||
float x = (float)(((xz.x - getLocalTranslation().x) / getLocalScale().x) + (float)totalSize / 2f);
|
float x = (float)(((xz.x - getLocalTranslation().x) / getLocalScale().x) + (float)totalSize / 2f);
|
||||||
float z = (float)(((xz.y - getLocalTranslation().z) / getLocalScale().z) + (float)totalSize / 2f);
|
float z = (float)(((xz.y - getLocalTranslation().z) / getLocalScale().z) + (float)totalSize / 2f);
|
||||||
float height = getHeight(x, z, xz);
|
float height = getHeight(x, z);
|
||||||
height *= getLocalScale().y;
|
height *= getLocalScale().y;
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
@ -974,7 +1018,7 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
* @param x coordinate translated into actual (positive) terrain grid coordinates
|
* @param x coordinate translated into actual (positive) terrain grid coordinates
|
||||||
* @param y coordinate translated into actual (positive) terrain grid coordinates
|
* @param y coordinate translated into actual (positive) terrain grid coordinates
|
||||||
*/
|
*/
|
||||||
protected float getHeight(float x, float z, Vector2f xz) {
|
protected float getHeight(float x, float z) {
|
||||||
x-=0.5f;
|
x-=0.5f;
|
||||||
z-=0.5f;
|
z-=0.5f;
|
||||||
float col = FastMath.floor(x);
|
float col = FastMath.floor(x);
|
||||||
@ -1000,6 +1044,38 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3f getNormal(Vector2f xz) {
|
||||||
|
// offset
|
||||||
|
float x = (float)(((xz.x - getLocalTranslation().x) / getLocalScale().x) + (float)totalSize / 2f);
|
||||||
|
float z = (float)(((xz.y - getLocalTranslation().z) / getLocalScale().z) + (float)totalSize / 2f);
|
||||||
|
Vector3f normal = getNormal(x, z, xz);
|
||||||
|
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Vector3f getNormal(float x, float z, Vector2f xz) {
|
||||||
|
x-=0.5f;
|
||||||
|
z-=0.5f;
|
||||||
|
float col = FastMath.floor(x);
|
||||||
|
float row = FastMath.floor(z);
|
||||||
|
boolean onX = false;
|
||||||
|
if(1 - (x - col)-(z - row) < 0) // what triangle to interpolate on
|
||||||
|
onX = true;
|
||||||
|
// v1--v2 ^
|
||||||
|
// | / | |
|
||||||
|
// | / | |
|
||||||
|
// v3--v4 | Z
|
||||||
|
// |
|
||||||
|
// <-------Y
|
||||||
|
// X
|
||||||
|
Vector3f n1 = getMeshNormal((int) FastMath.ceil(x), (int) FastMath.ceil(z));
|
||||||
|
Vector3f n2 = getMeshNormal((int) FastMath.floor(x), (int) FastMath.ceil(z));
|
||||||
|
Vector3f n3 = getMeshNormal((int) FastMath.ceil(x), (int) FastMath.floor(z));
|
||||||
|
Vector3f n4 = getMeshNormal((int) FastMath.floor(x), (int) FastMath.floor(z));
|
||||||
|
|
||||||
|
return n1.add(n2).add(n3).add(n4).normalize();
|
||||||
|
}
|
||||||
|
|
||||||
public void setHeight(Vector2f xz, float height) {
|
public void setHeight(Vector2f xz, float height) {
|
||||||
List<Vector2f> coord = new ArrayList<Vector2f>();
|
List<Vector2f> coord = new ArrayList<Vector2f>();
|
||||||
coord.add(xz);
|
coord.add(xz);
|
||||||
|
@ -32,12 +32,8 @@
|
|||||||
package jme3test.terrain;
|
package jme3test.terrain;
|
||||||
|
|
||||||
import com.jme3.app.SimpleApplication;
|
import com.jme3.app.SimpleApplication;
|
||||||
import com.jme3.bounding.BoundingBox;
|
|
||||||
import com.jme3.collision.CollisionResult;
|
import com.jme3.collision.CollisionResult;
|
||||||
import com.jme3.collision.CollisionResults;
|
import com.jme3.collision.CollisionResults;
|
||||||
import com.jme3.export.Savable;
|
|
||||||
import com.jme3.export.binary.BinaryExporter;
|
|
||||||
import com.jme3.export.binary.BinaryImporter;
|
|
||||||
import com.jme3.font.BitmapText;
|
import com.jme3.font.BitmapText;
|
||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
@ -52,9 +48,8 @@ import com.jme3.math.ColorRGBA;
|
|||||||
import com.jme3.math.Ray;
|
import com.jme3.math.Ray;
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.debug.Arrow;
|
||||||
import com.jme3.scene.shape.Sphere;
|
import com.jme3.scene.shape.Sphere;
|
||||||
import com.jme3.terrain.geomipmap.TerrainGrid;
|
import com.jme3.terrain.geomipmap.TerrainGrid;
|
||||||
import com.jme3.terrain.geomipmap.TerrainLodControl;
|
import com.jme3.terrain.geomipmap.TerrainLodControl;
|
||||||
@ -64,16 +59,8 @@ import com.jme3.terrain.heightmap.FractalHeightMapGrid;
|
|||||||
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
|
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
|
||||||
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.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import jme3tools.converters.ImageToAwt;
|
import jme3tools.converters.ImageToAwt;
|
||||||
import org.novyon.noise.ShaderUtils;
|
import org.novyon.noise.ShaderUtils;
|
||||||
import org.novyon.noise.basis.FilteredBasis;
|
import org.novyon.noise.basis.FilteredBasis;
|
||||||
@ -106,6 +93,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
|||||||
private boolean lowerTerrain = false;
|
private boolean lowerTerrain = false;
|
||||||
|
|
||||||
private Geometry marker;
|
private Geometry marker;
|
||||||
|
private Geometry markerNormal;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TerrainTestModifyHeight app = new TerrainTestModifyHeight();
|
TerrainTestModifyHeight app = new TerrainTestModifyHeight();
|
||||||
@ -132,6 +120,10 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
|||||||
float h = terrain.getHeight(new Vector2f(intersection.x, intersection.z));
|
float h = terrain.getHeight(new Vector2f(intersection.x, intersection.z));
|
||||||
Vector3f tl = terrain.getWorldTranslation();
|
Vector3f tl = terrain.getWorldTranslation();
|
||||||
marker.setLocalTranslation(tl.add(new Vector3f(intersection.x, h, intersection.z)) );
|
marker.setLocalTranslation(tl.add(new Vector3f(intersection.x, h, intersection.z)) );
|
||||||
|
markerNormal.setLocalTranslation(tl.add(new Vector3f(intersection.x, h, intersection.z)) );
|
||||||
|
|
||||||
|
Vector3f normal = terrain.getNormal(new Vector2f(intersection.x, intersection.z));
|
||||||
|
((Arrow)markerNormal.getMesh()).setArrowExtent(normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +140,8 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
|||||||
matWire.getAdditionalRenderState().setWireframe(true);
|
matWire.getAdditionalRenderState().setWireframe(true);
|
||||||
matWire.setColor("Color", ColorRGBA.Green);
|
matWire.setColor("Color", ColorRGBA.Green);
|
||||||
|
|
||||||
//createTerrain();
|
createTerrain();
|
||||||
createTerrainGrid();
|
//createTerrainGrid();
|
||||||
|
|
||||||
DirectionalLight light = new DirectionalLight();
|
DirectionalLight light = new DirectionalLight();
|
||||||
light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());
|
light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());
|
||||||
@ -422,6 +414,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createMarker() {
|
private void createMarker() {
|
||||||
|
// collision marker
|
||||||
Sphere sphere = new Sphere(8, 8, 0.5f);
|
Sphere sphere = new Sphere(8, 8, 0.5f);
|
||||||
marker = new Geometry("Marker");
|
marker = new Geometry("Marker");
|
||||||
marker.setMesh(sphere);
|
marker.setMesh(sphere);
|
||||||
@ -433,5 +426,12 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
|||||||
marker.setMaterial(mat);
|
marker.setMaterial(mat);
|
||||||
rootNode.attachChild(marker);
|
rootNode.attachChild(marker);
|
||||||
|
|
||||||
|
|
||||||
|
// surface normal marker
|
||||||
|
Arrow arrow = new Arrow(new Vector3f(0,1,0));
|
||||||
|
markerNormal = new Geometry("MarkerNormal");
|
||||||
|
markerNormal.setMesh(arrow);
|
||||||
|
markerNormal.setMaterial(mat);
|
||||||
|
rootNode.attachChild(markerNormal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user