Browse Source

framerate limited to 60 (or any value), block rendering, test blocks

Kajetan Johannes Hammerle 5 years ago
parent
commit
4e6ccad27d

+ 9 - 2
Makefile

@@ -5,7 +5,8 @@ LDFLAGS = $(shell pkg-config --static --libs glfw3) -lGL -lGLEW -lpng
 all: run_client
 
 run_client: game_client
-	vblank_mode=0 optirun ./game_client
+	#vblank_mode=0 optirun ./game_client
+	optirun ./game_client
 	
 game_client: MainClient.cpp\
 	Clock.o DirectRenderer.o KeyManager.o Mesh.o MouseManager.o Shader.o\
@@ -15,7 +16,7 @@ game_client: MainClient.cpp\
 	Client.o\
 	Block.o Blocks.o BlockAir.o\
 	Face.o\
-	Chunk.o World.o ChunkRenderer.o ClientChunkProvider.o
+	Chunk.o World.o ChunkRenderer.o ClientChunkProvider.o BlockRenderer.o BlockRenderers.o
 	g++ $(VERSION) -o $@ MainClient.cpp *.o $(LDFLAGS)
 
 # ------------------------------------------------------------------------------	
@@ -82,6 +83,12 @@ ChunkRenderer.o: client/rendering/ChunkRenderer.h client/rendering/ChunkRenderer
 	
 ClientChunkProvider.o: client/rendering/ClientChunkProvider.h client/rendering/ClientChunkProvider.cpp world/IChunkProvider.h
 	g++ $(VERSION) -c client/rendering/ClientChunkProvider.cpp -o $@
+	
+BlockRenderer.o: client/rendering/block/BlockRenderer.h client/rendering/block/BlockRenderer.cpp
+	g++ $(VERSION) -c client/rendering/block/BlockRenderer.cpp -o $@
+	
+BlockRenderers.o: client/rendering/block/BlockRenderers.h client/rendering/block/BlockRenderers.cpp
+	g++ $(VERSION) -c client/rendering/block/BlockRenderers.cpp -o $@
 
 # ------------------------------------------------------------------------------	
 # Utils

+ 5 - 1
block/Blocks.cpp

@@ -1,10 +1,12 @@
 #include "Blocks.h"
 
-const int BlockRegistry::BLOCK_AMOUNT = 2;
+const int BlockRegistry::BLOCK_AMOUNT = 4;
 const Block* BlockRegistry::BLOCKS[BLOCK_AMOUNT];
 
 const BlockAir Blocks::AIR;
 const Block Blocks::GRASS;
+const Block Blocks::DIRT;
+const Block Blocks::STONE;
 
 BlockRegistry::BlockRegistry()
 {
@@ -38,5 +40,7 @@ void BlockRegistry::registerBlocks()
     
     registerBlock(Blocks::AIR);
     registerBlock(Blocks::GRASS);
+    registerBlock(Blocks::DIRT);
+    registerBlock(Blocks::STONE);
 }
 

+ 2 - 0
block/Blocks.h

@@ -23,6 +23,8 @@ namespace Blocks
 {
     extern const BlockAir AIR;
     extern const Block GRASS;
+    extern const Block DIRT;
+    extern const Block STONE;
 };
 
 #endif

+ 6 - 8
client/Client.cpp

@@ -1,17 +1,14 @@
 #include "Client.h"
 #include <iostream>
 #include "../block/Blocks.h"
+#include "../client/rendering/block/BlockRenderers.h"
 
 using namespace std;
 
 Client::Client() : world(&chunkProvider)
 {    
     BlockRegistry::registerBlocks();
-    
-    cout << "HI" << endl;
-    //cout << (Blocks::AIR.getId() == Blocks::AIR.getId()) << endl;
-    cout << Blocks::AIR.getId() << endl;
-    //cout << Blocks::GRASS.getId() << endl;
+    BlockRenderers::init();
 
     position.set(16, 50, -5);
     lengthAngle = -15;
@@ -104,9 +101,8 @@ void Client::render3DTick(float lag)
     
     camera.update(lag);
     Engine::setWorldViewMatrix(camera.getViewMatrix());
-    
     shader.setToIdentity();
-    Engine::setWorldModelMatrix(shader.getModelMatrix());
+    Engine::setWorldModelMatrix(shader.getModelMatrix());    
     chunkRenderer.renderTick(shader, camera, directRenderer, lag);
 }
 
