/** * Called internally by com.jme3.util.clone.Cloner. Do not call directly. */ @Override public void cloneFields( Cloner cloner, Object original ) { super.cloneFields(cloner, original); this.stepScale = cloner.clone(stepScale); this.offset = cloner.clone(offset); this.leftNeighbour = null; this.topNeighbour = null; this.rightNeighbour = null; this.bottomNeighbour = null; // Don't feel like making geomap cloneable tonight // so I'll copy the old logic. this.geomap = new LODGeomap(size, geomap.getHeightArray()); Mesh m = geomap.createMesh(stepScale, Vector2f.UNIT_XY, offset, offsetAmount, totalSize, false); this.setMesh(m); // In this case, we always clone material even if the cloner is setup // not to clone it. Terrain uses mutable textures and stuff so it's important // to clone it. (At least that's my understanding and is evidenced by the old // clone code specifically cloning material.) -pspeed this.material = material.clone(); }
int numIndexes = calculateNumIndexesLodDiff(lod); for (int r = lod; r < getWidth() - (2 * lod); r += lod) { // row int rowIdx = r * getWidth(); int nextRowIdx = (r + 1 * lod) * getWidth(); for (int c = lod; c < getWidth() - (1 * lod); c += lod) { // column int idx = rowIdx + c; buffer.put(idx); if (r < getWidth() - (3 * lod)) { int idx = nextRowIdx + getWidth() - (1 * lod) - 1; buffer.put(idx); idx = nextRowIdx + (1 * lod); // inset by 1 int br = getWidth() * (getWidth() - lod) - 1 - lod; int corner = getWidth() * getWidth() - 1; for (int row = getWidth() - lod; row >= 1 + lod; row -= 2 * lod) { int idx = (row) * getWidth() - 1 - lod; buffer.put(idx); idx = (row - lod) * getWidth() - 1; buffer.put(idx); if (row > lod + 1) { //if not the last one idx = (row - lod) * getWidth() - 1 - lod; buffer.put(idx); idx = (row - lod) * getWidth() - 1; buffer.put(idx); } else {
int index = findClosestHeightIndex(x, z); if (index < 0) { return Float.NaN;
public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize) { if (store != null) { if (store.remaining() < getWidth() * getHeight() * 2) { throw new BufferUnderflowException(); } } else { store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 2); } if (offset == null) { offset = new Vector2f(); } Vector2f tcStore = new Vector2f(); // work from bottom of heightmap up, so we don't flip the coords for (int y = getHeight() - 1; y >= 0; y--) { for (int x = 0; x < getWidth(); x++) { getUV(x, y, tcStore, offset, offsetAmount, totalSize); float tx = tcStore.x * scale.x; float ty = tcStore.y * scale.y; store.put(tx); store.put(ty); } } return store; }
protected void setHeight(List<LocationHeight> locationHeights, boolean overrideHeight) { final float[] heightArray = geomap.getHeightArray(); final VertexBuffer vertexBuffer = mesh.getBuffer(Type.Position); final FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position); for (LocationHeight lh : locationHeights) { if (lh.x < 0 || lh.z < 0 || lh.x >= size || lh.z >= size) { continue; } int idx = lh.z * size + lh.x; if (overrideHeight) { heightArray[idx] = lh.h; } else { float currentHeight = floatBuffer.get(idx * 3 + 1); heightArray[idx] = currentHeight + lh.h; } } floatBuffer.clear(); geomap.writeVertexArray(floatBuffer, stepScale, false); vertexBuffer.setUpdateNeeded(); }
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 texb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize); FloatBuffer nb = writeNormalArray(null, scale); Buffer ib; IndexBuffer idxB = writeIndexArrayLodDiff(lod, rightLod, topLod, leftLod, bottomLod, totalSize); if (idxB.getBuffer() instanceof IntBuffer) ib = (IntBuffer)idxB.getBuffer(); else ib = (ShortBuffer)idxB.getBuffer(); FloatBuffer bb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); FloatBuffer tanb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); writeTangentArray(nb, tanb, bb, texb, scale); Mesh m = new Mesh(); m.setMode(Mode.TriangleStrip); m.setBuffer(Type.Position, 3, pb); m.setBuffer(Type.Normal, 3, nb); m.setBuffer(Type.Tangent, 3, tanb); m.setBuffer(Type.Binormal, 3, bb); m.setBuffer(Type.TexCoord, 2, texb); if (ib instanceof IntBuffer) m.setBuffer(Type.Index, 3, (IntBuffer)ib); else if (ib instanceof ShortBuffer) m.setBuffer(Type.Index, 3, (ShortBuffer)ib); m.setStatic(); m.updateBound(); return m; }
@Override public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) { if (!isLoaded()) { throw new NullPointerException(); if (store.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); for (int r = 0; r < getHeight(); r++) { for (int c = 0; c < getWidth(); c++) { rootPoint.set(0, getValue(c, r), 0); Vector3f normal = vars.vect8; rightPoint.set(1, getValue(c + 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); getNormal(bottomPoint, rootPoint, rightPoint, scale, normal); } else if (c == getWidth() - 1) { // last column leftPoint.set(-1, getValue(c - 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); getNormal(leftPoint, rootPoint, bottomPoint, scale, normal); } else { // all middle columns leftPoint.set(-1, getValue(c - 1, r), 0); rightPoint.set(1, getValue(c + 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); normal.set( getNormal(leftPoint, rootPoint, bottomPoint, scale, tmp1) ); normal.addLocal( getNormal(bottomPoint, rootPoint, rightPoint, scale, tmp1) );
public FloatBuffer[] writeTangentArray(FloatBuffer normalBuffer, FloatBuffer tangentStore, FloatBuffer binormalStore, FloatBuffer textureBuffer, Vector3f scale) { if (!isLoaded()) { throw new NullPointerException(); if (tangentStore.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); tangentStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); if (binormalStore.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); binormalStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); for (int r = 0; r < getHeight(); r++) { for (int c = 0; c < getWidth(); c++) { int idx = (r * getWidth() + c) * 3; normal.set(normalBuffer.get(idx), normalBuffer.get(idx+1), normalBuffer.get(idx+2)); tangent.set(normal.cross(new Vector3f(0,0,1))); binormal.set(new Vector3f(1,0,0).cross(normal)); BufferUtils.setInBuffer(tangent.normalizeLocal(), tangentStore, (r * getWidth() + c)); // save the tangent BufferUtils.setInBuffer(binormal.normalizeLocal(), binormalStore, (r * getWidth() + c)); // save the binormal
geomap = new LODGeomap(size, heightMap); Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false); setMesh(m);
/** * Get the triangles at the specified grid point. Probably only 2 triangles * @param x local to the terrain patch * @param z local to the terrain patch * @return the triangles in world coordinates, or null if the point does intersect this patch on the XZ axis */ public Triangle[] getGridTriangles(float x, float z) { return geomap.getGridTrianglesAtPoint(x, z, getWorldScale() , getWorldTranslation()); }
/** * Get the triangle of this geometry at the specified local coordinate. * @param x local to the terrain patch * @param z local to the terrain patch * @return the triangle in world coordinates, or null if the point does intersect this patch on the XZ axis */ public Triangle getTriangle(float x, float z) { return geomap.getTriangleAtPoint(x, z, getWorldScale() , getWorldTranslation()); }
public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center) { return this.createMesh(scale, tcScale, tcOffset, offsetAmount, totalSize, center, 1, false, false, false, false); }
public float[] getHeightMap() { return geomap.getHeightArray(); }
protected float getHeight(int x, int z, float xm, float zm) { return geomap.getHeight(x,z,xm,zm); }
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 texb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize); FloatBuffer nb = writeNormalArray(null, scale); Buffer ib; IndexBuffer idxB = writeIndexArrayLodDiff(lod, rightLod, topLod, leftLod, bottomLod, totalSize); if (idxB.getBuffer() instanceof IntBuffer) ib = (IntBuffer)idxB.getBuffer(); else ib = (ShortBuffer)idxB.getBuffer(); FloatBuffer bb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); FloatBuffer tanb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); writeTangentArray(nb, tanb, bb, texb, scale); Mesh m = new Mesh(); m.setMode(Mode.TriangleStrip); m.setBuffer(Type.Position, 3, pb); m.setBuffer(Type.Normal, 3, nb); m.setBuffer(Type.Tangent, 3, tanb); m.setBuffer(Type.Binormal, 3, bb); m.setBuffer(Type.TexCoord, 2, texb); if (ib instanceof IntBuffer) m.setBuffer(Type.Index, 3, (IntBuffer)ib); else if (ib instanceof ShortBuffer) m.setBuffer(Type.Index, 3, (ShortBuffer)ib); m.setStatic(); m.updateBound(); return m; }
@Override public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) { if (!isLoaded()) { throw new NullPointerException(); if (store.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); for (int r = 0; r < getHeight(); r++) { for (int c = 0; c < getWidth(); c++) { rootPoint.set(0, getValue(c, r), 0); Vector3f normal = vars.vect8; rightPoint.set(1, getValue(c + 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); getNormal(bottomPoint, rootPoint, rightPoint, scale, normal); } else if (c == getWidth() - 1) { // last column leftPoint.set(-1, getValue(c - 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); getNormal(leftPoint, rootPoint, bottomPoint, scale, normal); } else { // all middle columns leftPoint.set(-1, getValue(c - 1, r), 0); rightPoint.set(1, getValue(c + 1, r), 0); bottomPoint.set(0, getValue(c, r + 1), 1); normal.set( getNormal(leftPoint, rootPoint, bottomPoint, scale, tmp1) ); normal.addLocal( getNormal(bottomPoint, rootPoint, rightPoint, scale, tmp1) );
public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize) { if (store != null) { if (store.remaining() < getWidth() * getHeight() * 2) { throw new BufferUnderflowException(); } } else { store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 2); } if (offset == null) { offset = new Vector2f(); } Vector2f tcStore = new Vector2f(); // work from bottom of heightmap up, so we don't flip the coords for (int y = getHeight() - 1; y >= 0; y--) { for (int x = 0; x < getWidth(); x++) { getUV(x, y, tcStore, offset, offsetAmount, totalSize); float tx = tcStore.x * scale.x; float ty = tcStore.y * scale.y; store.put(tx); store.put(ty); } } return store; }
public FloatBuffer[] writeTangentArray(FloatBuffer normalBuffer, FloatBuffer tangentStore, FloatBuffer binormalStore, FloatBuffer textureBuffer, Vector3f scale) { if (!isLoaded()) { throw new NullPointerException(); if (tangentStore.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); tangentStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); if (binormalStore.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); binormalStore = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); for (int r = 0; r < getHeight(); r++) { for (int c = 0; c < getWidth(); c++) { int idx = (r * getWidth() + c) * 3; normal.set(normalBuffer.get(idx), normalBuffer.get(idx+1), normalBuffer.get(idx+2)); tangent.set(normal.cross(new Vector3f(0,0,1))); binormal.set(new Vector3f(1,0,0).cross(normal)); BufferUtils.setInBuffer(tangent.normalizeLocal(), tangentStore, (r * getWidth() + c)); // save the tangent BufferUtils.setInBuffer(binormal.normalizeLocal(), binormalStore, (r * getWidth() + c)); // save the binormal
protected void setHeight(List<LocationHeight> locationHeights, boolean overrideHeight) { for (LocationHeight lh : locationHeights) { if (lh.x < 0 || lh.z < 0 || lh.x >= size || lh.z >= size) continue; int idx = lh.z * size + lh.x; if (overrideHeight) { geomap.getHeightArray()[idx] = lh.h; } else { float h = getMesh().getFloatBuffer(Type.Position).get(idx*3+1); geomap.getHeightArray()[idx] = h+lh.h; } } FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false); getMesh().clearBuffer(Type.Position); getMesh().setBuffer(Type.Position, 3, newVertexBuffer); }
geomap = new LODGeomap(size, heightMap); Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false); setMesh(m);