Skip to content

Commit bddf3b0

Browse files
committedMar 31, 2015
Initial commit
0 parents  commit bddf3b0

25 files changed

+2414
-0
lines changed
 

‎.gitignore

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
build/
2+
lib/
3+
bin/
4+
raknet/
5+
.gitattributes
6+
7+
## Vim
8+
*~
9+
*.swp
10+
11+
## eclipse
12+
.cproject
13+
.project
14+
.settings
15+
16+
#################################
17+
## Code::Blocks
18+
#################################
19+
*.bmarks
20+
*.cbp
21+
*.layout
22+
*_build_log.html
23+
24+
################################
25+
# CMake
26+
################################
27+
CMakeCache.txt
28+
CMakeFiles/
29+
CMakeScripts/
30+
cmake_install.cmake
31+
compile_commands.json
32+
cscope.out
33+
*.cscope_file_list
34+
*.depend
35+
# We don't want to see Makefiles modifications
36+
Makefile
37+
38+
################################
39+
#Xcode
40+
################################
41+
42+
trillek-client-core.build
43+
trillek-client-core.xcodeproj
44+
45+
###############################
46+
# NetBean
47+
###############################
48+
nbproject/

‎CMakeLists.txt

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
2+
3+
PROJECT("VoxelVolution")
4+
5+
# Set the directory of cmake modules
6+
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/modules")
7+
8+
# Put the executable in the bin folder
9+
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
10+
11+
# find all source files in the src directory
12+
FILE(GLOB_RECURSE VV_SRC "src/*.cpp")
13+
14+
# find all the files in the includes directory
15+
FILE(GLOB_RECURSE VV_INCLUDES "include/*.h" "include/*.hpp")
16+
17+
#Check if we can build with the current tool chain
18+
INCLUDE(SetCompilerFlags)
19+
20+
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/include/)
21+
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include/")
22+
23+
# If we are on windows add in the local search directories as well.
24+
IF (WIN32 AND NOT MINGW) # Windows
25+
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/lib/include/)
26+
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/lib/include/")
27+
LINK_DIRECTORIES("${CMAKE_SOURCE_DIR}/lib/")
28+
SET(CMAKE_LIBRARY_PATH ${CMAKE_SOURCE_DIR}/lib/)
29+
ENDIF (WIN32 AND NOT MINGW)
30+
31+
FIND_PACKAGE(GLM REQUIRED)
32+
FIND_PACKAGE(OpenGL REQUIRED)
33+
FIND_PACKAGE(GLFW3 REQUIRED)
34+
35+
# Give these some dummy values and if the platform is LINUX or OSX they will be set accordingly.
36+
SET(X11_LIBRARIES "")
37+
SET(OSX_LIBRARIES "")
38+
39+
IF (NOT APPLE) # X11 and GLEW are not needed on OSX.
40+
FIND_PACKAGE(X11)
41+
FIND_PACKAGE(GLEW REQUIRED) # We find GLEW here as OSX doesn't need it.
42+
ENDIF (NOT APPLE)
43+
44+
IF (APPLE) # Mac OSX
45+
SET(GLEW_LIBRARY "") # Set a dummy value for GLEW.
46+
47+
SET(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS macosx)
48+
49+
# Need the 10.7 SDK or later.
50+
EXECUTE_PROCESS(COMMAND xcodebuild -sdk macosx -version SDKVersion OUTPUT_VARIABLE OSX_SDK_VERSION)
51+
IF (NOT (OSX_SDK_VERSION VERSION_GREATER 10.7 OR OSX_SDK_VERSION VERSION_EQUAL 10.7))
52+
MESSAGE(FATAL_ERROR "The installed version of Xcode does not support the 10.7 SDK or later. Please upgrade Xcode and try again.")
53+
ENDIF (NOT (OSX_SDK_VERSION VERSION_GREATER 10.7 OR OSX_SDK_VERSION VERSION_EQUAL 10.7))
54+
55+
# Configure the project to use the correct SDK.
56+
IF (XCODE_VERSION)
57+
SET(CMAKE_OSX_SYSROOT macosx)
58+
ELSE (XCODE_VERSION)
59+
# Non-Xcode generators need the full path.
60+
EXECUTE_PROCESS(COMMAND xcodebuild -sdk macosx -version Path | head -n 1 OUTPUT_VARIABLE CMAKE_OSX_SYSROOT)
61+
STRING(REGEX REPLACE "(\r?\n)+$" "" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}")
62+
ENDIF (XCODE_VERSION)
63+
64+
# Can deploy back to 10.7, the first OS X to support the GL Core.
65+
SET(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
66+
67+
# Need Core Foundation and libobjc.
68+
SET(OSX_LIBRARIES "-framework CoreFoundation /usr/lib/libobjc.dylib")
69+
ENDIF (APPLE)
70+
71+
# define all required external libraries
72+
set(VV_ALL_LIBS
73+
${OPENGL_LIBRARIES}
74+
${GLFW3_LIBRARIES}
75+
${X11_LIBRARIES}
76+
${OSX_LIBRARIES}
77+
${GLEW_LIBRARIES}
78+
)
79+
80+
ADD_EXECUTABLE("VoxelVolution"
81+
${VV_SRC}
82+
${VV_INCLUDES}
83+
)
84+
85+
TARGET_LINK_LIBRARIES("VoxelVolution" ${VV_ALL_LIBS})

‎assets/basic.frag

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#version 330 core
2+
in vec3 pass_Color;
3+
out vec4 color;
4+
5+
void main(){
6+
color = vec4(pass_Color, 1.0);
7+
}

‎assets/basic.vert

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#version 330
2+
layout(location = 0) in vec3 in_Position;
3+
layout(location = 1) in vec3 in_Color;
4+
uniform mat4 model;
5+
uniform mat4 view;
6+
uniform mat4 projection;
7+
out vec3 pass_Color;
8+
void main(void)
9+
{
10+
mat4 mvp = projection * view * model;
11+
gl_Position = mvp * vec4(in_Position, 1.0);
12+
pass_Color = in_Color;
13+
}

‎assets/overlay.frag

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#version 330 core
2+
in vec3 pass_Color;
3+
out vec4 color;
4+
5+
void main(){
6+
gl_FragCoord.z - (1.0f / 1600000.0);
7+
color = vec4(0.0,0.0,0.0,1.0);
8+
}

‎include/command-queue.hpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <queue>
4+
#include <memory>
5+
#include <atomic>
6+
#include "multiton.hpp"
7+
8+
namespace vv {
9+
// Base class used for commands. T is the command id type (e.g. enum, int, char).
10+
template <typename T>
11+
struct Command {
12+
Command(T c, GUID entity_id) : command(c), entity_id(entity_id) { }
13+
T command;
14+
GUID entity_id;
15+
};
16+
17+
// T is the command id type (e.g. enum, int, char), and U is the derived command type.
18+
template <class T>
19+
class CommandQueue {
20+
public:
21+
CommandQueue() :
22+
local_queue(new std::queue<std::shared_ptr<Command<T>>>()) { }
23+
~CommandQueue() { }
24+
25+
template <typename U, typename V>
26+
static void QueueCommand(const T c, const GUID entity_id, V data = nullptr) {
27+
auto command = std::make_shared<U>(c, entity_id, data);
28+
(*global_queue).push(command);
29+
}
30+
31+
static void QueueCommand(const T c, const GUID entity_id) {
32+
auto command = std::make_shared<Command<T>>(c, entity_id);
33+
(*global_queue).push(command);
34+
}
35+
protected:
36+
static std::atomic<std::queue<std::shared_ptr<Command<T>>>*> global_queue;
37+
std::queue<std::shared_ptr<Command<T>>>* local_queue;
38+
};
39+
}

‎include/dispatcher.hpp

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#pragma once
2+
3+
#include <list>
4+
#include <map>
5+
#include <memory>
6+
#include <mutex>
7+
8+
#include "multiton.hpp"
9+
10+
namespace vv {
11+
// Base class for data change subscriptions.
12+
template <typename T>
13+
class Subscriber {
14+
public:
15+
virtual void Notify(const GUID entity_id, const T* data) { }
16+
virtual void Notify(const T* data) { }
17+
virtual void Notify(const GUID entity_id, const T data) { }
18+
virtual void Notify(const T data) { }
19+
};
20+
21+
// Dispatches data change notifications to the various subscribers.
22+
template <typename T>
23+
class Dispatcher final {
24+
private:
25+
Dispatcher() { }
26+
Dispatcher(const Dispatcher& right) {
27+
instance = right.instance;
28+
}
29+
Dispatcher& operator=(const Dispatcher& right) {
30+
if (this != &right) {
31+
instance = right.instance;
32+
}
33+
34+
return *this;
35+
}
36+
static std::once_flag only_one;
37+
static std::shared_ptr<Dispatcher<T>> instance;
38+
public:
39+
static std::shared_ptr<Dispatcher<T>> GetInstance() {
40+
std::call_once(Dispatcher::only_one,
41+
[ ] () {
42+
Dispatcher<T>::instance.reset(new Dispatcher<T>());
43+
}
44+
);
45+
46+
return Dispatcher<T>::instance;
47+
}
48+
~Dispatcher() { }
49+
50+
/**
51+
* \brief Subscribes to be notified of data change events.
52+
*
53+
* \param const unsigned int entity_id ID of the entity to subscribe to.
54+
* \param const Subscriber<T>* subscriber The subscriber to add.
55+
* \return void
56+
*/
57+
void Subscribe(const GUID entity_id, Subscriber<T>* subscriber) {
58+
auto sube = this->subcriberss.find(entity_id);
59+
if (sube == this->subcriberss.end()) {
60+
// no subscriptions for entity, add the entity and subscriber
61+
this->subcriberss[entity_id].push_back(subscriber);
62+
return;
63+
}
64+
else {
65+
// check if subscriber already exists
66+
for (auto sub : sube->second) {
67+
if (sub == subscriber) {
68+
return; // already subscribed
69+
}
70+
}
71+
sube->second.push_back(subscriber);
72+
}
73+
}
74+
75+
/**
76+
* \brief Subscribes to be notified of data change events for any entity ID.
77+
*
78+
* \param const Subscriber<T>* subscriber The subscriber to add.
79+
* \return void
80+
*/
81+
void Subscribe(Subscriber<T>* subscriber) {
82+
this->subcriberss[0].push_back(subscriber);
83+
}
84+
85+
/**
86+
* \brief Unsubscribes to notification of data change events.
87+
*
88+
* \param const unsigned int entity_id ID of the entity to unsubscribe from.
89+
* \param const Subscriber<T>* subscriber The subscriber to remove.
90+
* \return void
91+
*/
92+
void Unsubscribe(const GUID entity_id, Subscriber<T>* subscriber) {
93+
if (this->subcriberss.find(entity_id) != this->subcriberss.end()) {
94+
this->subcriberss[entity_id].remove(subscriber);
95+
}
96+
}
97+
98+
/**
99+
* \brief Unsubscribes to notification of data change events.
100+
*
101+
* \param const Subscriber<T>* subscriber The subscriber to remove.
102+
* \return void
103+
*/
104+
void Unsubscribe(Subscriber<T>* subscriber) {
105+
if (this->subcriberss.find(0) != this->subcriberss.end()) {
106+
this->subcriberss[0].remove(subscriber);
107+
}
108+
}
109+
110+
/**
111+
* \brief Called to notify all subscribers that the data has changed.
112+
*
113+
* \param const unsigned int entity_id ID of the entity to update.
114+
* \param const T* data The changed data.
115+
* \return void
116+
*/
117+
void NotifySubscribers(const GUID entity_id, const T* data) {
118+
if (this->subcriberss.find(entity_id) != this->subcriberss.end()) {
119+
auto subscriber_list = this->subcriberss.at(entity_id);
120+
for (Subscriber<T>* subscriber : subscriber_list) {
121+
subscriber->Notify(entity_id, data);
122+
}
123+
}
124+
125+
if (this->subcriberss.find(0) != this->subcriberss.end()) {
126+
auto subscriber_list = this->subcriberss.at(0);
127+
for (Subscriber<T>* subscriber : subscriber_list) {
128+
subscriber->Notify(entity_id, data);
129+
}
130+
}
131+
}
132+
void NotifySubscribers(const GUID entity_id, const T data) {
133+
if (this->subcriberss.find(entity_id) != this->subcriberss.end()) {
134+
auto subscriber_list = this->subcriberss.at(entity_id);
135+
for (Subscriber<T>* subscriber : subscriber_list) {
136+
subscriber->Notify(entity_id, data);
137+
}
138+
}
139+
140+
if (this->subcriberss.find(0) != this->subcriberss.end()) {
141+
auto subscriber_list = this->subcriberss.at(0);
142+
for (Subscriber<T>* subscriber : subscriber_list) {
143+
subscriber->Notify(entity_id, data);
144+
}
145+
}
146+
}
147+
148+
/**
149+
* \brief Called to notify all subscribers for entity ID 0 that the data has changed.
150+
*
151+
* \param const T* data The changed data.
152+
* \return void
153+
*/
154+
void NotifySubscribers(const T* data) {
155+
if (this->subcriberss.find(0) != this->subcriberss.end()) {
156+
auto subscriber_list = this->subcriberss.at(0);
157+
for (Subscriber<T>* subscriber : subscriber_list) {
158+
subscriber->Notify(data);
159+
}
160+
}
161+
}
162+
void NotifySubscribers(const T data) {
163+
if (this->subcriberss.find(0) != this->subcriberss.end()) {
164+
auto subscriber_list = this->subcriberss.at(0);
165+
for (Subscriber<T>* subscriber : subscriber_list) {
166+
subscriber->Notify(data);
167+
}
168+
}
169+
}
170+
private:
171+
std::map<GUID, std::list<Subscriber<T>*>> subcriberss;
172+
};
173+
174+
template<typename T>
175+
std::once_flag Dispatcher<T>::only_one;
176+
177+
template<typename T>
178+
std::shared_ptr<Dispatcher<T>> Dispatcher<T>::instance = nullptr;
179+
}

‎include/material.hpp

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <memory>
4+
5+
#ifndef __APPLE__
6+
#include <GL/glew.h>
7+
#else
8+
#include <OpenGL/gl3.h>
9+
#endif
10+
11+
namespace vv {
12+
class Shader;
13+
14+
typedef Multiton<std::string, std::shared_ptr<Material>> MaterialMap;
15+
16+
class Material {
17+
public:
18+
Material(const std::weak_ptr<Shader> shader) : shader(shader), fill_mode(GL_FILL) { }
19+
20+
GLenum GetFillMode() {
21+
return this->fill_mode;
22+
}
23+
24+
void SetFillMode(const GLenum mode) {
25+
switch (mode) {
26+
case GL_LINE:
27+
case GL_FILL:
28+
this->fill_mode = mode;
29+
break;
30+
default:
31+
this->fill_mode = GL_FILL;
32+
}
33+
}
34+
35+
std::weak_ptr<Shader> GetShader() {
36+
return this->shader;
37+
}
38+
private:
39+
GLenum fill_mode;
40+
std::weak_ptr<Shader> shader;
41+
};
42+
}

‎include/multiton.hpp

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#pragma once
2+
3+
#include <map>
4+
5+
namespace vv {
6+
typedef long long GUID;
7+
8+
/* Based class to be used for instace or state storage.
9+
*
10+
* This is useful in place of static instances or globals. Derived classes
11+
* can operate on the static instance member using instances of the derived
12+
* class. This could allow, for example, and animation controller to derive
13+
* from this and have each instance use a separate animation sequence, but
14+
* all animation instance data would be stored in one map.
15+
*
16+
* Additionally by encapsulating the maps in this pattern we provide better
17+
* data hiding and can better control access methods to the instance data.
18+
*
19+
* Modeled after http://en.wikipedia.org/wiki/Multiton_pattern.
20+
*/
21+
template <typename ID, typename T>
22+
class Multiton {
23+
public:
24+
/**
25+
* \brief Get the default instance.
26+
*
27+
* \return T The default instance.
28+
*/
29+
static T Default() {
30+
return default_value;
31+
}
32+
33+
/**
34+
* \brief Set the default instance.
35+
*
36+
* \return void
37+
*/
38+
static void Default(const T value) {
39+
default_value = value;
40+
}
41+
42+
static typename std::map<ID, T>::const_iterator Begin() {
43+
return instances.begin();
44+
}
45+
46+
static typename std::map<ID, T>::const_iterator End() {
47+
return instances.end();
48+
}
49+
50+
/**
51+
* \brief Get the instance for the given ID.
52+
*
53+
* This doesn't create an instanc if the ID doesn't exist.
54+
* Instead it just returns the default.
55+
* \param[in] const ID The ID of the instace to get.
56+
* \return T The ID's instacnce or the default one.
57+
*/
58+
static T Get(const ID id) {
59+
if (instances.find(id) != instances.end()) {
60+
return instances.at(id);
61+
}
62+
return default_value;
63+
}
64+
65+
/**
66+
* \brief Set (or add/create) an instance for the given ID.
67+
*
68+
* \param[in] const ID id The ID of the instance to set.
69+
* \param[in] T instance The ID's instance.
70+
* \return void
71+
*/
72+
static void Set(const ID id, const T instance) {
73+
instances[id] = instance;
74+
}
75+
76+
/**
77+
* \brief Remove the instance for the given ID.
78+
*
79+
* \param[in] const ID id The ID of the instance to remove.
80+
* \return void
81+
*/
82+
static void Remove(const ID id) {
83+
instances.erase(id);
84+
}
85+
protected:
86+
static T default_value; // Default instance.
87+
88+
// TODO: Replace this with a weak_ptr to allow pruning?
89+
static std::map<ID, T> instances; // Mapping of ID to instance.
90+
};
91+
92+
93+
template <typename ID, typename T>
94+
std::map<ID, T> Multiton<ID, T>::instances;
95+
96+
template <typename ID, typename T>
97+
T Multiton<ID, T>::default_value;
98+
}

‎include/os.hpp

+239
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
#pragma once
2+
3+
#ifndef __APPLE__
4+
#include <GL/glew.h>
5+
#ifndef __unix
6+
#include <GL/wglew.h>
7+
#endif
8+
#endif
9+
10+
#include <GLFW/glfw3.h>
11+
#include <string>
12+
#include <chrono>
13+
14+
namespace vv {
15+
struct KeyboardEvent {
16+
enum KEY_ACTION { KEY_DOWN, KEY_UP, KEY_REPEAT, KEY_CHAR };
17+
int key;
18+
int scancode;
19+
KEY_ACTION action;
20+
int mods;
21+
};
22+
23+
struct MouseBtnEvent {
24+
enum MOUSE_BTN_ACTION { DOWN, UP };
25+
enum MOUSE_BTN { LEFT, RIGHT, MIDDLE };
26+
MOUSE_BTN_ACTION action;
27+
MOUSE_BTN button;
28+
};
29+
30+
struct MouseMoveEvent {
31+
double norm_x, norm_y; // Resolution independent new x, y (0-1) from upper-left to lower-right.
32+
int old_x, old_y; // Client space old x, y.
33+
int new_x, new_y; // Client space new x, y.
34+
};
35+
36+
class OS {
37+
public:
38+
OS() : mouse_lock(false) { }
39+
~OS() { }
40+
41+
/**
42+
* \brief Initialize the rendering window and makes the window's context the current one.
43+
*
44+
* \param[in] const unsigned int width, height The window's client width and height
45+
* \param[in] const std::string title The title to show in the title bar and task manager.
46+
* \return bool If creation was successful or not.
47+
*/
48+
bool InitializeWindow(const int width, const int height, const std::string title,
49+
const unsigned int glMajor = 3, const unsigned int glMinor = 2);
50+
51+
/** \brief Make the context of the window current for the calling thread
52+
*
53+
*/
54+
void MakeCurrent();
55+
56+
/** \brief Detach the context of the window from the calling thread
57+
*
58+
*/
59+
void DetachContext();
60+
61+
/**
62+
* \brief Calls GLFWTerminate to close the window.
63+
*
64+
* This is a static method so it can be called from anywhere to terminate the current winodw.
65+
* \return void
66+
*/
67+
static void Terminate();
68+
69+
/**
70+
* \brief Checks if the window is closing.
71+
*
72+
* \return bool True if the window is closing.
73+
*/
74+
bool Closing();
75+
76+
/**
77+
* \brief Swap the front and back buffers. Call after rendering.
78+
*
79+
* \return void
80+
*/
81+
void SwapBuffers();
82+
83+
/**
84+
* \brief Processes events in the OS message event loop.
85+
*
86+
*/
87+
void OSMessageLoop();
88+
89+
/**
90+
* \brief Gets the cached window width.
91+
*
92+
* \return int The window width.
93+
*/
94+
int GetWindowWidth();
95+
96+
/**
97+
* \brief Gets the cached window height.
98+
*
99+
* \return int The window height.
100+
*/
101+
int GetWindowHeight();
102+
103+
/**
104+
* \brief Returns the time since the start of the program.
105+
*
106+
* \return double The number of nanoseconds that have pass since the last call.
107+
* that have passed.
108+
*/
109+
double GetDeltaTime();
110+
111+
/**
112+
* \brief Callback for when the window is resized.
113+
*
114+
* \param[in] GLFWwindow* window
115+
* \param[in] int width, height The new client width and height of the window.
116+
* \return void
117+
*/
118+
static void WindowResized(GLFWwindow* window, int width, int height);
119+
120+
/**
121+
* \brief Callback for keyboard events.
122+
*
123+
* \param[in] GLFWwindow* window
124+
* \param[in] int key ASCII key number.
125+
* \param[in] int scancode The converted key value
126+
* \param[in] int action The event type.
127+
* \param[in] int mods Modifier keys.
128+
* \return void
129+
*/
130+
static void KeyboardEventCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
131+
132+
/**
133+
* \brief Callback for unicode character event.
134+
*
135+
* This is different from just a normal keyboard event as it has been translated and modified by
136+
* the OS and is just like typing into a text editor.
137+
* \param[in] GLFWwindow* window
138+
* \param[in] unsigned int uchar The unicode character key code.
139+
* \return void
140+
*/
141+
static void CharacterEventCallback(GLFWwindow* window, unsigned int uchar);
142+
143+
/**
144+
* \brief Callback for mouse move events.
145+
*
146+
* \param[in] GLFWwindow* window
147+
* \param[in] double x, y The new x and y coordinate of the mouse in screen coordinates.
148+
* \return void
149+
*/
150+
static void MouseMoveEventCallback(GLFWwindow* window, double x, double y);
151+
152+
/**
153+
* \brief Callback for mouse button events.
154+
*
155+
* \param[in] GLFWwindow* window
156+
* \param[in] int button The button that the action occurred on.
157+
* \param[in] int action The action that occurred.
158+
* \param[in] int mods Modifier keys.
159+
* \return void
160+
*/
161+
static void MouseButtonEventCallback(GLFWwindow* window, int button, int action, int mods);
162+
163+
/**
164+
* \brief Callback for window focus change events.
165+
*
166+
* \param[in] GLFWwindow* window
167+
* \param[in] int focused GL_TRUE if focused, GL_FALSE if unfocused.
168+
* \return void
169+
*/
170+
static void WindowFocusChangeCallback(GLFWwindow* window, int focused);
171+
172+
/**
173+
* \brief Toggles wether the mouse cursor should be locked to the current window.
174+
*
175+
* \return void
176+
*/
177+
void ToggleMouseLock();
178+
179+
/**
180+
* \brief Sets the mouse cursor position relative to the upper-left corner of the window.
181+
*
182+
* \param[in] double x, y The new x and y coordinate of the mouse in screen coordinates.
183+
* \return void
184+
*/
185+
void SetMousePosition(const double x, const double y);
186+
private:
187+
/**
188+
* \brief Updates the internal size variables from the windowResized callback.
189+
*
190+
* \param[in] const int width, height The new client width and height of the window
191+
* \return void
192+
*/
193+
void UpdateWindowSize(const int width, const int height);
194+
195+
/**
196+
* \brief Dispatches keyboard events from the callback.
197+
*
198+
* \param[in] const int key ASCII key number.
199+
* \param[in] const int scancode The converted key value
200+
* \param[in] const int action The event type.
201+
* \param[in] const int mods Modifier keys.
202+
* \return void
203+
*/
204+
void DispatchKeyboardEvent(const int key, const int scancode, const int action, const int mods);
205+
206+
/**
207+
* \brief Dispatches a character event.
208+
*
209+
* \param[in] const unsigned int uchar The unicode character key code.
210+
* \return void
211+
*/
212+
void DispatchCharacterEvent(const unsigned int uchar);
213+
214+
/**
215+
* \brief Dispatches mouse movement events.
216+
*
217+
* It determines the changes in mouse position and stores the new position for later.
218+
* \param[in] const double x, y The new x and y coordinate of the mouse in screen coordinates.
219+
* \return void
220+
*/
221+
void DispatchMouseMoveEvent(const double x, const double y);
222+
223+
/**
224+
* \brief Dispatches mouse button events from the callback.
225+
*
226+
* \param[in] const int button The button that the action occurred on.
227+
* \param[in] const int action The action that occurred.
228+
* \param[in] const int mods Modifier keys.
229+
* \return void
230+
*/
231+
void DispatchMouseButtonEvent(const int button, const int action, const int mods);
232+
233+
GLFWwindow* window;
234+
int client_width, client_height; // Current window's client width and height.
235+
double old_mouse_x, old_mouse_y;
236+
double last_time; // The time at the last call to GetDeltaTime().
237+
bool mouse_lock; // If mouse lock is enabled causing the cursor to snap to mid-window each movement event.
238+
};
239+
}

‎include/polygonmeshdata.hpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <memory>
5+
#include <map>
6+
#include "vertexbuffer.hpp"
7+
8+
namespace vv {
9+
class Material;
10+
11+
class PolygonMeshData {
12+
public:
13+
void SetMaterial(std::weak_ptr<Material> m, size_t submesh = 0) {
14+
this->materials[submesh] = m;
15+
}
16+
17+
// Returns the Material for specified submesh.
18+
std::weak_ptr<Material> GetMaterial(size_t submesh = 0) {
19+
if (this->materials.find(submesh) != this->materials.end()) {
20+
return this->materials[submesh];
21+
}
22+
}
23+
24+
void AddVertex(Vertex v, size_t submesh = 0) {
25+
this->verts[submesh].push_back(v);
26+
}
27+
28+
// Returns the vertex buffer for specified submesh.
29+
const std::vector<Vertex>& GetVertexBuffer(size_t submesh = 0) {
30+
if (this->verts.find(submesh) != this->verts.end()) {
31+
return this->verts[submesh];
32+
}
33+
}
34+
35+
void AddIndex(unsigned int i, size_t submesh = 0) {
36+
this->indicies[submesh].push_back(i);
37+
}
38+
39+
// Returns the index buffer for specified submesh.
40+
const std::vector<unsigned int>& GetIndexBuffer(size_t submesh = 0) {
41+
if (this->indicies.find(submesh) != this->indicies.end()) {
42+
return this->indicies[submesh];
43+
}
44+
}
45+
private:
46+
std::map<size_t, std::weak_ptr<Material>> materials;
47+
std::map<size_t, std::vector<Vertex>> verts;
48+
std::map<size_t, std::vector<unsigned int>> indicies;
49+
};
50+
}

‎include/render-system.hpp

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <list>
5+
#include <map>
6+
#include <atomic>
7+
#include <queue>
8+
#include <glm/mat4x4.hpp>
9+
#include <glm/gtc/quaternion.hpp>
10+
11+
#ifndef __APPLE__
12+
#include <GL/glew.h>
13+
#else
14+
#include <OpenGL/gl3.h>
15+
#endif
16+
17+
#include "multiton.hpp"
18+
#include "command-queue.hpp"
19+
20+
namespace vv {
21+
struct VertexBuffer;
22+
class Material;
23+
24+
enum RS_COMMAND {
25+
VIEW_ADD,
26+
VIEW_UPDATE,
27+
VIEW_ACTIVATE,
28+
VIEW_REMOVE,
29+
MODEL_MATRIX_ADD,
30+
MODEL_MATRIX_UPDATE,
31+
MODEL_MATRIX_REMOVE,
32+
VB_ADD,
33+
VB_REMOVE,
34+
};
35+
36+
template <typename T>
37+
struct RenderCommand : Command < RS_COMMAND > {
38+
RenderCommand(const RS_COMMAND rs_c, const GUID entity_id, T data) :
39+
Command(rs_c, entity_id), data(data) { }
40+
T data;
41+
};
42+
43+
struct ModelMatrix {
44+
glm::mat4 transform;
45+
};
46+
47+
typedef Multiton<GUID, std::shared_ptr<ModelMatrix>> ModelMatrixMap;
48+
49+
class RenderSystem : public CommandQueue < RS_COMMAND > {
50+
public:
51+
RenderSystem();
52+
53+
void SetViewportSize(const unsigned int width, const unsigned int height);
54+
55+
void Update(const double delta);
56+
57+
void AddVertexBuffer(const std::weak_ptr<Material> mat, const std::weak_ptr<VertexBuffer> buffer, const GUID entity_id);
58+
59+
protected:
60+
void ProcessCommandQueue();
61+
62+
void UpdateModelMatrix(const GUID entity_id);
63+
64+
void RemoveModelMatrix(const GUID entity_id);
65+
66+
void UpdateViewMatrix(const GUID eneity_id);
67+
68+
//void CreateVertexBuffer(GUID entity_id, const std::vector<Vertex>& verts, const std::vector<GLuint>& indicies);
69+
private:
70+
glm::mat4 projection;
71+
std::map<GUID, glm::mat4> views;
72+
GUID current_view;
73+
unsigned int window_width, window_height;
74+
std::map<std::weak_ptr<Material>, std::pair<std::weak_ptr<VertexBuffer>, std::list<GUID>>, std::owner_less<std::weak_ptr<Material>>> buffers;
75+
};
76+
}

‎include/shader.hpp

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#pragma once
2+
3+
#ifndef __APPLE__
4+
#include <GL/glew.h>
5+
#else
6+
#include <OpenGL/gl3.h>
7+
#endif
8+
9+
#include <string>
10+
#include <map>
11+
#include <vector>
12+
#include <fstream>
13+
#include <iostream>
14+
15+
namespace vv {
16+
class Shader;
17+
18+
typedef Multiton<std::string, std::shared_ptr<Shader>> ShaderMap;
19+
20+
class Shader {
21+
public:
22+
enum ShaderType : GLenum {
23+
VERTEX = GL_VERTEX_SHADER,
24+
FRAGMENT = GL_FRAGMENT_SHADER,
25+
GEOMETRY = GL_GEOMETRY_SHADER,
26+
};
27+
28+
29+
Shader::Shader() : program(0) { }
30+
31+
Shader::~Shader() {
32+
DeleteProgram();
33+
}
34+
35+
void DeleteProgram() {
36+
if (this->program != 0) {
37+
glDeleteProgram(this->program);
38+
}
39+
this->program = 0;
40+
for (auto s : this->shaders) {
41+
glDeleteShader(s);
42+
}
43+
this->shaders.clear();
44+
}
45+
46+
void LoadFromFile(const ShaderType type, const std::string fname) {
47+
std::ifstream fp;
48+
fp.open(fname, std::ios_base::in);
49+
if (fp.is_open()) {
50+
std::string buffer(std::istreambuf_iterator<char>(fp), (std::istreambuf_iterator<char>()));
51+
LoadFromString(type, buffer);
52+
}
53+
}
54+
55+
void LoadFromString(const ShaderType type, const std::string source) {
56+
glGetError();
57+
GLuint shader = glCreateShader(type);
58+
if (glGetError()) {
59+
return;
60+
}
61+
62+
GLint length = source.length();
63+
const GLchar *str = source.data();
64+
glShaderSource(shader, 1, &str, &length);
65+
if (glGetError()) {
66+
return;
67+
}
68+
69+
glCompileShader(shader);
70+
if (glGetError()) {
71+
return;
72+
}
73+
GLint status;
74+
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
75+
if (status == GL_FALSE) {
76+
GLint log_length;
77+
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
78+
GLchar *info_log = new GLchar[log_length];
79+
glGetShaderInfoLog(shader, log_length, NULL, info_log);
80+
std::cout << "Error compiling shader: " << info_log;
81+
delete[] info_log;
82+
}
83+
if (glGetError()) {
84+
return;
85+
}
86+
this->shaders.push_back(shader);
87+
}
88+
89+
void Build() {
90+
this->program = glCreateProgram();
91+
92+
for (auto shader : this->shaders) {
93+
glAttachShader(this->program, shader);
94+
}
95+
96+
glLinkProgram(this->program);
97+
98+
GLint is_linked = 0;
99+
glGetProgramiv(this->program, GL_LINK_STATUS, (int *)&is_linked);
100+
if (is_linked == GL_FALSE) {
101+
GLint max_length = 0;
102+
glGetProgramiv(this->program, GL_INFO_LOG_LENGTH, &max_length);
103+
104+
std::vector<GLchar> info_log(max_length);
105+
glGetProgramInfoLog(this->program, max_length, &max_length, &info_log[0]);
106+
std::copy(info_log.begin(), info_log.end(), std::ostream_iterator<GLchar>(std::cout, ""));
107+
108+
DeleteProgram();
109+
110+
return;
111+
}
112+
113+
for (auto shader : this->shaders) {
114+
glDetachShader(this->program, shader);
115+
}
116+
}
117+
118+
void Use() {
119+
glUseProgram(this->program);
120+
}
121+
122+
void UnUse() {
123+
glUseProgram(0);
124+
}
125+
126+
void ActivateTextureUnit(const GLuint unit, const GLuint name) {
127+
128+
}
129+
130+
static void DeactivateTextureUnit(const GLuint unit) {
131+
132+
}
133+
134+
GLint GetUniform(const std::string name) {
135+
if (this->uniforms.find(name) != this->uniforms.end()) {
136+
return this->uniforms.at(name);
137+
}
138+
else {
139+
GLint uniform_id = glGetUniformLocation(this->program, name.c_str());
140+
if (uniform_id) {
141+
this->uniforms[name] = uniform_id;
142+
}
143+
return uniform_id;
144+
}
145+
return 0;
146+
}
147+
148+
GLint GetAttribute(const std::string name) {
149+
if (this->attributes.find(name) != this->attributes.end()) {
150+
return this->attributes.at(name);
151+
}
152+
else {
153+
GLint attribute_id = glGetAttribLocation(this->program, name.c_str());
154+
if (attribute_id) {
155+
this->attributes[name] = attribute_id;
156+
}
157+
return attribute_id;
158+
}
159+
return 0;
160+
}
161+
private:
162+
GLuint program;
163+
std::vector<GLuint> shaders;
164+
std::map<std::string, GLint> attributes;
165+
std::map<std::string, GLint> uniforms;
166+
};
167+
}

‎include/transform.hpp

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <glm/glm.hpp>
5+
#include <glm/gtx/quaternion.hpp>
6+
#include <glm/gtc/quaternion.hpp>
7+
#include "multiton.hpp"
8+
9+
namespace vv {
10+
enum TRANSFORM_COMMAND { TRANSFORM_ADDED, TRANSFORM_UPDATED, TRANSFORM_REMOVED };
11+
12+
class Transform;
13+
typedef Multiton<GUID, std::shared_ptr<Transform>> TransformMap;
14+
15+
static glm::vec3 FORWARD_VECTOR(0.0f, 0.0f, -1.0f);
16+
static glm::vec3 UP_VECTOR(0.0f, 1.0f, 0.0f);
17+
static glm::vec3 RIGHT_VECTOR(1.0f, 0.0f, 0.0f);
18+
19+
class Transform final {
20+
public:
21+
Transform() : Transform(0) { };
22+
23+
Transform(GUID entity_id);
24+
/**
25+
* \brief Translates by the provided amount relative to the current translation.
26+
*
27+
* \param[in] const glm::vec3 amount The amount to translate by.
28+
*/
29+
void Translate(const glm::vec3 amount);
30+
31+
/**
32+
* \brief Rotates by the provided amount relative to the current rotation.
33+
*
34+
* The arguments are in the form of (rotation about x, rotation about y, rotation about z).
35+
* The orientation is also updated by computing the axis-angle.
36+
* \param[in] const glm::vec3 amount The amount to rotate by.
37+
*/
38+
void Rotate(const glm::vec3 amount);
39+
40+
/**
41+
* \brief Translates by the provided amount relative to the current translation and orientation.
42+
*
43+
* \param[in] const glm::vec3 amount The amount to translate by.
44+
*/
45+
void OrientedTranslate(const glm::vec3 amount);
46+
47+
/**
48+
* \brief Rotates by the provided amount relative to the current rotation and orientation.
49+
*
50+
* The arguments are in the form of (rotation about x, rotation about y, rotation about z).
51+
* The orientation is also updated by computing the axis-angle.
52+
* \param[in] const glm::vec3 amount The amount to rotate by.
53+
*/
54+
void OrientedRotate(const glm::vec3 amount);
55+
56+
/**
57+
* \brief Scales by the provided amount relative to the current scale.
58+
*
59+
* The current scale is multiplied by the given amount.
60+
* \param[in] const glm::vec3 amount The amount to scale by.
61+
*/
62+
void Scale(const glm::vec3 amount);
63+
64+
/**
65+
* \brief Sets the translation.
66+
*
67+
* \param[in] const glm::vec3 new_translation The new translation.
68+
*/
69+
void SetTranslation(const glm::vec3 new_translation);
70+
71+
/**
72+
* \brief Sets the rotation.
73+
*
74+
* The arguments are in the form of (rotation about x, rotation about y, rotation about z).
75+
* The orientation is also set by computing the axis-angle.
76+
* \param[in] const glm::vec3 new_rotation The new rotation.
77+
*/
78+
void SetRotation(const glm::vec3 new_rotation);
79+
80+
/**
81+
* \brief Sets the rotation.
82+
*
83+
* \param[in] const glm::quat new_orientation The new orientation.
84+
*/
85+
void SetOrientation(const glm::quat new_orientation);
86+
87+
/**
88+
* \brief Sets the scale.
89+
*
90+
* \param[in] const glm::vec3 new_scale The new scale.
91+
*/
92+
void SetScale(const glm::vec3 new_scale);
93+
94+
/**
95+
* \brief Translates by the provided amount relative to the current translation
96+
*
97+
* \return glm::vec3 The current transform.
98+
*/
99+
glm::vec3 GetTranslation() const;
100+
101+
/**
102+
* \brief Returns the current rotation, not orientation.
103+
*
104+
* \return glm::vec3 The current rotation.
105+
*/
106+
glm::vec3 GetRotation() const;
107+
108+
/**
109+
* \brief Returns the current orientation, not rotation.
110+
*
111+
* \return glm::quat The current orientation.
112+
*/
113+
glm::quat GetOrientation() const;
114+
115+
/**
116+
* \brief Returns the current scale.
117+
*
118+
* \return glm::vec3 The current scale.
119+
*/
120+
glm::vec3 GetScale() const;
121+
122+
GUID GetEntityID() const {
123+
return this->entity_id;
124+
}
125+
private:
126+
glm::vec3 translation;
127+
glm::vec3 rotation;
128+
glm::vec3 scale;
129+
glm::quat orientation;
130+
GUID entity_id;
131+
};
132+
133+
}

‎include/vertexbuffer.hpp

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <memory>
5+
6+
#include "multiton.hpp"
7+
8+
#ifndef __APPLE__
9+
#include <GL/glew.h>
10+
#else
11+
#include <OpenGL/gl3.h>
12+
#endif
13+
14+
namespace vv {
15+
struct VertexBuffer;
16+
typedef Multiton<GUID, std::shared_ptr<VertexBuffer>> VertexBufferMap;
17+
18+
// TODO: Move to Mesh class file
19+
struct Vertex {
20+
Vertex(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f, const float r = 0.0f, const float g = 0.0f, const float b = 0.0f) {
21+
this->position[0] = x; this->position[1] = y; this->position[2] = z;
22+
this->color[0] = r; this->color[1] = g; this->color[2] = b;
23+
}
24+
float position[3];
25+
float color[3];
26+
};
27+
28+
// Holds vertex and index buffer "names".
29+
struct VertexBuffer {
30+
VertexBuffer() : vao(0), vbo(0), ibo(0), vertex_count(0), index_count(0) { }
31+
void Buffer(const std::vector<Vertex>& verts, const std::vector<GLuint>& indicies) {
32+
if (!this->vao) {
33+
glGenVertexArrays(1, &this->vao);
34+
}
35+
if (!this->vbo) {
36+
glGenBuffers(1, &this->vbo);
37+
}
38+
if (!this->ibo) {
39+
glGenBuffers(1, &this->ibo);
40+
}
41+
42+
glBindVertexArray(this->vao);
43+
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
44+
// If the size hasn't changed we can call update
45+
if (this->vertex_count >= verts.size()) {
46+
auto* buffer = glMapBufferRange(GL_ARRAY_BUFFER, 0, verts.size() * sizeof(Vertex), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
47+
if (buffer) {
48+
memcpy(buffer, &verts[0], verts.size() * sizeof(Vertex));
49+
glUnmapBuffer(GL_ARRAY_BUFFER);
50+
}
51+
else {
52+
//std::err << "glMapBufferRange() failed" << __LINE__ << __FILE__ << std::endl;
53+
}
54+
}
55+
else {
56+
glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(Vertex), &verts[0], GL_STATIC_DRAW);
57+
this->vertex_count = verts.size();
58+
}
59+
60+
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
61+
glEnableVertexAttribArray(0);
62+
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
63+
glEnableVertexAttribArray(1);
64+
65+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ibo);
66+
if (this->index_count >= indicies.size()) {
67+
auto* buffer = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, indicies.size() * sizeof(GLuint), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
68+
if (buffer) {
69+
memcpy(buffer, &indicies[0], indicies.size() * sizeof(Vertex));
70+
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
71+
}
72+
else {
73+
//std::err << "glMapBufferRange() failed" << __LINE__ << __FILE__ << std::endl;
74+
}
75+
}
76+
else {
77+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(GLuint), &indicies[0], GL_STATIC_DRAW);
78+
this->index_count = indicies.size();
79+
}
80+
glBindVertexArray(0);
81+
}
82+
GLuint vao, vbo, ibo;
83+
size_t vertex_count;
84+
size_t index_count;
85+
};
86+
}