@@ -117,7 +113,9 @@ void Client::render2DTick(float lag)
     
     string wusi;
     wusi = "FPS: " + to_string(fps.getUpdatesPerSecond());
-    directRenderer.drawString(10, 10, true, wusi);
+    float y = directRenderer.drawString(10, 10, true, wusi);
+    wusi = "TPS: " + to_string(tps.getUpdatesPerSecond());
+    directRenderer.drawString(10, y, true, wusi);
 }
 
 void Client::onKeyEvent(int key, int scancode, int action, int mods)

+ 24 - 173
client/rendering/ChunkRenderer.cpp

@@ -1,7 +1,9 @@
 #include "ChunkRenderer.h"
 #include "../../engine/Wrapper.h"
+#include "block/BlockRenderers.h"
+#include "block/BlockRenderer.h"
 
-ChunkRenderer::ChunkRenderer()
+ChunkRenderer::ChunkRenderer() : blockTexture("resources/textures.png")
 {
     mesh = new ChunkMesh[chunkX * chunkZ * Chunk::HEIGHT_PARTIONS];
 }
@@ -13,6 +15,7 @@ ChunkRenderer::~ChunkRenderer()
 
 void ChunkRenderer::renderTick(Shader& shader, Camera3D camera, DirectRenderer& dr, float lag)
 {
+    blockTexture.bind();
     //int frustumCull1 = 0;
     //int frustumCull2 = 0;
     for(int x = 0; x < chunkX; x++)
@@ -79,179 +82,27 @@ void ChunkRenderer::buildChunk(int partionY, Chunk& c, Chunk* north, Chunk* east
         {
             for(int z = 0; z < Chunk::DEPTH; z++)
             {
-                if(!c.getBlock(x, y, z).isEmpty())
+                const Block& block = c.getBlock(x, y, z);
+                if(!block.isEmpty())
                 {
-                    // bottom
-                    if(y <= 0 || !c.getBlock(x, y - 1, z).isBlockingFace(Face::UP))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-
-                        //m.addTexture(0.125f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0f);
-                        //m.addTexture(0.125f, 0.0625f);
-                        //m.addTexture(0.1875f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.125f, 0.0625f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(0.0f, -1.0f, 0.0f);
-                        }
-
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
-                    }
-
-                    // top
-                    if(y + 1 >= Chunk::HEIGHT || !c.getBlock(x, y + 1, z).isBlockingFace(Face::DOWN))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-                        
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.3125f, 0.0f);
-                        //m.addTexture(0.3125f, 0.0f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.3125f, 0.0625f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(0.0f, 1.0f, 0.0f);
-                        }
-
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 1.0f);
-                    }
-                    
-                    // right
-                    if((x + 1 < Chunk::WIDTH && !c.getBlock(x + 1, y, z).isBlockingFace(Face::SOUTH)) ||
-                        (x + 1 >= Chunk::WIDTH && (north == nullptr || !north->getBlock(x + 1 - Chunk::WIDTH, y, z).isBlockingFace(Face::SOUTH))))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-                        
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.1875f, 0.0f);
-                        //m.addTexture(0.25f, 0.0f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(1.0f, 0.0f, 0.0f);
-                        }
-
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 1.0f);
-                    }
-                     
-                    // left
-                    if((x - 1 >= 0 && !c.getBlock(x - 1, y, z).isBlockingFace(Face::NORTH)) ||
-                        (x - 1 < 0 && (south == nullptr || !south->getBlock(x - 1 + Chunk::WIDTH, y, z).isBlockingFace(Face::NORTH))))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-                        
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(-1.0f, 0.0f, 0.0f);
-                        }
-
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 0.0f);
-                    }
-
-                    // back
-                    if((z + 1 < Chunk::DEPTH && !c.getBlock(x, y, z + 1).isBlockingFace(Face::WEST)) ||
-                        (z + 1 >= Chunk::DEPTH && (east == nullptr || !east->getBlock(x, y, z + 1 - Chunk::DEPTH).isBlockingFace(Face::WEST))))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-                        
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.1875f, 0.0f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(0.0f, 0.0f, 1.0f);
-                        }
-
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 1.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 1.0f);
-                    }
-
-                    // front
-                    if((z - 1 >= 0 && !c.getBlock(x, y, z - 1).isBlockingFace(Face::EAST)) ||
-                        (z - 1 < 0 && (west == nullptr || !west->getBlock(x, y, z - 1 + Chunk::DEPTH).isBlockingFace(Face::EAST))))
-                    {
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addColor(1, 0, 0, 1);
-                        }
-                        
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.25f, 0.0f);
-                        //m.addTexture(0.25f, 0.0625f);
-                        //m.addTexture(0.1875f, 0.0625f);
-                        //m.addTexture(0.1875f, 0.0f);
-                        //m.addTexture(0.25f, 0.0f);
-
-                        for(int i = 0; i < 6; i++)
-                        {
-                            m.addNormal(0.0f, 0.0f, -1.0f);
-                        }
-
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);
-                        m.addPosition(x + 0.0f, y + 1.0f, z + 0.0f);
-                        m.addPosition(x + 1.0f, y + 1.0f, z + 0.0f);
-                    }
+                    BlockRenderers::getBlockRenderer(block.getId()).addToMesh(m, x, y, z,
+                        Face::getCullData(
+                            // top
+                            y + 1 < Chunk::HEIGHT && c.getBlock(x, y + 1, z).isBlockingFace(Face::DOWN), 
+                            // bottom
+                            y > 0 && c.getBlock(x, y - 1, z).isBlockingFace(Face::UP), 
+                            // north
+                            (x + 1 >= Chunk::WIDTH || c.getBlock(x + 1, y, z).isBlockingFace(Face::SOUTH)) && 
+                            (x + 1 < Chunk::WIDTH || (north != nullptr && north->getBlock(x + 1 - Chunk::WIDTH, y, z).isBlockingFace(Face::SOUTH))), 
+                            // south
+                            (x - 1 < 0 || c.getBlock(x - 1, y, z).isBlockingFace(Face::NORTH)) && 
+                            (x - 1 >= 0 || (south != nullptr && south->getBlock(x - 1 + Chunk::WIDTH, y, z).isBlockingFace(Face::NORTH))), 
+                            // east
+                            (z + 1 >= Chunk::DEPTH || c.getBlock(x, y, z + 1).isBlockingFace(Face::WEST)) && 
+                            (z + 1 < Chunk::DEPTH || (east != nullptr && east->getBlock(x, y, z + 1 - Chunk::DEPTH).isBlockingFace(Face::WEST))), 
+                            // west
+                            (z - 1 < 0 || c.getBlock(x, y, z - 1).isBlockingFace(Face::EAST)) && 
+                            (z - 1 >= 0 || (west != nullptr && west->getBlock(x, y, z - 1 + Chunk::DEPTH).isBlockingFace(Face::EAST)))));
                 }
             }
         }

