diff options
author | olamedia <[email protected]> | 2012-10-17 09:52:48 +0600 |
---|---|---|
committer | olamedia <[email protected]> | 2012-10-17 09:52:48 +0600 |
commit | 5320fd1dad5b77fa227e83fbbe0a958f2c5fc283 (patch) | |
tree | 1b49b91cf820ad5536241fa093c34fd2ae9731db /src/ru/olamedia/olacraft | |
parent | e2b667011c8fc93388c3ebee6e2a64090456e2a1 (diff) |
fps
Diffstat (limited to 'src/ru/olamedia/olacraft')
21 files changed, 844 insertions, 334 deletions
diff --git a/src/ru/olamedia/olacraft/network/GameClient.java b/src/ru/olamedia/olacraft/network/GameClient.java index 2312c3d..f74340a 100644 --- a/src/ru/olamedia/olacraft/network/GameClient.java +++ b/src/ru/olamedia/olacraft/network/GameClient.java @@ -25,7 +25,6 @@ import ru.olamedia.olacraft.network.packet.WorldInfoPacket; import ru.olamedia.olacraft.scene.GameScene; import ru.olamedia.olacraft.world.WorldInfo; import ru.olamedia.olacraft.world.dataProvider.CachedChunkDataProvider; -import ru.olamedia.olacraft.world.dataProvider.LocalChunkDataProvider; import ru.olamedia.olacraft.world.dataProvider.RemoteChunkDataProvider; import ru.olamedia.olacraft.world.provider.WorldProvider; @@ -33,7 +32,7 @@ public class GameClient extends ConnectionStateListener implements IPacketListen private WorldProvider worldProvider; private GameScene scene; - private Client client = new Client(10 * 1024 * 1024, 10 * 1024 * 1024); + private Client client = new Client(10 * 1024 * 1024, 30 * 1024 * 1024); private String hostname = "127.0.0.1"; @Override @@ -65,7 +64,8 @@ public class GameClient extends ConnectionStateListener implements IPacketListen // INIT WORLD worldProvider = new WorldProvider(); worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new RemoteChunkDataProvider(this))); - //worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new LocalChunkDataProvider(worldProvider.getInfo().name))); + // worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new + // LocalChunkDataProvider(worldProvider.getInfo().name))); // CREATE SCENE scene = new GameScene(worldProvider); Kryo kryo = client.getKryo(); diff --git a/src/ru/olamedia/olacraft/network/GameServer.java b/src/ru/olamedia/olacraft/network/GameServer.java index e1e7723..717b40b 100644 --- a/src/ru/olamedia/olacraft/network/GameServer.java +++ b/src/ru/olamedia/olacraft/network/GameServer.java @@ -33,7 +33,7 @@ public class GameServer { private WorldProvider worldProvider; private ExecutorService threadPool = Executors.newFixedThreadPool(1); - public static Server server = new Server(10 * 1024 * 1024, 1024 * 1024) { + public static Server server = new Server(30 * 1024 * 1024, 1024 * 1024) { @Override protected PlayerConnection newConnection() { // By providing our own connection implementation, we can store per diff --git a/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java b/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java index f53bba6..4aaf38c 100644 --- a/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java +++ b/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java @@ -1,7 +1,5 @@ package ru.olamedia.olacraft.render.jogl; -import javax.media.opengl.GLAutoDrawable; - import ru.olamedia.Options; import ru.olamedia.geom.SimpleQuadMesh; import ru.olamedia.math.Box; @@ -21,6 +19,8 @@ public class ChunkRenderer { this.slice = slice; } + public int testedChunks = 0; + public int visibleTop = 0; public int visibleBottom = 0; public int visibleLeft = 0; @@ -32,20 +32,16 @@ public class ChunkRenderer { public int frustumIntersectChunks = 0; public boolean renderChunk(Chunk chunk, boolean skipnew) { - - if (!chunk.isAvailable()) { - System.out.println("not available " + chunk); - chunk.request(); + float d = (float) Math.sqrt(Math.pow(chunk.getOffset().x + 8 - cameraBlock.x, 2) + + Math.pow(chunk.getOffset().y + 8 - cameraBlock.y, 2) + + Math.pow(chunk.getOffset().z + 8 - cameraBlock.z, 2)); + if (d > Options.renderDistance) { return skipnew; } - - if (!chunk.isNeighborsAvailable()) { - System.out.println("not available " + chunk); - chunk.requestNeighbors(); + testedChunks++; + if (!chunk.inWorldRange()) { return skipnew; } - - // System.out.println("available"); Box box = new Box(chunk.getOffset().x, chunk.getOffset().y, chunk.getOffset().z, chunk.getOffset().x + chunk.getWidth(), chunk.getOffset().y + chunk.getHeight(), chunk.getOffset().z + chunk.getDepth()); if (Game.instance.camera.frustum.quickClassify(box) == Classifier.OUTSIDE) { @@ -53,53 +49,74 @@ public class ChunkRenderer { return skipnew; } - // // boolean inside = true; - // if (Game.camera.frustum != null) { - // if (Game.camera.frustum.quickClassify(box) == - // Classifier.Classification.OUTSIDE) { - // frustumCulledChunks++; - // return; - // } - // } - // } else if (Game.camera.frustum.test(box) == Classifier.INTERSECT) { - // inside = false; - // frustumIntersectChunks++; - // } else { - // frustumCulledChunks++; - // return; - // } + chunk.render(); if (!chunk.isMeshCostructed) { - if (skipnew) { + if (!chunk.isAvailable()) { + // System.out.println("not available " + chunk); + chunk.request(); return skipnew; } - } - if (!chunk.isMeshCostructed) { - ChunkMeshBulder.instance.add(chunk); - if (ChunkMeshBulder.instance.isFull()) { - // System.out.println("queue is full, skipping"); - skipnew = true; + + if (!chunk.isNeighborsAvailable()) { + // System.out.println("not available " + chunk); + chunk.requestNeighbors(); + return skipnew; } - // System.out.println("not constructed"); + // compute visibility + + // System.out.println("available"); + + // // boolean inside = true; + // if (Game.camera.frustum != null) { + // if (Game.camera.frustum.quickClassify(box) == + // Classifier.Classification.OUTSIDE) { + // frustumCulledChunks++; + // return; + // } + // } + // } else if (Game.camera.frustum.test(box) == Classifier.INTERSECT) + // { + // inside = false; + // frustumIntersectChunks++; + // } else { + // frustumCulledChunks++; + // return; + // } + if (!chunk.isMeshCostructed) { + if (skipnew) { + return skipnew; + } + } + if (!chunk.isMeshCostructed) { + ChunkMeshBulder.instance.add(chunk); + if (ChunkMeshBulder.instance.isFull()) { + // System.out.println("queue is full, skipping"); + skipnew = true; + } + // System.out.println("not constructed"); + return skipnew; + } + return skipnew; - } - if (null == chunk.getMesh()) { - // System.out.println("mesh is null"); - // skipnew = true; } else { - SimpleQuadMesh mesh = chunk.getMesh(); - // System.out.println("render " + chunk + " " + - // mesh.getVertexCount()); - mesh.joglRender(); + return skipnew; } - return skipnew; } - public void render(GLAutoDrawable drawable) { + BlockLocation cameraBlock; + ChunkLocation cameraChunk; + int distance; + public ChunkSlice chunkSlice; + + public void render() { if (!ChunkMeshBulder.instance.isAlive() && !ChunkMeshBulder.instance.isInterrupted()) { ChunkMeshBulder.instance.start(); } - + if (null == chunkSlice) { + chunkSlice = slice.getChunkSlice(); + } + testedChunks = 0; visibleTop = 0; visibleBottom = 0; visibleLeft = 0; @@ -107,164 +124,45 @@ public class ChunkRenderer { visibleFront = 0; visibleBack = 0; frustumCulledChunks = 0; + + cameraBlock = Game.client.getScene().getPlayer().getCameraBlockLocation(); + cameraChunk = cameraBlock.getChunkLocation(); + ChunkLocation renderLoc; + boolean skipnew = false; - ChunkSlice cs = slice.getChunkSlice(); - for (int x = cs.getX(); x < cs.getX() + cs.getWidth(); x++) { - for (int z = cs.getZ(); z < cs.getZ() + cs.getDepth(); z++) { - for (int y = cs.getY(); y < cs.getY() + cs.getHeight(); y++) { - skipnew = renderChunk(cs.getChunk(new ChunkLocation(x, y, z)), skipnew); - } - } - } - if (true) { - return; - } - // rendering from center - int x, y, z; - int half = (Options.renderDistance / 16) / 2 + 1; - BlockLocation camera = new BlockLocation(); - camera.x = (int) Game.client.getScene().getPlayer().getCameraX(); - camera.y = (int) Game.client.getScene().getPlayer().getCameraY(); - camera.z = (int) Game.client.getScene().getPlayer().getCameraZ(); - ChunkLocation cameraChunk = camera.getChunkLocation(); - int cx = cameraChunk.x; - int cy = cameraChunk.y; - int cz = cameraChunk.z; - ChunkLocation cLoc = new ChunkLocation(cx, cy, cz); - for (int r = 0; r <= half; r++) { - // +x - x = cx + r; - for (z = cz - r - 1; z <= cz + r; z++) { - for (y = cy - r - 1; y <= cy + r; y++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); - } - } - // -x - x = cx - r - 1; - for (z = cz - r - 1; z <= cz + r; z++) { - for (y = cy - r - 1; y <= cy + r; y++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); - } - } - // +z - z = cz + r; - for (x = cx - r - 1; x <= cz + r; x++) { - for (y = cy - r - 1; y <= cy + r; y++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); + for (distance = 0; distance <= Options.renderDistance / 16; distance++) { + if (distance > 0) { + int shortDistance = distance - 1; + renderLoc = new ChunkLocation(cameraChunk); + for (renderLoc.x = cameraChunk.x - distance; renderLoc.x <= cameraChunk.x + distance; renderLoc.x += distance * 2) { + // render ZY sides + for (renderLoc.y = cameraChunk.y - distance; renderLoc.y <= cameraChunk.y + distance; renderLoc.y++) { + for (renderLoc.z = cameraChunk.z - distance; renderLoc.z <= cameraChunk.z + distance; renderLoc.z++) { + skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew); + } + } } - } - // -z - z = cz - r - 1; - for (x = cx - r - 1; x <= cz + r; x++) { - for (y = cy - r - 1; y <= cy + r; y++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); + for (renderLoc.z = cameraChunk.z - distance; renderLoc.z <= cameraChunk.z + distance; renderLoc.z += distance * 2) { + // render XY sides + for (renderLoc.x = cameraChunk.x - shortDistance; renderLoc.x <= cameraChunk.x + shortDistance; renderLoc.x++) { + for (renderLoc.y = cameraChunk.y - distance; renderLoc.y <= cameraChunk.y + distance; renderLoc.y++) { + skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew); + } + } } - } - // +y - y = cy + r; - for (x = cx - r - 1; x <= cz + r; x++) { - for (z = cz - r - 1; z <= cz + r; z++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); + for (renderLoc.y = cameraChunk.y - distance; renderLoc.y <= cameraChunk.y + distance; renderLoc.y += distance * 2) { + // render XZ sides + for (renderLoc.x = cameraChunk.x - shortDistance; renderLoc.x <= cameraChunk.x + shortDistance; renderLoc.x++) { + for (renderLoc.z = cameraChunk.z - shortDistance; renderLoc.z <= cameraChunk.z + shortDistance; renderLoc.z++) { + skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew); + } + } } + } else { + renderLoc = new ChunkLocation(cameraChunk); + skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew); } - // -y - y = cy - r - 1; - for (x = cx - r - 1; x <= cz + r; x++) { - for (z = cz - r - 1; z <= cz + r; z++) { - cLoc = new ChunkLocation(x, y, z); - skipnew = renderChunk(cs.getChunk(cLoc), skipnew); - } - } - if (skipnew) { - // break; - } - // break; } - - // int dw = cs.getWidth() / 2; - // int dd = cs.getDepth() / 2; - // int dh = cs.getHeight() / 2; - // for (int dx = 0; dx < dw; dx++) { - // x = cs.getX() + dw + dx; - // for (int dz = 0; dz < dd; dz++) { - // z = cs.getZ() + dd + dz; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // z = cs.getZ() + dd - dz - 1; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // } - // x = cs.getX() + dw - dx - 1; - // for (int dz = 0; dz < dd; dz++) { - // z = cs.getZ() + dd + dz; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // int dd = cs.getDepth() / 2; - // int dh = cs.getHeight() / 2; - // for (int dx = 0; dx < dw; dx++) { - // x = cs.getX() + dw + dx; - // for (int dz = 0; dz < dd; dz++) { - // z = cs.getZ() + dd + dz; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // z = cs.getZ() + dd - dz - 1; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // } - // x = cs.getX() + dw - dx - 1; - // for (int dz = 0; dz < dd; dz++) { - // z = cs.getZ() + dd + dz; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // z = cs.getZ() + dd - dz - 1; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // } - // } - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // z = cs.getZ() + dd - dz - 1; - // for (int dy = 0; dy < dh; dy++) { - // y = cs.getY() + dh + dy; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // y = cs.getY() + dh - dy - 1; - // skipnew = renderChunk(cs.getChunk(x, y, z), skipnew); - // } - // } - // } - - // System.out.println("visible top " + visibleTop); } } diff --git a/src/ru/olamedia/olacraft/render/jogl/joglViewport.java b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java index b3da2ce..ef59352 100644 --- a/src/ru/olamedia/olacraft/render/jogl/joglViewport.java +++ b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java @@ -16,9 +16,11 @@ public class joglViewport { } public void drawText(String text, int x, int y) { - sans11.setColor(1, 1, 1, 0.7f); + sans11.setColor(0, 0, 0, 0.7f); sans11.beginRendering(drawable.getWidth(), drawable.getHeight()); - sans11.draw(text, x, y); + sans11.draw(text, x - 1, y - 1); + // sans11.setColor(1, 1, 1, 0.7f); + // sans11.draw(text, x, y); sans11.endRendering(); } } diff --git a/src/ru/olamedia/olacraft/scene/GameScene.java b/src/ru/olamedia/olacraft/scene/GameScene.java index 86b9574..e5655c9 100644 --- a/src/ru/olamedia/olacraft/scene/GameScene.java +++ b/src/ru/olamedia/olacraft/scene/GameScene.java @@ -11,8 +11,6 @@ import javax.media.opengl.glu.GLUquadric; import org.ode4j.ode.DBody; -import com.jogamp.opengl.util.PMVMatrix; - import ru.olamedia.Options; import ru.olamedia.game.GameTime; import ru.olamedia.liveEntity.LiveEntity; @@ -25,18 +23,19 @@ import ru.olamedia.olacraft.weapon.Bullet; import ru.olamedia.olacraft.weapon.BulletScene; import ru.olamedia.olacraft.world.block.Block; import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType; +import ru.olamedia.olacraft.world.blockTypes.DirtBlockType; import ru.olamedia.olacraft.world.blockTypes.GrassBlockType; +import ru.olamedia.olacraft.world.blockTypes.GravelBlockType; +import ru.olamedia.olacraft.world.blockTypes.StoneBlockType; import ru.olamedia.olacraft.world.chunk.BlockSlice; +import ru.olamedia.olacraft.world.chunk.Chunk; import ru.olamedia.olacraft.world.chunk.ChunkSlice; -import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException; +import ru.olamedia.olacraft.world.location.BlockLocation; import ru.olamedia.olacraft.world.provider.WorldProvider; import ru.olamedia.player.Player; -import ru.olamedia.vbo.VBO; public class GameScene { - private PMVMatrix matrix; - private HashMap<Integer, LiveEntity> liveEntities = new HashMap<Integer, LiveEntity>(); WorldProvider provider; private int renderDistance = Options.renderDistance; @@ -44,8 +43,6 @@ public class GameScene { private BulletScene bullets = new BulletScene(); private GamePhysicsWorld physics = new GamePhysicsWorld(); - private VBO testObject; - private boolean isInitialized = false; BlockSlice viewSlice; public GameTime time = new GameTime(); @@ -81,13 +78,18 @@ public class GameScene { time.init(); registerTextures(); viewport = new joglViewport(drawable); - testObject = new VBO(drawable); } private void registerTextures() { AbstractBlockType t; t = new GrassBlockType(); - t.register(); + t.register(provider); + t = new StoneBlockType(); + t.register(provider); + t = new DirtBlockType(); + t.register(provider); + t = new GravelBlockType(); + t.register(provider); } /** @@ -107,7 +109,7 @@ public class GameScene { blockRenderer = new ChunkRenderer(viewSlice); } - ChunkRenderer blockRenderer = new ChunkRenderer(viewSlice); + public ChunkRenderer blockRenderer = new ChunkRenderer(viewSlice); GLU glu = new GLU(); public void registerLiveEntity(LiveEntity entity) { @@ -136,7 +138,7 @@ public class GameScene { return liveEntities; } - Block nearestBlock = null; + public Block nearestBlock = null; public void tick() { time.tick(); @@ -146,12 +148,18 @@ public class GameScene { // bullets.update(Game.instance.getDelta()); physics.getWorld().step(Game.instance.getDelta()); BlockSlice pickSlice = new BlockSlice(provider, 10, 10, 10); - pickSlice.setCenter(player.getCameraX(), player.getCameraY(), player.getCameraZ()); - nearestBlock = pickSlice.getNearest(Game.instance.camera); + if (null != player) { + if (player.isOrientationChanged || Game.instance.camera.isOrientationChanged) { + player.isOrientationChanged = false; + Game.instance.camera.isOrientationChanged = false; + pickSlice.setCenter(player.getCameraX(), player.getCameraY(), player.getCameraZ()); + nearestBlock = pickSlice.getNearest(Game.instance.camera); + } + } } public void render(GLAutoDrawable drawable) { - if (!Game.instance.isRunning()) { + if (null == player || !Game.instance.isRunning()) { // not running, just clear screen GL2 gl = drawable.getGL().getGL2(); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); @@ -169,30 +177,33 @@ public class GameScene { gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); Game.instance.camera.setUp(drawable); // RENDER SUN - gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); - gl.glEnable(GL2.GL_BLEND); // Enable Blending - gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE); // Set Blending Mode To - // Mix Based On SRC - // Alpha - GLUquadric sun = glu.gluNewQuadric(); - glu.gluQuadricDrawStyle(sun, GLU.GLU_FILL); - glu.gluQuadricNormals(sun, GLU.GLU_SMOOTH); - gl.glPushMatrix(); - gl.glTranslatef(time.sun.getX() + player.getCameraX(), time.sun.getY(), time.sun.getZ() + player.getCameraZ()); - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); - gl.glColor4f(1, 1, 1, 0.02f); - glu.gluSphere(sun, 100f, 10, 10); - glu.gluSphere(sun, 90f, 10, 10); - glu.gluSphere(sun, 80f, 10, 10); - glu.gluSphere(sun, 70f, 10, 10); - glu.gluSphere(sun, 60f, 10, 10); - glu.gluSphere(sun, 50f, 10, 10); - glu.gluSphere(sun, 40f, 10, 10); - glu.gluSphere(sun, 35f, 10, 10); - gl.glColor4f(1, 1, 1, 1f); - glu.gluSphere(sun, 30f, 10, 10); - gl.glPopMatrix(); - gl.glPopAttrib(); + // gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); + // gl.glEnable(GL2.GL_BLEND); // Enable Blending + // gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE); // Set Blending Mode To + // // Mix Based On SRC + // // Alpha + // GLUquadric sun = glu.gluNewQuadric(); + // glu.gluQuadricDrawStyle(sun, GLU.GLU_FILL); + // glu.gluQuadricNormals(sun, GLU.GLU_SMOOTH); + // gl.glPushMatrix(); + // gl.glTranslatef(time.sun.getX() + player.getCameraX(), + // time.sun.getY(), time.sun.getZ() + player.getCameraZ()); + // gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); + // gl.glColor4f(1, 1, 1, 0.02f); + // gl.glColor4f((float) 251 / 255, (float) 255 / 255, (float) 228 / 255, + // 0.02f); + // glu.gluSphere(sun, 100f, 10, 10); + // glu.gluSphere(sun, 90f, 10, 10); + // glu.gluSphere(sun, 80f, 10, 10); + // glu.gluSphere(sun, 70f, 10, 10); + // glu.gluSphere(sun, 60f, 10, 10); + // glu.gluSphere(sun, 50f, 10, 10); + // glu.gluSphere(sun, 40f, 10, 10); + // glu.gluSphere(sun, 35f, 10, 10); + // gl.glColor4f(1, 1, 1, 1f); + // glu.gluSphere(sun, 30f, 10, 10); + // gl.glPopMatrix(); + // gl.glPopAttrib(); viewSlice.setCenter((int) Game.instance.camera.getX(), (int) Game.instance.camera.getY(), (int) Game.instance.camera.getZ()); @@ -212,7 +223,7 @@ public class GameScene { // gl.glFogf(GL2.GL_FOG_DENSITY, 0.002f); // new float[] { 49f / 255f, 119f / 255f, 243f / 255f } // gl.glFogfv(GL2.GL_FOG_COLOR, new float[] { 1, 1, 1, 0.2f }, 0); - blockRenderer.render(drawable); + blockRenderer.render(); gl.glPopAttrib(); // RENDER ANYTHING ELSE gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); @@ -227,6 +238,11 @@ public class GameScene { gl.glPopMatrix(); } gl.glPopAttrib(); + if (nearestBlock != null) { + gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); + nearestBlock.renderFrame(); + gl.glPopAttrib(); + } // bullets.render(drawable); gl.glPopMatrix(); @@ -273,35 +289,68 @@ public class GameScene { // inventoryRenderer.render(drawable); } - viewport.drawText("avg fps: " + (int) Game.timer.getAvgFps(), 10, height - 20); - viewport.drawText("fps: " + (int) Game.timer.getFps(), 10, height - 35); + viewport.drawText("rad: " + Options.renderDistance, 10, height - 20); + viewport.drawText("avg fps: " + (int) Game.timer.getAvgFps(), 10, height - 35); + viewport.drawText("fps: " + (int) Game.timer.getFps(), 10, height - 50); MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); viewport.drawText("mem: " + (heap.getUsed() / (1024 * 1024)) + "/" + (heap.getMax() / (1024 * 1024)), 10, - height - 50); - - viewport.drawText("y: " + Game.instance.player.getY(), width - msz - 10, height - msz - 20); - viewport.drawText("y: " + Game.instance.player.getCameraY() + " (cam)", width - msz - 10, height - msz - 30); - viewport.drawText("x: " + Game.instance.player.getX(), width - msz - 10, height - msz - 40); - viewport.drawText("z: " + Game.instance.player.getZ(), width - msz - 10, height - msz - 50); - viewport.drawText("players: " + liveEntities.size(), width - msz - 10, height - msz - 70); - viewport.drawText("bullets: " + getBulletsCount(), width - msz - 10, height - msz - 95); - viewport.drawText("y velocity: " + player.velocity.y + " y accel: " + player.acceleration.y + " inJump: " - + player.inJump + " onGround: " + player.onGround, width - msz - 350 - 10, height - msz - 110); - viewport.drawText("rdistance: " + renderDistance, width - msz - 10, height - msz - 155); - - ChunkSlice cs = viewSlice.getChunkSlice(); - viewport.drawText("slice x: " + cs.getX() + ".." + (cs.getX() + cs.getWidth() - 1) + " y: " + cs.getY() + ".." - + (cs.getY() + cs.getHeight() - 1) + " z: " + cs.getZ() + ".." + (cs.getZ() + cs.getDepth() - 1), width - - msz * 2 - 10, height - msz - 170); - viewport.drawText("time: " + time.getDateTimeString(), width - msz * 2 - 10, height - msz - 185); - if (nearestBlock != null) { - viewport.drawText("block: " + nearestBlock.getX() + ":" + nearestBlock.getY() + ":" + nearestBlock.getZ() - + " d " + nearestBlock.getDistance(Game.instance.camera), width - msz * 2 - 10, height - msz - 200); - } + height - 65); + // + // viewport.drawText("y: " + Game.instance.player.getY(), width - msz - + // 10, height - msz - 20); + // viewport.drawText("y: " + Game.instance.player.getCameraY() + + // " (cam)", width - msz - 10, height - msz - 30); + // viewport.drawText("x: " + Game.instance.player.getX(), width - msz - + // 10, height - msz - 40); + // viewport.drawText("z: " + Game.instance.player.getZ(), width - msz - + // 10, height - msz - 50); + // viewport.drawText("players: " + liveEntities.size(), width - msz - + // 10, height - msz - 70); + // viewport.drawText("bullets: " + getBulletsCount(), width - msz - 10, + // height - msz - 95); + // viewport.drawText("y velocity: " + player.velocity.y + " y accel: " + + // player.acceleration.y + " inJump: " + // + player.inJump + " onGround: " + player.onGround, width - msz - 350 + // - 10, height - msz - 110); + // viewport.drawText("rdistance: " + Options.renderDistance, width - msz + // - 10, height - msz - 155); + + // ChunkSlice cs = viewSlice.getChunkSlice(); + // viewport.drawText("slice x: " + cs.getX() + ".." + (cs.getX() + + // cs.getWidth() - 1) + " y: " + cs.getY() + ".." + // + (cs.getY() + cs.getHeight() - 1) + " z: " + cs.getZ() + ".." + + // (cs.getZ() + cs.getDepth() - 1), width + // - msz * 2 - 10, height - msz - 170); + // viewport.drawText("time: " + time.getDateTimeString(), width - msz * + // 2 - 10, height - msz - 185); + // if (nearestBlock != null) { + // viewport.drawText("pick: " + nearestBlock.getX() + "," + + // nearestBlock.getY() + "," + nearestBlock.getZ() + // + " d " + nearestBlock.getDistance(Game.instance.camera), width - msz + // * 2 - 10, height - msz - 200); + // viewport.drawText( + // "edge: " + nearestBlock.location.isChunkEdge() + " left " + + // nearestBlock.location.isChunkLeftEdge(), + // width - msz * 2 - 10, height - msz - 210); + // } + + // BlockLocation camloc = player.getCameraBlockLocation(); + // viewport.drawText("cam chunk: " + camloc.getChunkLocation(), width - + // 200 - msz * 2 - 10, height - msz - 225); + // Chunk camc = + // viewSlice.getChunkSlice().getChunk(camloc.getChunkLocation()); + // viewport.drawText("cam chunk: " + camc.isMeshCostructed + " mesh: " + + // camc.mesh, width - 200 - msz * 2 - 10, + // height - msz - 235); + // viewport.drawText( + // "chunk available: " + camc.isAvailable() + " chunk empty: " + // + (camc.isAvailable() ? camc.isEmpty() : "unknown"), width - 200 - + // msz * 2 - 10, height - msz + // - 245); gl.glPopAttrib(); gl.glPopMatrix(); - gl.glFlush(); + // gl.glFlush(); } public Player getPlayer() { 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); + } } |