‎include/voxelvolume.hpp

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#pragma once
2+
3+
#include <unordered_map>
4+
#include <map>
5+
#include <vector>
6+
#include <queue>
7+
8+
#include "command-queue.hpp"
9+
10+
namespace vv {
11+
struct Vertex;
12+
13+
struct Voxel {
14+
Voxel() {
15+
this->neighbors[UP] = nullptr; this->neighbors[DOWN] = nullptr;
16+
this->neighbors[LEFT] = nullptr; this->neighbors[RIGHT] = nullptr;
17+
this->neighbors[FRONT] = nullptr; this->neighbors[BACK] = nullptr;
18+
}
19+
enum NEIGHBORS { UP = 0, DOWN, LEFT, RIGHT, FRONT, BACK };
20+
float color[3];
21+
Voxel* neighbors[6];
22+
};
23+
24+
enum VOXEL_COMMAND { VOXEL_ADD, VOXEL_REMOVE };
25+
26+
struct VoxelCommand : Command < VOXEL_COMMAND > {
27+
VoxelCommand(const VOXEL_COMMAND voxel_c, const GUID entity_id, std::tuple<short, short, short> position) :
28+
Command(voxel_c, entity_id) {
29+
this->row = std::get<0>(position);
30+
this->column = std::get<1>(position);
31+
this->slice = std::get<2>(position);
32+
}
33+
short row, column, slice;
34+
};
35+
36+
class VoxelVolume : public CommandQueue < VOXEL_COMMAND > {
37+
public:
38+
VoxelVolume();
39+
~VoxelVolume();
40+
41+
protected:
42+
// All values are relative to the front orientation and centered on the root voxel.
43+
// Slize is depth (away from the screen is positive). Row is up/down. Column is left/right.
44+
// Therefore adding a voxel to the front face is AddVoxel(0, 0, 1).
45+
void AddVoxel(const short row, const short column, const short slice);
46+
47+
// See AddVoxel().
48+
void RemoveVoxel(const short row, const short column, const short slice);
49+
50+
void ProcessCommandQueue();
51+
public:
52+
// Iterates over all the actions queued before the call to update.
53+
void Update(double delta);
54+
55+
// Generates a vertex (and index) buffer for the current voxel state.
56+
void UpdateVertexBuffers();
57+
58+
// Returns the vertex buffer.
59+
const std::vector<Vertex>& GetVertexBuffer() {
60+
return this->verts;
61+
}
62+
63+
// Returns the index buffer.
64+
const std::vector<unsigned int>& GetIndexBuffer() {
65+
return this->indicies;
66+
}
67+
private:
68+
std::unordered_map<long long, Voxel> voxels;
69+
std::vector<Vertex> verts;
70+
std::vector<unsigned int> indicies;
71+
std::map<std::tuple<float, float, float>, unsigned int> index_list;
72+
};
73+
}