+ 3 - 0
client/rendering/ChunkRenderer.h

@@ -3,6 +3,7 @@
 
 #include "../../engine/Mesh.h"
 #include "../../engine/Shader.h"
+#include "../../engine/Texture.h"
 #include "../../engine/DirectRenderer.h"
 #include "../../world/IChunkListener.h"
 #include "../../math/Camera3D.h"
@@ -21,6 +22,8 @@ private:
     const int chunkX = 2;
     const int chunkZ = 2;
     ChunkMesh* mesh;
+    
+    Texture blockTexture;
 };
 
 #endif

+ 153 - 0
client/rendering/block/BlockRenderer.cpp

@@ -0,0 +1,153 @@
+#include "BlockRenderer.h"
+#include "../../../utils/Face.h"
+
+BlockRenderer::BlockRenderer()
+{
+}
+
+void BlockRenderer::addTriangle(float p1x, float p1y, float p1z, float p1nx, float p1ny, float p1nz, float p1texX, float p1texY, 
+                                float p2x, float p2y, float p2z, float p2nx, float p2ny, float p2nz, float p2texX, float p2texY, 
+                                float p3x, float p3y, float p3z, float p3nx, float p3ny, float p3nz, float p3texX, float p3texY, 
+                                int cullData)
+{
+    data.push_back(Triangle());
+    Triangle& tri = data[data.size() - 1];
+    
+    tri.p1x = p1x;
+    tri.p1y = p1y;
+    tri.p1z = p1z;
+    
+    tri.p1nx = p1nx;
+    tri.p1ny = p1ny;
+    tri.p1nz = p1nz;
+    
+    tri.p1texX = p1texX;
+    tri.p1texY = p1texY;
+    
+    tri.p2x = p2x;
+    tri.p2y = p2y;
+    tri.p2z = p2z;
+    
+    tri.p2nx = p2nx;
+    tri.p2ny = p2ny;
+    tri.p2nz = p2nz;
+    
+    tri.p2texX = p2texX;
+    tri.p2texY = p2texY;
+    
+    tri.p3x = p3x;
+    tri.p3y = p3y;
+    tri.p3z = p3z;
+    
+    tri.p3nx = p3nx;
+    tri.p3ny = p3ny;
+    tri.p3nz = p3nz;
+    
+    tri.p3texX = p3texX;
+    tri.p3texY = p3texY;
+    
+    tri.cullData = cullData;
+}
+    
+void BlockRenderer::addCuboid(float sx, float sy, float sz, float ex, float ey, float ez,
+               float topTexStartX, float topTexStartY, float topTexEndX, float topTexEndY, 
+               float bottomTexStartX, float bottomTexStartY, float bottomTexEndX, float bottomTexEndY, 
+               float northTexStartX, float northTexStartY, float northTexEndX, float northTexEndY, 
+               float southTexStartX, float southTexStartY, float southTexEndX, float southTexEndY, 
+               float eastTexStartX, float eastTexStartY, float eastTexEndX, float eastTexEndY, 
+               float westTexStartX, float westTexStartY, float westTexEndX, float westTexEndY)
+{
+    // bottom side
+    addTriangle(
+            sx, sy, sz, 0.0f, -1.0f, 0.0f, bottomTexStartX, bottomTexStartY,
+            ex, sy, sz, 0.0f, -1.0f, 0.0f, bottomTexEndX, bottomTexStartY,
+            sx, sy, ez, 0.0f, -1.0f, 0.0f, bottomTexStartX, bottomTexEndY,
+            Face::DOWN.getCullData());
+    addTriangle(
+            ex, sy, sz, 0.0f, -1.0f, 0.0f, bottomTexEndX, bottomTexStartY,
+            ex, sy, ez, 0.0f, -1.0f, 0.0f, bottomTexEndX, bottomTexEndY,
+            sx, sy, ez, 0.0f, -1.0f, 0.0f, bottomTexStartX, bottomTexEndY,
+            Face::DOWN.getCullData());
+    
+    // top side
+    addTriangle(
+            sx, ey, sz, 0.0f, 1.0f, 0.0f, topTexStartX, topTexStartY,
+            sx, ey, ez, 0.0f, 1.0f, 0.0f, topTexStartX, topTexEndY,
+            ex, ey, sz, 0.0f, 1.0f, 0.0f, topTexEndX, topTexStartY,
+            Face::UP.getCullData());
+    addTriangle(
+            ex, ey, sz, 0.0f, 1.0f, 0.0f, topTexEndX, topTexStartY,
+            sx, ey, ez, 0.0f, 1.0f, 0.0f, topTexStartX, topTexEndY,
+            ex, ey, ez, 0.0f, 1.0f, 0.0f, topTexEndX, topTexEndY,
+            Face::UP.getCullData());
+    
+    // north side
+    addTriangle(
+            ex, sy, sz, 1.0f, 0.0f, 0.0f, northTexStartX, northTexEndY,
+            ex, ey, ez, 1.0f, 0.0f, 0.0f, northTexEndX, northTexStartY,
+            ex, sy, ez, 1.0f, 0.0f, 0.0f, northTexEndX, northTexEndY,
+            Face::NORTH.getCullData());
+    addTriangle(
+            ex, sy, sz, 1.0f, 0.0f, 0.0f, northTexStartX, northTexEndY,
+            ex, ey, sz, 1.0f, 0.0f, 0.0f, northTexStartX, northTexStartY,
+            ex, ey, ez, 1.0f, 0.0f, 0.0f, northTexEndX, northTexStartY,
+            Face::NORTH.getCullData());
+    
+    // south side
+    addTriangle(
+            sx, sy, sz, -1.0f, 0.0f, 0.0f, southTexStartX, southTexEndY,
+            sx, sy, ez, -1.0f, 0.0f, 0.0f, southTexEndX, southTexEndY,
+            sx, ey, ez, -1.0f, 0.0f, 0.0f, southTexEndX, southTexStartY,
+            Face::SOUTH.getCullData());
+    addTriangle(
+            sx, sy, sz, -1.0f, 0.0f, 0.0f, southTexStartX, southTexEndY,
+            sx, ey, ez, -1.0f, 0.0f, 0.0f, southTexEndX, southTexStartY,
+            sx, ey, sz, -1.0f, 0.0f, 0.0f, southTexStartX, southTexStartY,
+            Face::SOUTH.getCullData());
+    
+    // east side
+    addTriangle(
+            sx, sy, ez, 0.0f, 0.0f, 1.0f, eastTexStartX, eastTexEndY,
+            ex, sy, ez, 0.0f, 0.0f, 1.0f, eastTexEndX, eastTexEndY,
+            ex, ey, ez, 0.0f, 0.0f, 1.0f, eastTexEndX, eastTexStartY,
+            Face::EAST.getCullData());
+    addTriangle(
+            sx, sy, ez, 0.0f, 0.0f, 1.0f, eastTexStartX, eastTexEndY,
+            ex, ey, ez, 0.0f, 0.0f, 1.0f, eastTexEndX, eastTexStartY,
+            sx, ey, ez, 0.0f, 0.0f, 1.0f, eastTexStartX, eastTexStartY,
+            Face::EAST.getCullData());
+    
+    // west side
+    addTriangle(
+            sx, sy, sz, 0.0f, 0.0f, -1.0f, westTexStartX, westTexEndY,
+            ex, ey, sz, 0.0f, 0.0f, -1.0f, westTexEndX, westTexStartY,
+            ex, sy, sz, 0.0f, 0.0f, -1.0f, westTexEndX, westTexEndY,
+            Face::WEST.getCullData());
+    addTriangle(
+            sx, sy, sz, 0.0f, 0.0f, -1.0f, westTexStartX, westTexEndY,
+            sx, ey, sz, 0.0f, 0.0f, -1.0f, westTexStartX, westTexStartY,
+            ex, ey, sz, 0.0f, 0.0f, -1.0f, westTexEndX, westTexStartY,
+            Face::WEST.getCullData());
+}
+
+void BlockRenderer::addToMesh(Mesh& m, int offsetX, int offsetY, int offsetZ, int cullData) const
+{
+    for(const Triangle& tri : data)
+    {
+        // if any cull bits of a block are the same as of a triangle => do not render
+        if((cullData & tri.cullData) == 0)
+        {
+            m.addPosition(offsetX + tri.p1x, offsetY + tri.p1y, offsetZ + tri.p1z);
+            m.addPosition(offsetX + tri.p2x, offsetY + tri.p2y, offsetZ + tri.p2z);
+            m.addPosition(offsetX + tri.p3x, offsetY + tri.p3y, offsetZ + tri.p3z);
+            
+            m.addNormal(tri.p1nx, tri.p1ny, tri.p1nz);
+            m.addNormal(tri.p2nx, tri.p2ny, tri.p2nz);
+            m.addNormal(tri.p3nx, tri.p3ny, tri.p3nz);
+            
+            m.addTexture(tri.p1texX, tri.p1texY);
+            m.addTexture(tri.p2texX, tri.p2texY);
+            m.addTexture(tri.p3texX, tri.p3texY);
+        }
+    }
+}

