Initial structure

This commit is contained in:
2015-09-04 10:02:06 +02:00
commit 98e363eda6
457 changed files with 127943 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
project(daydream)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLFW REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono)
find_package(assimp REQUIRED)
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
# GLM
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include/dd)
include_directories(
${INCLUDE_PATH}
${OPENGL_INCLUDE_DIR}
${GLEW_INCLUDE_DIRS}
${GLFW_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${assimp_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS}
)
file(GLOB SOURCE_FILES_Core
"${INCLUDE_PATH}/Core/*.h"
"Core/*.cpp"
)
file(GLOB SOURCE_FILES_Core_Util
"${INCLUDE_PATH}/Core/Util/*.h"
"Core/Util/*.cpp"
)
source_group(Core FILES ${SOURCE_FILES_Core})
source_group(Core\\Util FILES ${SOURCE_FILES_Core_Util})
file(GLOB SOURCE_FILES_Input
"${INCLUDE_PATH}/Input/*.h"
"Input/*.cpp"
)
source_group(Input FILES ${SOURCE_FILES_Input})
file(GLOB SOURCE_FILES_Particles
"${INCLUDE_PATH}/Particles/*.h"
"Particles/*.cpp"
)
source_group(Particles FILES ${SOURCE_FILES_Particles})
file(GLOB SOURCE_FILES_Rendering
"${INCLUDE_PATH}/Rendering/*.h"
)
source_group(Rendering FILES ${SOURCE_FILES_Rendering})
file(GLOB SOURCE_FILES_Timer
"${INCLUDE_PATH}/Timer/*.h"
"Timer/*.cpp"
)
source_group(Timer FILES ${SOURCE_FILES_Timer})
file(GLOB SOURCE_FILES_Transform
"${INCLUDE_PATH}/Transform/*.h"
"Transform/*.cpp"
)
source_group(Transform FILES ${SOURCE_FILES_Transform})
file(GLOB SOURCE_FILES_Trigger
"${INCLUDE_PATH}/Trigger/*.h"
"Trigger/*.cpp"
)
source_group(Trigger FILES ${SOURCE_FILES_Trigger})
set(SOURCE_FILES
${SOURCE_FILES_Core}
${SOURCE_FILES_Core_Util}
${SOURCE_FILES_Input}
${SOURCE_FILES_Particles}
${SOURCE_FILES_Rendering}
${SOURCE_FILES_Timer}
${SOURCE_FILES_Transform}
${SOURCE_FILES_Trigger}
)
add_library(daydream ${SOURCE_FILES})
target_link_libraries(daydream
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
${GLFW_LIBRARIES}
${Boost_LIBRARIES}
${assimp_LIBRARIES}
${PNG_LIBRARIES}
)
+38
View File
@@ -0,0 +1,38 @@
project(game)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLFW REQUIRED)
find_package(Boost REQUIRED)
find_package(assimp REQUIRED)
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
include_directories(
${CMAKE_SOURCE_DIR}/include/dd
${OPENGL_INCLUDE_DIR}
${GLEW_INCLUDE_DIRS}
${GLFW_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${assimp_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS}
)
set(SOURCE_FILES
main.cpp
)
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
add_executable(game ${SOURCE_FILES})
target_link_libraries(game
daydream
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
${GLFW_LIBRARIES}
${Boost_LIBRARIES}
${assimp_LIBRARIES}
${PNG_LIBRARIES}
)
+116
View File
@@ -0,0 +1,116 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Camera.h"
dd::Camera::Camera(float aspectRatio, float yFOV, float nearClip, float farClip)
{
m_AspectRatio = aspectRatio;
m_FOV = yFOV;
m_NearClip = nearClip;
m_FarClip = farClip;
m_Position = glm::vec3(0.0);
UpdateProjectionMatrix();
UpdateViewMatrix();
}
glm::vec3 dd::Camera::Forward()
{
return m_Orientation * glm::vec3(0, 0, -1);
}
//
//glm::vec3 Camera::Right()
//{
// return glm::rotate(glm::vec3(1.f, 0.f, 0.f), -m_Yaw, glm::vec3(0.f, 1.f, 0.f));
//}
//glm::mat4 Camera::Orientation()
//{
// glm::mat4 orientation(1.f);
// orientation = glm::rotate(orientation, m_Pitch, glm::vec3(1.f, 0.f, 0.f));
// orientation = glm::rotate(orientation, m_Yaw, glm::vec3(0.f, 1.f, 0.f));
// return orientation;
//}
void dd::Camera::SetPosition(glm::vec3 val)
{
m_Position = val;
UpdateViewMatrix();
}
void dd::Camera::SetOrientation(glm::quat val)
{
m_Orientation = val;
UpdateViewMatrix();
}
//void Camera::Pitch(float val)
//{
// m_Pitch = val;
// UpdateViewMatrix();
//}
//
//void Camera::Yaw(float val)
//{
// m_Yaw = val;
// UpdateViewMatrix();
//}
void dd::Camera::UpdateProjectionMatrix()
{
m_ProjectionMatrix = glm::perspective(
m_FOV,
m_AspectRatio,
m_NearClip,
m_FarClip
);
}
void dd::Camera::UpdateViewMatrix()
{
m_ViewMatrix = glm::toMat4(glm::inverse(m_Orientation))
* glm::translate(-m_Position);
}
void dd::Camera::SetAspectRatio(float val)
{
m_AspectRatio = val;
UpdateProjectionMatrix();
}
void dd::Camera::SetFOV(float val)
{
m_FOV = val;
UpdateProjectionMatrix();
}
void dd::Camera::SetNearClip(float val)
{
m_NearClip = val;
UpdateProjectionMatrix();
}
void dd::Camera::SetFarClip(float val)
{
m_FarClip = val;
UpdateProjectionMatrix();
}
+85
View File
@@ -0,0 +1,85 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/EventBroker.h"
dd::BaseEventRelay::~BaseEventRelay()
{
if (m_Broker != nullptr)
{
m_Broker->Unsubscribe(*this);
}
}
void dd::EventBroker::Unsubscribe(BaseEventRelay &relay) // ?
{
auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName);
if (contextIt == m_ContextRelays.end())
return;
auto eventRelays = contextIt->second;
auto itpair = eventRelays.equal_range(relay.m_EventTypeName);
for (auto it = itpair.first; it != itpair.second; ++it)
{
if (it->second == &relay)
{
eventRelays.erase(it);
break;
}
}
}
void dd::EventBroker::Subscribe(BaseEventRelay &relay)
{
relay.m_Broker = this;
m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay));
}
int dd::EventBroker::Process(std::string contextTypeName)
{
auto it = m_ContextRelays.find(contextTypeName);
if (it == m_ContextRelays.end())
return 0;
EventRelays_t &relays = it->second;
int eventsProcessed = 0;
for (auto &pair : *m_EventQueueRead)
{
std::string &eventTypeName = pair.first;
std::shared_ptr<Event> event = pair.second;
auto itpair = relays.equal_range(eventTypeName);
for (auto it2 = itpair.first; it2 != itpair.second; ++it2)
{
auto relay = it2->second;
relay->Receive(event);
eventsProcessed++;
}
}
return eventsProcessed;
}
void dd::EventBroker::Clear()
{
std::swap(m_EventQueueRead, m_EventQueueWrite);
m_EventQueueWrite->clear();
}
+248
View File
@@ -0,0 +1,248 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/InputManager.h"
void dd::InputManager::Initialize()
{
// TODO: Gamepad
//m_LastGamepadAxisState = std::array<GamepadAxisState, XUSER_MAX_COUNT>();
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
}
void dd::InputManager::Update(double dt)
{
EventBroker->Process<InputManager>();
m_LastKeyState = m_CurrentKeyState;
m_LastMouseState = m_CurrentMouseState;
m_LastMouseX = m_CurrentMouseX;
m_LastMouseY = m_CurrentMouseY;
// Keyboard input
for (int i = 0; i <= GLFW_KEY_LAST; ++i)
{
m_CurrentKeyState[i] = glfwGetKey(m_GLFWWindow, i);
if (m_CurrentKeyState[i] != m_LastKeyState[i])
{
// Publish key events
if (m_CurrentKeyState[i])
{
Events::KeyDown e;
e.KeyCode = i;
EventBroker->Publish(e);
}
else
{
Events::KeyUp e;
e.KeyCode = i;
EventBroker->Publish(e);
}
}
}
// Mouse buttons
for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i)
{
m_CurrentMouseState[i] = glfwGetMouseButton(m_GLFWWindow, i);
if (m_CurrentMouseState[i] != m_LastMouseState[i])
{
double x, y;
glfwGetCursorPos(m_GLFWWindow, &x, &y);
// Publish mouse button events
if (m_CurrentMouseState[i])
{
Events::MousePress e;
e.Button = i;
e.X = x;
e.Y = y;
EventBroker->Publish(e);
}
else
{
Events::MouseRelease e;
e.Button = i;
e.X = x;
e.Y = y;
EventBroker->Publish(e);
}
}
}
// Mouse movement
glfwGetCursorPos(m_GLFWWindow, &m_CurrentMouseX, &m_CurrentMouseY);
m_CurrentMouseDeltaX = m_CurrentMouseX - m_LastMouseX;
m_CurrentMouseDeltaY = m_CurrentMouseY - m_LastMouseY;
if (m_CurrentMouseDeltaX != 0 || m_CurrentMouseDeltaY != 0)
{
// Publish mouse move events
Events::MouseMove e;
e.X = m_CurrentMouseX;
e.Y = m_CurrentMouseY;
e.DeltaX = m_CurrentMouseDeltaX;
e.DeltaY = m_CurrentMouseDeltaY;
EventBroker->Publish(e);
}
// // Lock mouse while holding LMB
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
// {
// m_LastMouseX = m_Renderer->Width() / 2.f; // xpos;
// m_LastMouseY = m_Renderer->Height() / 2.f; // ypos;
// glfwSetCursorPos(m_GLFWWindow, m_LastMouseX, m_LastMouseY);
// }
// // Hide/show cursor with LMB
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT] && !m_LastMouseState[GLFW_MOUSE_BUTTON_LEFT])
// {
// glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
// }
// if (!m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT] && m_LastMouseState[GLFW_MOUSE_BUTTON_LEFT])
// {
// glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// }
// TODO: Xbox360 controller
/*DWORD dwResult;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
XINPUT_STATE state = { 0 };
// Simply get the state of the controller from XInput.
dwResult = XInputGetState(i, &state);
if (dwResult == 0)
{
if(std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLX = 0;
if(std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLY = 0;
if(std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRX = 0;
if(std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRY = 0;
if(std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bLeftTrigger = 0;
if(std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bRightTrigger = 0;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
}
}*/
m_LastKeyState = m_CurrentKeyState;
m_LastMouseState = m_CurrentMouseState;
m_LastMouseX = m_CurrentMouseX;
m_LastMouseY = m_CurrentMouseY;
m_LastGamepadAxisState = m_CurrentGamepadAxisState;
m_LastGamepadButtonState = m_CurrentGamepadButtonState;
}
void dd::InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis)
{
float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
if (currentValue != lastValue)
{
Events::GamepadAxis e;
e.GamepadID = gamepadID;
e.Axis = axis;
e.Value = currentValue;
EventBroker->Publish(e);
}
}
void dd::InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
{
bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
if (currentState != lastState)
{
if (currentState == true)
{
Events::GamepadButtonDown e;
e.GamepadID = gamepadID;
e.Button = button;
EventBroker->Publish(e);
}
else
{
Events::GamepadButtonUp e;
e.GamepadID = gamepadID;
e.Button = button;
EventBroker->Publish(e);
}
}
}
bool dd::InputManager::OnLockMouse(const Events::LockMouse &event)
{
m_MouseLocked = true;
glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
return true;
}
bool dd::InputManager::OnUnlockMouse(const Events::UnlockMouse &event)
{
m_MouseLocked = false;
glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
return true;
}
+113
View File
@@ -0,0 +1,113 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/PNG.h"
dd::PNG::PNG(std::string path)
{
FILE* file = fopen(path.c_str(), "rb");
if (!file) {
LOG_ERROR("Failed to open texture file \"%s\": %s", path.c_str(), const_cast<const char*>(strerror(errno)));
return;
}
png_byte header[8];
fread(header, 1, 8, file);
bool isPNG = !png_sig_cmp(header, 0, 8);
if (!isPNG) {
LOG_ERROR("Failed to load texture file \"%s\": File isn't PNG", path.c_str());
fclose(file);
return;
}
// Initialize libpng
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr) {
LOG_ERROR("libpng: Failed to initialze png_struct");
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
fclose(file);
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
LOG_ERROR("libpng: Failed to initialze png_info");
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
fclose(file);
return;
}
png_infop info_end_ptr = png_create_info_struct(png_ptr);
if (!info_end_ptr) {
LOG_ERROR("libpng: Failed to initialze second png_info");
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
fclose(file);
return;
}
png_init_io(png_ptr, file);
// We already read the first 8 bytes of the header
png_set_sig_bytes(png_ptr, 8);
// Read all the info up to the image data
png_read_info(png_ptr, info_ptr);
// Get info
int bit_depth, color_type;
unsigned int width, height;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
if (bit_depth != 8) {
LOG_ERROR("libpng: Unsupported bit depth \"%i\" of image \"%s\", must be 8", bit_depth, path.c_str());
return;
}
switch (color_type) {
case PNG_COLOR_TYPE_RGB:
Format = Image::ImageFormat::RGB;
break;
case PNG_COLOR_TYPE_RGBA:
Format = Image::ImageFormat::RGBA;
break;
default:
LOG_ERROR("libpng: Unsupported color format \"%i\" of image \"%s\"", color_type, path.c_str());
return;
}
unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
this->Data = new unsigned char[height * row_bytes];
png_bytep* row_pointers = new png_bytep[height];
// Point each row to the continuous data array
for (int i = 0; i < height; ++i) {
// Invert Y for OpenGL
row_pointers[height - 1 - i] = this->Data + i * row_bytes;
}
// Read in the data
png_read_image(png_ptr, row_pointers);
this->Width = width;
this->Height = height;
png_destroy_read_struct(&png_ptr, &info_ptr, &info_end_ptr);
fclose(file);
}
dd::PNG::~PNG()
{
if (Data) {
delete[] Data;
}
}
+429
View File
@@ -0,0 +1,429 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Renderer.h"
void dd::Renderer::Initialize()
{
// Initialize GLFW
if (!glfwInit()) {
LOG_ERROR("GLFW: Initialization failed");
exit(EXIT_FAILURE);
}
// Create a window
GLFWmonitor* monitor = nullptr;
if (m_Fullscreen) {
monitor = glfwGetPrimaryMonitor();
}
glfwWindowHint(GLFW_SAMPLES, 8);
m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height, "daydream", monitor, nullptr);
if (!m_Window) {
LOG_ERROR("GLFW: Failed to create window");
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(m_Window);
// GL version info
glGetIntegerv(GL_MAJOR_VERSION, &m_GLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &m_GLVersion[1]);
m_GLVendor = (GLchar*)glGetString(GL_VENDOR);
std::stringstream ss;
ss << m_GLVendor << " OpenGL " << m_GLVersion[0] << "." << m_GLVersion[1];
#ifdef DEBUG
ss << " DEBUG";
#endif
LOG_INFO(ss.str().c_str());
glfwSetWindowTitle(m_Window, ss.str().c_str());
// Initialize GLEW
if (glewInit() != GLEW_OK) {
LOG_ERROR("GLEW: Initialization failed");
exit(EXIT_FAILURE);
}
// Create default camera
m_DefaultCamera = std::unique_ptr<dd::Camera>(new dd::Camera((float)m_Resolution.Width / m_Resolution.Height, 45.f, 0.01f, 5000.f));
m_DefaultCamera->SetPosition(glm::vec3(0, 0, 0));
if (m_Camera == nullptr) {
m_Camera = m_DefaultCamera.get();
}
glfwSwapInterval(m_VSYNC);
LoadShaders();
CreateBuffers();
m_CurrentScreenBuffer = m_tFinal;
}
void dd::Renderer::LoadShaders()
{
/*
Deferred rendering
*/
// Pass #1: Fill G-buffers
m_spDeferred1 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/1/");
m_spDeferred1->BindFragDataLocation(0, "GDiffuse");
m_spDeferred1->BindFragDataLocation(1, "GPosition");
m_spDeferred1->BindFragDataLocation(2, "GNormal");
m_spDeferred1->BindFragDataLocation(3, "GSpecular");
m_spDeferred1->Link();
// Pass #2: Lighting
m_spDeferred2 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/2/");
//glBindFragDataLocation(m_SPDeferred2, 0, "FragmentLighting");
m_spDeferred2->Link();
// Pass #3: Combining into final image
m_spDeferred3 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/3/");
m_spDeferred3->Link();
/*
Forward rendering
*/
m_spForward = ResourceManager::Load<ShaderProgram>("Shaders/Forward/");
m_spForward->Link();
/*
Screen draw
*/
m_spScreen = ResourceManager::Load<ShaderProgram>("Shaders/Screen/");
m_spScreen->Link();
}
void dd::Renderer::CreateBuffers()
{
m_UnitQuad = CreateQuad();
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
glGenRenderbuffers(1, &m_rbDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_rbDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height);
// Generate G-buffer textures
glGenTextures(1, &m_GDiffuse);
glBindTexture(GL_TEXTURE_2D, m_GDiffuse);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GPosition);
glBindTexture(GL_TEXTURE_2D, m_GPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GNormal);
glBindTexture(GL_TEXTURE_2D, m_GNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GSpecular);
glBindTexture(GL_TEXTURE_2D, m_GSpecular);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Create first pass framebuffer
glGenFramebuffers(1, &m_fbDeferred1);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred1);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbDepthBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_GDiffuse, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_GPosition, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_GNormal, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, m_GSpecular, 0);
GLenum firstPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, firstPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_fbDeferred1 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
// Generate lighting texture
glGenTextures(1, &m_tLighting);
glBindTexture(GL_TEXTURE_2D, m_tLighting);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Create second pass framebuffer
glGenFramebuffers(1, &m_fbDeferred2);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred2);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tLighting, 0);
GLenum secondPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, secondPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_fbDeferred2 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
// Generate final deferred texture
glGenTextures(1, &m_tFinal);
glBindTexture(GL_TEXTURE_2D, m_tFinal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Create third pass framebuffer
glGenFramebuffers(1, &m_fbDeferred3);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred3);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbDepthBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tFinal, 0);
GLenum thirdPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, thirdPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_fbDeferred3 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
}
void dd::Renderer::Draw(RenderQueueCollection& rq)
{
DrawDeferred(rq.Deferred, rq.Lights);
DrawForward(rq.Forward, rq.Lights);
// Finally: Draw the deferred+forward combined texture to the screen
glCullFace(GL_BACK);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_spScreen->Bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_CurrentScreenBuffer);
glBindVertexArray(m_UnitQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(m_Window);
DebugKeys();
}
void dd::Renderer::DrawDeferred(RenderQueue &objects, RenderQueue &lights)
{
// Pass #1: Fill G-buffers
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred1);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_spDeferred1->Bind();
DrawScene(objects, *m_spDeferred1);
// Pass #2: Lighting
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glDepthMask(GL_FALSE);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred2);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_spDeferred2->Bind();
DrawLightSpheres(lights);
// Pass #3: Combine into final deferred image
glCullFace(GL_BACK);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbDeferred3);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_spDeferred3->Bind();
glUniform3fv(glGetUniformLocation(*m_spDeferred3, "La"), 1, glm::value_ptr(glm::vec3(0.3f)));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_GDiffuse);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_tLighting);
glBindVertexArray(m_UnitQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
void dd::Renderer::DrawForward(RenderQueue &objects, RenderQueue &lights)
{
// Forward-render semi-transparent objects on top of the current framebuffer
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
m_spForward->Bind();
DrawScene(objects, *m_spForward);
}
void dd::Renderer::DrawScene(RenderQueue &objects, ShaderProgram &program)
{
GLuint shaderProgramHandle = program;
glm::mat4 viewMatrix = m_Camera->ViewMatrix();
glm::mat4 PV = m_Camera->ProjectionMatrix() * viewMatrix;
glm::mat4 MVP;
for (auto &job : objects) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) {
glm::mat4 modelMatrix = modelJob->ModelMatrix;
MVP = PV * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "MaterialShininess"), modelJob->Shininess);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture);
if (modelJob->NormalTexture != 0) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, modelJob->NormalTexture);
}
if (modelJob->SpecularTexture != 0) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, modelJob->SpecularTexture);
}
glBindVertexArray(modelJob->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
}
}
}
void dd::Renderer::DrawLightSpheres(RenderQueue &lights)
{
GLuint shaderProgramHandle = *m_spDeferred2;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_GPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_GNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, m_GSpecular);
glm::mat4 projectionMatrix = m_Camera->ProjectionMatrix();
glm::mat4 viewMatrix = m_Camera->ViewMatrix();
glm::mat4 PV = projectionMatrix * viewMatrix;
glm::mat4 MVP;
for (auto &job : lights) {
auto pointLightJob = std::dynamic_pointer_cast<PointLightJob>(job);
if (pointLightJob) {
glm::mat4 modelMatrix = glm::translate(pointLightJob->Position) * glm::scale(glm::vec3(pointLightJob->Radius * 2.f));
MVP = PV * modelMatrix;
glUniform2fv(glGetUniformLocation(shaderProgramHandle, "ViewportSize"), 1, glm::value_ptr(glm::vec2(m_Resolution.Width, m_Resolution.Height)));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightPosition"), 1, glm::value_ptr(pointLightJob->Position));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "LightRadius"), pointLightJob->Radius);
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightDiffuse"), 1, glm::value_ptr(pointLightJob->DiffuseColor));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightSpecular"), 1, glm::value_ptr(pointLightJob->SpecularColor));
glBindVertexArray(m_UnitSphere->VAO);
glDrawArrays(GL_TRIANGLES, 0, m_UnitSphere->m_Vertices.size());
}
}
}
GLuint dd::Renderer::CreateQuad()
{
float quadVertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
float quadTexCoords[] =
{
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
GLuint vbo[2], vao;
glGenBuffers(2, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 3 * 6 * sizeof(float), quadVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 2 * 6 * sizeof(float), quadTexCoords, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return vao;
}
void dd::Renderer::DebugKeys()
{
if (glfwGetKey(m_Window, GLFW_KEY_F1)) {
m_CurrentScreenBuffer = m_tFinal;
}
if (glfwGetKey(m_Window, GLFW_KEY_F2)) {
m_CurrentScreenBuffer = m_GDiffuse;
}
if (glfwGetKey(m_Window, GLFW_KEY_F3)) {
m_CurrentScreenBuffer = m_GPosition;
}
if (glfwGetKey(m_Window, GLFW_KEY_F4)) {
m_CurrentScreenBuffer = m_GNormal;
}
if (glfwGetKey(m_Window, GLFW_KEY_F5)) {
m_CurrentScreenBuffer = m_GSpecular;
}
if (glfwGetKey(m_Window, GLFW_KEY_F6)) {
m_CurrentScreenBuffer = m_tLighting;
}
}
+85
View File
@@ -0,0 +1,85 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/ResourceManager.h"
std::unordered_map<std::string, std::function<dd::Resource*(std::string)>> dd::ResourceManager::m_FactoryFunctions;
std::unordered_map<std::pair<std::string, std::string>, dd::Resource*> dd::ResourceManager::m_ResourceCache;
std::unordered_map<std::string, dd::Resource*> dd::ResourceManager::m_ResourceFromName;
std::unordered_map<dd::Resource*, dd::Resource*> dd::ResourceManager::m_ResourceParents;
unsigned int dd::ResourceManager::m_CurrentResourceTypeID = 0;
std::unordered_map<std::string, unsigned int> dd::ResourceManager::m_ResourceTypeIDs;
std::unordered_map<unsigned int, unsigned int> dd::ResourceManager::m_ResourceCount;
bool dd::ResourceManager::m_Preloading = false;
dd::FileWatcher dd::ResourceManager::m_FileWatcher;
unsigned int dd::ResourceManager::GetTypeID(std::string resourceType)
{
if (m_ResourceTypeIDs.find(resourceType) == m_ResourceTypeIDs.end())
{
m_ResourceTypeIDs[resourceType] = m_CurrentResourceTypeID++;
}
return m_ResourceTypeIDs[resourceType];
}
void dd::ResourceManager::Reload(std::string resourceName)
{
auto it = m_ResourceFromName.find(resourceName);
if (it != m_ResourceFromName.end()) {
LOG_INFO("Reloading resource \"%s\"", resourceName.c_str());
Resource* resource = it->second;
resource->Reload();
// Notify parent
auto it2 = m_ResourceParents.find(resource);
if (it2 != m_ResourceParents.end())
{
it2->second->OnChildReloaded(resource);
}
}
}
unsigned int dd::ResourceManager::GetNewResourceID(unsigned int typeID)
{
return m_ResourceCount[typeID]++;
}
bool dd::ResourceManager::IsResourceLoaded(std::string resourceType, std::string resourceName)
{
return m_ResourceCache.find(std::make_pair(resourceType, resourceName)) != m_ResourceCache.end();
}
void dd::ResourceManager::fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags)
{
if (flags & FileWatcher::FileEventFlags::SizeChanged
|| flags & FileWatcher::FileEventFlags::TimestampChanged)
{
auto it = m_ResourceFromName.find(path);
if (it != m_ResourceFromName.end())
{
Reload(path);
}
}
}
void dd::ResourceManager::Update()
{
m_FileWatcher.Check();
}
+192
View File
@@ -0,0 +1,192 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/ShaderProgram.h"
void dd::Shader::Compile()
{
LOG_INFO("Compiling shader \"%s\"", m_FileName.c_str());
std::string shaderFile;
std::ifstream in(m_FileName, std::ios::in);
if (!in)
{
LOG_ERROR("Error: Failed to open shader file \"%s\"", m_FileName.c_str());
return;
}
in.seekg(0, std::ios::end);
shaderFile.resize((int)in.tellg());
in.seekg(0, std::ios::beg);
in.read(&shaderFile[0], shaderFile.size());
in.close();
const GLchar* shaderFileC = shaderFile.c_str();
const GLint length = shaderFile.length();
glShaderSource(m_ShaderHandle, 1, &shaderFileC, &length);
if(GLERROR("glShaderSource"))
return;
glCompileShader(m_ShaderHandle);
GLint compileStatus;
glGetShaderiv(m_ShaderHandle, GL_COMPILE_STATUS, &compileStatus);
if(compileStatus != GL_TRUE)
{
LOG_ERROR("Shader compilation failed");
GLsizei infoLogLength;
glGetShaderiv(m_ShaderHandle, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* infolog = new GLchar[infoLogLength];
glGetShaderInfoLog(m_ShaderHandle, infoLogLength, &infoLogLength, infolog);
LOG_ERROR(infolog);
delete[] infolog;
}
if(GLERROR("glCompileShader"))
return;
}
dd::Shader::Shader(GLenum shaderType, std::string resourceName)
: m_ShaderType(shaderType)
, m_FileName(resourceName)
{
m_ShaderHandle = glCreateShader(shaderType);
if (GLERROR("glCreateShader"))
return;
Compile();
}
dd::Shader::~Shader()
{
if (m_ShaderHandle != 0)
{
glDeleteShader(m_ShaderHandle);
}
}
GLenum dd::Shader::GetType() const
{
return m_ShaderType;
}
std::string dd::Shader::GetFileName() const
{
return m_FileName;
}
GLuint dd::Shader::GetHandle() const
{
return m_ShaderHandle;
}
dd::ShaderProgram::ShaderProgram(std::string resourceName)
{
auto path = boost::filesystem::path(resourceName);
if (!boost::filesystem::is_directory(path))
{
LOG_ERROR("Failed to load shader program: \"%s\" is not a directory", resourceName.c_str());
return;
}
for (auto it = boost::filesystem::directory_iterator(path); it != boost::filesystem::directory_iterator(); it++)
{
std::string filename = it->path().filename().string();
std::string filepath = it->path().string();
if (filename == "Vertex.glsl")
{
m_Shaders.push_back(ResourceManager::Load<VertexShader>(filepath, this));
}
else if (filename == "Fragment.glsl")
{
m_Shaders.push_back(ResourceManager::Load<FragmentShader>(filepath, this));
}
else if (filename == "Geometry.glsl")
{
m_Shaders.push_back(ResourceManager::Load<GeometryShader>(filepath, this));
}
}
}
dd::ShaderProgram::~ShaderProgram()
{
if (m_ShaderProgramHandle != 0)
{
glDeleteProgram(m_ShaderProgramHandle);
}
}
GLuint dd::ShaderProgram::Link()
{
if (m_Shaders.size() == 0)
{
LOG_ERROR("Failed to link shader program: No shaders bound");
return 0;
}
if (m_ShaderProgramHandle == 0)
{
m_ShaderProgramHandle = glCreateProgram();
}
LOG_INFO("Linking shader program");
for (auto &shader : m_Shaders)
{
glAttachShader(m_ShaderProgramHandle, shader->GetHandle());
}
glLinkProgram(m_ShaderProgramHandle);
if (GLERROR("glLinkProgram"))
return 0;
return m_ShaderProgramHandle;
}
GLuint dd::ShaderProgram::GetHandle()
{
return m_ShaderProgramHandle;
}
void dd::ShaderProgram::Bind()
{
if (m_ShaderProgramHandle == 0)
return;
glUseProgram(m_ShaderProgramHandle);
}
void dd::ShaderProgram::Unbind()
{
glActiveShaderProgram(0, 0);
}
void dd::ShaderProgram::BindFragDataLocation(int colorNumber, std::string name)
{
if (m_ShaderProgramHandle == 0)
return;
glBindFragDataLocation(m_ShaderProgramHandle, colorNumber, name.c_str());
}
void dd::ShaderProgram::OnChildReloaded(dd::Resource* child) {
LOG_INFO("Re-linking shader program");
glLinkProgram(m_ShaderProgramHandle);
if (GLERROR("glLinkProgram"))
return;
}
@@ -0,0 +1,65 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (binding = 0) uniform sampler2D DiffuseTexture;
layout (binding = 1) uniform sampler2D NormalMap;
layout (binding = 2) uniform sampler2D SpecularMap;
uniform mat4 V;
uniform float MaterialShininess;
in VertexData
{
vec3 Position;
vec3 Normal;
vec3 Tangent;
vec3 BiTangent;
vec2 TextureCoord;
vec4 DiffuseColor;
vec4 SpecularColor;
vec4 BoneIndices1;
vec4 BoneIndices2;
vec4 BoneWeights1;
vec4 BoneWeights2;
} Input;
out vec4 GDiffuse;
out vec4 GPosition;
out vec4 GNormal;
out vec4 GSpecular;
void main()
{
// Diffuse Texture
GDiffuse = texture(DiffuseTexture, Input.TextureCoord) * Input.DiffuseColor;
// G-buffer Position
GPosition = vec4(Input.Position.xyz, 1.0);
// G-buffer Normal
mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal);
GNormal = normalize(vec4(TBN * vec3(texture(NormalMap, Input.TextureCoord)), 0.0));
// G-buffer Specular
vec4 specularGloss = texture(SpecularMap, Input.TextureCoord);
float specularExponent = MaterialShininess;
GSpecular = vec4(specularGloss.rgb, specularExponent);
}
@@ -0,0 +1,81 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform mat4 Bones[100];
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec3 Tangent;
layout (location = 3) in vec3 BiTangent;
layout (location = 4) in vec2 TextureCoord;
layout (location = 5) in vec4 DiffuseColor;
layout (location = 6) in vec4 SpecularColor;
layout (location = 7) in vec4 BoneIndices1;
layout (location = 8) in vec4 BoneIndices2;
layout (location = 9) in vec4 BoneWeights1;
layout (location = 10) in vec4 BoneWeights2;
out VertexData
{
vec3 Position;
vec3 Normal;
vec3 Tangent;
vec3 BiTangent;
vec2 TextureCoord;
vec4 DiffuseColor;
vec4 SpecularColor;
vec4 BoneIndices1;
vec4 BoneIndices2;
vec4 BoneWeights1;
vec4 BoneWeights2;
} Output;
void main()
{
mat4 boneTransform = mat4(1);
if (length(BoneWeights1 + BoneWeights2) > 0) {
boneTransform = BoneWeights1[0] * Bones[int(BoneIndices1[0])]
+ BoneWeights1[1] * Bones[int(BoneIndices1[1])]
+ BoneWeights1[2] * Bones[int(BoneIndices1[2])]
+ BoneWeights1[3] * Bones[int(BoneIndices1[3])]
+ BoneWeights2[0] * Bones[int(BoneIndices2[0])]
+ BoneWeights2[1] * Bones[int(BoneIndices2[1])]
+ BoneWeights2[2] * Bones[int(BoneIndices2[2])]
+ BoneWeights2[3] * Bones[int(BoneIndices2[3])];
}
gl_Position = MVP * boneTransform * vec4(Position, 1.0);
Output.Position = (V * M * boneTransform * vec4(Position, 1.0)).xyz;
Output.Normal = (inverse(transpose(V * M)) * boneTransform * vec4(Normal, 0.0)).xyz;
Output.Tangent = Tangent;
Output.BiTangent = BiTangent;
Output.TextureCoord = TextureCoord;
Output.DiffuseColor = DiffuseColor;
Output.SpecularColor = SpecularColor;
Output.BoneIndices1 = BoneIndices1;
Output.BoneIndices2 = BoneIndices2;
Output.BoneWeights1 = BoneWeights1;
Output.BoneWeights2 = BoneWeights2;
}
@@ -0,0 +1,72 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (binding=0) uniform sampler2D PositionTexture;
layout (binding=1) uniform sampler2D NormalTexture;
layout (binding=2) uniform sampler2D SpecularTexture;
uniform vec2 ViewportSize;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform vec3 LightPosition;
uniform float LightRadius;
uniform vec3 LightSpecular;
uniform vec3 LightDiffuse;
out vec4 FragmentColor;
vec4 phong(vec3 position, vec3 normal, vec3 specular, float specularExponent)
{
// Diffuse
vec3 lightPos = vec3(V * vec4(LightPosition, 1.0));
vec3 distanceToLight = lightPos - position;
vec3 directionToLight = normalize(distanceToLight);
float dotProd = dot(directionToLight, normal);
dotProd = max(dotProd, 0.0);
vec3 Idiffuse = LightDiffuse * dotProd;
// Specular
//vec3 reflection = reflect(-directionToLight, normal);
vec3 surfaceToViewer = normalize(-position);
vec3 halfWay = normalize(surfaceToViewer + directionToLight);
float dotSpecular = max(dot(halfWay, normal), 0.0);
float specularFactor = pow(dotSpecular, specularExponent);
vec3 Ispecular = specular * LightSpecular * specularFactor;
//Attenuation
float dist = distance(lightPos, position);
//float attenuation = 1.0 - pow(dist / LightRadius, 2);
float attenuation = pow(max(0.0f, 1.0 - (dist / LightRadius)), 2);
return vec4((Idiffuse + Ispecular) * attenuation, 1.0);
}
void main()
{
vec2 TextureCoord = gl_FragCoord.xy / ViewportSize;
vec4 PositionTexel = texture(PositionTexture, TextureCoord);
vec4 NormalTexel = texture(NormalTexture, TextureCoord);
vec4 SpecularTexel = texture(SpecularTexture, TextureCoord);
FragmentColor = phong(PositionTexel.xyz, normalize(NormalTexel.xyz), SpecularTexel.rgb, SpecularTexel.a);
//FragmentColor = vec4(1, 1, 1, 1);
}
@@ -0,0 +1,36 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
uniform mat4 MVP;
layout (location = 0) in vec3 Position;
out VertexData
{
vec3 Position;
vec2 TextureCoord;
} Output;
void main()
{
gl_Position = MVP * vec4(Position, 1.0);
Output.Position = Position;
Output.TextureCoord = (vec2(Position) + 1.0) / 2.0;
}
@@ -0,0 +1,42 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
uniform vec3 La;
layout (binding=0) uniform sampler2D DiffuseTexture;
layout (binding=1) uniform sampler2D LightingTexture;
in VertexData
{
vec3 Position;
vec2 TextureCoord;
} Input;
out vec4 frag_Diffuse;
void main()
{
vec4 DiffuseTexel = texture(DiffuseTexture, Input.TextureCoord);
vec4 LightingTexel = texture(LightingTexture, Input.TextureCoord);
//frag_Diffuse = DiffuseTexel * (vec4(La, 0.0) * (vec4(LightingTexel.rgb, 0.0) + vec4(LightingTexel.a, LightingTexel.a, LightingTexel.a, 0.0)));
frag_Diffuse = DiffuseTexel * (vec4(La, 0.0) + LightingTexel);
//frag_Diffuse = vec4(LightingTexel.r, LightingTexel.g, LightingTexel.b, 1.0);
}
@@ -0,0 +1,34 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (location = 0) in vec3 Position;
out VertexData
{
vec3 Position;
vec2 TextureCoord;
} Output;
void main()
{
gl_Position = vec4(Position, 1.0);
Output.Position = Position;
Output.TextureCoord = (vec2(Position) + 1) / 2;
}
@@ -0,0 +1,89 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (binding=0) uniform sampler2D DiffuseTexture;
layout (binding=1) uniform sampler2D NormalMap;
layout (binding=2) uniform sampler2D SpecularMap;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform vec3 LightPosition;
uniform float LightRadius;
uniform vec3 LightSpecular;
uniform vec3 LightDiffuse;
in VertexData
{
vec3 Position;
vec3 Normal;
vec3 Tangent;
vec3 BiTangent;
vec2 TextureCoord;
vec4 DiffuseColor;
vec4 SpecularColor;
vec4 BoneIndices1;
vec4 BoneIndices2;
vec4 BoneWeights1;
vec4 BoneWeights2;
} Input;
out vec4 FragmentColor;
vec4 phong(vec3 position, vec3 normal, vec3 specular, float specularExponent)
{
// Diffuse
vec3 lightPos = vec3(V * vec4(LightPosition, 1.0));
vec3 distanceToLight = lightPos - position;
vec3 directionToLight = normalize(distanceToLight);
float dotProd = dot(directionToLight, normal);
dotProd = max(dotProd, 0.0);
vec3 Idiffuse = LightDiffuse * dotProd;
// Specular
//vec3 reflection = reflect(-directionToLight, normal);
vec3 surfaceToViewer = normalize(-position);
vec3 halfWay = normalize(surfaceToViewer + directionToLight);
float dotSpecular = max(dot(halfWay, normal), 0.0);
float specularFactor = pow(dotSpecular, specularExponent);
vec3 Ispecular = specular * LightSpecular * specularFactor;
//Attenuation
float dist = distance(lightPos, position);
//float attenuation = 1.0 - pow(dist / LightRadius, 2);
float attenuation = pow(max(0.0f, 1.0 - (dist / LightRadius)), 2);
return vec4((Idiffuse + Ispecular) * attenuation, 1.0);
}
void main()
{
vec4 normalTexel = texture(NormalMap, Input.TextureCoord);
mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal);
vec3 normal = normalize(vec4(TBN * normalTexel.xyz, 0.0).xyz);
vec4 specularTexel = texture(SpecularMap, Input.TextureCoord);
vec4 diffuseTexel = texture(DiffuseTexture, Input.TextureCoord);
//FragmentColor = phong(Input.Position, normalize(normal), specularTexel.rgb, specularTexel.a);
FragmentColor = diffuseTexel;
}
+81
View File
@@ -0,0 +1,81 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform mat4 Bones[100];
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec3 Tangent;
layout (location = 3) in vec3 BiTangent;
layout (location = 4) in vec2 TextureCoord;
layout (location = 5) in vec4 DiffuseColor;
layout (location = 6) in vec4 SpecularColor;
layout (location = 7) in vec4 BoneIndices1;
layout (location = 8) in vec4 BoneIndices2;
layout (location = 9) in vec4 BoneWeights1;
layout (location = 10) in vec4 BoneWeights2;
out VertexData
{
vec3 Position;
vec3 Normal;
vec3 Tangent;
vec3 BiTangent;
vec2 TextureCoord;
vec4 DiffuseColor;
vec4 SpecularColor;
vec4 BoneIndices1;
vec4 BoneIndices2;
vec4 BoneWeights1;
vec4 BoneWeights2;
} Output;
void main()
{
mat4 boneTransform = mat4(1);
if (length(BoneWeights1 + BoneWeights2) > 0) {
boneTransform = BoneWeights1[0] * Bones[int(BoneIndices1[0])]
+ BoneWeights1[1] * Bones[int(BoneIndices1[1])]
+ BoneWeights1[2] * Bones[int(BoneIndices1[2])]
+ BoneWeights1[3] * Bones[int(BoneIndices1[3])]
+ BoneWeights2[0] * Bones[int(BoneIndices2[0])]
+ BoneWeights2[1] * Bones[int(BoneIndices2[1])]
+ BoneWeights2[2] * Bones[int(BoneIndices2[2])]
+ BoneWeights2[3] * Bones[int(BoneIndices2[3])];
}
gl_Position = MVP * boneTransform * vec4(Position, 1.0);
Output.Position = (V * M * boneTransform * vec4(Position, 1.0)).xyz;
Output.Normal = (inverse(transpose(V * M)) * boneTransform * vec4(Normal, 0.0)).xyz;
Output.Tangent = Tangent;
Output.BiTangent = BiTangent;
Output.TextureCoord = TextureCoord;
Output.DiffuseColor = DiffuseColor;
Output.SpecularColor = SpecularColor;
Output.BoneIndices1 = BoneIndices1;
Output.BoneIndices2 = BoneIndices2;
Output.BoneWeights1 = BoneWeights1;
Output.BoneWeights2 = BoneWeights2;
}
@@ -0,0 +1,30 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (binding=0) uniform sampler2D DiffuseTexture;
in vec2 TextureCoord;
out vec4 FragmentColor;
void main()
{
FragmentColor = texture(DiffuseTexture, TextureCoord);
}
+29
View File
@@ -0,0 +1,29 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#version 440
layout (location = 0) in vec3 Position;
out vec2 TextureCoord;
void main()
{
gl_Position = vec4(Position, 1.0);
TextureCoord = (vec2(Position) + 1.0) / 2.0;
}
+65
View File
@@ -0,0 +1,65 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Texture.h"
dd::Texture::Texture(std::string path)
{
std::unique_ptr<Image> image = std::make_unique<PNG>(path);
if (image->Width == 0 && image->Height == 0 || image->Format == Image::ImageFormat::Unknown) {
image = std::make_unique<PNG>("Textures/ErrorTexture.png");
if (image->Width == 0 && image->Height == 0 || image->Format == Image::ImageFormat::Unknown) {
LOG_ERROR("Couldn't even load the error texture. This is a dark day indeed.");
return;
}
}
GLint format;
switch (image->Format) {
case Image::ImageFormat::RGB:
format = GL_RGB;
break;
case Image::ImageFormat::RGBA:
format = GL_RGBA;
break;
}
// Construct the OpenGL texture
glGenTextures(1, &m_Texture);
glBindTexture(GL_TEXTURE_2D, m_Texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, format, image->Width, image->Height, 0, format, GL_UNSIGNED_BYTE, image->Data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLERROR("Texture load");
}
dd::Texture::~Texture()
{
glDeleteTextures(1, &m_Texture);
}
void dd::Texture::Bind(GLenum textureUnit /* = GL_TEXTURE0 */)
{
glActiveTexture(textureUnit);
glBindTexture(GL_TEXTURE_2D, m_Texture);
}
+135
View File
@@ -0,0 +1,135 @@
#include "PrecompiledHeader.h"
#include "Core/Util/FileWatcher.h"
dd::FileWatcher::FileWatcher()
{
m_Worker = new Worker;
}
dd::FileWatcher::FileWatcher(std::string rootPath)
{
m_RootPath = rootPath;
m_Worker = new Worker;
}
dd::FileWatcher::~FileWatcher()
{
m_Thread.interrupt();
if (m_Worker != nullptr)
{
delete m_Worker;
}
}
void dd::FileWatcher::AddWatch(std::string path, FileEventCallback_t callback)
{
m_Worker->AddWatch(path, callback);
}
void dd::FileWatcher::Start()
{
m_Thread.interrupt();
m_Thread = boost::thread(boost::ref(*m_Worker));
m_IsRunning = true;
}
void dd::FileWatcher::Stop()
{
m_Thread.interrupt();
m_IsRunning = false;
}
void dd::FileWatcher::Check()
{
m_Worker->Check();
}
void dd::FileWatcher::Worker::operator()()
{
while (true)
{
boost::this_thread::interruption_point();
Check();
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
}
}
void dd::FileWatcher::Worker::AddWatch(std::string path, FileEventCallback_t callback)
{
m_Mutex.lock();
boost::filesystem::path bpath(path);
m_FileCallbacks[bpath] = callback;
if (boost::filesystem::exists(bpath))
{
m_FileInfo[bpath] = GetFileInfo(bpath);
}
m_Mutex.unlock();
}
void dd::FileWatcher::Worker::Check()
{
m_Mutex.lock();
for (auto &kv : m_FileCallbacks)
{
boost::filesystem::path path = kv.first;
FileEventCallback_t& callback = kv.second;
FileEventFlags flags = UpdateFileInfo(path);
if (flags != FileEventFlags::None && callback != nullptr)
{
callback(path.string(), flags);
}
}
m_Mutex.unlock();
}
dd::FileWatcher::Worker::FileInfo dd::FileWatcher::Worker::GetFileInfo(boost::filesystem::path path)
{
FileInfo fi;
fi.Size = boost::filesystem::file_size(path);
fi.Timestamp = boost::filesystem::last_write_time(path);
return fi;
}
dd::FileWatcher::FileEventFlags dd::FileWatcher::Worker::UpdateFileInfo(boost::filesystem::path path)
{
FileEventFlags flags = FileEventFlags::None;
if (boost::filesystem::exists(path))
{
FileInfo fi = GetFileInfo(path);
auto lastFileInfoIt = m_FileInfo.find(path);
if (lastFileInfoIt != m_FileInfo.end())
{
FileInfo lastFileInfo = lastFileInfoIt->second;
if (fi.Size != lastFileInfo.Size)
{
LOG_DEBUG("FileWatcher: \"%s\" size changed!", path.string().c_str());
flags = flags | FileEventFlags::SizeChanged;
}
if (fi.Timestamp != lastFileInfo.Timestamp)
{
LOG_DEBUG("FileWatcher: \"%s\" timestamp changed!", path.string().c_str());
flags = flags | FileEventFlags::TimestampChanged;
}
}
else
{
LOG_DEBUG("FileWatcher: \"%s\" was created!", path.string().c_str());
flags = flags | FileEventFlags::Created;
}
m_FileInfo[path] = GetFileInfo(path);
}
else
{
auto fileInfoIt = m_FileInfo.find(path);
if (fileInfoIt != m_FileInfo.end())
{
m_FileInfo.erase(fileInfoIt);
LOG_DEBUG("FileWatcher: \"%s\" was deleted!", path.string().c_str());
flags = flags | FileEventFlags::Deleted;
}
}
return flags;
}
+232
View File
@@ -0,0 +1,232 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/World.h"
void dd::World::RecycleEntityID(EntityID id)
{
m_RecycledEntityIDs.push(id);
}
EntityID dd::World::GenerateEntityID()
{
if (!m_RecycledEntityIDs.empty())
{
EntityID id = m_RecycledEntityIDs.top();
m_RecycledEntityIDs.pop();
return id;
}
else
{
return ++m_LastEntityID;
}
}
void dd::World::RecursiveUpdate(std::shared_ptr<System> system, double dt, EntityID parentEntity)
{
for (auto &pair : m_EntityParents)
{
EntityID child = pair.first;
EntityID parent = pair.second;
system->UpdateEntity(dt, child, parent);
//RecursiveUpdate(system, dt, child);
}
}
void dd::World::Update(double dt)
{
for (auto pair : m_Systems)
{
const std::string &type = pair.first;
auto system = pair.second;
EventBroker->Process(type);
system->Update(dt);
RecursiveUpdate(system, dt, 0);
}
ProcessEntityRemovals();
}
//std::vector<EntityID> GetEntityChildren(EntityID entity);
//{
// std::vector<EntityID> children;
// auto range = m_SceneGraph.equal_range(entity);
// for (auto it = range.first; it != range.second; ++it)
// children.push_back(it->second);
// return children;
//}
EntityID dd::World::GetEntityParent(EntityID entity)
{
auto it = m_EntityParents.find(entity);
return it == m_EntityParents.end() ? 0 : it->second;
}
EntityID dd::World::GetEntityBaseParent(EntityID entity)
{
EntityID parent = GetEntityParent(entity);
if (parent == 0)
return entity;
else
return GetEntityBaseParent(parent);
}
bool dd::World::ValidEntity(EntityID entity)
{
return m_EntityParents.find(entity) != m_EntityParents.end()
&& m_EntitiesToRemove.find(entity) == m_EntitiesToRemove.end();
}
void dd::World::RemoveEntity(EntityID entity)
{
m_EntitiesToRemove.insert(entity);
auto it = m_EntityChildren.find(entity);
if (it != m_EntityChildren.end())
{
for (auto entity : it->second)
{
RemoveEntity(entity);
}
}
}
void dd::World::ProcessEntityRemovals()
{
for (auto entity : m_EntitiesToRemove)
{
m_EntityParents.erase(entity);
m_EntityChildren.erase(entity);
// Remove components
for (auto pair : m_EntityComponents[entity])
{
auto type = pair.first;
auto component = pair.second;
// Trigger events
for (auto pair : m_Systems)
{
auto system = pair.second;
system->OnComponentRemoved(entity, type, component.get());
}
m_ComponentsOfType[type].remove(component);
}
m_EntityComponents.erase(entity);
RecycleEntityID(entity);
// Trigger events
for (auto pair : m_Systems)
{
auto system = pair.second;
system->OnEntityRemoved(entity);
}
}
m_EntitiesToRemove.clear();
}
EntityID dd::World::CreateEntity(EntityID parent /*= 0*/)
{
EntityID newEntity = GenerateEntityID();
m_EntityParents[newEntity] = parent;
m_EntityChildren[parent].push_back(newEntity);
return newEntity;
}
void dd::World::Initialize()
{
RegisterSystems();
AddSystems();
for (auto pair : m_Systems)
{
auto system = pair.second;
system->RegisterComponents(&ComponentFactory);
system->RegisterResourceTypes(ResourceManager);
system->Initialize();
}
}
void dd::World::CommitEntity(EntityID entity)
{
for (auto pair : m_Systems)
{
auto system = pair.second;
system->OnEntityCommit(entity);
}
}
void dd::World::AddComponent(EntityID entity, std::string componentType, std::shared_ptr<Component> component)
{
component->Entity = entity;
m_ComponentsOfType[componentType].push_back(component);
m_EntityComponents[entity][componentType] = component;
Events::ComponentCreated e;
e.Entity = entity;
e.Component = component;
EventBroker->Publish(e);
}
EntityID dd::World::CloneEntity(EntityID entity, EntityID parent /* = 0 */)
{
int clone = CreateEntity(parent);
for (auto pair : m_EntityComponents[entity])
{
auto type = pair.first;
auto component = std::shared_ptr<Component>(ComponentFactory.Copy(type, pair.second.get()));
if (component != nullptr)
{
AddComponent(clone, type, component);
}
}
auto itChildren = m_EntityChildren.find(entity);
if (itChildren != m_EntityChildren.end())
{
for (EntityID child : itChildren->second)
{
CloneEntity(child, clone);
}
}
CommitEntity(clone);
return clone;
}
std::list<EntityID> dd::World::GetEntityChildren(EntityID entity)
{
auto it = m_EntityChildren.find(entity);
if (it == m_EntityChildren.end())
{
return std::list<EntityID>();
}
else
{
return it->second;
}
}
void dd::World::SetEntityParent(EntityID entity, EntityID newParent)
{
EntityID currentParent = m_EntityParents[entity];
m_EntityChildren[currentParent].remove(entity);
m_EntityParents[entity] = newParent;
m_EntityChildren[newParent].push_back(entity);
}
+266
View File
@@ -0,0 +1,266 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Input/InputSystem.h"
#include "Core/World.h"
void dd::Systems::InputSystem::RegisterComponents(ComponentFactory* cf)
{
}
void dd::Systems::InputSystem::Initialize()
{
// Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Systems::InputSystem::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Systems::InputSystem::OnKeyUp);
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Systems::InputSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Systems::InputSystem::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &Systems::InputSystem::OnGamepadAxis);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &Systems::InputSystem::OnGamepadButtonDown);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &Systems::InputSystem::OnGamepadButtonUp);
EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &Systems::InputSystem::OnBindKey);
EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &Systems::InputSystem::OnBindMouseButton);
EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &Systems::InputSystem::OnBindGamepadAxis);
EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &Systems::InputSystem::OnBindGamepadButton);
}
void dd::Systems::InputSystem::Update(double dt)
{
// #ifdef DEBUG
// // Wireframe
// if (m_CurrentKeyState[GLFW_KEY_F1] && !m_LastKeyState[GLFW_KEY_F1])
// {
// m_Renderer->DrawWireframe(!m_Renderer->DrawWireframe());
// }
// // Normals
// if (m_CurrentKeyState[GLFW_KEY_F2] && !m_LastKeyState[GLFW_KEY_F2])
// {
// m_Renderer->DrawNormals(!m_Renderer->DrawNormals());
// }
// // Bounds
// if (m_CurrentKeyState[GLFW_KEY_F3] && !m_LastKeyState[GLFW_KEY_F3])
// {
// m_Renderer->DrawBounds(!m_Renderer->DrawBounds());
// }
// #endif
}
bool dd::Systems::InputSystem::OnKeyDown(const Events::KeyDown &event)
{
auto range = m_KeyBindings.equal_range(event.KeyCode);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandKeyboardValues[command][event.KeyCode] = value;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnKeyUp(const Events::KeyUp &event)
{
auto range = m_KeyBindings.equal_range(event.KeyCode);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandKeyboardValues[command][event.KeyCode] = 0;
PublishCommand(1, command, GetCommandTotalValue(command));;
}
return true;
}
bool dd::Systems::InputSystem::OnMousePress(const Events::MousePress &event)
{
auto range = m_MouseButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandMouseButtonValues[command][event.Button] = value;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnMouseRelease(const Events::MouseRelease &event)
{
auto range = m_MouseButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandMouseButtonValues[command][event.Button] = 0;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnGamepadAxis(const Events::GamepadAxis &event)
{
auto range = m_GamepadAxisBindings.equal_range(event.Axis);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadAxisValues[command][event.Axis] = event.Value * value;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnGamepadButtonDown(const Events::GamepadButtonDown &event)
{
auto range = m_GamepadButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadButtonValues[command][event.Button] = value;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnGamepadButtonUp(const Events::GamepadButtonUp &event)
{
auto range = m_GamepadButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++)
{
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadButtonValues[command][event.Button] = 0;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool dd::Systems::InputSystem::OnBindKey(const Events::BindKey &event)
{
if (event.Command.empty())
return false;
m_KeyBindings.insert(std::make_pair(event.KeyCode, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound key %i to %s", event.KeyCode, event.Command.c_str());
return true;
}
bool dd::Systems::InputSystem::OnBindMouseButton(const Events::BindMouseButton &event)
{
if (event.Command.empty())
return false;
m_MouseButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound mouse button %i to %s", event.Button, event.Command.c_str());
return true;
}
bool dd::Systems::InputSystem::OnBindGamepadAxis(const Events::BindGamepadAxis &event)
{
if (event.Command.empty())
return false;
m_GamepadAxisBindings.insert(std::make_pair(event.Axis, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Axis, event.Command.c_str());
return true;
}
bool dd::Systems::InputSystem::OnBindGamepadButton(const Events::BindGamepadButton &event)
{
if (event.Command.empty())
return false;
m_GamepadButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Button, event.Command.c_str());
return true;
}
float dd::Systems::InputSystem::GetCommandTotalValue(std::string command)
{
float value = 0.f;
auto keyboardIt = m_CommandKeyboardValues.find(command);
if (keyboardIt != m_CommandKeyboardValues.end())
{
for (auto &key : keyboardIt->second)
{
value += key.second;
}
}
auto mouseButtonIt = m_CommandMouseButtonValues.find(command);
if (mouseButtonIt != m_CommandMouseButtonValues.end())
{
for (auto &button : mouseButtonIt->second)
{
value += button.second;
}
}
auto gamepadAxisIt = m_CommandGamepadAxisValues.find(command);
if (gamepadAxisIt != m_CommandGamepadAxisValues.end())
{
for (auto &axis : gamepadAxisIt->second)
{
value += axis.second;
}
}
auto gamepadButtonIt = m_CommandGamepadButtonValues.find(command);
if (gamepadButtonIt != m_CommandGamepadButtonValues.end())
{
for (auto &button : gamepadButtonIt->second)
{
value += button.second;
}
}
return std::max(-1.f, std::min(value, 1.f));
}
void dd::Systems::InputSystem::PublishCommand(int playerID, std::string command, float value)
{
Events::InputCommand e;
e.PlayerID = playerID;
e.Command = command;
e.Value = value;
EventBroker->Publish(e);
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID);
}
+19
View File
@@ -0,0 +1,19 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
+105
View File
@@ -0,0 +1,105 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Transform/TransformSystem.h"
#include "Core/World.h"
void dd::Systems::TransformSystem::Initialize()
{
}
glm::vec3 dd::Systems::TransformSystem::AbsolutePosition(EntityID entity)
{
glm::vec3 absPosition;
glm::quat accumulativeOrientation;
do
{
auto transform = m_World->GetComponent<Components::Transform>(entity);
//absPosition += transform->Position;
entity = m_World->GetEntityParent(entity);
auto transform2 = m_World->GetComponent<Components::Transform>(entity);
if (entity == 0)
absPosition += transform->Position;
else
absPosition = transform2->Orientation * (absPosition + transform->Position);
} while (entity != 0);
return absPosition * accumulativeOrientation;
}
glm::quat dd::Systems::TransformSystem::AbsoluteOrientation(EntityID entity)
{
glm::quat absOrientation;
do
{
auto transform = m_World->GetComponent<Components::Transform>(entity);
absOrientation = transform->Orientation * absOrientation;
entity = m_World->GetEntityParent(entity);
} while (entity != 0);
return absOrientation;
}
glm::vec3 dd::Systems::TransformSystem::AbsoluteScale(EntityID entity)
{
glm::vec3 absScale(1);
do
{
auto transform = m_World->GetComponent<Components::Transform>(entity);
absScale *= transform->Scale;
entity = m_World->GetEntityParent(entity);
} while (entity != 0);
return absScale;
}
dd::Components::Transform dd::Systems::TransformSystem::AbsoluteTransform(EntityID entity)
{
glm::vec3 absPosition;
glm::quat absOrientation;
glm::vec3 absScale(1);
do
{
auto transform = m_World->GetComponent<Components::Transform>(entity);
entity = m_World->GetEntityParent(entity);
auto transform2 = m_World->GetComponent<Components::Transform>(entity);
// Position
if (entity == 0)
absPosition += transform->Position;
else
absPosition = transform2->Orientation * (absPosition + transform->Position);
// Orientation
absOrientation = transform->Orientation * absOrientation;
// Scale
absScale *= transform->Scale;
} while (entity != 0);
Components::Transform transform;
transform.Position = absPosition;
transform.Orientation = absOrientation;
transform.Scale = absScale;
return transform;
}
+24
View File
@@ -0,0 +1,24 @@
project(tests)
find_package(Boost REQUIRED COMPONENTS chrono thread unit_test_framework)
include_directories(
${CMAKE_SOURCE_DIR}/include/dd
${Boost_INCLUDE_DIRS}
)
set(SOURCE_FILES
main.cpp
FileWatcherTest.cpp
ComponentCopyTest.cpp
)
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
add_executable(tests ${SOURCE_FILES})
target_link_libraries(tests
daydream
${Boost_LIBRARIES}
)
+29
View File
@@ -0,0 +1,29 @@
#include <boost/test/unit_test.hpp>
#include "Core/Component.h"
using namespace dd;
struct TestComponent : public Component
{
int Int = 5;
float Float = 1.33333f;
double Double = 1.33333;
std::string String = "Hello World";
};
BOOST_AUTO_TEST_CASE(component_copy)
{
auto componentFactory = new Factory<Component>();
componentFactory->Register<TestComponent>();
auto component1 = static_cast<TestComponent*>(componentFactory->Create<TestComponent>());
auto component2 = static_cast<TestComponent*>(componentFactory->Copy<TestComponent>(component1));
BOOST_CHECK(component1->Int == component2->Int);
BOOST_CHECK_CLOSE(component1->Float, component2->Float, 0.00001f);
BOOST_CHECK_CLOSE(component1->Double, component2->Double, 0.00001f);
BOOST_CHECK(component1->String == component2->String);
delete component2;
delete component1;
delete componentFactory;
}
+69
View File
@@ -0,0 +1,69 @@
#include <chrono>
#include <thread>
#include <fstream>
#include <cstdio>
#include <boost/test/unit_test.hpp>
#include "Core/Util/FileWatcher.h"
using namespace dd;
const std::string testFileName = "FileWatcherTestFile";
BOOST_AUTO_TEST_CASE(file_watcher)
{
auto fw = new FileWatcher("");
bool f_created = false;
bool f_size_changed = false;
bool f_timestamp_changed = false;
bool f_deleted = false;
// Make sure the test file doesn't exist
remove(testFileName.c_str());
// Set up the file watcher to watch for changes
fw->AddWatch(testFileName,
[&f_created, &f_size_changed, &f_timestamp_changed, &f_deleted]
(std::string path, FileWatcher::FileEventFlags flags)
{
if (flags & FileWatcher::FileEventFlags::Created)
f_created = true;
if (flags & FileWatcher::FileEventFlags::SizeChanged)
f_size_changed = true;
if (flags & FileWatcher::FileEventFlags::TimestampChanged)
f_timestamp_changed = true;
if (flags & FileWatcher::FileEventFlags::Deleted)
f_deleted = true;
});
// Create the file
FILE* testFile = fopen(testFileName.c_str(), "w");
fw->Check();
// Write to the file
fputs("test", testFile);
fclose(testFile);
fw->Check();
// Change file timestamp
std::time_t time;
std::localtime(&time);
time -= 1;
boost::filesystem::last_write_time(testFileName, time);
fw->Check();
// Delete the file;
remove(testFileName.c_str());
fw->Check();
BOOST_CHECK(f_created);
BOOST_CHECK(f_size_changed);
BOOST_CHECK(f_timestamp_changed);
BOOST_CHECK(f_deleted);
delete fw;
}
+2
View File
@@ -0,0 +1,2 @@
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>