Эх сурвалжийг харах

refactoring (static -> class, camera -> shader), engines loads after GL init, model matrix

Kajetan Johannes Hammerle 5 жил өмнө
parent
commit
f987f6025d

+ 5 - 2
Makefile

@@ -7,7 +7,7 @@ all: game
 run_client: game_client
 	vblank_mode=0 optirun ./game_client
 	
-game_client: MainClient.cpp engine math client *.o
+game_client: MainClient.cpp engine math client world *.o
 	g++ $(VERSION) -o $@ MainClient.cpp *.o $(LDFLAGS)
 	
 engine: engine/*.cpp engine/*.h
@@ -19,6 +19,9 @@ math: math/*.cpp math/*.h
 client: client/*.cpp client/*.h
 	g++ $(VERSION) -c client/*.cpp $(LDFLAGS)
 	
+world: world/*.cpp world/*.h
+	g++ $(VERSION) -c world/*.cpp $(LDFLAGS)
+	
 run_server: game_server
 	./game_server
 	
@@ -26,4 +29,4 @@ game_server: MainServer.cpp
 	g++ $(VERSION) -o $@ MainServer.cpp
 	
 clean:
-	rm -f game_server game_client
+	rm -f game_server game_client *.o

+ 80 - 205
client/Client.cpp

@@ -1,263 +1,138 @@
 #include "Client.h"
-#include "../engine/Mouse.h"
-#include "../math/Matrix3D.h"
-#include "../math/Matrix3DStack.h"
-#include "../engine/Key.h"
+#include "../engine/GameEngine.h"
+#include <cmath>
 
-Mesh Client::mesh;
-TextureMesh Client::tmesh;
-Vector3D Client::position;
-Texture Client::texture;
-Texture Client::texture2;
-float Client::lengthAngle = 0;
-float Client::widthAngle = 0;
+Client* Client::instance;
 
-Client::Client()
-{
-}
-
-void Client::init()
+void Client::start()
 {
-    if(texture.load("resources/textures.png"))
+    GameEngine::start(1024, 620, "Test Game", []()
     {
-        cout << "texture success" << endl;
-    }
-    else
-    {
-        cout << "texture fail" << endl;
-    }
-    if(texture2.load("resources/font8x8.png"))
+        Client::instance = new Client();
+    }, []() 
     {
-        cout << "texture2 success" << endl;
-    }
-    else
+        Client::instance->tick();
+    }, [](float lag) 
     {
-        cout << "texture2 fail" << endl;
-    }
-    
-    cout << "init" << endl;
-    mesh.init();
-    
-    // bottom
-    mesh.addPoint(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
-    
-    // top
-    mesh.addPoint(0.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 1.0f);
-    
-    // right
-    mesh.addPoint(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
-    
-    // left
-    mesh.addPoint(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f);
-    
-    // back
-    mesh.addPoint(0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
-    
-    // front
-    mesh.addPoint(0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    mesh.addPoint(0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    mesh.addPoint(1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f);
-    
-    mesh.build();
-    
-    tmesh.init();
-    
-    // bottom
-    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.125f, 0.0f);
-    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0f);
-    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.125f, 0.0625f);
-    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0f);
-    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.125f, 0.0625f);
-    
-    // top
-    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.25f, 0.0f);
-    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.3125f, 0.0f);
-    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.3125f, 0.0f);
-    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.3125f, 0.0625f);
-    
-    // right
-    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
-    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    
-    // left
-    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
-    
-    // back
-    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
-    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.1875f, 0.0f);
-    
-    // front
-    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.25f, 0.0f);
-    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.25f, 0.0625f);
-    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
-    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
-    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.25f, 0.0f);
-    
-    tmesh.build();
+        Client::instance->renderTick(lag);
+    });
+    delete instance;
+}
+
+void Client::stop()
+{
+    GameEngine::stop();
+}
+
+
+Client::Client() : chunk(0, 0), texture("resources/textures.png")
+{    
+    //chunk.init();
     
     position.set(0, 0, -2);
-    GameEngine::getCamera().setPosition(position.getX(), position.getY(), position.getZ());
-    GameEngine::getCamera().storePosition();
-    
-    Key::map(KEY_LEFT, GLFW_KEY_A);
-    Key::map(KEY_RIGHT, GLFW_KEY_D);
-    Key::map(KEY_UP, GLFW_KEY_W);
-    Key::map(KEY_DOWN, GLFW_KEY_S);
-    Key::map(KEY_JUMP, GLFW_KEY_SPACE);
-    Key::map(KEY_SNEAK, GLFW_KEY_LEFT_SHIFT);
-    
-    Key::map(KEY_CAM_LEFT, GLFW_KEY_H);
-    Key::map(KEY_CAM_RIGHT, GLFW_KEY_K);
-    Key::map(KEY_CAM_UP, GLFW_KEY_U);
-    Key::map(KEY_CAM_DOWN, GLFW_KEY_J);
+    GameEngine::get()->getShader().setCamera(position.getX(), position.getY(), position.getZ(), 0, 0);
+    GameEngine::get()->getShader().storeCamera();
+    
+    GameEngine::get()->getKeyManager().map(KEY_LEFT, GLFW_KEY_A);
+    GameEngine::get()->getKeyManager().map(KEY_RIGHT, GLFW_KEY_D);
+    GameEngine::get()->getKeyManager().map(KEY_UP, GLFW_KEY_W);
+    GameEngine::get()->getKeyManager().map(KEY_DOWN, GLFW_KEY_S);
+    GameEngine::get()->getKeyManager().map(KEY_JUMP, GLFW_KEY_SPACE);
+    GameEngine::get()->getKeyManager().map(KEY_SNEAK, GLFW_KEY_LEFT_SHIFT);
+    GameEngine::get()->getKeyManager().map(KEY_CAM_LEFT, GLFW_KEY_H);
+    GameEngine::get()->getKeyManager().map(KEY_CAM_RIGHT, GLFW_KEY_K);
+    GameEngine::get()->getKeyManager().map(KEY_CAM_UP, GLFW_KEY_U);
+    GameEngine::get()->getKeyManager().map(KEY_CAM_DOWN, GLFW_KEY_J);
 }
 
+Client::~Client()
+{
+}
+
+float oldTicker = 0;
+float ticker = 0;
+
 void Client::tick()
 {
-    /*Camera& c = GameEngine::getCamera();
+    oldTicker = ticker;
+    ticker += 1;
+    if(ticker >= 360)
+    {
+        oldTicker = 0;
+        ticker = 0;
+    }
     
-    c.storePosition();
-    c.storeAngles();
+    Shader& c = GameEngine::get()->getShader();
+    c.storeCamera();
+    
+    KeyManager& key = GameEngine::get()->getKeyManager();
     
     float factor = 0.125f;
-    if(Key::isDown(KEY_LEFT))
+    if(key.isDown(KEY_LEFT))
     {
         position.addMul(c.getLeft(), factor);
     }
-    if(Key::isDown(KEY_RIGHT))
+    if(key.isDown(KEY_RIGHT))
     {
         position.addMul(c.getRight(), factor);
     }
-    if(Key::isDown(KEY_UP))
+    if(key.isDown(KEY_UP))
     {
         position.addMul(c.getFront(), factor);
     }
-    if(Key::isDown(KEY_DOWN))
+    if(key.isDown(KEY_DOWN))
     {
         position.addMul(c.getBack(), factor);
     }
-    if(Key::isDown(KEY_JUMP))
+    if(key.isDown(KEY_JUMP))
     {
         position.addMul(c.getUp(), factor);
     }
-    if(Key::isDown(KEY_SNEAK))
+    if(key.isDown(KEY_SNEAK))
     {
         position.addMul(c.getDown(), factor);
     }
     
-    if(Key::isDown(KEY_CAM_LEFT))
+    if(key.isDown(KEY_CAM_LEFT))
     {
         lengthAngle += 2;
     }
-    if(Key::isDown(KEY_CAM_RIGHT))
+    if(key.isDown(KEY_CAM_RIGHT))
     {
         lengthAngle -= 2;
     }
-    if(Key::isDown(KEY_CAM_UP))
+    if(key.isDown(KEY_CAM_UP))
     {
         widthAngle += 2;
     }
-    if(Key::isDown(KEY_CAM_DOWN))
+    if(key.isDown(KEY_CAM_DOWN))
     {
         widthAngle -= 2;
     }
     
-    c.setPosition(position.getX(), position.getY(), position.getZ());
-    c.setAngles(lengthAngle, widthAngle);*/
+    c.setCamera(position.getX(), position.getY(), position.getZ(), lengthAngle, widthAngle);
 }
 
 void Client::renderTick(float lag)
 {
-    
-    
-    //GameEngine::getCamera().updateView(lag);
-    //texture.bind();
-    
-    /*GameEngine::setTextureEnabled(false);
-    GameEngine::setColorEnabled(true);
-    
-    GameEngine::getDirectRenderer().prepare();
-    GameEngine::getDirectRenderer().drawRectangle(0, 0, 200, 300, 0, 0, 1, 1, Color::getColor(255, 0, 0));
-    GameEngine::getDirectRenderer().drawRectangle(200, 0, 400, 300, 0, 0, 1, 1, Color::getColor(0, 255, 0));
-    GameEngine::getDirectRenderer().drawRectangle(400, 0, 600, 300, 0, 0, 1, 1, Color::getColor(0, 0, 255));
-    
+    /*GameEngine::getCamera().updateView(lag);
+    texture.bind();
+    GameEngine::setColorEnabled(false);
+    GameEngine::setUseBlending(false);
     GameEngine::setTextureEnabled(true);
-    GameEngine::setColorEnabled(true);
-    
+    chunk.renderTick(lag);*/
+    
+    GameEngine::get()->getShader().set2DMode();
+    GameEngine::get()->getShader().setToIdentity();
+    GameEngine::get()->getShader().translateTo(200, 200, 0);
+    GameEngine::get()->getShader().rotateZ(interpolate(lag, oldTicker, ticker));
+    GameEngine::get()->getShader().updateModelMatrix();
+    GameEngine::get()->getShader().setTextMode();
     string wusi;
-    GameEngine::setUseBlending(true);
-    
     float y = 30;
-    y = GameEngine::getDirectRenderer().drawString(30, y, true, wusi);
-    
-    wusi = "FPS: " + to_string(GameEngine::getFramesPerSecond());
-    y = GameEngine::getDirectRenderer().drawString(30, y, true, wusi);
-    
-    wusi = "TPS: " + to_string(GameEngine::getTicksPerSecond());
-    y = GameEngine::getDirectRenderer().drawString(30, y, true, wusi);*/
-    
-    GameEngine::setTextureEnabled(true);
-    GameEngine::setColorEnabled(true);
-    GameEngine::setUseBlending(true);
-    GameEngine::getDirectRenderer().prepare();
-    string fps = "FPS: " + to_string(GameEngine::getFramesPerSecond());
-    GameEngine::getDirectRenderer().drawString(30, 30, true, fps);
-    //tmesh.draw();
-    //cout << "renderTick" << endl;
+    wusi = "FPS: " + to_string(GameEngine::get()->getFramesPerSecond());
+    y = GameEngine::get()->getDirectRenderer().drawString(30, y, true, wusi);
 }
 