+ 72 - 0
client/rendering/block/BlockRenderer.h

@@ -0,0 +1,72 @@
+#ifndef BLOCKRENDERER_H
+#define BLOCKRENDERER_H
+
+#include <vector>
+#include "../../../engine/Mesh.h"
+
+using namespace std;
+
+class BlockRenderer
+{
+public:
+    BlockRenderer();
+    
+    void addTriangle(float p1x, float p1y, float p1z, float p1nx, float p1ny, float p1nz, float p1texX, float p1texY, 
+                     float p2x, float p2y, float p2z, float p2nx, float p2ny, float p2nz, float p2texX, float p2texY, 
+                     float p3x, float p3y, float p3z, float p3nx, float p3ny, float p3nz, float p3texX, float p3texY, 
+                     int cullData);
+    
+    void addCuboid(float sx, float sy, float sz, float ex, float ey, float ez,
+                   float topTexStartX, float topTexStartY, float topTexEndX, float topTexEndY, 
+                   float bottomTexStartX, float bottomTexStartY, float bottomTexEndX, float bottomTexEndY, 
+                   float northTexStartX, float northTexStartY, float northTexEndX, float northTexEndY, 
+                   float southTexStartX, float southTexStartY, float southTexEndX, float southTexEndY, 
+                   float eastTexStartX, float eastTexStartY, float eastTexEndX, float eastTexEndY, 
+                   float westTexStartX, float westTexStartY, float westTexEndX, float westTexEndY);
+    
+    void addToMesh(Mesh& m, int offsetX, int offsetY, int offsetZ, int cullData) const;
+    
+private:
+    struct Triangle
+    {
+        float p1x;
+        float p1y;
+        float p1z;
+        
+        float p1nx;
+        float p1ny;
+        float p1nz;
+        
+        float p1texX;
+        float p1texY;
+        
+        float p2x;
+        float p2y;
+        float p2z;
+        
+        float p2nx;
+        float p2ny;
+        float p2nz;
+        
+        float p2texX;
+        float p2texY;
+        
+        float p3x;
+        float p3y;
+        float p3z;
+        
+        float p3nx;
+        float p3ny;
+        float p3nz;
+        
+        float p3texX;
+        float p3texY;
+        
+        int cullData;
+    };
+    
+    vector<Triangle> data;
+};
+
+#endif
+