‎modules/FindGLEW.cmake

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# - Find the OpenGL Extension Wrangler Library (GLEW)
2+
# This module defines the following variables:
3+
# GLEW_INCLUDE_DIRS - include directories for GLEW
4+
# GLEW_LIBRARIES - libraries to link against GLEW
5+
# GLEW_FOUND - true IF GLEW has been found and can be used
6+
7+
#=============================================================================
8+
# Copyright 2012 Benjamin Eikel
9+
#
10+
# Distributed under the OSI-approved BSD License (the "License");
11+
# see accompanying file Copyright.txt for details.
12+
#
13+
# This software is distributed WITHOUT ANY WARRANTY; without even the
14+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15+
# See the License for more information.
16+
#=============================================================================
17+
# (To distribute this file outside of CMake, substitute the full
18+
# License text for the above reference.)
19+
20+
find_path(GLEW_INCLUDE_DIR GL/glew.h)
21+
SET(GLEW_DEBUG_NAMES glew32_debug)
22+
SET(GLEW_NAMES glew32)
23+
add_definitions(-DGLEW_STATIC)
24+
25+
# Reset the variables so that find_library will rescan in case we changed from static to none (or vice versa).
26+
UNSET(GLEW_LIBRARY)
27+
UNSET(GLEW_DEBUG_LIBRARY)
28+
29+
FIND_LIBRARY(GLEW_LIBRARY NAMES ${GLEW_NAMES} PATH_SUFFIXES x64 amd64 lib64)
30+
FIND_LIBRARY(GLEW_DEBUG_LIBRARY NAMES ${GLEW_DEBUG_NAMES} PATH_SUFFIXES x64 amd64 lib64)
31+
32+
IF(NOT GLEW_DEBUG_LIBRARY AND GLEW_LIBRARY)
33+
SET(GLEW_DEBUG_LIBRARY ${GLEW_LIBRARY})
34+
ENDIF(NOT GLEW_DEBUG_LIBRARY AND GLEW_LIBRARY)
35+
36+
SET(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR})
37+
SET(GLEW_LIBRARIES debug ${GLEW_DEBUG_LIBRARY} optimized ${GLEW_LIBRARY})
38+
39+
INCLUDE(FindPackageHandleStandardArgs)
40+
FIND_PACKAGE_HANDLE_STANDARD_ARGS( GLEW
41+
DEFAULT_MSG
42+
GLEW_LIBRARIES
43+
GLEW_INCLUDE_DIR
44+
)
45+
46+
MARK_AS_ADVANCED(GLEW_INCLUDE_DIR GLEW_LIBRARY GLEW_DEBUG_LIBRARY)

