aboutsummaryrefslogtreecommitdiffstats
path: root/src/ru/olamedia/olacraft/world
diff options
context:
space:
mode:
authorolamedia <[email protected]>2012-10-17 09:52:48 +0600
committerolamedia <[email protected]>2012-10-17 09:52:48 +0600
commit5320fd1dad5b77fa227e83fbbe0a958f2c5fc283 (patch)
tree1b49b91cf820ad5536241fa093c34fd2ae9731db /src/ru/olamedia/olacraft/world
parente2b667011c8fc93388c3ebee6e2a64090456e2a1 (diff)
fps
Diffstat (limited to 'src/ru/olamedia/olacraft/world')
-rw-r--r--src/ru/olamedia/olacraft/world/block/Block.java235
-rw-r--r--src/ru/olamedia/olacraft/world/block/BlockRegistry.java17
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java5
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java23
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/StoneBlockType.java29
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/BlockSlice.java3
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/Chunk.java72
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java5
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java42
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkData.java147
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java23
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java3
-rw-r--r--src/ru/olamedia/olacraft/world/generator/RegionGenerator.java4
-rw-r--r--src/ru/olamedia/olacraft/world/location/BlockLocation.java37
-rw-r--r--src/ru/olamedia/olacraft/world/location/ChunkLocation.java34
-rw-r--r--src/ru/olamedia/olacraft/world/provider/WorldProvider.java14
16 files changed, 627 insertions, 66 deletions
diff --git a/src/ru/olamedia/olacraft/world/block/Block.java b/src/ru/olamedia/olacraft/world/block/Block.java
index 44e9b1d..50752f0 100644
--- a/src/ru/olamedia/olacraft/world/block/Block.java
+++ b/src/ru/olamedia/olacraft/world/block/Block.java
@@ -1,34 +1,73 @@
package ru.olamedia.olacraft.world.block;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLContext;
import javax.vecmath.Vector3f;
import ru.olamedia.camera.MatrixCamera;
+import ru.olamedia.olacraft.game.Game;
import ru.olamedia.olacraft.world.blockTypes.BlockType;
import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.olacraft.world.chunk.Chunk;
import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.provider.WorldProvider;
public class Block {
- private WorldProvider provider;
- private int x;
- private int y;
- private int z;
+ public WorldProvider provider;
+ public BlockLocation location = new BlockLocation();
+
+ public void removeFromWorld() {
+ ChunkData cdata = provider.getChunk(location.getChunkLocation());
+ cdata.setEmpty(location, true);
+ Chunk chunk = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation());
+ chunk.invalidate();
+ if (location.isChunkEdge()) {
+ if (location.isChunkBackEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getBack());
+ neighbor.invalidate();
+ } else if (location.isChunkFrontEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getFront());
+ neighbor.invalidate();
+ } else if (location.isChunkLeftEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getLeft());
+ neighbor.invalidate();
+ } else if (location.isChunkRightEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getRight());
+ neighbor.invalidate();
+ } else if (location.isChunkTopEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getTop());
+ neighbor.invalidate();
+ } else if (location.isChunkBottomEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getBottom());
+ neighbor.invalidate();
+ }
+ }
+ }
/**
* Inventory block
*/
public Block() {
this.provider = null;
- this.x = 0;
- this.y = 0;
- this.z = 0;
+ location.x = 0;
+ location.y = 0;
+ location.z = 0;
}
public void putIntoWorld(WorldProvider worldProvider, int x, int y, int z) {
this.provider = worldProvider;
- this.x = x;
- this.y = y;
- this.z = z;
+ location.x = x;
+ location.y = y;
+ location.z = z;
}
public Block(WorldProvider worldProvider, int x, int y, int z) {
@@ -39,7 +78,7 @@ public class Block {
* @return the x
*/
public int getX() {
- return x;
+ return location.x;
}
/**
@@ -47,14 +86,14 @@ public class Block {
* the x to set
*/
public void setX(int x) {
- this.x = x;
+ location.x = x;
}
/**
* @return the y
*/
public int getY() {
- return y;
+ return location.y;
}
/**
@@ -62,14 +101,14 @@ public class Block {
* the y to set
*/
public void setY(int y) {
- this.y = y;
+ location.y = y;
}
/**
* @return the z
*/
public int getZ() {
- return z;
+ return location.z;
}
/**
@@ -77,15 +116,15 @@ public class Block {
* the z to set
*/
public void setZ(int z) {
- this.z = z;
+ location.z = z;
}
public boolean isEmpty() throws ChunkUnavailableException {
- return provider.isEmptyBlock(x, y, z);
+ return provider.isEmptyBlock(location.x, location.y, location.z);
}
public Block getNeighbor(int dx, int dy, int dz) {
- return new Block(provider, x + dx, y + dy, z + dz);
+ return new Block(provider, location.x + dx, location.y + dy, location.z + dz);
}
public Block[] getNeighbors() {
@@ -153,34 +192,178 @@ public class Block {
}
private Vector3f getBottomRightBack() {
- return new Vector3f(x + 0.5f, y - 0.5f, z - 0.5f);
+ return new Vector3f(location.x + 0.5f, location.y - 0.5f, location.z - 0.5f);
}
private Vector3f getBottomRightFront() {
- return new Vector3f(x + 0.5f, y - 0.5f, z + 0.5f);
+ return new Vector3f(location.x + 0.5f, location.y - 0.5f, location.z + 0.5f);
}
private Vector3f getBottomLeftFront() {
- return new Vector3f(x - 0.5f, y - 0.5f, z + 0.5f);
+ return new Vector3f(location.x - 0.5f, location.y - 0.5f, location.z + 0.5f);
}
private Vector3f getBottomLeftBack() {
- return new Vector3f(x - 0.5f, y - 0.5f, z - 0.5f);
+ return new Vector3f(location.x - 0.5f, location.y - 0.5f, location.z - 0.5f);
}
private Vector3f getTopRightBack() {
- return new Vector3f(x + 0.5f, y + 0.5f, z - 0.5f);
+ return new Vector3f(location.x + 0.5f, location.y + 0.5f, location.z - 0.5f);
}
private Vector3f getTopLeftFront() {
- return new Vector3f(x - 0.5f, y + 0.5f, z + 0.5f);
+ return new Vector3f(location.x - 0.5f, location.y + 0.5f, location.z + 0.5f);
}
private Vector3f getTopRightFront() {
- return new Vector3f(x + 0.5f, y + 0.5f, z + 0.5f);
+ return new Vector3f(location.x + 0.5f, location.y + 0.5f, location.z + 0.5f);
}
private Vector3f getTopLeftBack() {
- return new Vector3f(x - 0.5f, y + 0.5f, z - 0.5f);
+ return new Vector3f(location.x - 0.5f, location.y + 0.5f, location.z - 0.5f);
+ }
+
+ public void request() {
+ provider.loadChunk(location.getChunkLocation());
+ }
+
+ public void renderFrame() {
+ GL2 gl = GLContext.getCurrentGL().getGL2();
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ gl.glEnable(GL2.GL_DEPTH_TEST);
+ gl.glEnable(GL2.GL_LINE_SMOOTH);
+ gl.glEnable(GL2.GL_POLYGON_SMOOTH);
+ gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
+ gl.glHint(GL2.GL_POLYGON_SMOOTH_HINT, GL2.GL_NICEST);
+ // gl.glEnable(GL2.GL_BLEND); // Enable Blending
+ // gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE);
+ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
+ float min = 0.505f;
+ float max = 0.495f;
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glColor4f(0, 0, 0, 0.8f);
+ // top: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z + min);
+ // top: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z + min);
+ // top: back
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - max);
+ // top: front
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z + max);
+ // bottom: right
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z + min);
+ // bottom: left
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z + min);
+ // bottom: back
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - max);
+ // bottom: front
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + max);
+ // front: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z + min);
+ // front: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z + min);
+ // front: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ // front: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z + min);
+ // back: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z - min);
+ // back: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z - min);
+ // back: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ // back: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z + min);
+ // left: back
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - max);
+ // left: front
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + max);
+ // left: top
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z + min);
+ // left: bottom
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z + min);
+ // right: back
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - max);
+ // right: front
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z + max);
+ // right: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z + min);
+ // right: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ }
+ gl.glEnd();
}
}
diff --git a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
index 19ccc94..ec9f9c1 100644
--- a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
+++ b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
@@ -23,16 +23,13 @@ public class BlockRegistry {
return names.get(id);
}
- public int registerBlockType(@SuppressWarnings("rawtypes") Class type) {
- if (type.isInstance(BlockType.class)) {
- autoincrement++;
- int id = autoincrement;
- String classId = type.getName();
- names.put(id, classId);
- // types.put(id, type);
- return autoincrement;
- }
- return 0;
+ public int registerBlockType(BlockType type) {
+ autoincrement++;
+ int id = autoincrement;
+ String classId = type.getClass().getName();
+ names.put(id, classId);
+ types.put(id, type);
+ return autoincrement;
}
public BlockRegistry getWorldRegistry() {
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
index 6e2a86f..717c01f 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
@@ -2,6 +2,8 @@ package ru.olamedia.olacraft.world.blockTypes;
import com.jogamp.opengl.util.texture.Texture;
+import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
import ru.olamedia.texture.TextureManager;
public abstract class AbstractBlockType implements BlockType {
@@ -75,12 +77,13 @@ public abstract class AbstractBlockType implements BlockType {
return TextureManager.get(this.getBackTextureFile());
}
- public void register(){
+ public void register(WorldProvider provider){
getBackTexture();
getBottomTexture();
getFrontTexture();
getLeftTexture();
getRightTexture();
getTopTexture();
+ provider.getTypeRegistry().registerBlockType(this);
}
}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java
new file mode 100644
index 0000000..a4e5dd7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class DirtBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Gravel";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/dirt.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/dirt.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/StoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/StoneBlockType.java
new file mode 100644
index 0000000..d2b3446
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/StoneBlockType.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class StoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Stone";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/terrain-cobb.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/terrain-cobb.png";
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return "texture/terrain-cobb.png";
+ }
+}
+
diff --git a/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
index bad802f..d02999d 100644
--- a/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
+++ b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
@@ -34,7 +34,8 @@ public class BlockSlice implements Iterator<Block> {
}
}
} catch (ChunkUnavailableException e) {
- e.printStackTrace();
+ //e.printStackTrace();
+ b.request();
}
}
return nearestBlock;
diff --git a/src/ru/olamedia/olacraft/world/chunk/Chunk.java b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
index 9c0afb7..f390ebc 100644
--- a/src/ru/olamedia/olacraft/world/chunk/Chunk.java
+++ b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
@@ -1,7 +1,8 @@
package ru.olamedia.olacraft.world.chunk;
import ru.olamedia.geom.SimpleQuadMesh;
-import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
import ru.olamedia.olacraft.world.provider.WorldProvider;
@@ -9,6 +10,8 @@ import ru.olamedia.olacraft.world.provider.WorldProvider;
public class Chunk extends BlockSlice {
public boolean isMeshCostructed = false;
public SimpleQuadMesh mesh;
+ public boolean usePrevMesh = false;
+ public SimpleQuadMesh prevMesh;
public int visibleTop = 0;
public int visibleBottom = 0;
@@ -17,6 +20,25 @@ public class Chunk extends BlockSlice {
public int visibleFront = 0;
public int visibleBack = 0;
+ public void render() {
+ if (isMeshCostructed) {
+ mesh.joglRender();
+ } else if (usePrevMesh) {
+ prevMesh.joglRender();
+ }
+ }
+
+ public void invalidate() {
+ if (null != mesh) {
+ prevMesh = mesh;
+ usePrevMesh = true;
+ if (null != mesh) {
+ mesh.restart();
+ }
+ }
+ isMeshCostructed = false;
+ }
+
public Chunk(WorldProvider provider) {
super(provider, 16, 16, 16);
}
@@ -93,32 +115,51 @@ public class Chunk extends BlockSlice {
* @return the mesh
*/
public SimpleQuadMesh getMesh() {
+ if (!isAvailable()) {
+ return null;
+ }
if (isMeshCostructed) {
return mesh;
}
- if (offset.y > provider.getInfo().maxHeight) {
- // isMeshCostructed = true;
- // return null;
+ if (offset.y >= provider.getInfo().maxHeight) {
+ isMeshCostructed = true;
+ return null;
}
if (offset.y < provider.getInfo().minHeight) {
- // isMeshCostructed = true;
- // return null;
+ isMeshCostructed = true;
+ return null;
}
- if (null == mesh) {
- mesh = new SimpleQuadMesh(14739); // unindexed
+
+ if (null == mesh || mesh.restart) {
+ ChunkData data = provider.getChunk(offset.getChunkLocation());
+ data.computeVisibility(provider);
+ // max 14739
+ System.out.println(data.visibleCount + " vis");
+ mesh = new SimpleQuadMesh(14739);
+ //mesh = new SimpleQuadMesh(Math.min(data.visibleCount * 6, 14739));
+ mesh.start();
// 17x17x17
// vertices
mesh.useColor();
mesh.useTexture();
// gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_FASTEST);
// gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
- GrassBlockType grass = new GrassBlockType();
- for (int x = offset.x; x < offset.x + getWidth(); x++) {
- for (int y = offset.y; y < offset.y + getHeight(); y++) {
- for (int z = offset.z; z < offset.z + getDepth(); z++) {
+ BlockType grass;
+ for (int dx = 0; dx < 16; dx++) {
+ for (int dy = 0; dy < 16; dy++) {
+ for (int dz = 0; dz < 16; dz++) {
+ int x = offset.x + dx;
+ int y = offset.y + dy;
+ int z = offset.z + dz;
+ if (mesh.restart) {
+ return null;
+ }
//
try {
- if (!isEmptyBlock(x, y, z)) {
+ int id = dx * 16 * 16 + dy * 16 + dz;
+ if (data.visible.get(id) && !data.emptyBlocks.get(id)) {
+ grass = provider.getTypeRegistry().getBlockType(
+ provider.getChunk((new BlockLocation(x, y, z)).getChunkLocation()).types[id]);
mesh.setTranslation(x, y, z);
// mesh.setColor4f(0, 1, 0, 1);
float cbase = (float) (y / 200.0) * (float) (7.0 / 10.0);
@@ -197,6 +238,7 @@ public class Chunk extends BlockSlice {
}
}
mesh.endMesh();
+ data.visible = null;
isMeshCostructed = true;
return null;
}
@@ -311,4 +353,8 @@ public class Chunk extends BlockSlice {
public void setLocation(ChunkLocation location) {
setLocation(location.getBlockLocation().x, location.getBlockLocation().y, location.getBlockLocation().z);
}
+
+ public boolean inWorldRange() {
+ return (offset.y + 16 < provider.getInfo().maxHeight) && (offset.y > provider.getInfo().minHeight);
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
index d362199..e823b2f 100644
--- a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
@@ -4,7 +4,7 @@ import java.util.concurrent.ArrayBlockingQueue;
public class ChunkMeshBulder extends Thread {
public static ChunkMeshBulder instance = new ChunkMeshBulder("Mesh builder");
- private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(16);
+ private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(256);
public ChunkMeshBulder(String name) {
super(name);
@@ -36,6 +36,9 @@ public class ChunkMeshBulder extends Thread {
// main loop
try {
tick();
+ if (chunks.isEmpty()){
+ Thread.sleep(50);
+ }
// Thread.sleep(10); // or wait/join etc
} catch (InterruptedException ex) {
// cleanup here
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
index d0307bb..14e2c1f 100644
--- a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
@@ -21,20 +21,41 @@ public class ChunkSlice {
}
protected HashMap<String, Chunk> chunks = new HashMap<String, Chunk>();
+ protected HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>> iChunks = new HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>>();
public Chunk getChunk(ChunkLocation location) {
- int x = location.x;
- int y = location.y;
- int z = location.z;
- String key = x + ";" + y + ";" + z;
- if (chunks.containsKey(key)) {
- return chunks.get(key);
+ // int x = location.x;
+ // int y = location.y;
+ // int z = location.z;
+ // String key = x + ";" + y + ";" + z;
+ if (iChunks.containsKey(location.x)) {
+ if (iChunks.get(location.x).containsKey(location.y)) {
+ if (iChunks.get(location.x).get(location.y).containsKey(location.z)) {
+ return iChunks.get(location.x).get(location.y).get(location.z);
+ } else {
+
+ }
+ } else {
+ iChunks.get(location.x).put(location.y, new HashMap<Integer, Chunk>());
+ }
} else {
- Chunk chunk = new Chunk(provider);
- chunk.setLocation(location);
- chunks.put(key, chunk);
- return chunk;
+ iChunks.put(location.x, new HashMap<Integer, HashMap<Integer, Chunk>>());
+ iChunks.get(location.x).put(location.y, new HashMap<Integer, Chunk>());
}
+
+ Chunk chunk = new Chunk(provider);
+ chunk.setLocation(location);
+ // chunks.put(key, chunk);
+ iChunks.get(location.x).get(location.y).put(location.z, chunk);
+ return chunk;
+ // if (chunks.containsKey(key)) {
+ // return chunks.get(key);
+ // } else {
+ // Chunk chunk = new Chunk(provider);
+ // chunk.setLocation(location);
+ // chunks.put(key, chunk);
+ // return chunk;
+ // }
}
/**
@@ -108,6 +129,7 @@ public class ChunkSlice {
public int getZ() {
return offset.z;
}
+
public void setLocation(ChunkLocation chunkOffset) {
offset = chunkOffset;
}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkData.java b/src/ru/olamedia/olacraft/world/data/ChunkData.java
index a6b9f34..42f7811 100644
--- a/src/ru/olamedia/olacraft/world/data/ChunkData.java
+++ b/src/ru/olamedia/olacraft/world/data/ChunkData.java
@@ -3,9 +3,11 @@ package ru.olamedia.olacraft.world.data;
import java.io.Serializable;
import ru.olamedia.math.OpenBitSet;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
import ru.olamedia.olacraft.world.chunk.Chunk;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
public class ChunkData implements Serializable {
private static final long serialVersionUID = -5704237444737895501L;
@@ -13,17 +15,160 @@ public class ChunkData implements Serializable {
public static transient int SIZE = 4096;
// private boolean[] notEmpty = new boolean[SIZE];
public OpenBitSet emptyBlocks = new OpenBitSet(4096);
+ public int visibleCount = 0;
+ public OpenBitSet visible = null; // fast precomputed
+ // visibility (true if
+ // any side is open)
+ //public OpenBitSet sunlight = new OpenBitSet(65536);
+ public byte[] types = new byte[4096];
public int notEmptyCount = 0;
+ public boolean visibilityPrecomputed = false;
// public transient int[] type = new int[SIZE];
public ChunkData() {
}
+ private void setVisible(int x, int y, int z) {
+ if (x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15) {
+ return;
+ }
+ int id = x * 16 * 16 + y * 16 + z;
+ if (!visible.get(id)){
+ visibleCount++;
+ }
+ visible.set(id);
+ }
+
+ private void setInvisible(int x, int y, int z) {
+ if (x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15) {
+ return;
+ }
+ int id = x * 16 * 16 + y * 16 + z;
+ if (visible.get(id)){
+ visibleCount--;
+ }
+ visible.clear(id);
+ }
+
+ public void computeVisibility(WorldProvider provider) {
+ visible = new OpenBitSet(4096);
+ visibleCount = 0;
+ precomputeVisibility();
+ computeVisibility(provider.getChunk(location.getLeft()), provider.getChunk(location.getRight()),
+ provider.getChunk(location.getTop()), provider.getChunk(location.getBottom()),
+ provider.getChunk(location.getFront()), provider.getChunk(location.getBack()));
+ }
+
+ public void computeVisibility(ChunkData left, ChunkData right, ChunkData top, ChunkData bottom, ChunkData front,
+ ChunkData back) {
+ // compute left/right
+ int x, y, z, id;
+ for (y = 0; y <= 15; y++) {
+ for (z = 0; z <= 15; z++) {
+ x = 15;
+ id = x * 16 * 16 + y * 16 + z;
+ if (left.emptyBlocks.get(id)) {
+ x = 0;
+ setVisible(x, y, z);
+ }
+ x = 0;
+ id = x * 16 * 16 + y * 16 + z;
+ if (right.emptyBlocks.get(id)) {
+ x = 15;
+ setVisible(x, y, z);
+ }
+ }
+ }
+ // top/bottom
+ for (x = 0; x <= 15; x++) {
+ for (z = 0; z <= 15; z++) {
+ y = 15;
+ id = x * 16 * 16 + y * 16 + z;
+ if (bottom.emptyBlocks.get(id)) {
+ y = 0;
+ setVisible(x, y, z);
+ }
+ y = 0;
+ id = x * 16 * 16 + y * 16 + z;
+ if (top.emptyBlocks.get(id)) {
+ y = 15;
+ setVisible(x, y, z);
+ }
+ }
+ }
+ // front/back
+ for (x = 0; x <= 15; x++) {
+ for (y = 0; y <= 15; y++) {
+ z = 15;
+ id = x * 16 * 16 + y * 16 + z;
+ if (back.emptyBlocks.get(id)) {
+ z = 0;
+ setVisible(x, y, z);
+ }
+ z = 0;
+ id = x * 16 * 16 + y * 16 + z;
+ if (front.emptyBlocks.get(id)) {
+ z = 15;
+ setVisible(x, y, z);
+ }
+ }
+ }
+ }
+
+ /**
+ * Compute visibility ("visible" if any side have non-opaque neighbor)
+ * Leaving side blocks invisible. Use computeVisibility(WorldProvider) to compute visibility of side blocks
+ */
+ public void precomputeVisibility() {
+ // first pass, make all blocks invisible, except side blocks
+ for (int x = 0; x <= 15; x++) {
+ for (int y = 0; y <= 15; y++) {
+ for (int z = 0; z <= 15; z++) {
+ // if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z
+ // == 15) {
+ // setVisible(x, y, z);
+ // } else {
+ // setInvisible(x, y, z);
+ // }
+ setInvisible(x, y, z);
+ }
+ }
+ }
+ // second pass, make some blocks visible
+ for (int x = 0; x <= 15; x++) {
+ for (int y = 0; y <= 15; y++) {
+ for (int z = 0; z <= 15; z++) {
+ int id = x * 16 * 16 + y * 16 + z;
+ if (emptyBlocks.get(id)) {
+ setVisible(x - 1, y, z);
+ setVisible(x + 1, y, z);
+ setVisible(x, y - 1, z);
+ setVisible(x, y + 1, z);
+ setVisible(x, y, z - 1);
+ setVisible(x, y, z + 1);
+ }
+ }
+ }
+ }
+ visibilityPrecomputed = true;
+ }
+
public void compact() {
if (emptyBlocks.cardinality() == 0) {
- emptyBlocks = null;
+ // emptyBlocks = null;
+ }
+ }
+
+ public BlockType getType(BlockLocation blockLocation, WorldProvider provider) {
+ if (emptyBlocks == null) {
+ return null;
+ }
+ int id = Chunk.in(blockLocation.x) * 16 * 16 + Chunk.in(blockLocation.y) * 16 + Chunk.in(blockLocation.z);
+ if (isEmpty(id)) {
+ return null;
}
+ return provider.getBlockTypeById(types[id]);
}
public boolean isEmpty(BlockLocation blockLocation) {
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
index 9ba9496..1e6c0c1 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
@@ -1,6 +1,9 @@
package ru.olamedia.olacraft.world.dataProvider;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import ru.olamedia.olacraft.world.data.RegionData;
import ru.olamedia.olacraft.world.location.RegionLocation;
@@ -8,6 +11,7 @@ import ru.olamedia.olacraft.world.location.RegionLocation;
public class CachedChunkDataProvider extends AbstractChunkDataProvider {
private AbstractChunkDataProvider provider;
private HashMap<String, RegionData> regionMap = new HashMap<String, RegionData>();
+ private ConcurrentHashMap<String, Integer> ticks = new ConcurrentHashMap<String, Integer>();
public CachedChunkDataProvider(AbstractChunkDataProvider provider) {
this.provider = provider;
@@ -21,6 +25,24 @@ public class CachedChunkDataProvider extends AbstractChunkDataProvider {
}
}
+ @SuppressWarnings("unused")
+ private void tick(String key) {
+ ticks.put(key, 0);
+ gc();
+ }
+
+ private void gc() {
+ Iterator<String> keys = ticks.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ ticks.put(key, ticks.get(key) + 1);
+ if (ticks.get(key) > 30) {
+ ticks.remove(key);
+ regionMap.remove(key);
+ }
+ }
+ }
+
@Override
public boolean isRegionAvailable(RegionLocation regionLocation) {
String key = regionLocation.toString();// regionLocation.x + "-" +
@@ -44,6 +66,7 @@ public class CachedChunkDataProvider extends AbstractChunkDataProvider {
@Override
public RegionData getRegion(RegionLocation regionLocation) {
String key = regionLocation.toString();
+ // tick(key);
if (regionMap.containsKey(key)) {
return regionMap.get(key);
} else {
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
index cd48071..0c52ced 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
@@ -19,6 +19,7 @@ public class RemoteChunkDataProvider extends AbstractChunkDataProvider implement
private GameClient client;
private HashMap<String, RegionData> map = new HashMap<String, RegionData>();
private List<String> loading = new ArrayList<String>();
+ private List<RegionLocation> queue = new ArrayList<RegionLocation>();
public RemoteChunkDataProvider(GameClient client) {
this.client = client;
@@ -36,7 +37,7 @@ public class RemoteChunkDataProvider extends AbstractChunkDataProvider implement
@Override
public void loadRegion(RegionLocation regionLocation) {
String key = regionLocation.toString();
- if (!loading.contains(key)) {
+ if (loading.isEmpty() && !loading.contains(key)) {
debug("loadRegion(" + key + ")");
loading.add(key);
client.send(new GetRegionPacket(regionLocation));
diff --git a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
index 05fc067..79ac898 100644
--- a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
+++ b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
@@ -1,5 +1,6 @@
package ru.olamedia.olacraft.world.generator;
+import ru.olamedia.olacraft.world.chunk.Chunk;
import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.data.HeightMap;
import ru.olamedia.olacraft.world.data.RegionData;
@@ -68,7 +69,10 @@ public class RegionGenerator {
// System.out.println("not empty, height: "
// + height);
}
+ int id = Chunk.in(blockOffset.x) * 16 * 16 + Chunk.in(blockOffset.y) * 16
+ + Chunk.in(blockOffset.z);
chunk.setEmpty(blockOffset, false);
+ chunk.types[id] = (byte) (1 + Math.random() * 4);
}
}
}
diff --git a/src/ru/olamedia/olacraft/world/location/BlockLocation.java b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
index b104bad..9639ac1 100644
--- a/src/ru/olamedia/olacraft/world/location/BlockLocation.java
+++ b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
@@ -13,12 +13,49 @@ public class BlockLocation implements Serializable {
public BlockLocation() {
}
+ public boolean isChunkEdge() {
+ int cx = Chunk.in(x);
+ int cy = Chunk.in(y);
+ int cz = Chunk.in(z);
+ return (cx == 0 || cy == 0 || cz == 0 || cx == 15 || cy == 15 || cz == 15);
+ }
+
+ public boolean isChunkLeftEdge() {
+ return Chunk.in(x) == 0;
+ }
+
+ public boolean isChunkRightEdge() {
+ return Chunk.in(x) == 15;
+ }
+
+ public boolean isChunkTopEdge() {
+ return Chunk.in(y) == 15;
+ }
+
+ public boolean isChunkBottomEdge() {
+ return Chunk.in(y) == 0;
+ }
+
+ public boolean isChunkFrontEdge() {
+ return Chunk.in(z) == 15;
+ }
+
+ public boolean isChunkBackEdge() {
+ return Chunk.in(z) == 0;
+ }
+
public BlockLocation(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
+ public BlockLocation(float x, float y, float z) {
+ this.x = (int) x;
+ this.y = (int) y;
+ this.z = (int) z;
+ }
+
public ChunkLocation getChunkLocation() {
return new ChunkLocation(Chunk.v(x), Chunk.v(y + 128), Chunk.v(z));
}
diff --git a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
index a772c6d..439b9be 100644
--- a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
+++ b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
@@ -17,6 +17,12 @@ public class ChunkLocation implements Serializable {
this.z = z;
}
+ public ChunkLocation(ChunkLocation loc) {
+ this.x = loc.x;
+ this.y = loc.y;
+ this.z = loc.z;
+ }
+
public int x;
public int y;
public int z;
@@ -42,4 +48,32 @@ public class ChunkLocation implements Serializable {
public BlockLocation getBlockLocation() {
return new BlockLocation(Chunk.rev(x), Chunk.rev(y) - 128, Chunk.rev(z));
}
+
+ public ChunkLocation getNeighbor(int dx, int dy, int dz) {
+ return new ChunkLocation(x + dx, y + dy, z + dz);
+ }
+
+ public ChunkLocation getLeft() {
+ return getNeighbor(-1, 0, 0);
+ }
+
+ public ChunkLocation getRight() {
+ return getNeighbor(1, 0, 0);
+ }
+
+ public ChunkLocation getTop() {
+ return getNeighbor(0, 1, 0);
+ }
+
+ public ChunkLocation getBottom() {
+ return getNeighbor(0, -1, 0);
+ }
+
+ public ChunkLocation getBack() {
+ return getNeighbor(0, 0, -1);
+ }
+
+ public ChunkLocation getFront() {
+ return getNeighbor(0, 0, 1);
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
index 9e76d1a..7471b52 100644
--- a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
+++ b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
@@ -3,7 +3,9 @@ package ru.olamedia.olacraft.world.provider;
import ru.olamedia.olacraft.game.SpawnLocation;
import ru.olamedia.olacraft.world.WorldInfo;
import ru.olamedia.olacraft.world.block.Block;
-import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.data.RegionData;
@@ -14,11 +16,16 @@ import ru.olamedia.olacraft.world.location.RegionLocation;
public class WorldProvider {
private WorldInfo info = new WorldInfo();
+ private BlockRegistry typeRegistry = new BlockRegistry();
private AbstractChunkDataProvider dataProvider;
public WorldInfo getInfo() {
return info;
}
+
+ public BlockRegistry getTypeRegistry(){
+ return typeRegistry;
+ }
public void setInfo(WorldInfo worldInfo) {
info = worldInfo;
@@ -126,11 +133,14 @@ public class WorldProvider {
}
public Block getBlock(int x, int y, int z) {
- BlockLocation blockLocation = new BlockLocation(x, y, z);
return new Block(this, x, y, z);
}
public ChunkData getChunk(ChunkLocation chunkLocation) {
return dataProvider.getChunk(chunkLocation);
}
+
+ public BlockType getBlockTypeById(int id) {
+ return typeRegistry.getBlockType(id);
+ }
}