+ 41 - 0
client/rendering/block/BlockRenderers.cpp

@@ -0,0 +1,41 @@
+#include "BlockRenderers.h"
+
+const int BlockRenderers::RENDERER_AMOUNT = 4;
+BlockRenderer BlockRenderers::RENDERER[RENDERER_AMOUNT];
+
+BlockRenderers::BlockRenderers()
+{
+}
+
+const BlockRenderer& BlockRenderers::getBlockRenderer(BlockId id)
+{
+    return RENDERER[id * (id >= 0 && id < RENDERER_AMOUNT)];
+}
+
+void BlockRenderers::init()
+{
+    RENDERER[1].addCuboid(-1, -1, -1, 0, 0, 0, 
+            0.25f, 0.0f, 0.3125f, 0.0625f, 
+            0.125f, 0.0f, 0.1875f, 0.0625f, 
+            0.1875f, 0.0f, 0.25f, 0.0625f, 
+            0.1875f, 0.0f, 0.25f, 0.0625f,
+            0.1875f, 0.0f, 0.25f, 0.0625f, 
+            0.1875f, 0.0f, 0.25f, 0.0625f);
+    
+    RENDERER[2].addCuboid(-1, -1, -1, 0, 0, 0, 
+            0.125f, 0.0f, 0.1875f, 0.0625f,
+            0.125f, 0.0f, 0.1875f, 0.0625f, 
+            0.125f, 0.0f, 0.1875f, 0.0625f, 
+            0.125f, 0.0f, 0.1875f, 0.0625f,
+            0.125f, 0.0f, 0.1875f, 0.0625f, 
+            0.125f, 0.0f, 0.1875f, 0.0625f);
+    
+    RENDERER[3].addCuboid(-1, -1, -1, 0, 0, 0, 
+            0.0625f, 0.0f, 0.125f, 0.0625f,
+            0.0625f, 0.0f, 0.125f, 0.0625f, 
+            0.0625f, 0.0f, 0.125f, 0.0625f, 
+            0.0625f, 0.0f, 0.125f, 0.0625f,
+            0.0625f, 0.0f, 0.125f, 0.0625f, 
+            0.0625f, 0.0f, 0.125f, 0.0625f);
+}
+

