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
|
||||
*/
|
||||
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
|
||||
|
@ -691,19 +691,19 @@ public class TerrainPatch extends Geometry {
|
||||
|
||||
Vector3f n1 = Vector3f.ZERO;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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();
|
||||
@ -713,12 +713,25 @@ public class TerrainPatch extends Geometry {
|
||||
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();
|
||||
normal.set(firstPoint).subtractLocal(rootPoint)
|
||||
.crossLocal(secondPoint.subtract(rootPoint)).normalizeLocal();
|
||||
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.
|
||||
|
@ -959,12 +959,56 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
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) {
|
||||
// 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);
|
||||
float height = getHeight(x, z, xz);
|
||||
float height = getHeight(x, z);
|
||||
height *= getLocalScale().y;
|
||||
return height;
|
||||
}
|
||||
@ -974,7 +1018,7 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
* @param x 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;
|
||||
z-=0.5f;
|
||||
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) {
|
||||
List<Vector2f> coord = new ArrayList<Vector2f>();
|
||||
coord.add(xz);
|
||||
|
@ -32,12 +32,8 @@
|
||||
package jme3test.terrain;
|
||||
|
||||
import com.jme3.app.SimpleApplication;
|
||||
import com.jme3.bounding.BoundingBox;
|
||||
import com.jme3.collision.CollisionResult;
|
||||
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.input.KeyInput;
|
||||
import com.jme3.input.MouseInput;
|
||||
@ -52,9 +48,8 @@ import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.Ray;
|
||||
import com.jme3.math.Vector2f;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||
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.terrain.geomipmap.TerrainGrid;
|
||||
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.texture.Texture;
|
||||
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.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import jme3tools.converters.ImageToAwt;
|
||||
import org.novyon.noise.ShaderUtils;
|
||||
import org.novyon.noise.basis.FilteredBasis;
|
||||
@ -106,6 +93,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
private boolean lowerTerrain = false;
|
||||
|
||||
private Geometry marker;
|
||||
private Geometry markerNormal;
|
||||
|
||||
public static void main(String[] args) {
|
||||
TerrainTestModifyHeight app = new TerrainTestModifyHeight();
|
||||
@ -132,6 +120,10 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
float h = terrain.getHeight(new Vector2f(intersection.x, intersection.z));
|
||||
Vector3f tl = terrain.getWorldTranslation();
|
||||
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.setColor("Color", ColorRGBA.Green);
|
||||
|
||||
//createTerrain();
|
||||
createTerrainGrid();
|
||||
createTerrain();
|
||||
//createTerrainGrid();
|
||||
|
||||
DirectionalLight light = new DirectionalLight();
|
||||
light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());
|
||||
@ -422,6 +414,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
}
|
||||
|
||||
private void createMarker() {
|
||||
// collision marker
|
||||
Sphere sphere = new Sphere(8, 8, 0.5f);
|
||||
marker = new Geometry("Marker");
|
||||
marker.setMesh(sphere);
|
||||
@ -433,5 +426,12 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
marker.setMaterial(mat);
|
||||
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