‎modules/FindGLFW3.cmake

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# Try to find GLFW library and include path.
3+
# Once done this will define
4+
#
5+
# GLFW3_FOUND
6+
# GLFW3_INCLUDE_PATH
7+
# GLFW3_LIBRARY
8+
#
9+
10+
IF(WIN32)
11+
FIND_PATH( GLFW3_INCLUDE_PATH GLFW/glfw3.h
12+
$ENV{PROGRAMFILES}/GLFW/include
13+
${GLFW_ROOT_DIR}/include
14+
DOC "The directory where GLFW/glfw3.h resides")
15+
16+
FIND_LIBRARY( GLFW3_LIBRARY
17+
NAMES glfw3 glfw3dll
18+
PATHS
19+
$ENV{PROGRAMFILES}/GLFW/lib
20+
${GLFW_ROOT_DIR}/lib
21+
PATH_SUFFIXES x64 amd64
22+
DOC "The GLFW library")
23+
FIND_LIBRARY( GLFW3_DEBUG_LIBRARY
24+
NAMES glfw3_debug glfw3dll
25+
PATHS
26+
$ENV{PROGRAMFILES}/GLFW/lib
27+
${GLFW_ROOT_DIR}/lib
28+
PATH_SUFFIXES x64 amd64
29+
DOC "The GLFW library")
30+
ELSE(WIN32)
31+
FIND_PATH( GLFW3_INCLUDE_PATH GLFW/glfw3.h
32+
/usr/include
33+
/usr/local/include
34+
/sw/include
35+
/opt/local/include
36+
${GLFW_ROOT_DIR}/include
37+
DOC "The directory where GLFW/glfw3.h resides")
38+
IF(APPLE)
39+
# For the case where GLFW is installed in a non-standard lib path such as /opt or /sw
40+
INCLUDE_DIRECTORIES( "${GLFW3_INCLUDE_PATH}" )
41+
ENDIF(APPLE)
42+
43+
FIND_LIBRARY( GLFW3_LIBRARY
44+
NAMES libglfw.so libglfw.so.3 libglfw.so.3.0 glfw.3 glfw3
45+
PATHS
46+
/usr/lib64
47+
/usr/lib
48+
/usr/local/lib64
49+
/usr/local/lib
50+
/sw/lib
51+
/opt/local/lib
52+
${GLFW_ROOT_DIR}/lib
53+
DOC "The GLFW library")
54+
ENDIF(WIN32)
55+
56+
IF(NOT GLFW3_DEBUG_LIBRARY AND GLFW3_LIBRARY)
57+
SET(GLFW3_DEBUG_LIBRARY ${GLFW3_LIBRARY})
58+
ENDIF()
59+
60+
set(GLFW3_INCLUDE_PATH ${GLFW3_INCLUDE_PATH})
61+
set(GLFW3_LIBRARIES debug ${GLFW3_DEBUG_LIBRARY} optimized ${GLFW3_LIBRARY})
62+
63+
INCLUDE(FindPackageHandleStandardArgs)
64+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW3 DEFAULT_MESSAGE GLFW3_LIBRARIES GLFW3_INCLUDE_PATH)
65+
66+
mark_as_advanced(GLFW3_LIBRARIES GLFW3_INCLUDE_PATH GLFW3_LIBRARY GLFW3_DEBUG_LIBRARY)