-void Client::start()
-{
-    GameEngine::start(1024, 620, "Test Game", init, tick, renderTick);
-    
-    for(char c = 'a'; c <= 'z'; c++)
-    {
-        cout << "&" << c << "O";
-    }
-}
+
 

+ 14 - 14
client/Client.h

@@ -2,8 +2,8 @@
 #define CLIENT_H
 
 #include "../engine/Mesh.h"
-#include "../engine/TextureMesh.h"
 #include "../math/Vector3D.h"
+#include "../world/Chunk.h"
 #include "../engine/Texture.h"
 
 using namespace std;
@@ -12,22 +12,13 @@ class Client
 {
 public:
     static void start();
+    static void stop();
+    static Client& get();
     
+    virtual ~Client();
 private:
     Client();
-
-    static void init();
-    static void tick();
-    static void renderTick(float lag);
-    
-    static Texture texture;
-    static Texture texture2;
-    static Mesh mesh;
-    static TextureMesh tmesh;
-    
-    static Vector3D position;
-    static float lengthAngle;
-    static float widthAngle;
+    static Client* instance;
     
     static const int KEY_LEFT = 0;
     static const int KEY_RIGHT = 1;
@@ -40,7 +31,16 @@ private:
     static const int KEY_CAM_RIGHT = 7;
     static const int KEY_CAM_UP = 8;
     static const int KEY_CAM_DOWN = 9;
+
+    void tick();
+    void renderTick(float lag);
+    
+    Texture texture;
+    Chunk chunk;
     
+    Vector3D position;
+    float lengthAngle = 0;
+    float widthAngle = 0;
 };
 
 #endif

+ 0 - 146
engine/Camera.cpp

@@ -1,146 +0,0 @@
-#include "Camera.h"
-#include "GameEngine.h"
-#include "Utils.h"
-#include <cmath>
-
-Camera::Camera()
-{
-}
-
-Camera::Camera(const Camera& orig)
-{
-}
-
-Camera::~Camera()
-{
-}
-
-void Camera::storePosition()
-{
-    oldCamera.set(camera);
-}
-
-void Camera::storeAngles()
-{
-    oldLengthAngle = lengthAngle;
-    oldWidthAngle = widthAngle;
-}
-
-void Camera::setPosition(float x, float y, float z)
-{
-    camera.set(x, y, z);
-}
-
-void Camera::setAngles(float length, float width)
-{
-    lengthAngle = length;
-    widthAngle = width;
-}
-
-void Camera::updateView(float lag)
-{
-    // -------------------------------------------------------------------------
-    // calculate vectors for the view matrix
-    // -------------------------------------------------------------------------
-    
-    // front
-    front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
-
-    // back
-    back.setInverse(front);
-
-    // right
-    right.set(front);
-    right.cross(0.0f, 1.0f, 0.0f);
-    right.normalize();
-    
-    // left
-    left.setInverse(right);
-    
-    // up
-    up.set(front);
-    up.cross(left);
-    up.normalize();
-    
-    interCamera.set(oldCamera);
-    interCamera.addMul(camera, lag);
-    interCamera.addMul(oldCamera, -lag);
-    
-    view.set(0, 0, right.getX());
-    view.set(0, 1, right.getY());
-    view.set(0, 2, right.getZ());
-    view.set(0, 3, right.dotInverse(interCamera));
-    
-    view.set(1, 0, up.getX());
-    view.set(1, 1, up.getY());
-    view.set(1, 2, up.getZ());
-    view.set(1, 3, up.dotInverse(interCamera));
-    
-    view.set(2, 0, back.getX());
-    view.set(2, 1, back.getY());
-    view.set(2, 2, back.getZ());
-    view.set(2, 3, back.dotInverse(interCamera));
-    
-    view.set(3, 0, 0.0f);
-    view.set(3, 1, 0.0f);
-    view.set(3, 0, 0.0f);
-    view.set(3, 3, 1.0f);
-   
-    // -------------------------------------------------------------------------
-    // calculate vectors for movement
-    // -------------------------------------------------------------------------
-    
-    // front
-    front.setY(0.0f);
-    front.normalize();
-
-    // back
-    back.setInverse(front);
-
-    // right
-    right.set(front);
-    right.cross(0.0f, 1.0f, 0.0f);
-    right.normalize();
-    
-    // left
-    left.setInverse(right);
-
-    // up
-    up.set(0.0f, 1.0f, 0.0f);
-    
-    // down
-    down.setInverse(up);
-    
-    GameEngine::updateView(view);
-}
-
-const Vector3D& Camera::getFront()
-{
-    return front;
-}
-
-const Vector3D& Camera::getBack()
-{
-    return back;
-}
-
-const Vector3D& Camera::getRight()
-{
-    return right;
-}
-
-const Vector3D& Camera::getLeft()
-{
-    return left;
-}
-
-const Vector3D& Camera::getUp()
-{
-    return up;
-}
-
-const Vector3D& Camera::getDown()
-{
-    return down;
-}
-

+ 0 - 49
engine/Camera.h

@@ -1,49 +0,0 @@
-#ifndef CAMERA_H
-#define CAMERA_H
-
-#include "../math/Vector3D.h"
-#include "../math/Matrix3D.h"
-
-class Camera
-{
-public:
-    Camera();
-    Camera(const Camera& orig);
-    virtual ~Camera();
-    
-    void storePosition();
-    void storeAngles();
-    
-    void setPosition(float x, float y, float z);
-    void setAngles(float length, float width);
-    void updateView(float lag);
-    
-    const Vector3D& getFront();
-    const Vector3D& getBack();
-    const Vector3D& getRight();
-    const Vector3D& getLeft();
-    const Vector3D& getUp();
-    const Vector3D& getDown();
-private:
-    Vector3D camera;
-    float lengthAngle;
-    float widthAngle;
-    
-    Vector3D oldCamera;
-    float oldLengthAngle;
-    float oldWidthAngle;
-    
-    Vector3D interCamera;
-    
-    Vector3D front;
-    Vector3D back;
-    Vector3D right;
-    Vector3D left;
-    Vector3D up;
-    Vector3D down;
-    
-    Matrix3D view;
-};
-
-#endif
-

