From 77a6a9715e8239bd08d20cfa2bbc818c05633a46 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Thu, 28 Jan 2021 03:10:37 +0100 Subject: [PATCH] Finish lua camera controller implementation --- assets/lua/cameracontroller.lua | 131 ++++++++++++++++-- inferno/src/inferno/scene/scene.cpp | 4 +- .../src/inferno/script/cameracontroller.cpp | 1 + inferno/src/inferno/script/luascript.cpp | 3 +- inferno/src/inferno/script/registration.cpp | 53 +++++-- inferno/src/inferno/script/registration.h | 1 + 6 files changed, 171 insertions(+), 22 deletions(-) diff --git a/assets/lua/cameracontroller.lua b/assets/lua/cameracontroller.lua index a5a9856..2f179e5 100644 --- a/assets/lua/cameracontroller.lua +++ b/assets/lua/cameracontroller.lua @@ -1,3 +1,10 @@ +TRANSLATE_SPEED = 2.5 +ROTATE_SPEED = 90.0 +ZOOM_SENSITIVITY = 2.5 +MOUSE_SENSITIVITY = 0.25 +NEAR_PLANE = 0.1 +FAR_PLANE = 100.0 + LuaScript = { camera = nil, @@ -11,22 +18,128 @@ LuaScript = { end, update = function(self, deltaTime) - self.camera = GetComponent("CameraComponent") - LuaScript:updateOrthographic(deltaTime) - LuaScript:updatePerspective(deltaTime) - - local tmp = self.camera.fov - self.camera.fov = 30.0 + self.camera = getCameraComponent() - -- + if self.camera.type == CameraType.Orthographic then + LuaScript:updateOrthographic(deltaTime) + elseif self.camera.type == CameraType.Perspective then + LuaScript:updatePerspective(deltaTime) + end end, updateOrthographic = function(self, deltaTime) - -- + + -- Update camera rotation + + cameraRotateSpeed = ROTATE_SPEED * deltaTime + + if Input.isKeyPressed(keyCode("GLFW_KEY_Q")) then + self.transform.rotate.z = self.transform.rotate.z - cameraRotateSpeed + end + if Input.isKeyPressed(keyCode("GLFW_KEY_E")) then + self.transform.rotate.z = self.transform.rotate.z + cameraRotateSpeed + end + + if self.transform.rotate.z > 180.0 then + self.transform.rotate.z = self.transform.rotate.z - 360.0 + elseif self.transform.rotate.z <= -180.0 then + self.transform.rotate.z = self.transform.rotate.z + 360.0 + end + + -- Update camera translation + + cameraTranslateSpeed = TRANSLATE_SPEED * deltaTime + + -- WASD movement + if Input.isKeyPressed(keyCode("GLFW_KEY_W")) then + self.transform.translate.x = self.transform.translate.x + -math.sin(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + self.transform.translate.y = self.transform.translate.y + math.cos(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + end + if Input.isKeyPressed(keyCode("GLFW_KEY_S")) then + self.transform.translate.x = self.transform.translate.x - -math.sin(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + self.transform.translate.y = self.transform.translate.y - math.cos(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + end + if Input.isKeyPressed(keyCode("GLFW_KEY_A")) then + self.transform.translate.x = self.transform.translate.x - math.cos(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + self.transform.translate.y = self.transform.translate.y - math.sin(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + end + if Input.isKeyPressed(keyCode("GLFW_KEY_D")) then + self.transform.translate.x = self.transform.translate.x + math.cos(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + self.transform.translate.y = self.transform.translate.y + math.sin(glm.radians(self.transform.rotate.z)) * cameraTranslateSpeed; + end + + -- Update camera zoom + + zoomSpeed = ZOOM_SENSITIVITY * deltaTime; + + if Input.isKeyPressed(keyCode("GLFW_KEY_EQUAL")) then + self.camera.zoomLevel = self.camera.zoomLevel - zoomSpeed + end + if Input.isKeyPressed(keyCode("GLFW_KEY_MINUS")) then + self.camera.zoomLevel = self.camera.zoomLevel + zoomSpeed + end + self.camera.zoomLevel = math.max(self.camera.zoomLevel, 0.25); + self.camera.zoomLevel = math.min(self.camera.zoomLevel, 10.0); + end, updatePerspective = function(self, deltaTime) - -- + + -- Get mouse movement offset compared to last frame + xOffset = Input.getXOffset() * MOUSE_SENSITIVITY; + yOffset = Input.getYOffset() * MOUSE_SENSITIVITY; + self.camera.yaw = self.camera.yaw + xOffset; + self.camera.pitch = self.camera.pitch + yOffset; + + -- Prevent gimbal lock + if self.camera.pitch > 89.0 then self.camera.pitch = 89.0 end + if self.camera.pitch < -89.0 then self.camera.pitch = -89.0 end + + -- Update camera rotation, by calculating direction vector via yaw and pitch + + self.transform.rotate = glm.vec3( + math.cos(glm.radians(self.camera.pitch)) * math.cos(glm.radians(self.camera.yaw)), + math.sin(glm.radians(self.camera.pitch)), + math.cos(glm.radians(self.camera.pitch)) * math.sin(glm.radians(self.camera.yaw)) + ) + self.transform.rotate = glm.normalize(self.transform.rotate) + -- The direction vector is based on + -- Camera direction (z): normalize(position - target) + -- Right axis (x): normalize(cross(up, direction)) + -- Up axis (y): cross(direction, right) + + -- Source: https://learnopengl.com/img/getting-started/camera_axes.png + + -- Cross = combination of two vectors in 3D space, + -- where result is always perpendicular to both of the vectors + + -- Update camera translation + + cameraSpeed = TRANSLATE_SPEED * deltaTime + + -- WASD movement + if Input.isKeyPressed(keyCode("GLFW_KEY_W")) then + self.transform.translate = glm.vec3( self.transform.translate + cameraSpeed * self.transform.rotate ) + end + if Input.isKeyPressed(keyCode("GLFW_KEY_S")) then + self.transform.translate = glm.vec3( self.transform.translate - cameraSpeed * self.transform.rotate ) + end + if Input.isKeyPressed(keyCode("GLFW_KEY_A")) then + self.transform.translate = glm.vec3( self.transform.translate - + glm.normalize(glm.cross(self.transform.rotate, self.camera.up)) * cameraSpeed ) + end + if Input.isKeyPressed(keyCode("GLFW_KEY_D")) then + self.transform.translate = glm.vec3( self.transform.translate + + glm.normalize(glm.cross(self.transform.rotate, self.camera.up)) * cameraSpeed ) + end + -- Up / down movement + if Input.isKeyPressed(keyCode("GLFW_KEY_SPACE")) then + self.transform.translate = glm.vec3( self.transform.translate.x, self.transform.translate.y + cameraSpeed, self.transform.translate.z ) + end + if Input.isKeyPressed(keyCode("GLFW_KEY_LEFT_SHIFT")) then + self.transform.translate = glm.vec3( self.transform.translate.x, self.transform.translate.y - cameraSpeed, self.transform.translate.z ) + end + end, } diff --git a/inferno/src/inferno/scene/scene.cpp b/inferno/src/inferno/scene/scene.cpp index 34989e7..41e3708 100644 --- a/inferno/src/inferno/scene/scene.cpp +++ b/inferno/src/inferno/scene/scene.cpp @@ -46,8 +46,8 @@ namespace Inferno { cameraTransform.rotate.z = -1.0f; cameraTransform.translate.z = 1.0f; addComponent(camera, CameraType::Perspective); - addComponent(camera).bind(); - // addComponent(camera, "assets/lua/cameracontroller.lua"); + // addComponent(camera).bind(); + addComponent(camera, "assets/lua/cameracontroller.lua"); uint32_t quad = createEntity("Quad"); addComponent(quad, glm::vec4 { 1.0f, 1.0f, 1.0f, 1.0f }, m_texture); diff --git a/inferno/src/inferno/script/cameracontroller.cpp b/inferno/src/inferno/script/cameracontroller.cpp index c4e7647..413aa2e 100644 --- a/inferno/src/inferno/script/cameracontroller.cpp +++ b/inferno/src/inferno/script/cameracontroller.cpp @@ -95,6 +95,7 @@ namespace Inferno { // Update camera translation float cameraSpeed = TRANSLATE_SPEED * deltaTime; + // WASD movement if (Input::isKeyPressed(KeyCode("GLFW_KEY_W"))) { transform->translate = { transform->translate + cameraSpeed * transform->rotate }; diff --git a/inferno/src/inferno/script/luascript.cpp b/inferno/src/inferno/script/luascript.cpp index 1a04ed3..e26353f 100644 --- a/inferno/src/inferno/script/luascript.cpp +++ b/inferno/src/inferno/script/luascript.cpp @@ -19,7 +19,7 @@ namespace Inferno { // Load libraries // --------------------------------- - m_state.open_libraries(sol::lib::base); + m_state.open_libraries(sol::lib::base, sol::lib::math); // Component get functions // --------------------------------- @@ -32,7 +32,6 @@ namespace Inferno { return &m_scene->getComponent(m_entity); }); - // (*m_state).set_function("GetComponent", &LuaScript::getComponentSol); m_state.set_function("getCameraComponent", [this]() -> CameraComponent* { return &m_scene->getComponent(m_entity); }); diff --git a/inferno/src/inferno/script/registration.cpp b/inferno/src/inferno/script/registration.cpp index 1c55230..63f19c1 100644 --- a/inferno/src/inferno/script/registration.cpp +++ b/inferno/src/inferno/script/registration.cpp @@ -1,7 +1,10 @@ -#include "glm/ext/vector_float2.hpp" // glm::vec2 -#include "glm/ext/vector_float3.hpp" // glm::vec3 -#include "glm/ext/vector_float4.hpp" // glm::vec4 +#include "glm/ext/vector_float2.hpp" // glm::vec2 +#include "glm/ext/vector_float3.hpp" // glm::vec3 +#include "glm/ext/vector_float4.hpp" // glm::vec4 +#include "glm/ext/matrix_transform.hpp" // glm::radians +#include "inferno/input.h" +#include "inferno/inputcodes.h" #include "inferno/scene/components.h" #include "inferno/script/registration.h" @@ -11,13 +14,16 @@ namespace Inferno { { glm(state); component(state); + input(state); } void Registration::glm(sol::state_view& state) { - auto vec2 = state.new_usertype( + auto glm = state["glm"].get_or_create(); + + auto vec2 = glm.new_usertype( "vec2", - sol::call_constructor, sol::constructors(), + sol::call_constructor, sol::constructors(), "x", &glm::vec2::x, "y", &glm::vec2::y, "r", &glm::vec2::r, "g", &glm::vec2::g, "s", &glm::vec2::s, "t", &glm::vec2::t, @@ -27,9 +33,9 @@ namespace Inferno { "__div", division() ); - auto vec3 = state.new_usertype( + auto vec3 = glm.new_usertype( "vec3", - sol::call_constructor, sol::constructors(), + sol::call_constructor, sol::constructors(), "x", &glm::vec3::x, "y", &glm::vec3::y, "z", &glm::vec3::z, "r", &glm::vec3::r, "g", &glm::vec3::g, "b", &glm::vec3::b, "s", &glm::vec3::s, "t", &glm::vec3::t, "p", &glm::vec3::p, @@ -40,9 +46,9 @@ namespace Inferno { // "__tostring", [](glm::vec3 self) { return self.x; } // Template!!! convert via logstream ); - auto vec4 = state.new_usertype( + auto vec4 = glm.new_usertype( "vec4", - sol::call_constructor, sol::constructors(), + sol::call_constructor, sol::constructors(), "x", &glm::vec4::x, "y", &glm::vec4::y, "z", &glm::vec4::z, "w", &glm::vec4::w, "r", &glm::vec4::r, "g", &glm::vec4::g, "b", &glm::vec4::b, "a", &glm::vec4::a, "s", &glm::vec4::s, "t", &glm::vec4::t, "p", &glm::vec4::p, "q", &glm::vec4::q, @@ -51,6 +57,21 @@ namespace Inferno { "__mul", multiplication(), "__div", division() ); + + glm.set_function("radians", sol::overload( + [](float v) { return glm::radians(v); }, + [](const glm::vec2& v) { return glm::radians(v); }, + [](const glm::vec3& v) { return glm::radians(v); }, + [](const glm::vec4& v) { return glm::radians(v); } + )); + + glm.set_function("normalize", sol::overload( + [](const glm::vec2& v) { return glm::normalize(v); }, + [](const glm::vec3& v) { return glm::normalize(v); }, + [](const glm::vec4& v) { return glm::normalize(v); } + )); + + glm.set_function("cross", [](const glm::vec3& x, const glm::vec3& y) { return glm::cross(x, y); }); } void Registration::component(sol::state_view& state) @@ -64,6 +85,10 @@ namespace Inferno { transformComponent["scale"] = &TransformComponent::scale; transformComponent["transform"] = &TransformComponent::transform; + auto cameraType = state.new_enum("CameraType", + "Orthographic", CameraType::Orthographic, + "Perspective", CameraType::Perspective); + auto cameraComponent = state.new_usertype("CameraComponent", sol::no_constructor); cameraComponent["type"] = &CameraComponent::type; cameraComponent["zoomLevel"] = &CameraComponent::zoomLevel; @@ -79,4 +104,14 @@ namespace Inferno { spriteComponent["texture"] = &SpriteComponent::texture; } + void Registration::input(sol::state_view& state) + { + state.set_function("keyCode", &KeyCode); + // state["keyCode"] = &KeyCode; + + auto input = state.new_usertype("Input", sol::no_constructor); + input["isKeyPressed"] = &Input::isKeyPressed; + input["getXOffset"] = &Input::getXOffset; + input["getYOffset"] = &Input::getYOffset; + } } diff --git a/inferno/src/inferno/script/registration.h b/inferno/src/inferno/script/registration.h index 7081e44..f5463e8 100644 --- a/inferno/src/inferno/script/registration.h +++ b/inferno/src/inferno/script/registration.h @@ -13,6 +13,7 @@ namespace Inferno { private: static void glm(sol::state_view& state); static void component(sol::state_view& state); + static void input(sol::state_view& state); template static auto addition()