+ 21 - 0
client/rendering/block/BlockRenderers.h

@@ -0,0 +1,21 @@
+#ifndef BLOCKRENDERERS_H
+#define BLOCKRENDERERS_H
+
+#include "../../../block/Block.h"
+#include "BlockRenderer.h"
+
+class BlockRenderers
+{
+public:
+    static const BlockRenderer& getBlockRenderer(BlockId id);
+    static void init();
+
+private:
+    BlockRenderers();
+    
+    static const int RENDERER_AMOUNT;
+    static BlockRenderer RENDERER[];
+};
+
+#endif
+

+ 1 - 1
engine/Clock.h

@@ -13,7 +13,7 @@ public:
     void update();
     double getUpdatesPerSecond() const;
 private:
-    static const int SIZE = 256;
+    static const int SIZE = 64;
     uint64_t oldTime = 0;
     uint64_t time[SIZE];
     uint64_t sum = 0;

+ 1 - 1
engine/Mesh.h

@@ -48,7 +48,7 @@ private:
 class ChunkMesh : public Mesh
 {
 public:
-    ChunkMesh() : Mesh(Mesh::COLOR | Mesh::NORMAL) {};
+    ChunkMesh() : Mesh(Mesh::TEXTURE | Mesh::NORMAL) {};
 };
 
 #endif

+ 64 - 19
engine/Wrapper.cpp

@@ -1,5 +1,7 @@
 #include "Wrapper.h"
 #include <cmath>
+#include <chrono>
+#include <thread>
 
 DummyClient DummyClient::dummy;
 