+ 1 - 1
engine/Clock.cpp

@@ -27,7 +27,7 @@ void Clock::update()
     sum -= time[index];
 }
 
-double Clock::getUpdatesPerSecond()
+double Clock::getUpdatesPerSecond() const
 {
     return (1000000000.0 * (SIZE - 1)) / sum;
 }

+ 1 - 1
engine/Clock.h

@@ -11,7 +11,7 @@ public:
     virtual ~Clock();
     
     void update();
-    double getUpdatesPerSecond();
+    double getUpdatesPerSecond() const;
 private:
     static const int SIZE = 256;
     uint64_t oldTime = 0;

+ 7 - 42
engine/DirectRenderer.cpp

@@ -2,37 +2,8 @@
 #include "GameEngine.h"
 #include <cmath>
 
-Texture DirectRenderer::FONTS[FONTS_LENGTH];
-
 DirectRenderer::DirectRenderer()
 {
-}
-
-DirectRenderer::DirectRenderer(const DirectRenderer& orig)
-{
-}
-
-DirectRenderer::~DirectRenderer()
-{
-    glDeleteVertexArrays(1, &vba);
-    glDeleteBuffers(1, &vbo);
-}
-
-void DirectRenderer::init()
-{
-    if(!FONTS[0].isLoaded())
-    {
-        FONTS[0].load("resources/font8x8.png");
-    }
-    if(!FONTS[1].isLoaded())
-    {
-        FONTS[1].load("resources/font16x16.png");
-    }
-    if(!FONTS[2].isLoaded())
-    {
-        FONTS[2].load("resources/font24x24.png");
-    }
-    
     glGenVertexArrays(1, &vba);
     glGenBuffers(1, &vbo);
 
@@ -49,20 +20,14 @@ void DirectRenderer::init()
     glVertexAttribPointer(2, 2, GL_FLOAT, false, 24, (GLvoid*) 16);
 }
 
-void DirectRenderer::prepare()
+DirectRenderer::DirectRenderer(const DirectRenderer& orig)
 {
-    int scale = GameEngine::scale;
-    view.set(0, 0, (2.0f * scale) / GameEngine::width);
-    view.set(1, 1, (-2.0f * scale) / GameEngine::height);
-    view.set(2, 2, (-1.0f * scale) / GameEngine::height);
-    
-    view.set(0, 3, -1.0f);
-    view.set(1, 3, 1.0f);
-    view.set(2, 3, 0.5f);
-    view.set(3, 3, 1.0f);
+}
 
-    GameEngine::updateView(view);
-    glUniformMatrix4fv(GameEngine::unifProjMatrix, 1, 0, proj.getValues());
+DirectRenderer::~DirectRenderer()
+{
+    glDeleteVertexArrays(1, &vba);
+    glDeleteBuffers(1, &vbo);
 }
 
 void DirectRenderer::drawRectangle(float minX, float minY, float maxX, float maxY, float tMinX, float tMinY, float tMaxX, float tMaxY, IntColor c)
@@ -153,7 +118,7 @@ float DirectRenderer::drawString(float x, float y, bool shadow, string& s)
     glUnmapBuffer(GL_ARRAY_BUFFER);
 
     glBindVertexArray(vba);
-    FONTS[min(GameEngine::scale - 1, FONTS_LENGTH - 1)].bind();
+    FONTS[min(GameEngine::get()->getScale() - 1, FONTS_LENGTH - 1)].bind();
     glDrawArrays(GL_TRIANGLE_STRIP, offset / (OBJECT_LENGTH / 4), (index + 1) / 6);
     offset += size;
     

+ 5 - 8
engine/DirectRenderer.h

@@ -13,20 +13,20 @@ public:
     DirectRenderer();
     DirectRenderer(const DirectRenderer& orig);
     virtual ~DirectRenderer();
-
-    void prepare();
+    
     void drawRectangle(float minX, float minY, float maxX, float maxY, float tMinX, float tMinY, float tMaxX, float tMaxY, IntColor c);
     void drawRectangle(float minX, float minY, float maxX, float maxY, IntColor c);
     void drawRectangle(float minX, float minY, float maxX, float maxY, float tMinX, float tMinY, float tMaxX, float tMaxY);
     
     float drawString(float x, float y, bool shadow, string& s);
-
-    void init();
 private:
     float addString(float x, float y, int& index, float* data, const IntColor* color, string& s);
     
     static const int FONTS_LENGTH = 3;
-    static Texture FONTS[FONTS_LENGTH];
+    Texture FONTS[FONTS_LENGTH]
+    {
+        Texture("resources/font8x8.png"), Texture("resources/font16x16.png"), Texture("resources/font24x24.png")
+    };
     
     static const char COLOR_CHAR = '&';
 
@@ -42,9 +42,6 @@ private:
     GLuint vbo = 0;
 
     unsigned int offset = BUFFER_LENGTH - OBJECT_LENGTH;
-
-    Matrix3D view;
-    Matrix3D proj;
 };
 
 #endif

+ 210 - 239
engine/GameEngine.cpp

@@ -1,48 +1,157 @@
 #include "GameEngine.h"
-#include "Key.h"
-#include "Mouse.h"
+#include "MouseManager.h"
 #include <cmath>
 
-Clock GameEngine::tps;
-Clock GameEngine::fps;
+GameEngine* GameEngine::instance = nullptr;
 
-InitFunction GameEngine::init = nullptr;
-TickFunction GameEngine::tick = nullptr;
-RenderTickFunction GameEngine::renderTick = nullptr;
+void GameEngine::start(int width, int height, const char* name, InitFunction init, TickFunction tick, RenderTickFunction renderTick)
+{    
+    if(!glfwInit())
+    {
+        cout << "could not initialize GLFW" << endl;
+        return;
+    }
+
+    glfwDefaultWindowHints();
+    glfwWindowHint(GLFW_VISIBLE, 0);
+    glfwWindowHint(GLFW_RESIZABLE, 1);
+    GLFWwindow* window = glfwCreateWindow(width, height, name, nullptr, nullptr);
+    if(!window)
+    {
+        cout << "could not create window" << endl;
+        glfwTerminate();
+        return;
+    }
+
+    glfwMakeContextCurrent(window);
+    glfwSwapInterval(1);
+
+    glfwShowWindow(window);
+
+    GLenum err = glewInit();
+    if(GLEW_OK != err)
+    {
+        cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
+        return;
+    }
+    cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
+
+    GLuint vShader = 0;
+    GLuint fShader = 0;
+    GLuint program = createProgram(vShader, program);
+    if(program == 0)
+    {
+        if(vShader != 0)
+        {
+            glDeleteShader(vShader);
+        }
+        if(fShader != 0)
+        {
+            glDeleteShader(fShader);
+        }
+        glfwDestroyWindow(window);
+        glfwTerminate();
+        return;
+    }
+    
+    GameEngine::instance = new GameEngine(program, vShader, fShader, window, width, height, tick, renderTick);
+    glfwSetKeyCallback(window, [](GLFWwindow* w, int key, int scancode, int action, int mods) 
+    {
+        GameEngine::instance->onKeyEvent(w, key, scancode, action, mods);
+    });
+    glfwSetMouseButtonCallback(window, [](GLFWwindow* w, int button, int action, int mods)
+    {
+        GameEngine::instance->onMouseClick(w, button, action, mods);
+    });
+    glfwSetFramebufferSizeCallback(window, [](GLFWwindow* w, int width, int height)
+    {
+        GameEngine::instance->onWindowResize(w, width, height);
+    }); 
+    //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+    //glfwSetCursorPosCallback(window, onMouseMove);
+    
+    init();
+    instance->run();
+    delete instance;
+}
+
+void GameEngine::stop()
+{
+    if(GameEngine::instance != nullptr)
+    {
+        glfwSetWindowShouldClose(GameEngine::instance->window, 1);
+    }
+}
+
+void GameEngine::run()
+{    
+    glEnable(GL_CULL_FACE);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LEQUAL);
+    
+    uint64_t newTime = glfwGetTimerValue();
+    uint64_t oldTime = newTime;
+    uint64_t lag = 0;
+    while(!glfwWindowShouldClose(window))
+    {
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        oldTime = newTime;
+        newTime = glfwGetTimerValue();
+        lag += newTime - oldTime;
 
-GLuint GameEngine::vShader = 0;
-GLuint GameEngine::fShader = 0;
+        int ticksPerFrame = 0;
+        while(lag >= NANOS_PER_TICK)
+        {
+            lag -= NANOS_PER_TICK;
 
-GLFWwindow* GameEngine::window = nullptr;
-GLuint GameEngine::program = 0;
+            tps.update();
+            tick();
+            keyManager.tick();
+            mouseManager.tick();
+            ticksPerFrame++;
 
-int GameEngine::scale = 1;
-int GameEngine::width = 0;
-int GameEngine::height = 0;
-float GameEngine::fovY = 60;
-float GameEngine::nearClip = 0.1f;
-float GameEngine::farClip = 1000.0f;
-Matrix3D GameEngine::proj;
+            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;
+            }
+        }
 
