Basic terrain mesh done

This commit is contained in:
Ziver Koc 2020-04-23 23:17:28 +02:00
parent 85ffe136d3
commit 722fd26511
7 changed files with 78 additions and 60 deletions

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<module version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>

View file

@ -9,7 +9,6 @@ import se.cookery.core.world.Block;
import se.cookery.core.world.gen.GrassLandWorldGenerator;
import se.cookery.gfx.character.Player;
import se.cookery.gfx.terrain.TerrainMesh;
import se.cookery.gfx.util.GeometryUtil;
import se.cookery.gfx.util.MaterialUtil;
import se.cookery.gfx.util.WireFrameProcessor;
@ -22,32 +21,9 @@ public class CookeryClient extends SimpleApplication {
cam.setLocation(new Vector3f(0,20,-10));
cam.lookAt(new Vector3f(0f,0f,0f), Vector3f.UNIT_Z);
/** 3. We have prepared material and heightmap.
* Now we create the actual terrain:
* 3.1) Create a TerrainQuad and name it "my terrain".
* 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
* 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
* 3.4) As LOD step scale we supply Vector3f(1,1,1).
* 3.5) We supply the prepared heightmap itself.
*/
Block block = new GrassLandWorldGenerator().generateBlock(0, 0);
/*float[] heightMap = new float[Block.BLOCK_SIZE*Block.BLOCK_SIZE];
for (int x=0; x<Block.BLOCK_SIZE; x++) {
for (int y=0; y<Block.BLOCK_SIZE; y++) {
heightMap[Block.BLOCK_SIZE * x + y] = block.getHeight(x, y);
}
}
heightMap[Block.BLOCK_SIZE*Block.BLOCK_SIZE/2+Block.BLOCK_SIZE/2] = 1;
terrain = new TerrainQuad("Ground", Block.BLOCK_SIZE+1, Block.BLOCK_SIZE+1, heightMap);
Material green = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
green.setColor("Color", ColorRGBA.Green);
terrain.setMaterial(green);
rootNode.attachChild(terrain);*/
Geometry terrain = new Geometry("terrain", new TerrainMesh(1, 1, 1, 1));
Geometry terrain = new Geometry("terrain", new TerrainMesh(1, 1, Block.BLOCK_SIZE, Block.BLOCK_SIZE));
terrain.setMaterial(MaterialUtil.createMaterial(assetManager, ColorRGBA.Green));
rootNode.attachChild(terrain);

View file

@ -11,7 +11,7 @@ public class Block {
/**
* The size of a block in units of squares. The block is a square with size BLOCK_SIZE x BLOCK_SIZE.
**/
public static final int BLOCK_SIZE = 64;
public static final int BLOCK_SIZE = 20;
// Variables

View file

@ -1,17 +1,8 @@
package se.cookery.gfx.terrain;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Class will generate a terrain mesh from a TerrainMap
@ -34,6 +25,8 @@ public class TerrainMesh extends Mesh {
public TerrainMesh(float width, float height, int widthCount, int heightCount){
this.width = width;
this.height = height;
this.widthCount = widthCount;
this.heightCount = heightCount;
updateGeometry();
}
@ -41,8 +34,8 @@ public class TerrainMesh extends Mesh {
protected void updateGeometry() {
setBuffer(VertexBuffer.Type.Position, 3, generateVertexBuffer());
setBuffer(VertexBuffer.Type.Index, 3, generateIndexBuffer());
setBuffer(VertexBuffer.Type.TexCoord, 2, generateTextureBuffer());
setBuffer(VertexBuffer.Type.Normal, 3, generateNormalBuffer());
// setBuffer(VertexBuffer.Type.TexCoord, 2, generateTextureBuffer());
// setBuffer(VertexBuffer.Type.Normal, 3, generateNormalBuffer());
updateBound();
setStatic();
@ -52,25 +45,49 @@ public class TerrainMesh extends Mesh {
* Generates a vertex buffer containing vertex xyz coordinates.
*/
protected float[] generateVertexBuffer() {
float[] vertexBuf = new float[3 * widthCount * heightCount];
int vertexCountWidth = widthCount + 1;
int vertexCountHeight = heightCount + 1;
float[] vertexBuf = new float[3 * vertexCountWidth * vertexCountHeight];
return new float[]{
// x, y, z
0, 0, 0,
0, 0, height,
width, 0, height,
width, 0, 0,
};
for (int row=0; row<vertexCountHeight; row++) {
for (int col=0; col<vertexCountWidth; col++) {
int vertexIndex = (3 * vertexCountWidth * row) + (3 * col);
vertexBuf[vertexIndex + 0] = width * col; // X
vertexBuf[vertexIndex + 1] = 0; // Y
vertexBuf[vertexIndex + 2] = height * row; // Z
}
}
return vertexBuf;
}
/**
* Generates a index buffer containing planes for the mesh.
*/
protected short[] generateIndexBuffer() {
return new short[]{
0, 1, 3,
3, 1, 2
};
int vertexCountWidth = widthCount + 1;
int triangleCount = widthCount * heightCount * 2;
short[] indexBuf = new short[3 * triangleCount];
for (int row=0; row<heightCount; row++) {
for (int col = 0; col<widthCount; col++) {
int vertexTopLeft = (row * vertexCountWidth) + col;
int vertexTopRight = vertexTopLeft + 1;
int vertexBottomLeft = ((row + 1) * vertexCountWidth) + col;
int vertexBottomRight = vertexBottomLeft + 1;
int indexOffset = 3 * 2 * ((row * widthCount) + col);
indexBuf[indexOffset + 0] = (short) vertexTopLeft;
indexBuf[indexOffset + 1] = (short) vertexBottomLeft;
indexBuf[indexOffset + 2] = (short) vertexTopRight;
indexBuf[indexOffset + 3] = (short) vertexTopRight;
indexBuf[indexOffset + 4] = (short) vertexBottomLeft;
indexBuf[indexOffset + 5] = (short) vertexBottomRight;
}
}
return indexBuf;
}
/**

View file

@ -10,27 +10,52 @@ class TerrainMeshTest {
public void singleSquareTerrain(){
TerrainMesh terrain = new TerrainMesh(1, 1, 1 ,1);
float[] index = terrain.generateVertexBuffer();
assertEquals(3*4, index.length);
float[] vertexBuffer = terrain.generateVertexBuffer();
assertEquals(3 * 4, vertexBuffer.length);
assertArrayEquals(new float[]{
0, 0, 0,
1, 0, 0,
0, 0, 1,
1, 0, 1,
1, 0, 0,
}, index);
}, vertexBuffer);
short[] indexBuffer = terrain.generateIndexBuffer();
assertEquals(3 * 2, indexBuffer.length);
assertArrayEquals(new short[]{
0, 2, 1,
1, 2, 3,
}, indexBuffer);
}
@Test
public void fourSquareTerrain(){
TerrainMesh terrain = new TerrainMesh(1, 1, 2 ,2);
float[] index = terrain.generateVertexBuffer();
assertEquals(3*9, index.length);
float[] vertexBuffer = terrain.generateVertexBuffer();
assertEquals(3 * 9, vertexBuffer.length);
assertArrayEquals(new float[]{
0, 0, 0,
1, 0, 0,
2, 0, 0,
0, 0, 1,
1, 0, 1,
1, 0, 0,
}, index);
2, 0, 1,
0, 0, 2,
1, 0, 2,
2, 0, 2,
}, vertexBuffer);
short[] indexBuffer = terrain.generateIndexBuffer();
assertEquals(3 * 8, indexBuffer.length);
assertArrayEquals(new short[]{
0, 3, 1,
1, 3, 4,
1, 4, 2,
2, 4, 5,
3, 6, 4,
4, 6, 7,
4, 7, 5,
5, 7, 8,
}, indexBuffer);
}
}