@@ -46,6 +48,11 @@ bool Engine::init(int width, int height, const char* name)
     glfwDefaultWindowHints();
     glfwWindowHint(GLFW_VISIBLE, 0);
     glfwWindowHint(GLFW_RESIZABLE, 1);
+    
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+    
     window = glfwCreateWindow(width, height, name, nullptr, nullptr);
     if(!window)
     {
@@ -82,6 +89,22 @@ bool Engine::init(int width, int height, const char* name)
     return true;
 }
 
+void Engine::sleep(uint64_t nanos)
+{
+    uint64_t end = glfwGetTimerValue() + nanos - 10000;
+    // non busy wait until a close range
+    while(end > glfwGetTimerValue() + 1000000)
+    {
+        this_thread::sleep_for(chrono::nanoseconds(1000000));
+    }
+    while(end > glfwGetTimerValue() + 100000)
+    {
+        this_thread::sleep_for(chrono::nanoseconds(100000));
+    }
+    // busy wait for higher accuracy at the end
+    while(end > glfwGetTimerValue());
+}
+
 void Engine::start(IClient* client)
 {
     if(client != nullptr)
@@ -95,36 +118,59 @@ void Engine::start(IClient* client)
     uint64_t newTime = glfwGetTimerValue();
     uint64_t oldTime = newTime;
     uint64_t lag = 0;
+    uint64_t frameLag = 0;
+    uint64_t lastFrame = 0;
+    
     while(!glfwWindowShouldClose(window))
     {
         oldTime = newTime;
         newTime = glfwGetTimerValue();
         lag += newTime - oldTime;
-
-        int ticksPerFrame = 0;
-        while(lag >= NANOS_PER_TICK)
+        frameLag += newTime - oldTime;
+        
+        if(lag >= NANOS_PER_TICK || frameLag >= NANOS_PER_FRAME)
         {
-            lag -= NANOS_PER_TICK;
+            int ticksPerFrame = 0;
+            while(lag >= NANOS_PER_TICK)
+            {
+                lag -= NANOS_PER_TICK;
+
+                Engine::client->tick();           
+                ticksPerFrame++;
 
-            Engine::client->tick();
-            ticksPerFrame++;
+                if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
+                {
+                    long skip = lag / NANOS_PER_TICK;
+                    lag -= skip * NANOS_PER_TICK;
+                    if(skip > 0)
+                    {
+                        cout << "skipped " << skip << " game ticks " << lag << endl;
+                    }
+                    break;
+                }
+            }
 
-            if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
+            if(frameLag >= NANOS_PER_FRAME)
             {
-                long skip = lag / NANOS_PER_TICK;
-                lag -= skip * NANOS_PER_TICK;
-                if(skip > 0)
+                frameLag -= NANOS_PER_FRAME;
+                // make sure no frames are rendered immediately after each other
+                // this happens if the game tick takes too long
+                if(lastFrame + NANOS_PER_FRAME - 1000000 < glfwGetTimerValue())
                 {
-                    cout << "skipped " << skip << " game ticks " << lag << endl;
+                    lastFrame = glfwGetTimerValue();
+                    onRenderTick((float) lag / NANOS_PER_TICK);
+                    glfwSwapBuffers(window);
                 }
-                break;
             }
-        }
 
-        onRenderTick((float) lag / NANOS_PER_TICK);
-        
-        glfwSwapBuffers(window);
-        glfwPollEvents();
+            glfwPollEvents();
+        }
+        else
+        {
+            // wait until next frame
+            long waitingTime = min(NANOS_PER_FRAME - frameLag, NANOS_PER_TICK - lag);
+            sleep(waitingTime);
+        }
     }
     
     glfwDestroyWindow(window);
@@ -312,5 +358,4 @@ void Engine::setWorldModelMatrix(const float* data)
 void Engine::setOverlayModelMatrix(const float* data)
 {
     overlayShader.setModelMatrix(data);
-}
-// 562
+}

+ 3 - 1
engine/Wrapper.h

@@ -63,9 +63,11 @@ public:
     static void setOverlayModelMatrix(const float* data);
 
 private:
+    static const uint64_t NANOS_PER_FRAME = 1000000000 / 60;
     static const uint64_t NANOS_PER_TICK = 50000000;
-    static const int MAX_TICKS_PER_FRAME = 5;
+    static const int MAX_TICKS_PER_FRAME = 1;
     
+    static void sleep(uint64_t nanos);
     static bool initOverlayShader();   
     
     static void onRenderTick(float lag);

+ 3 - 1
shader/worldFragment.fs

