changed normal and tangent generation for terrain to handle scale, removing artifacts

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8070 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
bre..ns 14 years ago
parent 1dbd617d2d
commit fa46b16e87
  1. 106
      engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java
  2. 93
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java
  3. 19
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java

@ -45,6 +45,7 @@ import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import com.jme3.scene.Mesh.Mode; import com.jme3.scene.Mesh.Mode;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.TangentBinormalGenerator; import com.jme3.util.TangentBinormalGenerator;
@ -78,16 +79,19 @@ public class LODGeomap extends GeoMap {
public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) { public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) {
FloatBuffer pb = writeVertexArray(null, scale, center); FloatBuffer pb = writeVertexArray(null, scale, center);
FloatBuffer tb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize); FloatBuffer texb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize);
FloatBuffer nb = writeNormalArray(null, scale); FloatBuffer nb = writeNormalArray(null, scale);
IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod); IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod);
FloatBuffer tanb = writeTangentArray(null, scale); FloatBuffer bb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
FloatBuffer tanb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
writeTangentArray(tanb, bb, texb, scale);
Mesh m = new Mesh(); Mesh m = new Mesh();
m.setMode(Mode.TriangleStrip); m.setMode(Mode.TriangleStrip);
m.setBuffer(Type.Position, 3, pb); m.setBuffer(Type.Position, 3, pb);
m.setBuffer(Type.Normal, 3, nb); m.setBuffer(Type.Normal, 3, nb);
m.setBuffer(Type.Tangent, 3, tanb); m.setBuffer(Type.Tangent, 3, tanb);
m.setBuffer(Type.TexCoord, 2, tb); m.setBuffer(Type.Binormal, 3, bb);
m.setBuffer(Type.TexCoord, 2, texb);
m.setBuffer(Type.Index, 3, ib); m.setBuffer(Type.Index, 3, ib);
m.setStatic(); m.setStatic();
m.updateBound(); m.updateBound();
@ -624,42 +628,120 @@ public class LODGeomap extends GeoMap {
return num; return num;
} }
public FloatBuffer writeTangentArray(FloatBuffer store, Vector3f scale) { public FloatBuffer[] writeTangentArray(FloatBuffer tangentStore, FloatBuffer binormalStore, FloatBuffer textureBuffer, Vector3f scale) {
if (!isLoaded()) { if (!isLoaded()) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (store != null) { if (tangentStore != null) {
if (store.remaining() < getWidth() * getHeight() * 3) { if (tangentStore.remaining() < getWidth() * getHeight() * 3) {
throw new BufferUnderflowException(); throw new BufferUnderflowException();
} }
} else { } else {
store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); tangentStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
} }
store.rewind(); tangentStore.rewind();
if (binormalStore != null) {
if (binormalStore.remaining() < getWidth() * getHeight() * 3) {
throw new BufferUnderflowException();
}
} else {
binormalStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
}
binormalStore.rewind();
Vector3f tangent = new Vector3f(); Vector3f tangent = new Vector3f();
Vector3f binormal = new Vector3f();
Vector3f v1 = new Vector3f(); Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f(); Vector3f v2 = new Vector3f();
Vector3f v3 = new Vector3f();
Vector2f t1 = new Vector2f();
Vector2f t2 = new Vector2f();
Vector2f t3 = new Vector2f();
scale = Vector3f.UNIT_XYZ;
for (int r = 0; r < getHeight(); r++) { for (int r = 0; r < getHeight(); r++) {
for (int c = 0; c < getWidth(); c++) { for (int c = 0; c < getWidth(); c++) {
int texIdx = ((getHeight()-1-r)*getWidth()+c)*2; // pull from the end
int texIdxPrev = ((getHeight()-1-(r-1))*getWidth()+c)*2; // pull from the end
int texIdxNext = ((getHeight()-1-(r+1))*getWidth()+c)*2; // pull from the end
v1.set(c, getValue(c, r), r); v1.set(c, getValue(c, r), r);
t1.set(textureBuffer.get(texIdx), textureBuffer.get(texIdx+1));
if (r == 0) { // first row
v3.set(c, getValue(c, r), r); // ???
t3.set(textureBuffer.get(texIdxNext), textureBuffer.get(texIdxNext+1)); // ???
} else {
v3.set(c, getValue(c, r-1 ), r-1);
t3.set(textureBuffer.get(texIdxPrev), textureBuffer.get(texIdxPrev+1));
}
if (c == getWidth()-1) { // last column if (c == getWidth()-1) { // last column
v2.set(c+1, getValue(c, r ), r); // use same height v2.set(c+1, getValue(c, r ), r); // use same height
t2.set(textureBuffer.get(texIdx), textureBuffer.get(texIdx+1));
} else { } else {
v2.set(c+1, getValue(c+1, r), r); v2.set(c+1, getValue(c+1, r), r); // one to the right
t2.set(textureBuffer.get(texIdx+2), textureBuffer.get(texIdx+3));
} }
tangent.set(v2.mult(scale).subtract(v1.mult(scale)));
BufferUtils.setInBuffer(tangent, store, (r * getWidth() + c)); // save the tangent calculateTangent(new Vector3f[]{v1.mult(scale),v2.mult(scale),v3.mult(scale)}, new Vector2f[]{t1,t2,t3}, tangent, binormal);
BufferUtils.setInBuffer(tangent, tangentStore, (r * getWidth() + c)); // save the tangent
BufferUtils.setInBuffer(binormal, binormalStore, (r * getWidth() + c)); // save the binormal
} }
} }
return store; return new FloatBuffer[]{tangentStore,binormalStore};
} }
/**
*
* @param v Takes 3 vertexes: root, right, top
* @param t Takes 3 tex coords: root, right, top
* @param tangent that will store the result
* @return the tangent store
*/
public static Vector3f calculateTangent(Vector3f[] v, Vector2f[] t, Vector3f tangent, Vector3f binormal) {
Vector3f edge1 = new Vector3f(); // y=0
Vector3f edge2 = new Vector3f(); // x=0
Vector2f edge1uv = new Vector2f(); // y=0
Vector2f edge2uv = new Vector2f(); // x=0
t[2].subtract(t[0], edge2uv);
t[1].subtract(t[0], edge1uv);
float det = edge1uv.x*edge2uv.y;// - edge1uv.y*edge2uv.x; = 0
boolean normalize = true;
if (Math.abs(det) < 0.0000001f) {
det = 1;
normalize = true;
}
v[1].subtract(v[0], edge1);
v[2].subtract(v[0], edge2);
tangent.set(edge1);
tangent.normalizeLocal();
binormal.set(edge2);
binormal.normalizeLocal();
float factor = 1/det;
tangent.x = (edge2uv.y*edge1.x)*factor;
tangent.y = 0;
tangent.z = (edge2uv.y*edge1.z)*factor;
if (normalize) tangent.normalizeLocal();
binormal.x = 0;
binormal.y = (edge1uv.x*edge2.y)*factor;
binormal.z = (edge1uv.x*edge2.z)*factor;
if (normalize) binormal.normalizeLocal();
return tangent;
}
@Override @Override
public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) { public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) {

@ -62,7 +62,6 @@ import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
import com.jme3.terrain.geomipmap.lodcalc.util.EntropyComputeUtil; import com.jme3.terrain.geomipmap.lodcalc.util.EntropyComputeUtil;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.TangentBinormalGenerator; import com.jme3.util.TangentBinormalGenerator;
import com.jme3.util.TangentBinormalGenerator.TriangleData;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -333,8 +332,13 @@ public class TerrainPatch extends Geometry {
protected void updateNormals() { protected void updateNormals() {
FloatBuffer newNormalBuffer = geomap.writeNormalArray(null, getWorldScale()); FloatBuffer newNormalBuffer = geomap.writeNormalArray(null, getWorldScale());
getMesh().getBuffer(Type.Normal).updateData(newNormalBuffer); getMesh().getBuffer(Type.Normal).updateData(newNormalBuffer);
//FloatBuffer newTangentBuffer = geomap.writeTangentArray(null, getWorldScale()); FloatBuffer newTangentBuffer = null;
//getMesh().getBuffer(Type.Tangent).updateData(newTangentBuffer); FloatBuffer newBinormalBuffer = null;
FloatBuffer[] tb = geomap.writeTangentArray(newTangentBuffer, newBinormalBuffer, (FloatBuffer)getMesh().getBuffer(Type.TexCoord).getData(), getWorldScale());
newTangentBuffer = tb[0];
newBinormalBuffer = tb[1];
getMesh().getBuffer(Type.Tangent).updateData(newTangentBuffer);
getMesh().getBuffer(Type.Binormal).updateData(newBinormalBuffer);
} }
/** /**
@ -359,7 +363,6 @@ public class TerrainPatch extends Geometry {
TerrainPatch topRight, TerrainPatch topRight,
TerrainPatch topLeft) TerrainPatch topLeft)
{ {
Vector3f rootPoint = new Vector3f(); Vector3f rootPoint = new Vector3f();
Vector3f rightPoint = new Vector3f(); Vector3f rightPoint = new Vector3f();
Vector3f leftPoint = new Vector3f(); Vector3f leftPoint = new Vector3f();
@ -372,9 +375,6 @@ public class TerrainPatch extends Geometry {
Vector2f bottomTex = new Vector2f(); Vector2f bottomTex = new Vector2f();
Vector3f normal = new Vector3f(); Vector3f normal = new Vector3f();
Vector3f tangent = new Vector3f(); Vector3f tangent = new Vector3f();
int[] indexes = new int[]{0,1,2};
Vector3f[] v = new Vector3f[3];
Vector2f[] t = new Vector2f[3];
int s = this.getSize()-1; int s = this.getSize()-1;
@ -390,7 +390,7 @@ public class TerrainPatch extends Geometry {
if (top == null) { if (top == null) {
bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1); bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
this.getTex(s,i+1, bottomTex); this.getTex(s,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, null, rootPoint, leftPoint, bottomPoint, rightPoint, null, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal); VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
@ -404,7 +404,7 @@ public class TerrainPatch extends Geometry {
bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1); bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
top.getTex(s,s-1, topTex); top.getTex(s,s-1, topTex);
this.getTex(s,i+1, bottomTex); this.getTex(s,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal); VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
@ -431,7 +431,7 @@ public class TerrainPatch extends Geometry {
if (bottom == null) { if (bottom == null) {
topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1); topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
this.getTex(s,i-1, topTex); this.getTex(s,i-1, topTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, null, rightPoint, topTex, rootTex, leftTex, null, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, null, rightPoint, topTex, rootTex, leftTex, null, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal); VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
@ -445,7 +445,7 @@ public class TerrainPatch extends Geometry {
bottomPoint.set(s, bottom.getHeightmapHeight(s,1), i+1); bottomPoint.set(s, bottom.getHeightmapHeight(s,1), i+1);
this.getTex(s,i-1, topTex); this.getTex(s,i-1, topTex);
bottom.getTex(s,1, bottomTex); bottom.getTex(s,1, bottomTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal); VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
@ -474,7 +474,7 @@ public class TerrainPatch extends Geometry {
bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1); bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
this.getTex(s,i-1, topTex); this.getTex(s,i-1, topTex);
this.getTex(s,i+1, bottomTex); this.getTex(s,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal); VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
@ -537,7 +537,7 @@ public class TerrainPatch extends Geometry {
rightPoint.set(i+1, this.getHeightmapHeight(i+1,s), s); rightPoint.set(i+1, this.getHeightmapHeight(i+1,s), s);
this.getTex(i-1,s, leftTex); this.getTex(i-1,s, leftTex);
this.getTex(i+1,s, rightTex); this.getTex(i+1,s, rightTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal); VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
@ -564,7 +564,7 @@ public class TerrainPatch extends Geometry {
if (top == null) { if (top == null) {
bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1); bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
this.getTex(0,i+1, bottomTex); this.getTex(0,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, null, rootPoint, leftPoint, bottomPoint, rightPoint, null, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal); VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
@ -578,7 +578,7 @@ public class TerrainPatch extends Geometry {
bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1); bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
top.getTex(0,i-1, topTex); top.getTex(0,i-1, topTex);
this.getTex(0,i+1, bottomTex); this.getTex(0,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal); VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
@ -619,7 +619,7 @@ public class TerrainPatch extends Geometry {
bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1); bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
this.getTex(0,i-1, topTex); this.getTex(0,i-1, topTex);
this.getTex(0,i+1, bottomTex); this.getTex(0,i+1, bottomTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal); VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
@ -655,7 +655,7 @@ public class TerrainPatch extends Geometry {
rightPoint.set(i+1, this.getHeightmapHeight(i+1,0), 0); rightPoint.set(i+1, this.getHeightmapHeight(i+1,0), 0);
this.getTex(i-1,0, leftTex); this.getTex(i-1,0, leftTex);
this.getTex(i+1,0, rightTex); this.getTex(i+1,0, rightTex);
averageNormalsTangents(v, t, indexes, topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent); averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, topTex, rootTex, leftTex, bottomTex, rightTex, normal, tangent);
VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal); VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent); VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
VertexBuffer topNB = top.getMesh().getBuffer(Type.Normal); VertexBuffer topNB = top.getMesh().getBuffer(Type.Normal);
@ -673,10 +673,12 @@ public class TerrainPatch extends Geometry {
this.getMesh().getBuffer(Type.Tangent).setUpdateNeeded(); this.getMesh().getBuffer(Type.Tangent).setUpdateNeeded();
} }
protected void averageNormalsTangents(Vector3f[] v, Vector2f[] t, int[] indexes, protected void averageNormalsTangents(
Vector3f topPoint, Vector3f topPoint,
Vector3f rootPoint, Vector3f rootPoint,
Vector3f leftPoint, Vector3f bottomPoint, Vector3f rightPoint, Vector3f leftPoint,
Vector3f bottomPoint,
Vector3f rightPoint,
Vector2f topTex, Vector2f topTex,
Vector2f rootTex, Vector2f rootTex,
Vector2f leftTex, Vector2f leftTex,
@ -685,65 +687,30 @@ public class TerrainPatch extends Geometry {
Vector3f normal, Vector3f normal,
Vector3f tangent) Vector3f tangent)
{ {
Vector3f scale = Vector3f.UNIT_XYZ;//getWorldScale(); Vector3f scale = getWorldScale();
v[0] = topPoint;
v[1] = rootPoint;
v[2] = leftPoint;
t[0] = topTex;
t[1] = rootTex;
t[2] = leftTex;
Vector3f n1 = Vector3f.ZERO; Vector3f n1 = Vector3f.ZERO;
Vector3f t1 = Vector3f.ZERO;
if (topPoint != null && leftPoint != null) { if (topPoint != null && leftPoint != null) {
TriangleData td1 = TangentBinormalGenerator.processTriangle(indexes, v, t);
n1 = getNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale)); n1 = getNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale));
t1 = td1.tangent; }
}
v[0] = leftPoint;
v[1] = rootPoint;
v[2] = bottomPoint;
t[0] = leftTex;
t[1] = rootTex;
t[2] = bottomTex;
Vector3f n2 = Vector3f.ZERO; Vector3f n2 = Vector3f.ZERO;
Vector3f t2 = Vector3f.ZERO;
if (leftPoint != null && bottomPoint != null) { if (leftPoint != null && bottomPoint != null) {
TriangleData td2 = TangentBinormalGenerator.processTriangle(indexes, v, t);
n2 = getNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale)); n2 = getNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale));
t2 = td2.tangent; }
}
v[0] = bottomPoint;
v[1] = rootPoint;
v[2] = rightPoint;
t[0] = bottomTex;
t[1] = rootTex;
t[2] = rightTex;
Vector3f n3 = Vector3f.ZERO; Vector3f n3 = Vector3f.ZERO;
Vector3f t3 = Vector3f.ZERO;
if (rightPoint != null && bottomPoint != null) { if (rightPoint != null && bottomPoint != null) {
TriangleData td3 = TangentBinormalGenerator.processTriangle(indexes, v, t);
n3 = getNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale)); n3 = getNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale));
t3 = td3.tangent; }
}
v[0] = rightPoint;
v[1] = rootPoint;
v[2] = topPoint;
t[0] = rightTex;
t[1] = rootTex;
t[2] = topTex;
Vector3f n4 = Vector3f.ZERO; Vector3f n4 = Vector3f.ZERO;
Vector3f t4 = Vector3f.ZERO;
if (rightPoint != null && topPoint != null) { if (rightPoint != null && topPoint != null) {
TriangleData td4 = TangentBinormalGenerator.processTriangle(indexes, v, t);
n4 = getNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale)); n4 = getNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale));
t4 = td4.tangent;
} }
Vector3f binormal = new Vector3f();
if (topPoint != null && rightPoint != null)
LODGeomap.calculateTangent(new Vector3f[]{rootPoint.mult(scale),rightPoint.mult(scale),topPoint.mult(scale)}, new Vector2f[]{rootTex,rightTex,topTex}, tangent, binormal);
normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal()); normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal());
tangent.set(t1.add(t2).add(t3).add(t4)).normalizeLocal();
/*if (rightPoint != null) {
tangent.set(rootPoint.mult(scale).subtract(rightPoint.mult(scale)));
}*/
} }
private Vector3f getNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) { private Vector3f getNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) {

@ -134,14 +134,14 @@ public class TerrainQuad extends Node implements Terrain {
public TerrainQuad(String name, int patchSize, int size, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) { public TerrainQuad(String name, int patchSize, int size, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {
this(name, patchSize, size, Vector3f.UNIT_XYZ, heightMap, totalSize, new Vector2f(), 0, lodCalculatorFactory); this(name, patchSize, size, Vector3f.UNIT_XYZ, heightMap, totalSize, new Vector2f(), 0, lodCalculatorFactory);
affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size); affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);
fixNormalEdges(affectedAreaBBox); fixNormalEdges(affectedAreaBBox);
addControl(new NormalRecalcControl(this)); addControl(new NormalRecalcControl(this));
} }
public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) { public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {
this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory); this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory);
affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size); affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);
fixNormalEdges(affectedAreaBBox); fixNormalEdges(affectedAreaBBox);
addControl(new NormalRecalcControl(this)); addControl(new NormalRecalcControl(this));
} }
@ -691,7 +691,7 @@ public class TerrainQuad extends Node implements Terrain {
((TerrainQuad)child).generateDebugTangents(mat); ((TerrainQuad)child).generateDebugTangents(mat);
} else if (child instanceof TerrainPatch) { } else if (child instanceof TerrainPatch) {
Geometry debug = new Geometry( "Debug " + name, Geometry debug = new Geometry( "Debug " + name,
TangentBinormalGenerator.genTbnLines( ((TerrainPatch)child).getMesh(), 0.1f)); TangentBinormalGenerator.genTbnLines( ((TerrainPatch)child).getMesh(), 0.8f));
attachChild(debug); attachChild(debug);
debug.setLocalTranslation(child.getLocalTranslation()); debug.setLocalTranslation(child.getLocalTranslation());
debug.setCullHint(CullHint.Never); debug.setCullHint(CullHint.Never);
@ -734,7 +734,7 @@ public class TerrainQuad extends Node implements Terrain {
patch1.setModelBound(new BoundingBox()); patch1.setModelBound(new BoundingBox());
patch1.updateModelBound(); patch1.updateModelBound();
patch1.setLodCalculator(lodCalculatorFactory); patch1.setLodCalculator(lodCalculatorFactory);
TangentBinormalGenerator.generate(patch1); //TangentBinormalGenerator.generate(patch1);
// 2 lower left // 2 lower left
float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1, float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,
@ -756,7 +756,7 @@ public class TerrainQuad extends Node implements Terrain {
patch2.setModelBound(new BoundingBox()); patch2.setModelBound(new BoundingBox());
patch2.updateModelBound(); patch2.updateModelBound();
patch2.setLodCalculator(lodCalculatorFactory); patch2.setLodCalculator(lodCalculatorFactory);
TangentBinormalGenerator.generate(patch2); //TangentBinormalGenerator.generate(patch2);
// 3 upper right // 3 upper right
float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0, float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,
@ -778,7 +778,7 @@ public class TerrainQuad extends Node implements Terrain {
patch3.setModelBound(new BoundingBox()); patch3.setModelBound(new BoundingBox());
patch3.updateModelBound(); patch3.updateModelBound();
patch3.setLodCalculator(lodCalculatorFactory); patch3.setLodCalculator(lodCalculatorFactory);
TangentBinormalGenerator.generate(patch3); //TangentBinormalGenerator.generate(patch3);
// 4 lower right // 4 lower right
float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1, float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,
@ -800,7 +800,7 @@ public class TerrainQuad extends Node implements Terrain {
patch4.setModelBound(new BoundingBox()); patch4.setModelBound(new BoundingBox());
patch4.updateModelBound(); patch4.updateModelBound();
patch4.setLodCalculator(lodCalculatorFactory); patch4.setLodCalculator(lodCalculatorFactory);
TangentBinormalGenerator.generate(patch4); //TangentBinormalGenerator.generate(patch4);
} }
public float[] createHeightSubBlock(float[] heightMap, int x, public float[] createHeightSubBlock(float[] heightMap, int x,
@ -878,10 +878,11 @@ public class TerrainQuad extends Node implements Terrain {
protected boolean needToRecalculateNormals() { protected boolean needToRecalculateNormals() {
if (affectedAreaBBox != null) if (affectedAreaBBox != null)
return true; return true;
/*if (!lastScale.equals(getWorldScale())) { if (!lastScale.equals(getWorldScale())) {
affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size);
lastScale = getWorldScale(); lastScale = getWorldScale();
return true; return true;
}*/ }
return false; return false;
} }

Loading…
Cancel
Save