-Camera GameEngine::camera;
+        fps.update();
+        renderTick((float) lag / NANOS_PER_TICK);
 
-DirectRenderer GameEngine::directRenderer;
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+    }
+    
+    glDeleteShader(vShader);
+    glDeleteShader(fShader);
+    glDeleteProgram(program);
+    glfwDestroyWindow(window);
+    glfwTerminate();
+}
 
-GLint GameEngine::unifProjMatrix = 0;
-GLint GameEngine::unifViewMatrix = 0;
-GLint GameEngine::unifUseTexture = 0;
-GLint GameEngine::unifUseColor = 0;
-GLint GameEngine::unifUseMixColor = 0;
-GLint GameEngine::unifMixColorLoc = 0;
+GLuint GameEngine::setInstance(GLuint program, GameEngine* en)
+{
+    GameEngine::instance = en;
+    return program;
+}
 
-Camera& GameEngine::getCamera()
+GameEngine::GameEngine(GLuint program, GLuint vShader, GLuint fShader, GLFWwindow* window, 
+        int width, int height, TickFunction tick, RenderTickFunction renderTick) :
+    program(setInstance(program, this)), vShader(vShader), fShader(fShader), window(window), width(width), height(height), tick(tick), renderTick(renderTick)
 {
-    return camera;
+    updateScale();
 }
 
-DirectRenderer& GameEngine::getDirectRenderer()
+GameEngine::~GameEngine()
 {
-    return directRenderer;
 }
 
 void GameEngine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
@@ -54,11 +163,11 @@ void GameEngine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, in
             //activeFocus = 0;
             glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
         }
-        Key::release(key);
+        keyManager.release(key);
     }
     else if(action == GLFW_PRESS)
     {
-        Key::press(key);
+        keyManager.press(key);
     }
 }
 
@@ -75,16 +184,16 @@ void GameEngine::onMouseClick(GLFWwindow* w, int button, int action, int mods)
         }
         else
         {*/
-            Mouse::press(button);
+            mouseManager.press(button);
         //}
     }
     else if(action == GLFW_RELEASE)
     {
-        Mouse::release(button);
+        mouseManager.release(button);
     }
 }
 
