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

2
.idea/misc.xml generated
View file

@ -8,5 +8,5 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK" /> <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
</project> </project>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle"> <facet type="android-gradle" name="Android-Gradle">
<configuration> <configuration>

View file

@ -9,7 +9,6 @@ import se.cookery.core.world.Block;
import se.cookery.core.world.gen.GrassLandWorldGenerator; import se.cookery.core.world.gen.GrassLandWorldGenerator;
import se.cookery.gfx.character.Player; import se.cookery.gfx.character.Player;
import se.cookery.gfx.terrain.TerrainMesh; import se.cookery.gfx.terrain.TerrainMesh;
import se.cookery.gfx.util.GeometryUtil;
import se.cookery.gfx.util.MaterialUtil; import se.cookery.gfx.util.MaterialUtil;
import se.cookery.gfx.util.WireFrameProcessor; import se.cookery.gfx.util.WireFrameProcessor;
@ -22,32 +21,9 @@ public class CookeryClient extends SimpleApplication {
cam.setLocation(new Vector3f(0,20,-10)); cam.setLocation(new Vector3f(0,20,-10));
cam.lookAt(new Vector3f(0f,0f,0f), Vector3f.UNIT_Z); 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); 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++) { Geometry terrain = new Geometry("terrain", new TerrainMesh(1, 1, Block.BLOCK_SIZE, Block.BLOCK_SIZE));
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));
terrain.setMaterial(MaterialUtil.createMaterial(assetManager, ColorRGBA.Green)); terrain.setMaterial(MaterialUtil.createMaterial(assetManager, ColorRGBA.Green));
rootNode.attachChild(terrain); 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. * 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 // Variables

View file

@ -1,17 +1,8 @@
package se.cookery.gfx.terrain; 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.Mesh;
import com.jme3.scene.VertexBuffer; 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 * 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){ public TerrainMesh(float width, float height, int widthCount, int heightCount){
this.width = width; this.width = width;
this.height = height; this.height = height;
this.widthCount = widthCount;
this.heightCount = heightCount;
updateGeometry(); updateGeometry();
} }
@ -41,8 +34,8 @@ public class TerrainMesh extends Mesh {
protected void updateGeometry() { protected void updateGeometry() {
setBuffer(VertexBuffer.Type.Position, 3, generateVertexBuffer()); setBuffer(VertexBuffer.Type.Position, 3, generateVertexBuffer());
setBuffer(VertexBuffer.Type.Index, 3, generateIndexBuffer()); setBuffer(VertexBuffer.Type.Index, 3, generateIndexBuffer());
setBuffer(VertexBuffer.Type.TexCoord, 2, generateTextureBuffer()); // setBuffer(VertexBuffer.Type.TexCoord, 2, generateTextureBuffer());
setBuffer(VertexBuffer.Type.Normal, 3, generateNormalBuffer()); // setBuffer(VertexBuffer.Type.Normal, 3, generateNormalBuffer());
updateBound(); updateBound();
setStatic(); setStatic();
@ -52,25 +45,49 @@ public class TerrainMesh extends Mesh {
* Generates a vertex buffer containing vertex xyz coordinates. * Generates a vertex buffer containing vertex xyz coordinates.
*/ */
protected float[] generateVertexBuffer() { 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[]{ for (int row=0; row<vertexCountHeight; row++) {
// x, y, z for (int col=0; col<vertexCountWidth; col++) {
0, 0, 0, int vertexIndex = (3 * vertexCountWidth * row) + (3 * col);
0, 0, height, vertexBuf[vertexIndex + 0] = width * col; // X
width, 0, height, vertexBuf[vertexIndex + 1] = 0; // Y
width, 0, 0, vertexBuf[vertexIndex + 2] = height * row; // Z
}; }
}
return vertexBuf;
} }
/** /**
* Generates a index buffer containing planes for the mesh. * Generates a index buffer containing planes for the mesh.
*/ */
protected short[] generateIndexBuffer() { protected short[] generateIndexBuffer() {
return new short[]{ int vertexCountWidth = widthCount + 1;
0, 1, 3, int triangleCount = widthCount * heightCount * 2;
3, 1, 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(){ public void singleSquareTerrain(){
TerrainMesh terrain = new TerrainMesh(1, 1, 1 ,1); TerrainMesh terrain = new TerrainMesh(1, 1, 1 ,1);
float[] index = terrain.generateVertexBuffer(); float[] vertexBuffer = terrain.generateVertexBuffer();
assertEquals(3*4, index.length); assertEquals(3 * 4, vertexBuffer.length);
assertArrayEquals(new float[]{ assertArrayEquals(new float[]{
0, 0, 0, 0, 0, 0,
1, 0, 0,
0, 0, 1, 0, 0, 1,
1, 0, 1, 1, 0, 1,
1, 0, 0, }, vertexBuffer);
}, index);
short[] indexBuffer = terrain.generateIndexBuffer();
assertEquals(3 * 2, indexBuffer.length);
assertArrayEquals(new short[]{
0, 2, 1,
1, 2, 3,
}, indexBuffer);
} }
@Test @Test
public void fourSquareTerrain(){ public void fourSquareTerrain(){
TerrainMesh terrain = new TerrainMesh(1, 1, 2 ,2); TerrainMesh terrain = new TerrainMesh(1, 1, 2 ,2);
float[] index = terrain.generateVertexBuffer(); float[] vertexBuffer = terrain.generateVertexBuffer();
assertEquals(3*9, index.length); assertEquals(3 * 9, vertexBuffer.length);
assertArrayEquals(new float[]{ assertArrayEquals(new float[]{
0, 0, 0, 0, 0, 0,
1, 0, 0,
2, 0, 0,
0, 0, 1, 0, 0, 1,
1, 0, 1, 1, 0, 1,
1, 0, 0, 2, 0, 1,
}, index); 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);
} }
} }

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle"> <facet type="android-gradle" name="Android-Gradle">
<configuration> <configuration>