, ctx(window.CreateContext())
, init_glew()
, program()
-, move_velocity(0.003f)
-, pitch_sensitivity(-0.0025f)
-, yaw_sensitivity(-0.001f)
, cam()
, hud()
, world()
, outline_visible(false)
, outline_transform(1.0f)
, running(false)
-, front(false)
-, back(false)
-, left(false)
-, right(false)
-, up(false)
-, down(false)
, place(false)
, remove(false)
, pick(false)
world.Generate();
- cam.Position(glm::vec3(0, 4, 4));
hud.Viewport(960, 600);
hud.Display(*world.BlockTypes()[place_id]);
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
- switch (event.key.keysym.sym) {
- case SDLK_w:
- front = event.key.state == SDL_PRESSED;
- break;
- case SDLK_s:
- back = event.key.state == SDL_PRESSED;
- break;
- case SDLK_a:
- left = event.key.state == SDL_PRESSED;
- break;
- case SDLK_d:
- right = event.key.state == SDL_PRESSED;
- break;
- case SDLK_q:
- case SDLK_SPACE:
- up = event.key.state == SDL_PRESSED;
- break;
- case SDLK_e:
- case SDLK_LSHIFT:
- down = event.key.state == SDL_PRESSED;
- break;
- }
+ world.Controller().HandleKeyboard(event.key);
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == 1) {
}
break;
case SDL_MOUSEMOTION:
- cam.RotateYaw(event.motion.xrel * yaw_sensitivity);
- cam.RotatePitch(event.motion.yrel * pitch_sensitivity);
+ world.Controller().HandleMouse(event.motion);
break;
case SDL_QUIT:
running = false;
}
void Application::Update(int dt) {
- glm::vec3 vel;
- if (right && !left) {
- vel.x = move_velocity;
- } else if (left && !right) {
- vel.x = -move_velocity;
- }
- if (up && !down) {
- vel.y = move_velocity;
- } else if (down && !up) {
- vel.y = -move_velocity;
- }
- if (back && !front) {
- vel.z = move_velocity;
- } else if (front && !back) {
- vel.z = -move_velocity;
- }
- cam.OrientationVelocity(vel);
+ world.Update(dt);
- cam.Update(dt);
-
- Ray aim = cam.Aim();
+ Ray aim = world.Controller().Aim();
Chunk *chunk;
int blkid;
float dist;
program.Activate();
- program.SetLightDirection({ -1.0f, -3.0f, -2.0f });
- program.SetVP(cam.View(), cam.Projection());
-
- for (Chunk &chunk : world.LoadedChunks()) {
- program.SetM(chunk.Transform());
- chunk.Draw();
- }
+ program.SetProjection(cam.Projection());
+ world.Render(program);
if (outline_visible) {
program.SetM(outline_transform);
InitGLEW init_glew;
DirectionalLighting program;
- float move_velocity;
- float pitch_sensitivity;
- float yaw_sensitivity;
-
Camera cam;
HUD hud;
World world;
- OutlineModel outline;
+ OutlineModel outline;
bool outline_visible;
glm::mat4 outline_transform;
bool running;
- bool front, back, left, right, up, down;
bool place, remove, pick;
int remove_id;
namespace blank {
Camera::Camera()
-: FPSController()
-, fov(45.0f)
+: fov(45.0f)
, aspect(1.0f)
, near_clip(0.1f)
, far_clip(100.0f)
-, projection(glm::perspective(fov, aspect, near_clip, far_clip))
-, view(glm::inverse(Transform())) {
+, projection(glm::perspective(fov, aspect, near_clip, far_clip)) {
}
UpdateProjection();
}
-Ray Camera::Aim() const {
- const glm::mat4 inv_vp(glm::inverse(projection * view));
- glm::vec4 from = inv_vp * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f);
- from /= from.w;
- glm::vec4 to = inv_vp * glm::vec4(0.0f, 0.0f, 1.0f, 1.0f);
- to /= to.w;
- return Ray{ glm::vec3(from), glm::normalize(glm::vec3(to - from)) };
-}
-
-
-void Camera::Update(int dt) {
- FPSController::Update(dt);
- view = glm::inverse(Transform());
-}
void Camera::UpdateProjection() {
projection = glm::perspective(fov, aspect, near_clip, far_clip);
#include <glm/glm.hpp>
-#include "controller.hpp"
-#include "geometry.hpp"
-
namespace blank {
-class Camera
-: public FPSController {
+class Camera {
public:
Camera();
- Camera(const Camera &) = delete;
- Camera &operator =(const Camera &) = delete;
-
void Viewport(int width, int height);
void Viewport(int x, int y, int width, int height);
void Aspect(float w, float h);
void Clip(float near, float far);
- Ray Aim() const;
-
const glm::mat4 &Projection() { return projection; }
- const glm::mat4 &View() { return view; }
-
- void Update(int dt);
private:
void UpdateProjection();
float far_clip;
glm::mat4 projection;
- glm::mat4 view;
};
: velocity(0, 0, 0)
, position(0, 0, 0)
, pitch(0)
-, yaw(0) {
+, yaw(0)
+, transform(1.0f)
+, dirty(true)
+, move_velocity(0.003f)
+, pitch_sensitivity(-0.0025f)
+, yaw_sensitivity(-0.001f)
+, front(false)
+, back(false)
+, left(false)
+, right(false)
+, up(false)
+, down(false) {
}
-glm::mat4 FPSController::Transform() const {
- return glm::translate(position) * glm::eulerAngleYX(yaw, pitch);
+const glm::mat4 &FPSController::Transform() const {
+ if (dirty) {
+ transform = glm::translate(position) * glm::eulerAngleYX(yaw, pitch);
+ dirty = false;
+ }
+ return transform;
+}
+
+Ray FPSController::Aim() const {
+ glm::vec4 from = Transform() * glm::vec4(0.0f, 0.0f, 1.0f, 1.0f);
+ from /= from.w;
+ glm::vec4 to = Transform() * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f);
+ to /= to.w;
+ return Ray{ glm::vec3(from), glm::normalize(glm::vec3(to - from)) };
}
void FPSController::OrientationVelocity(const glm::vec3 &vel) {
- velocity = glm::rotateY(vel, yaw);
+ Velocity(glm::rotateY(vel, yaw));
+}
+
+
+void FPSController::Pitch(float p) {
+ pitch = p;
+ if (pitch > PI / 2) {
+ pitch = PI / 2;
+ } else if (pitch < -PI / 2) {
+ pitch = -PI / 2;
+ }
+ dirty = true;
+}
+
+void FPSController::RotatePitch(float delta) {
+ Pitch(pitch + delta);
+}
+
+void FPSController::Yaw(float y) {
+ yaw = y;
+ if (yaw > PI) {
+ yaw -= PI * 2;
+ } else if (yaw < -PI) {
+ yaw += PI * 2;
+ }
+ dirty = true;
+}
+
+void FPSController::RotateYaw(float delta) {
+ Yaw(yaw + delta);
+}
+
+
+void FPSController::HandleKeyboard(const SDL_KeyboardEvent &event) {
+ switch (event.keysym.sym) {
+ case SDLK_w:
+ front = event.state == SDL_PRESSED;
+ break;
+ case SDLK_s:
+ back = event.state == SDL_PRESSED;
+ break;
+ case SDLK_a:
+ left = event.state == SDL_PRESSED;
+ break;
+ case SDLK_d:
+ right = event.state == SDL_PRESSED;
+ break;
+ case SDLK_q:
+ case SDLK_SPACE:
+ up = event.state == SDL_PRESSED;
+ break;
+ case SDLK_e:
+ case SDLK_LSHIFT:
+ down = event.state == SDL_PRESSED;
+ break;
+ }
+}
+
+void FPSController::HandleMouse(const SDL_MouseMotionEvent &event) {
+ RotateYaw(event.xrel * yaw_sensitivity);
+ RotatePitch(event.yrel * pitch_sensitivity);
}
void FPSController::Update(int dt) {
- position += velocity * float(dt);
+ glm::vec3 vel;
+ if (right && !left) {
+ vel.x = move_velocity;
+ } else if (left && !right) {
+ vel.x = -move_velocity;
+ }
+ if (up && !down) {
+ vel.y = move_velocity;
+ } else if (down && !up) {
+ vel.y = -move_velocity;
+ }
+ if (back && !front) {
+ vel.z = move_velocity;
+ } else if (front && !back) {
+ vel.z = -move_velocity;
+ }
+ OrientationVelocity(vel);
+
+ Move(velocity * float(dt));
}
}
#ifndef BLANK_CONTROLLER_HPP_
#define BLANK_CONTROLLER_HPP_
+#include "geometry.hpp"
+
+#include <SDL.h>
#include <glm/glm.hpp>
public:
FPSController();
- glm::mat4 Transform() const;
+ const glm::mat4 &Transform() const;
+ Ray Aim() const;
- void Velocity(glm::vec3 vel) { velocity = vel; }
+ void Velocity(glm::vec3 vel) { velocity = vel; dirty = true; }
void OrientationVelocity(const glm::vec3 &vel);
- void Position(glm::vec3 pos) { position = pos; }
- void Move(glm::vec3 delta) { position += delta; }
+ void Position(glm::vec3 pos) { position = pos; dirty = true; }
+ void Move(glm::vec3 delta) { Position(position + delta); }
// all angles in radians (full circle = 2π)
float Pitch() const { return pitch; }
- void Pitch(float p) { pitch = p; }
- void RotatePitch(float delta) { pitch += delta; }
+ void Pitch(float p);
+ void RotatePitch(float delta);
float Yaw() const { return yaw; }
- void Yaw(float y) { yaw = y; }
- void RotateYaw(float delta) { yaw += delta; }
+ void Yaw(float y);
+ void RotateYaw(float delta);
+
+ void HandleKeyboard(const SDL_KeyboardEvent &);
+ void HandleMouse(const SDL_MouseMotionEvent &);
void Update(int dt);
float pitch;
float yaw;
+ mutable glm::mat4 transform;
+ mutable bool dirty;
+
+ float move_velocity;
+ float pitch_sensitivity;
+ float yaw_sensitivity;
+
+ bool front, back, left, right, up, down;
+
};
}
namespace blank {
+constexpr float PI = 3.141592653589793238462643383279502884;
+
struct AABB {
glm::vec3 min;
glm::vec3 max;
glUniform3f(light_direction_handle, light_direction.x, light_direction.y, light_direction.z);
}
+void DirectionalLighting::SetProjection(const glm::mat4 &p) {
+ projection = p;
+ vp = p * view;
+}
+
+void DirectionalLighting::SetView(const glm::mat4 &v) {
+ view = v;
+ vp = projection * v;
+}
+
void DirectionalLighting::SetVP(const glm::mat4 &v, const glm::mat4 &p) {
+ projection = p;
+ view = v;
vp = p * v;
}
void SetLightDirection(const glm::vec3 &);
void SetM(const glm::mat4 &m);
+ void SetProjection(const glm::mat4 &p);
+ void SetView(const glm::mat4 &v);
void SetVP(const glm::mat4 &v, const glm::mat4 &p);
void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p);
glm::vec3 light_direction;
glm::vec3 light_color;
+ glm::mat4 projection;
+ glm::mat4 view;
glm::mat4 vp;
GLuint m_handle;
blockType.Add(BlockType{ true, { 0.0f, 0.0f, 1.0f }, &blockShape }); // blue block
blockType.Add(BlockType{ true, { 0.0f, 0.0f, 1.0f }, &stairShape }); // blue stair
blockType.Add(BlockType{ true, { 0.0f, 0.0f, 1.0f }, &slabShape }); // blue slab
+
+ player.Position({ 4.0f, 4.0f, 4.0f });
}
return Generate(tgt_pos);
}
+
+void World::Update(int dt) {
+ player.Update(dt);
+}
+
+
+void World::Render(DirectionalLighting &program) {
+ program.SetLightDirection({ -1.0f, -3.0f, -2.0f });
+ program.SetView(glm::inverse(player.Transform()));
+
+ for (Chunk &chunk : LoadedChunks()) {
+ program.SetM(chunk.Transform());
+ chunk.Draw();
+ }
+}
+
}
#ifndef BLANK_WORLD_HPP_
#define BLANK_WORLD_HPP_
+#include "controller.hpp"
#include "geometry.hpp"
#include "model.hpp"
#include "noise.hpp"
+#include "shader.hpp"
#include "shape.hpp"
#include <list>
BlockTypeRegistry &BlockTypes() { return blockType; }
std::list<Chunk> &LoadedChunks() { return chunks; }
+ FPSController &Controller() { return player; }
+
Chunk &Next(const Chunk &, const glm::vec3 &dir);
+ void Update(int dt);
+
+ void Render(DirectionalLighting &);
+
private:
Chunk &Generate(const glm::vec3 &);
SimplexNoise blockNoise;
SimplexNoise colorNoise;
+ FPSController player;
+
std::list<Chunk> chunks;
};