-/*static void onMouseMove(GLFWwindow* w, double x, double y)
+/*void GameEngine::onMouseMove(GLFWwindow* w, double x, double y)
 {
     if(activeFocus)
     {
@@ -185,7 +294,7 @@ bool GameEngine::checkShaderErrors(const char* name, GLuint shader)
     return returnValue;
 }
 
-GLuint GameEngine::compileProgram(const GLchar* vertex, const GLchar* fragment)
+GLuint GameEngine::compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* vertex, const GLchar* fragment)
 {
     vShader = glCreateShader(GL_VERTEX_SHADER);
     glShaderSource(vShader, 1, &vertex, nullptr);
@@ -246,7 +355,7 @@ GLuint GameEngine::compileProgram(const GLchar* vertex, const GLchar* fragment)
     return program;
 }
 
-GLuint GameEngine::createProgram()
+GLuint GameEngine::createProgram(GLuint& vShader, GLuint& fShader)
 {
     GLchar* vertex = readFile("shader/vertex.vs");
     if(vertex == nullptr)
@@ -262,206 +371,12 @@ GLuint GameEngine::createProgram()
         return 0;
     }
     
-    GLuint program = compileProgram(vertex, fragment);
+    GLuint program = compileProgram(vShader, fShader, vertex, fragment);
     delete[] vertex;
     delete[] fragment;
     return program;
 }
 
-void GameEngine::updateProjection()
-{
-    float q = 1.0f / tanf((0.5f * fovY) * M_PI / 180.0f);
-
-    proj.set(0, 0, (q * height) / width);
-    proj.set(1, 1, q);
-    proj.set(2, 2, (nearClip + farClip) / (nearClip - farClip));
-    proj.set(3, 2, -1.0f);
-    proj.set(2, 3, (2.0f * nearClip * farClip) / (nearClip - farClip));
-    proj.set(3, 3, 0);   
-    
-    glUniformMatrix4fv(unifProjMatrix, 1, 0, proj.getValues());
-}
-
-void GameEngine::updateView(Matrix3D& m)
-{
-    glUniformMatrix4fv(unifViewMatrix, 1, 0, m.getValues());
-}
-
-void GameEngine::onInit()
-{
-    Key::init();
-    Mouse::init();
-    init();
-    
-    unifProjMatrix = glGetUniformLocation(program, "projMatrix");
-    unifViewMatrix = glGetUniformLocation(program, "viewMatrix");
-    unifUseTexture = glGetUniformLocation(program, "useTexture");
-    unifUseColor = glGetUniformLocation(program, "useColor");
-    unifUseMixColor = glGetUniformLocation(program, "useMixColor");
-    unifMixColorLoc = glGetUniformLocation(program, "mixColor");
-    
-    directRenderer.init();
-}
-
-void GameEngine::onTick()
-{
-    tick();
-    Key::tick();
-    Mouse::tick();
-}
-
-void GameEngine::start(int width, int height, const char* name, InitFunction init, TickFunction tick, RenderTickFunction renderTick)
-{    
-    GameEngine::width = width;
-    GameEngine::height = height;
-    GameEngine::init = init;
-    GameEngine::tick = tick;
-    GameEngine::renderTick = renderTick;
-    updateScale();
-    
-    if(!glfwInit())
-    {
-        cout << "could not initialize GLFW" << endl;
-        return;
-    }
-
-    glfwDefaultWindowHints();
-    glfwWindowHint(GLFW_VISIBLE, 0);
-    glfwWindowHint(GLFW_RESIZABLE, 1);
-    window = glfwCreateWindow(width, height, name, nullptr, nullptr);
-    if(!window)
-    {
-        cout << "could not create window" << endl;
-        glfwTerminate();
-        return;
-    }
-
-    glfwSetKeyCallback(window, onKeyEvent);
-    glfwSetFramebufferSizeCallback(window, onWindowResize);
-    glfwSetMouseButtonCallback(window, onMouseClick);
-    //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
-    //glfwSetCursorPosCallback(window, onMouseMove);
-
-    glfwMakeContextCurrent(window);
-    glfwSwapInterval(1);
-
-    glfwShowWindow(window);
-
-    GLenum err = glewInit();
-    if(GLEW_OK != err)
-    {
-        cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
-        return;
-    }
-    cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
-
-    program = createProgram();
-    if(program == 0)
-    {
-        onTerm();
-        return;
-    }
-
-    glEnable(GL_CULL_FACE);
-    glEnable(GL_DEPTH_TEST);
-    glDepthFunc(GL_LEQUAL);
-    onInit();
-    
-    uint64_t newTime = glfwGetTimerValue();
-    uint64_t oldTime = newTime;
-    uint64_t lag = 0;
-    while(!glfwWindowShouldClose(window))
-    {
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-        oldTime = newTime;
-        newTime = glfwGetTimerValue();
-        lag += newTime - oldTime;
-
-        int ticksPerFrame = 0;
-        while(lag >= NANOS_PER_TICK)
-        {
-            lag -= NANOS_PER_TICK;
-
-            tps.update();
-            onTick();
-            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;
-            }
-        }
-
-        updateProjection();
-        fps.update();
-        renderTick((float) lag / NANOS_PER_TICK);
-
-        glfwSwapBuffers(window);
-        glfwPollEvents();
-    }
-    
-    onTerm();
-}
-
-void GameEngine::onTerm()
-{
-    if(vShader != 0)
-    {
-        glDeleteShader(vShader);
-    }
-    if(fShader != 0)
-    {
-        glDeleteShader(fShader);
-    }
-    if(program != 0)
-    {
-        glDeleteProgram(program);
-    }
-    glfwDestroyWindow(window);
-    glfwTerminate();
-}
-
-void GameEngine::setTextureEnabled(bool use)
-{
-    glUniform1i(unifUseTexture, use);
-}
-
-void GameEngine::setColorEnabled(bool use)
-{
-    glUniform1i(unifUseColor, use);
-}
-
-void GameEngine::setMixColorEnabled(bool use)
-{
-    glUniform1i(unifUseMixColor, use);
-}
-
-void GameEngine::setMixColor(float r, float g, float b, float a)
-{
-    glUniform4f(unifMixColorLoc, r, g, b, a);
-}
-
-void GameEngine::setUseBlending(bool use)
-{
-    if(use)
-    {
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        glBlendEquation(GL_FUNC_ADD);
-    }
-    else
-    {
-        glDisable(GL_BLEND);
-    }
-}
-
 void GameEngine::printError()
 {
     GLenum error = glGetError();
@@ -496,11 +411,6 @@ void GameEngine::printError()
     }
 }
 
-void GameEngine::stop()
-{
-    glfwSetWindowShouldClose(window, 1);
-}
-
 void GameEngine::updateScale()
 {
     scale = 1;
@@ -510,13 +420,74 @@ void GameEngine::updateScale()
     }
 }
 
-double GameEngine::getTicksPerSecond()
+GameEngine* GameEngine::get()
+{
+    return instance;
+}
+
+KeyManager& GameEngine::getKeyManager()
+{
+    return keyManager;
+}
+
+MouseManager& GameEngine::getMouseManager()
+{
+    return mouseManager;
+}
+
+Shader& GameEngine::getShader()
+{
+    return shader;
+}
+
+DirectRenderer& GameEngine::getDirectRenderer()
+{
+    return directRenderer;
+}
+
+double GameEngine::getTicksPerSecond() const
 {
     return tps.getUpdatesPerSecond();
 }
 
-double GameEngine::getFramesPerSecond()
+double GameEngine::getFramesPerSecond() const
 {
     return fps.getUpdatesPerSecond();
 }
 
+int GameEngine::getScale() const
+{
+    return scale;
+}
+
+int GameEngine::getWidth() const
+{
+    return width;
+}
+
+int GameEngine::getHeight() const
+{
+    return height;
+}
+
+GLint GameEngine::getUniformLocation(const GLchar* name) const
+{
+    return glGetUniformLocation(program, name);
+}
+
+void GameEngine::setMatrix(GLint location, const GLfloat* m)
+{
+    glUniformMatrix4fv(location, 1, 0, m);
+}
+
+void GameEngine::setInt(GLint location, GLint i)
+{
+    glUniform1i(location, i);
+}
+
+void GameEngine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
+{
+    glUniform4f(location, f1, f2, f3, f4);
+}
+
+

+ 54 - 70
engine/GameEngine.h

@@ -7,99 +7,83 @@
 #include <string>
 #include <fstream>
 #include <cstring>
-#include "../math/Matrix3D.h"
-#include "Camera.h"
-#include "Texture.h"
+#include "KeyManager.h"
+#include "MouseManager.h"
+#include "Shader.h"
 #include "DirectRenderer.h"
 #include "Clock.h"
 
 using namespace std;
 
-static const uint64_t NANOS_PER_TICK = 50000000;
-static const int MAX_TICKS_PER_FRAME = 5;
-
 typedef void (*InitFunction) ();
 typedef void (*TickFunction) ();
 typedef void (*RenderTickFunction) (float);
 
-class DirectRenderer;
-
 class GameEngine
 {
 public:
     static void start(int width, int height, const char* name, InitFunction init, TickFunction tick, RenderTickFunction renderTick);
-    static Camera& getCamera();
-    static DirectRenderer& getDirectRenderer();
-
-    static void setTextureEnabled(bool use);
-    static void setColorEnabled(bool use);
-    static void setMixColorEnabled(bool use);
-    static void setMixColor(float r, float g, float b, float a);
-    
-    static void setUseBlending(bool use);
-
-    static void printError();
     static void stop();
+    static GameEngine* get();
     
-    static double getTicksPerSecond();
-    static double getFramesPerSecond();
-
-    friend Camera;
-    friend Texture;
-    friend DirectRenderer;
+    virtual ~GameEngine();
+    
+    KeyManager& getKeyManager();
+    MouseManager& getMouseManager();
+    Shader& getShader();
+    DirectRenderer& getDirectRenderer();
+    
+    void printError();
+    
+    double getTicksPerSecond() const;
+    double getFramesPerSecond() const;
+    
+    int getScale() const;
+    int getWidth() const;
+    int getHeight() const;
+    
+    GLint getUniformLocation(const GLchar* name) const;
+    void setMatrix(GLint location, const GLfloat* m);
+    void setInt(GLint location, GLint i);
+    void setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4);
 private:
-    GameEngine();
+    GameEngine(GLuint program, GLuint vShader, GLuint fShader, GLFWwindow* window, int width, int height, TickFunction tick, RenderTickFunction renderTick);
+    static GLuint setInstance(GLuint program, GameEngine* en);
+    static GameEngine* instance;
+    static const uint64_t NANOS_PER_TICK = 50000000;
+    static const int MAX_TICKS_PER_FRAME = 5;
+    void run();
 
-    static void onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods);
-    static void onMouseClick(GLFWwindow* w, int button, int action, int mods);
-    static void onWindowResize(GLFWwindow* w, int width, int height);
+    void onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods);
+    void onMouseClick(GLFWwindow* w, int button, int action, int mods);
+    void onWindowResize(GLFWwindow* w, int width, int height);
 
     static GLchar* readFile(const char* name);
     static bool checkShaderErrors(const char* name, GLuint shader);
-    static GLuint compileProgram(const GLchar* vertex, const GLchar* fragment);
-    static GLuint createProgram();
+    static GLuint compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* vertex, const GLchar* fragment);
+    static GLuint createProgram(GLuint& vShader, GLuint& fShader);
 
-    static void updateProjection();
-    static void updateView(Matrix3D& m);
+    void updateScale();
 
-    static void onInit();
-    static void onTick();
-    static void onTerm();
-
-    static void updateScale();
-
-    static Clock tps;
-    static Clock fps;
+    TickFunction tick;
+    RenderTickFunction renderTick;
     
-    static InitFunction init;
-    static TickFunction tick;
-    static RenderTickFunction renderTick;
-
-    static GLuint vShader;
-    static GLuint fShader;
-
-    static GLFWwindow* window;
-    static GLuint program;
-
-    static int scale;
-    static int width;
-    static int height;
-    static float fovY;
-    static float nearClip;
-    static float farClip;
-    static Matrix3D proj;
-
-    static Camera camera;
-
-    static DirectRenderer directRenderer;
-
-    // uniforms
-    static GLint unifProjMatrix;
-    static GLint unifViewMatrix;
-    static GLint unifUseTexture;
-    static GLint unifUseColor;
-    static GLint unifUseMixColor;
-    static GLint unifMixColorLoc;
+    Clock tps;
+    Clock fps;
+    
+    GLFWwindow* window;
+    GLuint program = 0;
+    GLuint vShader = 0;
+    GLuint fShader = 0;
+
+    int scale = 1;
+    int width;
+    int height;
+    
+    KeyManager keyManager;
+    MouseManager mouseManager;
+    Shader shader;
+    DirectRenderer directRenderer;
 };
 
 #endif

+ 0 - 35
engine/Key.h

@@ -1,35 +0,0 @@
-#ifndef KEY_H
-#define KEY_H
-
-#include "GameEngine.h"
-
-class Key
-{
-public:
-    static bool isDown(int mapping);
-    static bool isReleased(int mapping);
-    static unsigned int getDownTime(int mapping);
-    static void resetDownTime(int mapping);
-    static bool map(int mapping, int key);
-    
-    friend GameEngine;
-private:
-    Key();
-    
-    static const int NUMBER_OF_KEYS = GLFW_KEY_LAST + 1;
-    static bool isInRange(int i);
-    static void init();
-    static void tick();
-    static bool press(int key);
-    static bool release(int key);
-    
-    bool down = false;
-    bool shouldRelease = false;
-    unsigned int downTime = 0;
-    
-    static Key keyArray[NUMBER_OF_KEYS];
-    static int mappingArray[NUMBER_OF_KEYS];
-};
-
-#endif
-

+ 15 - 22
engine/Key.cpp → engine/KeyManager.cpp

@@ -1,53 +1,46 @@
-#include "Key.h"
+#include "KeyManager.h"
 
-Key Key::keyArray[Key::NUMBER_OF_KEYS];
-int Key::mappingArray[Key::NUMBER_OF_KEYS];
-
-Key::Key()
+KeyManager::KeyManager()
 {
+    for(int i = 0; i < NUMBER_OF_KEYS; i++)
+    {
+        mappingArray[i] = 0;
+    }
 }
 
-bool Key::isDown(int mapping)
+bool KeyManager::isDown(int mapping)
 {
     return isInRange(mapping) && keyArray[mappingArray[mapping]].down;
 }
 
-bool Key::isReleased(int mapping)
+bool KeyManager::isReleased(int mapping)
 {
     return isInRange(mapping) && keyArray[mappingArray[mapping]].shouldRelease;
 }
 
-unsigned int Key::getDownTime(int mapping)
+unsigned int KeyManager::getDownTime(int mapping)
 {
     bool m = isInRange(mapping);
     return m * keyArray[mappingArray[mapping * m]].downTime;
 }
 
-void Key::resetDownTime(int mapping)
+void KeyManager::resetDownTime(int mapping)
 {
     keyArray[mappingArray[mapping * isInRange(mapping)]].downTime = 0;
 }
 
-bool Key::map(int mapping, int key)
+bool KeyManager::map(int mapping, int key)
 {
     bool b = isInRange(mapping) && isInRange(key);
     mappingArray[mapping * b] = b * key;
 }
 
-bool Key::isInRange(int i)
+bool KeyManager::isInRange(int i)
 {
     return i >= 0 && i < NUMBER_OF_KEYS;
 }
 
-void Key::init()
-{
-    for(int i = 0; i < NUMBER_OF_KEYS; i++)
-    {
-        mappingArray[i] = 0;
-    }
-}
-
-void Key::tick()
+void KeyManager::tick()
 {
     for(int i = 0; i < NUMBER_OF_KEYS; i++)
     {
@@ -59,14 +52,14 @@ void Key::tick()
     }
 }
 
-bool Key::press(int key)
+bool KeyManager::press(int key)
 {
     int index = isInRange(key) * key;
     keyArray[index].down = true;
     keyArray[index].shouldRelease = false;
 }
 
-bool Key::release(int key)
+bool KeyManager::release(int key)
 {
     int index = isInRange(key) * key;
     keyArray[index].shouldRelease = true;

+ 37 - 0
engine/KeyManager.h

@@ -0,0 +1,37 @@
+#ifndef KEY_H
+#define KEY_H
+
+#include <GLFW/glfw3.h>
+
+class KeyManager
+{
+public:
+    KeyManager();
+    
+    bool isDown(int mapping);
+    bool isReleased(int mapping);
+    unsigned int getDownTime(int mapping);
+    void resetDownTime(int mapping);
+    bool map(int mapping, int key);
+    
+    void tick();
+    bool press(int key);
+    bool release(int key);
+private:
+    static const int NUMBER_OF_KEYS = GLFW_KEY_LAST + 1;
+    
+    bool isInRange(int i);
+    
+    struct Key
+    {
+        bool down = false;
+        bool shouldRelease = false;
+        unsigned int downTime = 0;
+    };
+    
+    Key keyArray[NUMBER_OF_KEYS];
+    int mappingArray[NUMBER_OF_KEYS];
+};
+
+#endif
+

+ 0 - 35
engine/Mouse.h

@@ -1,35 +0,0 @@
-#ifndef MOUSE_H
-#define MOUSE_H
-
-#include "GameEngine.h"
-
-class Mouse
-{
-public:
-    static bool isDown(int mapping);
-    static bool isReleased(int mapping);
-    static unsigned int getDownTime(int mapping);
-    static void resetDownTime(int mapping);
-    static bool map(int mapping, int key);
-    
-    friend GameEngine;
-private:
-    Mouse();
-    
-    static const int NUMBER_OF_BUTTONS = GLFW_MOUSE_BUTTON_LAST + 1;
-    static bool isInRange(int i);
-    static void init();
-    static void tick();
-    static bool press(int button);
-    static bool release(int button);
-    
-    bool down = false;
-    bool shouldRelease = false;
-    unsigned int downTime = 0;
-    
-    static Mouse mouseArray[NUMBER_OF_BUTTONS];
-    static int mappingArray[NUMBER_OF_BUTTONS];
-};
-
-#endif
-

+ 15 - 22
engine/Mouse.cpp → engine/MouseManager.cpp

@@ -1,53 +1,46 @@
-#include "Mouse.h"
+#include "MouseManager.h"
 
-Mouse Mouse::mouseArray[Mouse::NUMBER_OF_BUTTONS];
-int Mouse::mappingArray[Mouse::NUMBER_OF_BUTTONS];
-
-Mouse::Mouse()
+MouseManager::MouseManager()
 {
+    for(int i = 0; i < NUMBER_OF_BUTTONS; i++)
+    {
+        mappingArray[i] = 0;
+    }
 }
 
-bool Mouse::isDown(int mapping)
+bool MouseManager::isDown(int mapping)
 {
     return isInRange(mapping) && mouseArray[mappingArray[mapping]].down;
 }
 
-bool Mouse::isReleased(int mapping)
+bool MouseManager::isReleased(int mapping)
 {
     return isInRange(mapping) && mouseArray[mappingArray[mapping]].shouldRelease;
 }
 
-unsigned int Mouse::getDownTime(int mapping)
+unsigned int MouseManager::getDownTime(int mapping)
 {
     bool m = isInRange(mapping);
     return m * mouseArray[mappingArray[mapping * m]].downTime;
 }
 
-void Mouse::resetDownTime(int mapping)
+void MouseManager::resetDownTime(int mapping)
 {
     mouseArray[mappingArray[mapping * isInRange(mapping)]].downTime = 0;
 }
 
-bool Mouse::map(int mapping, int mouse)
+bool MouseManager::map(int mapping, int mouse)
 {
     bool b = isInRange(mapping) && isInRange(mouse);
     mappingArray[mapping * b] = b * mouse;
 }
 
-bool Mouse::isInRange(int i)
+bool MouseManager::isInRange(int i)
 {
     return i >= 0 && i < NUMBER_OF_BUTTONS;
 }
 
-void Mouse::init()
-{
-    for(int i = 0; i < NUMBER_OF_BUTTONS; i++)
-    {
-        mappingArray[i] = 0;
-    }
-}
-
-void Mouse::tick()
+void MouseManager::tick()
 {
     for(int i = 0; i < NUMBER_OF_BUTTONS; i++)
     {
@@ -59,14 +52,14 @@ void Mouse::tick()
     }
 }
 
-bool Mouse::press(int mouse)
+bool MouseManager::press(int mouse)
 {
     int index = isInRange(mouse) * mouse;
     mouseArray[index].down = true;
     mouseArray[index].shouldRelease = false;
 }
 
-bool Mouse::release(int mouse)
+bool MouseManager::release(int mouse)
 {
     int index = isInRange(mouse) * mouse;
     mouseArray[index].shouldRelease = true;

+ 37 - 0
engine/MouseManager.h

@@ -0,0 +1,37 @@
+#ifndef MOUSE_H
+#define MOUSE_H
+
+#include <GLFW/glfw3.h>
+
+class MouseManager
+{
+public:
+    MouseManager();
+    
+    bool isDown(int mapping);
+    bool isReleased(int mapping);
+    unsigned int getDownTime(int mapping);
+    void resetDownTime(int mapping);
+    bool map(int mapping, int key);
+    
+    void tick();
+    bool press(int button);
+    bool release(int button);
+private:
+    static const int NUMBER_OF_BUTTONS = GLFW_MOUSE_BUTTON_LAST + 1;
+    
+    bool isInRange(int i);
+    
+    struct Mouse
+    {
+        bool down = false;
+        bool shouldRelease = false;
+        unsigned int downTime = 0;
+    };
+    
+    Mouse mouseArray[NUMBER_OF_BUTTONS];
+    int mappingArray[NUMBER_OF_BUTTONS];
+};
+
+#endif
+

+ 286 - 0
engine/Shader.cpp

@@ -0,0 +1,286 @@
+#include "Shader.h"
+#include "GameEngine.h"
+#include "Utils.h"
+#include <cmath>
+
+Shader::Shader()
+{
+    unifProjMatrix = GameEngine::get()->getUniformLocation("projMatrix");
+    unifViewMatrix = GameEngine::get()->getUniformLocation("viewMatrix");
+    unifModelMatrix = GameEngine::get()->getUniformLocation("modelMatrix");
+    
+    unifUseTexture = GameEngine::get()->getUniformLocation("useTexture");
+    unifUseColor = GameEngine::get()->getUniformLocation("useColor");
+    unifUseMixColor = GameEngine::get()->getUniformLocation("useMixColor");
+    unifMixColorLoc = GameEngine::get()->getUniformLocation("mixColor");
+}
+
+Shader::Shader(const Shader& orig)
+{
+}
+
+Shader::~Shader()
+{
+}
+
+void Shader::set3DMode(float lag)
+{
+    float q = 1.0f / tanf((0.5f * fovY) * M_PI / 180.0f);
+
+    proj.set(0, 0, (q * GameEngine::get()->getHeight()) / GameEngine::get()->getWidth());
+    proj.set(1, 1, q);
+    proj.set(2, 2, (nearClip + farClip) / (nearClip - farClip));
+    proj.set(3, 2, -1.0f);
+    proj.set(2, 3, (2.0f * nearClip * farClip) / (nearClip - farClip));
+    proj.set(3, 3, 0);   
+    
+    GameEngine::get()->setMatrix(unifProjMatrix, proj.getValues());
+    
+    // -------------------------------------------------------------------------
+    // calculate vectors for the view matrix
+    // -------------------------------------------------------------------------
+    
+    // front
+    front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
+
+    // back
+    back.setInverse(front);
+
+    // right
+    right.set(front);
+    right.cross(0.0f, 1.0f, 0.0f);
+    right.normalize();
+    
+    // left
+    left.setInverse(right);
+    
+    // up
+    up.set(front);
+    up.cross(left);
+    up.normalize();
+    
+    Vector3D interCamera = oldCamera;
+    interCamera.addMul(camera, lag);
+    interCamera.addMul(oldCamera, -lag);
+    
+    view.set(0, 0, right.getX());
+    view.set(0, 1, right.getY());
+    view.set(0, 2, right.getZ());
+    view.set(0, 3, right.dotInverse(interCamera));
+    
+    view.set(1, 0, up.getX());
+    view.set(1, 1, up.getY());
+    view.set(1, 2, up.getZ());
+    view.set(1, 3, up.dotInverse(interCamera));
+    
+    view.set(2, 0, back.getX());
+    view.set(2, 1, back.getY());
+    view.set(2, 2, back.getZ());
+    view.set(2, 3, back.dotInverse(interCamera));
+    
+    view.set(3, 0, 0.0f);
+    view.set(3, 1, 0.0f);
+    view.set(3, 0, 0.0f);
+    view.set(3, 3, 1.0f);
+   
+    // -------------------------------------------------------------------------
+    // calculate vectors for movement
+    // -------------------------------------------------------------------------
+    
+    // front
+    front.setY(0.0f);
+    front.normalize();
+
+    // back
+    back.setInverse(front);
+
+    // right
+    right.set(front);
+    right.cross(0.0f, 1.0f, 0.0f);
+    right.normalize();
+    
+    // left
+    left.setInverse(right);
+
+    // up
+    up.set(0.0f, 1.0f, 0.0f);
+    
+    // down
+    down.setInverse(up);
+    
+    GameEngine::get()->setMatrix(unifViewMatrix, view.getValues());
+}
+
+void Shader::set2DMode()
+{
+    proj.setToIdentity();
+    GameEngine::get()->setMatrix(unifProjMatrix, proj.getValues());
+    
+    int scale = GameEngine::get()->getScale();
+    view.set(0, 0, (2.0f * scale) / GameEngine::get()->getWidth());
+    view.set(1, 1, (-2.0f * scale) / GameEngine::get()->getHeight());
+    view.set(2, 2, (-1.0f * scale) / GameEngine::get()->getHeight());
+    
+    view.set(0, 3, -1.0f);
+    view.set(1, 3, 1.0f);
+    view.set(2, 3, 0.5f);
+    view.set(3, 3, 1.0f);
+    
+    GameEngine::get()->setMatrix(unifViewMatrix, view.getValues());
+}
+
+void Shader::storeCamera()
+{
+    oldCamera.set(camera);
+    oldLengthAngle = lengthAngle;
+    oldWidthAngle = widthAngle;
+}
+
+void Shader::setCamera(float x, float y, float z, float length, float width)
+{
+    camera.set(x, y, z);
+    lengthAngle = length;
+    widthAngle = width;
+}
+
+const Vector3D& Shader::getFront() const
+{
+    return front;
+}
+
+const Vector3D& Shader::getBack() const
+{
+    return back;
+}
+
+const Vector3D& Shader::getRight() const
+{
+    return right;
+}
+
+const Vector3D& Shader::getLeft() const
+{
+    return left;
+}
+
+const Vector3D& Shader::getUp() const
+{
+    return up;
+}
+
+const Vector3D& Shader::getDown() const
+{
+    return down;
+}
+
+void Shader::setTextureEnabled(bool use)
+{
+    GameEngine::get()->setInt(unifUseTexture, use);
+}
+
+void Shader::setColorEnabled(bool use)
+{
+    GameEngine::get()->setInt(unifUseColor, use);
+}
+
+void Shader::setMixColorEnabled(bool use)
+{
+    GameEngine::get()->setInt(unifUseMixColor, use);
+}
+
+void Shader::setMixColor(float r, float g, float b, float a)
+{
+    GameEngine::get()->setFloat(unifUseMixColor, r, g, b, a);
+}
+
+void Shader::setTextMode()
+{
+    setTextureEnabled(true);
+    setColorEnabled(true);
+    setUseBlending(true);
+    setMixColorEnabled(false);
+}
+
+void Shader::setUseBlending(bool use)
+{
+    if(use)
+    {
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glBlendEquation(GL_FUNC_ADD);
+    }
+    else
+    {
+        glDisable(GL_BLEND);
+    }
+}
+
+void Shader::pop()
+{
+    model.pop();
+}
+
+void Shader::push()
+{
+    model.push();
+}
+
+void Shader::setToIdentity()
+{
+    model.get().setToIdentity();
+}
+
+void Shader::scale(float sx, float sy, float sz)
+{
+    model.get().scale(sx, sy, sz);
+}
+
+void Shader::translate(float tx, float ty, float tz)
+{
+    model.get().translate(tx, ty, tz);
+}
+
+void Shader::translateX(float tx)
+{
+    model.get().translateX(tx);
+}
+
+void Shader::translateY(float ty)
+{
+    model.get().translateY(ty);
+}
+
+void Shader::translateZ(float tz)
+{
+    model.get().translateZ(tz);
+}
+
+void Shader::translateTo(float tx, float ty, float tz)
+{
+    model.get().translateTo(tx, ty, tz);
+}
+
+void Shader::rotate(float xDegrees, float yDegrees, float zDegrees)
+{
+    model.get().rotate(xDegrees, yDegrees, zDegrees);
+}
+
+void Shader::rotateX(float degrees)
+{
+    model.get().rotateX(degrees);
+}
+
+void Shader::rotateY(float degrees)
+{
+    model.get().rotateY(degrees);
+}
+
+void Shader::rotateZ(float degrees)
+{
+    model.get().rotateZ(degrees);
+}
+
+void Shader::updateModelMatrix()
+{
+    GameEngine::get()->setMatrix(unifModelMatrix, model.get().getValues());
+}

+ 86 - 0
engine/Shader.h

@@ -0,0 +1,86 @@
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include "../math/Vector3D.h"
+#include "../math/Matrix3D.h"
+#include "../math/Matrix3DStack.h"
+
+class Shader
+{
+public:
+    Shader();
+    Shader(const Shader& orig);
+    virtual ~Shader();
+    
+    void set3DMode(float lag);
+    void set2DMode();
+    
+    void storeCamera();
+    void setCamera(float x, float y, float z, float length, float width);
+
+    const Vector3D& getFront() const;
+    const Vector3D& getBack() const;
+    const Vector3D& getRight() const;
+    const Vector3D& getLeft() const;
+    const Vector3D& getUp() const;
+    const Vector3D& getDown() const;
+    
+    void setTextureEnabled(bool use);
+    void setColorEnabled(bool use);
+    void setMixColorEnabled(bool use);
+    void setMixColor(float r, float g, float b, float a);
+    void setTextMode();
+    
+    void setUseBlending(bool use);
+    
+    // model matrix operations
+    
+    void pop();
+    void push();
+    void setToIdentity();
+    void scale(float sx, float sy, float sz);
+    void translate(float tx, float ty, float tz);
+    void translateX(float tx);
+    void translateY(float ty);
+    void translateZ(float tz);
+    void translateTo(float tx, float ty, float tz);
+    void rotate(float xDegrees, float yDegrees, float zDegrees);
+    void rotateX(float degrees);
+    void rotateY(float degrees);
+    void rotateZ(float degrees);
+    void updateModelMatrix();
+
+private:
+    Matrix3D proj;
+    int unifProjMatrix = 0;
+    Matrix3D view;
+    int unifViewMatrix = 0;
+    Matrix3DStack model;
+    int unifModelMatrix = 0;
+    
+    Vector3D oldCamera;
+    Vector3D camera;
+    float oldLengthAngle;
+    float lengthAngle;
+    float oldWidthAngle;
+    float widthAngle;
+    
+    Vector3D front;
+    Vector3D back;
+    Vector3D right;
+    Vector3D left;
+    Vector3D up;
+    Vector3D down;   
+    
+    float fovY = 60;
+    float nearClip = 0.1f;
+    float farClip = 1000.0f;
+    
+    int unifUseTexture = 0;
+    int unifUseColor = 0;
+    int unifUseMixColor = 0;
+    int unifMixColorLoc = 0;
+};
+
+#endif
+

+ 6 - 6
engine/Texture.cpp

@@ -6,8 +6,13 @@ using namespace std;
 
 GLuint Texture::boundTexture = 0; 
 
-Texture::Texture()
+Texture::Texture(const char* path)
 {
+    if(!load(path))
+    {
+        loaded = true;
+        cout << "cannot load texture " << path << endl;
+    }
 }
 
 Texture::Texture(const Texture& orig)
@@ -28,11 +33,6 @@ Texture::~Texture()
 
 bool Texture::load(const char* path)
 {
-    if(loaded)
-    {
-        return false;
-    }
-    loaded = true;
     FILE* file = fopen(path, "r");
     if(file == NULL)
     {

+ 2 - 2
engine/Texture.h

@@ -8,14 +8,14 @@
 class Texture
 {
 public:
-    Texture();
+    Texture(const char* path);
     Texture(const Texture& orig);
     virtual ~Texture();
     
-    bool load(const char* path);
     void bind();
     bool isLoaded();
 private:
+    bool load(const char* path);
     bool load(const char* path, FILE* file);
     void initGL();
     

+ 1 - 2
engine/Utils.cpp

@@ -3,5 +3,4 @@
 float interpolate(float lag, float from, float to)
 {
     return from + lag * (to - from);
-}
-
+}

+ 1 - 4
math/Vector3D.cpp

@@ -9,11 +9,8 @@ Vector3D::Vector3D(float ix, float iy, float iz) : x(ix), y(iy), z(iz)
 {
 }
 
-Vector3D::Vector3D(const Vector3D& orig)
+Vector3D::Vector3D(const Vector3D& orig) : x(orig.x), y(orig.y), z(orig.z)
 {
-    x = orig.x;
-    y = orig.y;
-    z = orig.z;
 }
 
 Vector3D::~Vector3D()

+ 1 - 0
shader/fragment.fs

@@ -4,6 +4,7 @@ uniform sampler2D samp;
 
 uniform mat4 projMatrix;
 uniform mat4 viewMatrix;
+uniform mat4 modelMatrix;
 
 uniform bool useTexture;
 uniform bool useColor;

+ 2 - 1
shader/vertex.vs

@@ -8,6 +8,7 @@ uniform sampler2D samp;
 
 uniform mat4 projMatrix;
 uniform mat4 viewMatrix;
+uniform mat4 modelMatrix;
 
 uniform bool useTexture;
 uniform bool useColor;
@@ -21,5 +22,5 @@ void main(void)
 { 
     tc = tex; 
     outColor = color;
-    gl_Position = projMatrix * viewMatrix * vec4(pos, 1.0);
+    gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(pos, 1.0);
 }

+ 6 - 0
specs

@@ -0,0 +1,6 @@
+basic minecraft clone:
+- flat terrain, 16x16 chunks, 8x8 Chunk World
+- 2 blocks, stone and air
+- player model
+- collision of player with world
+- block aiming, left click: break block, right click: place block

+ 115 - 0
world/Chunk.cpp

@@ -0,0 +1,115 @@
+#include "Chunk.h"
+
+Chunk::Chunk(int chunkX, int chunkZ) : chunkX(chunkX), chunkZ(chunkZ)
+{
+    for(int i = 0; i < WORLD_HIGH; i++)
+    {
+        dirty[i] = true;
+    }
+    for(int y = 0; y < MAX_Y; y++)
+    {
+        for(int x = 0; x < CHUNK_SIZE; x++)
+        {
+            for(int z = 0; z < CHUNK_SIZE; z++)
+            {
+                blocks[y][x][z] = 0;
+            }
+        }
+    }
+}
+
+Chunk::Chunk(const Chunk& orig)
+{
+}
+
+Chunk::~Chunk()
+{
+}
+
+void Chunk::setBlock(int x, int y, int z, unsigned short block)
+{
+    if(x >= 0 && x < CHUNK_SIZE && y >= 0 && y < MAX_Y && z >= 0 && z < CHUNK_SIZE)
+    {
+        blocks[y][x][z] = block;
+    }
+}
+
+unsigned short Chunk::getBlock(int x, int y, int z)
+{
+    if(x >= 0 && x < CHUNK_SIZE && y >= 0 && y < MAX_Y && z >= 0 && z < CHUNK_SIZE)
+    {
+        return blocks[y][x][z];
+    }
+    return 0;
+}
+
+void Chunk::init()
+{
+    for(int i = 0; i < WORLD_HIGH; i++)
+    {
+        mesh[i].init();
+    }
+}
+
+void Chunk::renderTick(float lag)
+{
+    for(int i = 0; i < WORLD_HIGH; i++)
+    {
+        if(dirty[i])
+        {
+            mesh[i].build();
+            /*
+             // bottom
+    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.125f, 0.0f);
+    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0f);
+    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.125f, 0.0625f);
+    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0f);
+    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.125f, 0.0625f);
+    
+    // top
+    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.25f, 0.0f);
+    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.3125f, 0.0f);
+    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.3125f, 0.0f);
+    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.3125f, 0.0625f);
+    
+    // right
+    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
+    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    
+    // left
+    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
+    
+    // back
+    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(1.0f, 0.0f, 1.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    tmesh.addPoint(0.0f, 0.0f, 1.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 1.0f, 0.25f, 0.0f);
+    tmesh.addPoint(0.0f, 1.0f, 1.0f, 0.1875f, 0.0f);
+    
+    // front
+    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.25f, 0.0f);
+    tmesh.addPoint(1.0f, 0.0f, 0.0f, 0.25f, 0.0625f);
+    tmesh.addPoint(0.0f, 0.0f, 0.0f, 0.1875f, 0.0625f);
+    tmesh.addPoint(0.0f, 1.0f, 0.0f, 0.1875f, 0.0f);
+    tmesh.addPoint(1.0f, 1.0f, 0.0f, 0.25f, 0.0f);
+             
+             */
+        }
+        mesh[i].draw();
+    }
+}
+

+ 32 - 0
world/Chunk.h

@@ -0,0 +1,32 @@
+#ifndef CHUNK_H
+#define CHUNK_H
+
+#include "../engine/TextureMesh.h"
+
+class Chunk
+{
+public:
+    Chunk(int chunkX, int chunkZ);
+    Chunk(const Chunk& orig);
+    virtual ~Chunk();
+    
+    void setBlock(int x, int y, int z, unsigned short block);
+    unsigned short getBlock(int x, int y, int z);
+    
+    static const int WORLD_HIGH = 16;
+    static const int CHUNK_SIZE = 16;
+    static const int MAX_Y = WORLD_HIGH * CHUNK_SIZE;
+    
+    void init();
+    void renderTick(float lag);
+private:
+    int chunkX;
+    int chunkZ;
+    
+    unsigned short blocks[MAX_Y][CHUNK_SIZE][CHUNK_SIZE];
+    bool dirty[WORLD_HIGH];
+    TextureMesh mesh[WORLD_HIGH];
+};
+
+#endif
+