@@ -19,5 +19,7 @@ void main(void)
 {
     worldPosition = varPosition;
     worldNormal = normalize(varNormal);
-    worldColor = varColor; //texture(samp, varTextureCoord);
+    //worldColor = vec4(1, 0, 0, 1);
+    worldColor = texture(samp, varTextureCoord);
+    //worldColor = varColor;
 }

+ 18 - 8
utils/Face.cpp

@@ -2,12 +2,12 @@
 
 Face Face::FACES[6] =
 {
-    Face(0,  0,  1,  0, "Up"),
-    Face(1,  1,  0,  0, "North"),
-    Face(2,  0,  0,  1, "East"),
-    Face(3,  0, -1,  0, "Down"),
-    Face(4, -1,  0,  0, "South"),
-    Face(5,  0,  0, -1, "West")
+    Face(0,  0,  1,  0,  1, "Up"),
+    Face(1,  1,  0,  0,  2, "North"),
+    Face(2,  0,  0,  1,  4, "East"),
+    Face(3,  0, -1,  0,  8, "Down"),
+    Face(4, -1,  0,  0, 16, "South"),
+    Face(5,  0,  0, -1, 32, "West")
 };
 
 Face& Face::UP = FACES[0];
@@ -19,8 +19,13 @@ Face& Face::SOUTH = FACES[4];
 Face& Face::EAST = FACES[2];
 Face& Face::WEST = FACES[5];
 
-Face::Face(int index, int offsetX, int offsetY, int offsetZ, const char* name) : 
-    index(index), offsetX(offsetX), offsetY(offsetY), offsetZ(offsetZ), name(name)
+int Face::getCullData(bool up, bool down, bool north, bool south, bool east, bool west)
+{
+    return (up * 1) | (down * 8) | (north * 2) | (south * 16) | (east * 4) | (west * 32);
+}
+
+Face::Face(int index, int offsetX, int offsetY, int offsetZ, int cullBit, const char* name) : 
+    index(index), offsetX(offsetX), offsetY(offsetY), offsetZ(offsetZ), cullBit(cullBit), name(name)
 {
 }
 
@@ -49,6 +54,11 @@ const char* Face::getName() const
     return name;
 }
 
+int Face::getCullData() const
+{
+    return cullBit;
+}
+
 void Face::forEach(void* data, void (*fun) (Face&, void*))
 {
     for(int i = 0; i < 6; i++)

+ 7 - 1
utils/Face.h

@@ -11,6 +11,7 @@ public:
     int getZ() const;
     Face& getOpposite() const;
     const char* getName() const;
+    int getCullData() const;
     
     static void forEach(void* data, void (*fun) (Face&, void*));
     
@@ -20,9 +21,12 @@ public:
     static Face& SOUTH;
     static Face& EAST;
     static Face& WEST;
+    
+    static int getCullData(bool up, bool down, bool north, bool south, bool east, bool west);
 
+        
 private:
-    Face(int index, int offsetX, int offsetY, int offsetZ, const char* name);
+    Face(int index, int offsetX, int offsetY, int offsetZ, int cullBit, const char* name);
     
     static Face FACES[6];
     
@@ -30,6 +34,8 @@ private:
     int offsetY;
     int offsetZ;
     
+    int cullBit;
+    
     int index;
     
     const char* name;

+ 12 - 4
world/Chunk.cpp

@@ -19,15 +19,23 @@ Chunk::Chunk(int chunkX, int chunkZ) : chunkX(chunkX), chunkZ(chunkZ)
         {
             int maxY = (int) (sinf((x + chunkX * WIDTH) * 0.3) * 20 + 22) + (sinf((z + chunkZ * DEPTH) * 0.3) * 20 + 22);
             //maxY = 10;
-            if(maxY > HEIGHT)
+            if(maxY >= HEIGHT)
             {
-                maxY = HEIGHT;
+                maxY = HEIGHT - 1;
             }
             
-            for(int y = 0; y < maxY; y++)
+            for(int y = 0; y < maxY - 3; y++)
             {
-                setBlock(x, y, z, Blocks::GRASS);
+                setBlock(x, y, z, Blocks::STONE);
             }
+            
+            for(int y = maxY - 3; y < maxY - 1; y++)
+            {
+                setBlock(x, y, z, Blocks::DIRT);
+            }
+            
+            setBlock(x, maxY - 1, z, Blocks::GRASS);
+
             for(int y = maxY; y < HEIGHT; y++)
             {
                 setBlock(x, y, z, Blocks::AIR);