‎modules/FindGLM.cmake

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# FindGLM - attempts to locate the glm matrix/vector library.
2+
#
3+
# This module defines the following variables (on success):
4+
# GLM_INCLUDE_DIRS - where to find glm/glm.hpp
5+
# GLM_FOUND - if the library was successfully located
6+
#
7+
# It is trying a few standard installation locations, but can be customized
8+
# with the following variables:
9+
# GLM_ROOT_DIR - root directory of a glm installation
10+
# Headers are expected to be found in either:
11+
# <GLM_ROOT_DIR>/glm/glm.hpp OR
12+
# <GLM_ROOT_DIR>/include/glm/glm.hpp
13+
# This variable can either be a cmake or environment
14+
# variable. Note however that changing the value
15+
# of the environment varible will NOT result in
16+
# re-running the header search and therefore NOT
17+
# adjust the variables set by this module.
18+
19+
#=============================================================================
20+
# Copyright 2012 Carsten Neumann
21+
#
22+
# Distributed under the OSI-approved BSD License (the "License");
23+
# see accompanying file Copyright.txt for details.
24+
#
25+
# This software is distributed WITHOUT ANY WARRANTY; without even the
26+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27+
# See the License for more information.
28+
#=============================================================================
29+
# (To distribute this file outside of CMake, substitute the full
30+
# License text for the above reference.)
31+
32+
# default search dirs
33+
SET(_glm_HEADER_SEARCH_DIRS
34+
"/usr/include"
35+
"/usr/local/include")
36+
37+
# check environment variable
38+
SET(_glm_ENV_ROOT_DIR "$ENV{GLM_ROOT_DIR}")
39+
40+
IF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
41+
SET(GLM_ROOT_DIR "${_glm_ENV_ROOT_DIR}")
42+
ENDIF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
43+
44+
# put user specified location at beginning of search
45+
IF(GLM_ROOT_DIR)
46+
SET(_glm_HEADER_SEARCH_DIRS "${GLM_ROOT_DIR}"
47+
"${GLM_ROOT_DIR}/include"
48+
${_glm_HEADER_SEARCH_DIRS})
49+
ENDIF(GLM_ROOT_DIR)
50+
51+
# locate header
52+
FIND_PATH(GLM_INCLUDE_DIR "glm/glm.hpp"
53+
PATHS ${_glm_HEADER_SEARCH_DIRS})
54+
55+
INCLUDE(FindPackageHandleStandardArgs)
56+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLM DEFAULT_MSG
57+
GLM_INCLUDE_DIR)
58+
59+
IF(GLM_FOUND)
60+
SET(GLM_INCLUDE_DIRS "${GLM_INCLUDE_DIR}")
61+
mark_as_advanced(GLM_INCLUDE_DIR)
62+
MESSAGE(STATUS "GLM_INCLUDE_DIR = ${GLM_INCLUDE_DIR}")
63+
ENDIF(GLM_FOUND)

‎modules/SetCompilerFlags.cmake

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# check for gcc version to set c++11 or c++0x.
2+
# thanks to http://stackoverflow.com/questions/10984442/how-to-detect-c11-support-of-a-compiler-with-cmake .
3+
IF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
4+
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
5+
IF (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
6+
MESSAGE("Supported GCC!")
7+
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
8+
ENDIF (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
9+
ELSEIF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # Clang 3.3 and up support c++11.
10+
MESSAGE("Clang Version: " ${CMAKE_CXX_COMPILER_VERSION})
11+
# On OS X, Clang 3.3 would be Clang/LLVM 5.0.
12+
IF (APPLE)
13+
SET(CLANG_MIN_VERSION 5.0)
14+
ELSE (APPLE)
15+
SET(CLANG_MIN_VERSION 3.3)
16+
ENDIF (APPLE)
17+
IF (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER CLANG_MIN_VERSION OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL CLANG_MIN_VERSION))
18+
# clang 3.3 is the first release that completley implements the c++11 standard.
19+
# However, most of c++11 was implemented in previous versions.
20+
MESSAGE("clang ${CMAKE_CXX_COMPILER_VERSION} does not completely support c++11. This may cause some problems in the future. We recommend upgrading to clang-3.3 (Xcode 5.0) or greater.")
21+
ENDIF (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER CLANG_MIN_VERSION OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL CLANG_MIN_VERSION))
22+
# compiler is clang 3.3 or higher. Force c++11 and use libc++.
23+
IF (XCODE_VERSION)
24+
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD c++11)
25+
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY libc++)
26+
ELSE (XCODE_VERSION)
27+
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
28+
ENDIF (XCODE_VERSION)
29+
UNSET(CLANG_MIN_VERSION)
30+
ELSEIF (MSVC AND (MSVC_VERSION GREATER 1699))
31+
MESSAGE("Supported Visual Studio!")
32+
ELSE ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
33+
MESSAGE(FATAL_ERROR "Your C++ compiler does not support C++11.")
34+
ENDIF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")

‎src/main.cpp

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include "os.hpp"
2+
#include "dispatcher.hpp"
3+
#include "render-system.hpp"
4+
#include "vertexbuffer.hpp"
5+
#include "shader.hpp"
6+
#include "multiton.hpp"
7+
#include "voxelvolume.hpp"
8+
#include "transform.hpp"
9+
#include "material.hpp"
10+
#include <glm/gtc/matrix_transform.hpp>
11+
12+
struct CameraMover : public vv::Subscriber < vv::KeyboardEvent > {
13+
CameraMover() {
14+
vv::Dispatcher<vv::KeyboardEvent>::GetInstance()->Subscribe(this);
15+
}
16+
void Notify(const vv::KeyboardEvent* data) {
17+
auto transform = vv::TransformMap::Get(1);
18+
switch (data->action) {
19+
case vv::KeyboardEvent::KEY_UP:
20+
switch (data->key) {
21+
case GLFW_KEY_A:
22+
transform->OrientedRotate(glm::vec3(0.0, glm::radians(10.0f), 0.0));
23+
break;
24+
case GLFW_KEY_D:
25+
transform->OrientedRotate(glm::vec3(0.0, glm::radians(-10.0f), 0.0));
26+
break;
27+
case GLFW_KEY_W:
28+
transform->OrientedTranslate(glm::vec3(0.0, 0.0, -1.0));
29+
break;
30+
case GLFW_KEY_S:
31+
transform->OrientedTranslate(glm::vec3(0.0, 0.0, 1.0));
32+
break;
33+
case GLFW_KEY_SPACE:
34+
vv::RenderSystem::QueueCommand(vv::VIEW_ACTIVATE, 1);
35+
break;
36+
}
37+
vv::RenderSystem::QueueCommand(vv::MODEL_MATRIX_UPDATE, 1);
38+
break;
39+
default:
40+
break;
41+
}
42+
}
43+
};
44+
45+
int main(int argc, void* argv) {
46+
vv::OS os;
47+
48+
os.InitializeWindow(800, 600, "VoxelVolution 0.1", 3, 2);
49+
50+
vv::RenderSystem rs;
51+
52+
rs.SetViewportSize(800, 600);
53+
54+
vv::VoxelVolume voxvol;
55+
56+
auto s = std::make_shared<vv::Shader>();
57+
s->LoadFromFile(vv::Shader::VERTEX, "basic.vert");
58+
s->LoadFromFile(vv::Shader::FRAGMENT, "basic.frag");
59+
s->Build();
60+
vv::ShaderMap::Set("shader1", s);
61+
62+
auto basic_fill = std::make_shared<vv::Material>(s);
63+
vv::MaterialMap::Set("material_basic", basic_fill);
64+
65+
auto s_overlay = std::make_shared<vv::Shader>();
66+
s_overlay->LoadFromFile(vv::Shader::VERTEX, "basic.vert");
67+
s_overlay->LoadFromFile(vv::Shader::FRAGMENT, "overlay.frag");
68+
s_overlay->Build();
69+
vv::ShaderMap::Set("shader_overlay", s_overlay);
70+
71+
auto overlay = std::make_shared<vv::Material>(s_overlay);
72+
overlay->SetFillMode(GL_LINE);
73+
vv::MaterialMap::Set("material_overlay", overlay);
74+
75+
auto voxvol_transform = std::make_shared<vv::Transform>();
76+
vv::TransformMap::Set(100, voxvol_transform);
77+
auto vb = std::make_shared<vv::VertexBuffer>();
78+
vv::VertexBufferMap::Set(100, vb);
79+
80+
vv::VoxelVolume::QueueCommand<vv::VoxelCommand, std::tuple<short, short, short>>(vv::VOXEL_ADD, 100, std::tuple<short, short, short>(0, 1, 1));
81+
vv::VoxelVolume::QueueCommand<vv::VoxelCommand, std::tuple<short, short, short>>(vv::VOXEL_ADD, 100, std::tuple<short, short, short>(0, -1, 1));
82+
vv::VoxelVolume::QueueCommand<vv::VoxelCommand, std::tuple<short, short, short>>(vv::VOXEL_ADD, 100, std::tuple<short, short, short>(0, -1, 0));
83+
vv::VoxelVolume::QueueCommand<vv::VoxelCommand, std::tuple<short, short, short>>(vv::VOXEL_ADD, 100, std::tuple<short, short, short>(0, -1, -1));
84+
vv::VoxelVolume::QueueCommand<vv::VoxelCommand, std::tuple<short, short, short>>(vv::VOXEL_ADD, 100, std::tuple<short, short, short>(1, -1, 1));
85+
86+
voxvol.Update(0.0);
87+
vb->Buffer(voxvol.GetVertexBuffer(), voxvol.GetIndexBuffer());
88+
rs.AddVertexBuffer(basic_fill, vb, 100);
89+
rs.AddVertexBuffer(overlay, vb, 100);
90+
91+
auto vb2 = std::make_shared<vv::VertexBuffer>();
92+
vv::VertexBufferMap::Set(1, vb2);
93+
vb2->Buffer(voxvol.GetVertexBuffer(), voxvol.GetIndexBuffer());
94+
rs.AddVertexBuffer(basic_fill, vb2, 1);
95+
96+
auto camera_transform = std::make_shared<vv::Transform>();
97+
vv::TransformMap::Set(1, camera_transform);
98+
vv::RenderSystem::QueueCommand(vv::VIEW_ACTIVATE, 1);
99+
vv::RenderSystem::QueueCommand(vv::MODEL_MATRIX_ADD, 1);
100+
101+
auto camera_transform2 = std::make_shared<vv::Transform>();
102+
vv::TransformMap::Set(2, camera_transform2);
103+
vv::RenderSystem::QueueCommand(vv::MODEL_MATRIX_ADD, 2);
104+
105+
CameraMover cam_mover;
106+
107+
while (!os.Closing()) {
108+
rs.Update(os.GetDeltaTime());
109+
os.OSMessageLoop();
110+
os.SwapBuffers();
111+
}
112+
113+
return 0;
114+
}

‎src/os.cpp

+275
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#include "os.hpp"
2+
3+
#include <iostream>
4+
#include "dispatcher.hpp"
5+
6+
#ifdef __APPLE__
7+
// Needed so we can disable retina support for our window.
8+
#define GLFW_EXPOSE_NATIVE_COCOA 1
9+
#define GLFW_EXPOSE_NATIVE_NSGL 1
10+
#include <GLFW/glfw3native.h>
11+
// We can't just include objc/runtime.h and objc/message.h because glfw is too forward thinking for its own good.
12+
typedef void* SEL;
13+
extern "C" id objc_msgSend(id self, SEL op, ...);
14+
extern "C" SEL sel_getUid(const char *str);
15+
#endif
16+
17+
namespace vv {
18+
19+
// Error helper function used by GLFW for error messaging.
20+
// Currently outputs to std::cout.
21+
static void ErrorCallback(int error, const char* description) {
22+
std::cout << description << std::endl;
23+
}
24+
25+
bool OS::InitializeWindow(const int width, const int height, const std::string title,
26+
const unsigned int glMajor /*= 3*/, const unsigned int glMinor /*= 2*/) {
27+
glfwSetErrorCallback(ErrorCallback);
28+
29+
// Initialize the library.
30+
if (glfwInit() != GL_TRUE) {
31+
return false;
32+
}
33+
34+
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
35+
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor);
36+
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor);
37+
38+
#ifndef __APPLE__
39+
#ifdef _DEBUG
40+
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
41+
#else
42+
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
43+
#endif
44+
#else
45+
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
46+
#endif
47+
48+
// Create a windowed mode window and its OpenGL context.
49+
this->window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
50+
51+
if (!this->window) {
52+
glfwTerminate();
53+
return false;
54+
}
55+
56+
this->client_width = width;
57+
this->client_height = height;
58+
59+
#ifdef __APPLE__
60+
// Force retina displays to create a 1x framebuffer so we don't choke our fillrate.
61+
id cocoaWindow = glfwGetCocoaWindow(this->window);
62+
id cocoaGLView = ((id (*)(id, SEL)) objc_msgSend)(cocoaWindow, sel_getUid("contentView"));
63+
((void (*)(id, SEL, bool)) objc_msgSend)(cocoaGLView, sel_getUid("setWantsBestResolutionOpenGLSurface:"), false);
64+
#endif
65+
66+
// attach the context
67+
glfwMakeContextCurrent(this->window);
68+
69+
#ifndef __APPLE__
70+
// setting glewExperimental fixes a glfw context problem
71+
// (tested on Ubuntu 13.04)
72+
glewExperimental = GL_TRUE;
73+
74+
// Init GLEW.
75+
GLuint error = glewInit();
76+
if (error != GLEW_OK) {
77+
return false;
78+
}
79+
#endif
80+
81+
// Associate a pointer for this instance with this window.
82+
glfwSetWindowUserPointer(this->window, this);
83+
84+
// Set up some callbacks.
85+
glfwSetWindowSizeCallback(this->window, &OS::WindowResized);
86+
glfwSetKeyCallback(this->window, &OS::KeyboardEventCallback);
87+
glfwSetCursorPosCallback(this->window, &OS::MouseMoveEventCallback);
88+
glfwSetCharCallback(this->window, &OS::CharacterEventCallback);
89+
glfwSetMouseButtonCallback(this->window, &OS::MouseButtonEventCallback);
90+
glfwSetWindowFocusCallback(this->window, &OS::WindowFocusChangeCallback);
91+
92+
glfwGetCursorPos(this->window, &this->old_mouse_x, &this->old_mouse_y);
93+
94+
return true;
95+
}
96+
97+
void OS::MakeCurrent() {
98+
glfwMakeContextCurrent(this->window);
99+
}
100+
101+
void OS::DetachContext() {
102+
glfwMakeContextCurrent(NULL);
103+
}
104+
105+
void OS::Terminate() {
106+
glfwTerminate();
107+
}
108+
109+
bool OS::Closing() {
110+
return glfwWindowShouldClose(this->window) > 0;
111+
}
112+
113+
void OS::SwapBuffers() {
114+
glfwSwapBuffers(this->window);
115+
}
116+
117+
void OS::OSMessageLoop() {
118+
glfwPollEvents();
119+
}
120+
121+
int OS::GetWindowWidth() {
122+
return this->client_width;
123+
}
124+
125+
int OS::GetWindowHeight() {
126+
return this->client_height;
127+
}
128+
129+
double OS::GetDeltaTime() {
130+
double new_time = glfwGetTime();
131+
double delta_time = new_time - this->last_time;
132+
this->last_time = new_time;
133+
return delta_time;
134+
}
135+
136+
void OS::WindowResized(GLFWwindow* window, int width, int height) {
137+
// Get the user pointer and cast it.
138+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
139+
140+
if (os) {
141+
os->UpdateWindowSize(width, height);
142+
}
143+
}
144+
145+
void OS::KeyboardEventCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
146+
// Get the user pointer and cast it.
147+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
148+
149+
if (os) {
150+
os->DispatchKeyboardEvent(key, scancode, action, mods);
151+
}
152+
}
153+
154+
void OS::CharacterEventCallback(GLFWwindow* window, unsigned int uchar) {
155+
// Get the user pointer and cast it.
156+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
157+
158+
if (os) {
159+
os->DispatchCharacterEvent(uchar);
160+
}
161+
}
162+
163+
void OS::MouseMoveEventCallback(GLFWwindow* window, double x, double y) {
164+
// Get the user pointer and cast it.
165+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
166+
167+
if (os) {
168+
os->DispatchMouseMoveEvent(x, y);
169+
}
170+
}
171+
172+
void OS::MouseButtonEventCallback(GLFWwindow* window, int button, int action, int mods) {
173+
// Get the user pointer and cast it.
174+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
175+
176+
if (os) {
177+
os->DispatchMouseButtonEvent(button, action, mods);
178+
}
179+
}
180+
181+
void OS::WindowFocusChangeCallback(GLFWwindow* window, int focused) {
182+
if (focused == GL_FALSE) {
183+
// Get the user pointer and cast it.
184+
OS* os = static_cast<OS*>(glfwGetWindowUserPointer(window));
185+
186+
if (os) {
187+
// TODO: Implement a DispatchWindowFocusEvent() method in OS
188+
// TODO: Dispatch a focus changed event.
189+
}
190+
}
191+
}
192+
193+
void OS::UpdateWindowSize(const int width, const int height) {
194+
this->client_width = width;
195+
this->client_height = height;
196+
}
197+
198+
void OS::DispatchKeyboardEvent(const int key, const int scancode, const int action, const int mods) {
199+
KeyboardEvent key_event;
200+
if (action == GLFW_PRESS) {
201+
key_event = { key, scancode, KeyboardEvent::KEY_DOWN, mods };
202+
}
203+
else if (action == GLFW_REPEAT) {
204+
key_event = { key, scancode, KeyboardEvent::KEY_REPEAT, mods };
205+
}
206+
else if (action == GLFW_RELEASE) {
207+
key_event = { key, scancode, KeyboardEvent::KEY_UP, mods };
208+
}
209+
210+
Dispatcher<KeyboardEvent>::GetInstance()->NotifySubscribers(&key_event);
211+
}
212+
213+
void OS::DispatchCharacterEvent(const unsigned int uchar) {
214+
KeyboardEvent key_event { (const int)uchar, 0, KeyboardEvent::KEY_CHAR, 0 };
215+
Dispatcher<KeyboardEvent>::GetInstance()->NotifySubscribers(&key_event);
216+
}
217+
218+
void OS::DispatchMouseMoveEvent(const double x, const double y) {
219+
MouseMoveEvent mmov_event = {
220+
static_cast<double>(x) / this->client_width,
221+
static_cast<double>(y) / this->client_height,
222+
static_cast<int>(this->old_mouse_x),
223+
static_cast<int>(this->old_mouse_y),
224+
static_cast<int>(x),
225+
static_cast<int>(y)
226+
};
227+
Dispatcher<MouseMoveEvent>::GetInstance()->NotifySubscribers(&mmov_event);
228+
229+
// If we are in mouse lock we will snap the mouse to the middle of the screen.
230+
if (this->mouse_lock) {
231+
this->old_mouse_x = this->client_width / 2;
232+
this->old_mouse_y = this->client_height / 2;
233+
glfwSetCursorPos(this->window, this->old_mouse_x, this->old_mouse_y);
234+
}
235+
else {
236+
this->old_mouse_x = x;
237+
this->old_mouse_y = y;
238+
}
239+
}
240+
241+
void OS::DispatchMouseButtonEvent(const int button, const int action, const int mods) {
242+
MouseBtnEvent mbtn_event;
243+
if (action == GLFW_PRESS) {
244+
mbtn_event.action = MouseBtnEvent::DOWN;
245+
}
246+
else {
247+
mbtn_event.action = MouseBtnEvent::UP;
248+
}
249+
if (button == GLFW_MOUSE_BUTTON_LEFT) {
250+
mbtn_event.button = MouseBtnEvent::LEFT;
251+
}
252+
else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
253+
mbtn_event.button = MouseBtnEvent::RIGHT;
254+
}
255+
else if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
256+
mbtn_event.button = MouseBtnEvent::MIDDLE;
257+
}
258+
Dispatcher<MouseBtnEvent>::GetInstance()->NotifySubscribers(&mbtn_event);
259+
}
260+
261+
void OS::ToggleMouseLock() {
262+
this->mouse_lock = !this->mouse_lock;
263+
if (this->mouse_lock) {
264+
glfwSetInputMode(this->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
265+
}
266+
else {
267+
glfwSetInputMode(this->window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
268+
}
269+
}
270+
271+
void OS::SetMousePosition(const double x, const double y) {
272+
glfwSetCursorPos(this->window, x, y);
273+
}
274+
275+
}

‎src/render-system.cpp

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#include "render-system.hpp"
2+
#include <glm/gtc/matrix_transform.hpp>
3+
#include <iostream>
4+
#include <thread>
5+
6+
#include "shader.hpp"
7+
#include "vertexbuffer.hpp"
8+
#include "transform.hpp"
9+
#include "material.hpp"
10+
11+
namespace vv {
12+
class Texture {
13+
public:
14+
GLuint name;
15+
};
16+
17+
typedef Multiton<std::string, std::shared_ptr<Texture>> TextureMap;
18+
19+
std::atomic<std::queue<std::shared_ptr<Command<RS_COMMAND>>>*> RenderSystem::global_queue = new std::queue<std::shared_ptr<Command<RS_COMMAND>>>();
20+
21+
RenderSystem::RenderSystem() : current_view(0) {
22+
auto err = glGetError();
23+
if (err) {
24+
return;
25+
}
26+
// Use the GL3 way to get the version number
27+
int gl_version[3];
28+
glGetIntegerv(GL_MAJOR_VERSION, &gl_version[0]);
29+
glGetIntegerv(GL_MINOR_VERSION, &gl_version[1]);
30+
if (err) {
31+
return;
32+
}
33+
int opengl_version = gl_version[0] * 100 + gl_version[1] * 10;
34+
35+
if (opengl_version < 300) {
36+
std::cerr << "OpenGL version " << opengl_version << std::endl;
37+
assert(opengl_version >= 300);
38+
}
39+
40+
SetViewportSize(800, 600);
41+
glEnable(GL_DEPTH_TEST);
42+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
43+
}
44+
45+
void RenderSystem::SetViewportSize(const unsigned int width, const unsigned int height) {
46+
this->window_height = height;
47+
this->window_width = width;
48+
49+
float aspect_ratio = static_cast<float>(this->window_width) / static_cast<float>(this->window_height);
50+
if (aspect_ratio < 1.0f) {
51+
aspect_ratio = 4.0f / 3.0f;
52+
}
53+
54+
this->projection = glm::perspective(
55+
glm::radians(45.0f),
56+
aspect_ratio,
57+
0.1f,
58+
10000.0f
59+
);
60+
}
61+
62+
void RenderSystem::ProcessCommandQueue() {
63+
auto queue = global_queue.exchange(this->local_queue);
64+
65+
while (!queue->empty()) {
66+
auto action = queue->front();
67+
queue->pop();
68+
69+
switch (action->command) {
70+
case RS_COMMAND::VIEW_ACTIVATE:
71+
this->current_view = action->entity_id;
72+
case RS_COMMAND::VIEW_ADD:
73+
case RS_COMMAND::VIEW_UPDATE:
74+
UpdateViewMatrix(action->entity_id);
75+
break;
76+
case RS_COMMAND::VIEW_REMOVE:
77+
this->views.erase(action->entity_id);
78+
break;
79+
case RS_COMMAND::MODEL_MATRIX_ADD:
80+
case RS_COMMAND::MODEL_MATRIX_UPDATE:
81+
UpdateModelMatrix(action->entity_id);
82+
break;
83+
case RS_COMMAND::MODEL_MATRIX_REMOVE:
84+
RemoveModelMatrix(action->entity_id);
85+
break;
86+
case RS_COMMAND::VB_ADD:
87+
/*auto cast_command = static_cast<RenderCommand<std::weak_ptr<vv::VertexBuffer>>*>(action);
88+
if (cast_command->data.lock()) {
89+
cast_command->data.reset();
90+
}*/
91+
break;
92+
}
93+
}
94+
}
95+
96+
void RenderSystem::Update(const double delta) {
97+
ProcessCommandQueue();
98+
static float red = 0.3f, blue = 0.3f, green = 0.3f;
99+
100+
glClearColor(red, green, blue, 1.0f);
101+
glViewport(0, 0, this->window_width, this->window_height);
102+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
103+
104+
auto camera_matrix = this->views[this->current_view];
105+
106+
for (auto material_group : this->buffers) {
107+
auto material = material_group.first.lock();
108+
if (!material) {
109+
continue;
110+
}
111+
glPolygonMode(GL_FRONT_AND_BACK, material->GetFillMode());
112+
auto shader = material->GetShader().lock();
113+
if (!material) {
114+
continue;
115+
}
116+
shader->Use();
117+
118+
glUniformMatrix4fv(shader->GetUniform("view"), 1, GL_FALSE, &camera_matrix[0][0]);
119+
glUniformMatrix4fv(shader->GetUniform("projection"), 1, GL_FALSE, &this->projection[0][0]);
120+
GLint model_index = shader->GetUniform("model");
121+
122+
auto vb = material_group.second.first.lock();
123+
if (!vb) {
124+
continue;
125+
}
126+
glBindVertexArray(vb->vao);
127+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vb->ibo);
128+
/*for (size_t i = 0; i < mesh_group.second.textures.size(); ++i) {
129+
auto tex = mesh_group.second.textures[i].lock();
130+
GLuint name = 0;
131+
if (tex) {
132+
name = tex->name;
133+
}
134+
shader->ActivateTextureUnit(i, name);
135+
}*/
136+
137+
for (GUID entity_id : material_group.second.second) {
138+
auto transform = ModelMatrixMap::Get(entity_id);
139+
if (transform) {
140+
glUniformMatrix4fv(model_index, 1, GL_FALSE,
141+
&transform->transform[0][0]);
142+
}
143+
else {
144+
static glm::mat4 identity(1.0);
145+
glUniformMatrix4fv(model_index, 1, GL_FALSE,
146+
&identity[0][0]);
147+
}
148+
/*auto renanim = ren_group.animations.find(entity_id);
149+
if (renanim != ren_group.animations.end()) {
150+
glUniform1i(u_animate_loc, 1);
151+
auto &animmatricies = renanim->second->matrices;
152+
glUniformMatrix4fv(u_animatrix_loc, animmatricies.size(), GL_FALSE, &animmatricies[0][0][0]);
153+
}
154+
else {
155+
glUniform1i(u_animate_loc, 0);
156+
}*/
157+
glDrawElements(GL_TRIANGLES, vb->index_count, GL_UNSIGNED_INT, 0);
158+
}
159+
160+
shader->UnUse();
161+
}
162+
}
163+
164+
void RenderSystem::AddVertexBuffer(const std::weak_ptr<Material> mat, const std::weak_ptr<VertexBuffer> buffer, const GUID entity_id) {
165+
auto mat1 = mat.lock();
166+
for (auto material_group : this->buffers) {
167+
auto mat2 = material_group.first.lock();
168+
if ((mat1 && mat2) && (mat1 == mat2)) {
169+
auto vb1 = buffer.lock();
170+
auto vb2 = material_group.second.first.lock();
171+
if ((vb1 && vb2) && (vb1 == vb2)) {
172+
material_group.second.second.push_back(entity_id);
173+
return;
174+
}
175+
}
176+
}
177+
std::list<GUID> entity_list;
178+
entity_list.push_back(entity_id);
179+
this->buffers[mat] = std::make_pair(buffer, std::move(entity_list));
180+
}
181+
182+
void RenderSystem::UpdateModelMatrix(const GUID entity_id) {
183+
auto model_matrix = ModelMatrixMap::Get(entity_id);
184+
auto transform = TransformMap::Get(entity_id);
185+
if (!model_matrix && transform) {
186+
model_matrix = std::make_shared<ModelMatrix>();
187+
ModelMatrixMap::Set(entity_id, model_matrix);
188+
}
189+
else if (!transform) {
190+
return;
191+
}
192+
193+
auto camera_translation = transform->GetTranslation();
194+
auto camera_orientation = transform->GetOrientation();
195+
model_matrix->transform = glm::translate(glm::mat4(1.0), camera_translation) * glm::mat4_cast(camera_orientation);
196+
if (this->views.find(entity_id) != this->views.end()) {
197+
UpdateViewMatrix(entity_id);
198+
}
199+
}
200+
201+
void RenderSystem::RemoveModelMatrix(const GUID entity_id) {
202+
ModelMatrixMap::Remove(entity_id);
203+
}
204+
205+
void RenderSystem::UpdateViewMatrix(const GUID entity_id) {
206+
auto model_matrix = ModelMatrixMap::Get(entity_id);
207+
if (!model_matrix) {
208+
return;
209+
}
210+
this->views[entity_id] = glm::inverse(model_matrix->transform);
211+
}
212+
}

‎src/transform.cpp

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "transform.hpp"
2+
3+
namespace vv {
4+
Transform::Transform(GUID entity_id) :
5+
orientation(glm::quat(1, 0, 0, 0)), scale(1.0f), entity_id(entity_id) { }
6+
7+
void Transform::Translate(const glm::vec3 amount) {
8+
this->translation += amount;
9+
}
10+
11+
void Transform::Rotate(const glm::vec3 amount) {
12+
this->rotation += amount;
13+
14+
glm::quat change(this->rotation);
15+
this->orientation = glm::normalize(change * this->orientation);
16+
}
17+
18+
void Transform::OrientedTranslate(const glm::vec3 amount) {
19+
this->translation += this->orientation * amount;
20+
}
21+
22+
void Transform::OrientedRotate(const glm::vec3 amount) {
23+
this->rotation += amount;
24+
25+
glm::quat qX = glm::angleAxis(amount.x, this->orientation * RIGHT_VECTOR);
26+
glm::quat qY = glm::angleAxis(amount.y, this->orientation * UP_VECTOR);
27+
glm::quat qZ = glm::angleAxis(amount.z, this->orientation * glm::vec3(0.0, 0.0, 1.0)); // Z axis not Forward
28+
glm::quat change = qX * qY * qZ;
29+
30+
this->orientation = glm::normalize(change * this->orientation);
31+
}
32+
33+
void Transform::Scale(const glm::vec3 amount) {
34+
this->scale *= amount;
35+
}
36+
37+
void Transform::SetTranslation(const glm::vec3 new_translation) {
38+
this->translation = new_translation;
39+
}
40+
41+
void Transform::SetRotation(const glm::vec3 new_rotation) {
42+
this->orientation = glm::normalize(glm::quat(new_rotation));
43+
this->rotation.x = atan2(2.0f * (this->orientation.y * this->orientation.z +
44+
this->orientation.w * this->orientation.x),
45+
this->orientation.w * this->orientation.w - this->orientation.x *
46+
this->orientation.x - this->orientation.y * this->orientation.y +
47+
this->orientation.z * this->orientation.z);
48+
this->rotation.y = glm::asin(-2.0f * (this->orientation.x * this->orientation.z - this->orientation.w * this->orientation.y));
49+
this->rotation.z = atan2(2.0f * (this->orientation.x * this->orientation.y +
50+
this->orientation.w * this->orientation.z),
51+
this->orientation.w * this->orientation.w + this->orientation.x *
52+
this->orientation.x - this->orientation.y * this->orientation.y -
53+
this->orientation.z * this->orientation.z);
54+
}
55+
56+
void Transform::SetOrientation(const glm::quat new_orientation) {
57+
this->orientation = new_orientation;
58+
this->rotation.x = atan2(2.0f * (this->orientation.y * this->orientation.z +
59+
this->orientation.w * this->orientation.x),
60+
this->orientation.w * this->orientation.w - this->orientation.x *
61+
this->orientation.x - this->orientation.y * this->orientation.y +
62+
this->orientation.z * this->orientation.z);
63+
this->rotation.y = glm::asin(-2.0f * (this->orientation.x * this->orientation.z - this->orientation.w * this->orientation.y));
64+
this->rotation.z = atan2(2.0f * (this->orientation.x * this->orientation.y +
65+
this->orientation.w * this->orientation.z),
66+
this->orientation.w * this->orientation.w + this->orientation.x *
67+
this->orientation.x - this->orientation.y * this->orientation.y -
68+
this->orientation.z * this->orientation.z);
69+
}
70+
71+
void Transform::SetScale(const glm::vec3 new_scale) {
72+
this->scale = new_scale;
73+
}
74+
75+
glm::vec3 Transform::GetTranslation() const {
76+
return this->translation;
77+
}
78+
79+
glm::vec3 Transform::GetRotation() const {
80+
return this->rotation;
81+
}
82+
83+
glm::quat Transform::GetOrientation() const {
84+
return this->orientation;
85+
}
86+
87+
glm::vec3 Transform::GetScale() const {
88+
return this->scale;
89+
}
90+
}

‎src/voxelvolume.cpp

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include "voxelvolume.hpp"
2+
#include "vertexbuffer.hpp"
3+
4+
namespace vv {
5+
std::atomic<std::queue<std::shared_ptr<Command<VOXEL_COMMAND>>>*> VoxelVolume::global_queue = new std::queue<std::shared_ptr<Command<VOXEL_COMMAND>>>();
6+
7+
VoxelVolume::VoxelVolume() { }
8+
9+
VoxelVolume::~VoxelVolume() { }
10+
11+
void VoxelVolume::AddVoxel(const short row, const short column, const short slice) {
12+
Voxel v;
13+
long long index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
14+
15+
if (this->voxels.find(index) == this->voxels.end()) {
16+
this->voxels[index] = v;
17+
18+
// Since we are adding a voxel we must set the new voxels neighors.
19+
long long up_index, down_index, left_index, right_index, back_index, front_index;
20+
up_index = (unsigned long long((row + 1) & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
21+
down_index = (unsigned long long((row - 1) & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
22+
left_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int((column - 1) & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
23+
right_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int((column + 1) & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
24+
front_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned((slice - 1) & 0xFFFF);
25+
back_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned((slice + 1) & 0xFFFF);
26+
27+
if (this->voxels.find(up_index) != this->voxels.end()) {
28+
v.neighbors[Voxel::UP] = &this->voxels[up_index];
29+
this->voxels[up_index].neighbors[Voxel::DOWN] = &this->voxels[index];
30+
}
31+
if (this->voxels.find(down_index) != this->voxels.end()) {
32+
v.neighbors[Voxel::DOWN] = &this->voxels[down_index];
33+
this->voxels[down_index].neighbors[Voxel::UP] = &this->voxels[index];
34+
}
35+
if (this->voxels.find(left_index) != this->voxels.end()) {
36+
v.neighbors[Voxel::LEFT] = &this->voxels[left_index];
37+
this->voxels[left_index].neighbors[Voxel::RIGHT] = &this->voxels[index];
38+
}
39+
if (this->voxels.find(right_index) != this->voxels.end()) {
40+
v.neighbors[Voxel::RIGHT] = &this->voxels[right_index];
41+
this->voxels[right_index].neighbors[Voxel::LEFT] = &this->voxels[index];
42+
}
43+
if (this->voxels.find(front_index) != this->voxels.end()) {
44+
v.neighbors[Voxel::FRONT] = &this->voxels[front_index];
45+
this->voxels[front_index].neighbors[Voxel::BACK] = &this->voxels[index];
46+
}
47+
if (this->voxels.find(back_index) != this->voxels.end()) {
48+
v.neighbors[Voxel::BACK] = &this->voxels[back_index];
49+
this->voxels[back_index].neighbors[Voxel::FRONT] = &this->voxels[index];
50+
}
51+
}
52+
}
53+
54+
void VoxelVolume::RemoveVoxel(const short row, const short column, const short slice) {
55+
long long index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
56+
57+
if (this->voxels.find(index) != this->voxels.end()) {
58+
Voxel& v = this->voxels[index];
59+
60+
long long up_index, down_index, left_index, right_index, back_index, front_index;
61+
up_index = (unsigned long long((row + 1) & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
62+
down_index = (unsigned long long((row - 1) & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
63+
left_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int((column - 1) & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
64+
right_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int((column + 1) & 0xFFFF) << 16) + unsigned(slice & 0xFFFF);
65+
front_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned((slice - 1) & 0xFFFF);
66+
back_index = (unsigned long long(row & 0xFFFF) << 32) + (unsigned int(column & 0xFFFF) << 16) + unsigned((slice + 1) & 0xFFFF);
67+
68+
if (this->voxels.find(up_index) != this->voxels.end()) {
69+
this->voxels[up_index].neighbors[Voxel::DOWN] = nullptr;
70+
}
71+
if (this->voxels.find(down_index) != this->voxels.end()) {
72+
this->voxels[down_index].neighbors[Voxel::UP] = nullptr;
73+
}
74+
if (this->voxels.find(left_index) != this->voxels.end()) {
75+
this->voxels[left_index].neighbors[Voxel::RIGHT] = nullptr;
76+
}
77+
if (this->voxels.find(right_index) != this->voxels.end()) {
78+
this->voxels[right_index].neighbors[Voxel::LEFT] = nullptr;
79+
}
80+
if (this->voxels.find(front_index) != this->voxels.end()) {
81+
this->voxels[front_index].neighbors[Voxel::BACK] = nullptr;
82+
}
83+
if (this->voxels.find(back_index) != this->voxels.end()) {
84+
this->voxels[back_index].neighbors[Voxel::FRONT] = nullptr;
85+
}
86+
this->voxels.erase(index);
87+
}
88+
}
89+
90+
void VoxelVolume::Update(double delta) {
91+
ProcessCommandQueue();
92+
UpdateVertexBuffers();
93+
}
94+
95+
void VoxelVolume::ProcessCommandQueue() {
96+
auto queue = global_queue.exchange(this->local_queue);
97+
98+
while (!queue->empty()) {
99+
auto action = queue->front();
100+
queue->pop();
101+
auto voxel_action = static_cast<VoxelCommand*>(action.get());
102+
103+
switch (action->command) {
104+
case VOXEL_ADD:
105+
AddVoxel(voxel_action->row, voxel_action->column, voxel_action->slice);
106+
break;
107+
case VOXEL_REMOVE:
108+
RemoveVoxel(voxel_action->row, voxel_action->column, voxel_action->slice);
109+
break;
110+
}
111+
}
112+
}
113+
114+
void VoxelVolume::UpdateVertexBuffers() {
115+
this->verts.clear();
116+
this->index_list.clear();
117+
this->indicies.clear();
118+
static std::vector<Vertex> IdentityVerts({
119+
// Front
120+
Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f), // Bottom left
121+
Vertex(1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f), // Bottom right
122+
Vertex(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f), // Top right
123+
Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f), // Top Left
124+
// Back
125+
Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f), // Bottom left
126+
Vertex(1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f), // Bottom right
127+
Vertex(1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f), // Top right
128+
Vertex(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f) // Top left
129+
});
130+
131+
for (auto v : this->voxels) {
132+
short row = short((v.first & 0xFFFF00000000) >> 32);
133+
short column = short((v.first & 0xFFFF0000) >> 16);
134+
short slice = short(v.first & 0xFFFF);
135+
GLuint index[8];
136+
137+
for (size_t i = 0; i < 8; ++i) {
138+
auto vert_position = std::make_tuple(IdentityVerts[i].position[0] + column * 2,
139+
IdentityVerts[i].position[1] + row * 2, IdentityVerts[i].position[2] + slice * 2);
140+
141+
if (this->index_list.find(vert_position) == this->index_list.end()) {
142+
this->verts.push_back(Vertex(IdentityVerts[i].position[0] + column * 2,
143+
IdentityVerts[i].position[1] + row * 2, IdentityVerts[i].position[2] + slice * 2,
144+
IdentityVerts[i].color[0], IdentityVerts[i].color[1], IdentityVerts[i].color[2]));
145+
//v.second.color[0], v.second.color[1], v.second.color[2]));
146+
this->index_list[vert_position] = this->index_list.size();
147+
}
148+
index[i] = this->index_list[vert_position];
149+
}
150+
151+
// Front
152+
this->indicies.push_back(index[0]); this->indicies.push_back(index[1]); this->indicies.push_back(index[2]);
153+
this->indicies.push_back(index[2]); this->indicies.push_back(index[3]); this->indicies.push_back(index[0]);
154+
// Top
155+
this->indicies.push_back(index[3]); this->indicies.push_back(index[2]); this->indicies.push_back(index[6]);
156+
this->indicies.push_back(index[6]); this->indicies.push_back(index[7]); this->indicies.push_back(index[3]);
157+
// Back
158+
this->indicies.push_back(index[7]); this->indicies.push_back(index[6]); this->indicies.push_back(index[5]);
159+
this->indicies.push_back(index[5]); this->indicies.push_back(index[4]); this->indicies.push_back(index[7]);
160+
// Bottom
161+
this->indicies.push_back(index[4]); this->indicies.push_back(index[5]); this->indicies.push_back(index[1]);
162+
this->indicies.push_back(index[1]); this->indicies.push_back(index[0]); this->indicies.push_back(index[4]);
163+
// Left
164+
this->indicies.push_back(index[4]); this->indicies.push_back(index[0]); this->indicies.push_back(index[3]);
165+
this->indicies.push_back(index[3]); this->indicies.push_back(index[7]); this->indicies.push_back(index[4]);
166+
// Right
167+
this->indicies.push_back(index[1]); this->indicies.push_back(index[5]); this->indicies.push_back(index[6]);
168+
this->indicies.push_back(index[6]); this->indicies.push_back(index[2]); this->indicies.push_back(index[1]);
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)
Please sign in to comment.