From dc6bc60dd93f2ebf24db4b72eb0e5f44246e6d12 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sat, 14 Jan 2017 17:14:23 +0100 Subject: [PATCH] Refactored character into separate module --- src/main.cc | 4 + src/modules/CMakeLists.txt | 11 +- src/modules/CharacterModule.cc | 203 ++++++++++++++++++++++++++++++ src/modules/CharacterModule.h | 56 +++++++++ src/modules/TestModule.cc | 222 +-------------------------------- src/modules/imgui_protot_ext.h | 60 +++++++++ 6 files changed, 338 insertions(+), 218 deletions(-) create mode 100644 src/modules/CharacterModule.cc create mode 100644 src/modules/CharacterModule.h create mode 100644 src/modules/imgui_protot_ext.h diff --git a/src/main.cc b/src/main.cc index 520dd6b..b3d89fd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -80,6 +80,9 @@ int main(void) int width, height; glfwGetWindowSize(gWindow, &width, &height); + std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl; + std::cout << "GLSL Version : " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + // Initialize Renderer bgfx::glfwSetWindow(gWindow); bgfx::renderFrame(); @@ -99,6 +102,7 @@ int main(void) printf("Initializing ModuleManager...\n"); RuntimeModuleManager module_manager; module_manager.RegisterModule("src/modules/libRenderModule.so"); + module_manager.RegisterModule("src/modules/libCharacterModule.so"); module_manager.RegisterModule("src/modules/libTestModule.so"); // Setup global variables diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 58e1535..2e43af3 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -11,6 +11,15 @@ ADD_LIBRARY (TestModule SHARED TestModule.cc ) -TARGET_LINK_LIBRARIES ( TestModule +ADD_LIBRARY (CharacterModule SHARED + CharacterModule.cc + ) + +TARGET_LINK_LIBRARIES ( CharacterModule + RenderModule + ) + +TARGET_LINK_LIBRARIES ( TestModule + CharacterModule RenderModule ) diff --git a/src/modules/CharacterModule.cc b/src/modules/CharacterModule.cc new file mode 100644 index 0000000..1d4b70e --- /dev/null +++ b/src/modules/CharacterModule.cc @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include + +#include "3rdparty/ocornut-imgui/imgui.h" +#include "imgui/imgui.h" +#include + +#include "RuntimeModule.h" +#include "Globals.h" +#include "modules/RenderModule.h" +#include "Serializer.h" + +#include "CharacterModule.h" + +using namespace std; + +const float cJumpVelocity = 4.0f; +const float cVelocityDamping = 4.0f; +const float cGravity = 9.81f; +const float cGroundAcceleration = 30.0f; +const float cCharacterHeight = 1.8f; +const float cCharacterWidth = 1.f; + +CharacterEntity::CharacterEntity() { + entity = gRenderer->createEntity(); + position = Vector3f (0.f, 0.0f, 0.0f); + cout << "Creating render entity ... success!" << endl; + + cout << "Creating render entity mesh ..." << endl; + + // Build the snowman + entity->mesh.addMesh( + - 1, + Transform::fromTrans( + Vector3f (0.0f, 0.9 * 0.5f, 0.0f) + ), + bgfxutils::createUVSphere (45, 45, 0.9) + ); + + entity->mesh.addMesh( + 0, + Transform::fromTrans( + Vector3f (0.0f, 0.55f, 0.0f) + ), + bgfxutils::createUVSphere (45, 45, 0.7) + ); + + entity->mesh.addMesh( + 1, + Transform::fromTrans( + Vector3f (0.0f, 0.4f, 0.0f) + ), + bgfxutils::createUVSphere (45, 45, 0.5) + ); + + // state->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f); + // state->character->entity->mesh = bgfxutils::createCylinder (20); + cout << "Creating render entity mesh ... success!" << endl; +} + +CharacterEntity::~CharacterEntity() { + gRenderer->destroyEntity(entity); + entity = nullptr; +} + +void CharacterEntity::update(float dt) { + Vector3f controller_acceleration ( + controller.direction[0] * cGroundAcceleration, + controller.direction[1] * cGroundAcceleration, + controller.direction[2] * cGroundAcceleration + ); + + Vector3f gravity (0.0f, -cGravity, 0.0f); + Vector3f damping ( + -velocity[0] * cVelocityDamping, + 0.0f, + -velocity[2] * cVelocityDamping + ); + + Vector3f acceleration = controller_acceleration + gravity + damping; + + velocity = velocity + acceleration * dt; + + if (position[1] == 0.0f + && controller.state[CharacterController::ControlStateJump]) { + velocity[1] = cJumpVelocity; + } + + // integrate position + position += velocity * dt; + + if (position[1] < 0.f) { + position[1] = 0.f; + velocity[1] = 0.0f; + } + + // apply transformation + entity->transform.translation.set( + position[0], + position[1], + position[2]); + + entity->mesh.updateMatrices(entity->transform.toMatrix()); +} + +void ShowCharacterPropertiesWindow (CharacterEntity* character) { + assert (character != nullptr); + ImGui::SetNextWindowSize (ImVec2(600.f, 300.0f), ImGuiSetCond_Once); + ImGui::SetNextWindowPos (ImVec2(400.f, 16.0f), ImGuiSetCond_Once); + ImGui::Begin("Character"); + + if (ImGui::Button ("Reset")) { + character->reset(); + } + + ImGui::DragFloat3 ("Position", character->position.data(), 0.01, -10.0f, 10.0f); + ImGui::DragFloat3 ("Velocity", character->velocity.data(), 0.01, -10.0f, 10.0f); + + + for (int i = 0; i < character->entity->mesh.meshes.size(); ++i) { + char buf[32]; + snprintf (buf, 32, "Mesh %d", i); + + ImGuiTreeNodeFlags node_flags = 0; + + bool node_open = ImGui::TreeNodeEx( + buf, + node_flags); + + if (node_open) { + Transform &transform = character->entity->mesh.localTransforms[i]; + + ImGui::DragFloat3 ("Position", transform.translation.data(), 0.01, -10.0f, 10.0f); + if (ImGui::Protot::DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) { + if (isnan(transform.rotation.squaredNorm())) { + std::cout << "nan! " << transform.rotation.transpose() << std::endl; + abort(); + } + } + ImGui::DragFloat3 ("Scale", transform.scale.data(), 0.01, 0.001f, 10.0f); + + ImGui::TreePop(); + } + } + + ImGui::End(); +} + +struct module_state { +}; + +static struct module_state *module_init() { + std::cout << "Module init called" << std::endl; + module_state *state = (module_state*) malloc(sizeof(*state)); + return state; +} + +template +static void module_serialize ( + struct module_state *state, + Serializer* serializer) { +// SerializeVec3(*serializer, "protot.TestModule.entity.position", state->character->position); +} + +static void module_finalize(struct module_state *state) { + std::cout << "Module finalize called" << std::endl; + free(state); +} + +static void module_reload(struct module_state *state, void* read_serializer) { + std::cout << "Module reload called. State: " << state << std::endl; + // load the state of the entity + if (read_serializer != nullptr) { + module_serialize(state, static_cast(read_serializer)); + } +} + +static void module_unload(struct module_state *state, void* write_serializer) { + glfwSetScrollCallback (gWindow, nullptr); + + // serialize the state of the entity + if (write_serializer != nullptr) { + module_serialize(state, static_cast(write_serializer)); + } +} + +static bool module_step(struct module_state *state, float dt) { + return true; +} + +extern "C" { + +const struct module_api MODULE_API = { + .init = module_init, + .reload = module_reload, + .step = module_step, + .unload = module_unload, + .finalize = module_finalize +}; +} diff --git a/src/modules/CharacterModule.h b/src/modules/CharacterModule.h new file mode 100644 index 0000000..e861a82 --- /dev/null +++ b/src/modules/CharacterModule.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include +#include + +#include "math_types.h" + +#include "Globals.h" + +#include "imgui_protot_ext.h" + +struct CharacterController { + enum ControllerState { + ControlStateJump, + ControlStateLast + }; + + bool state[ControlStateLast]; + + Vector3f direction = Vector3f::Zero(); + + void reset() { + for (int i = 0; i < ControlStateLast; i++) { + state[i] = false; + } + + direction.setZero(); + } + + CharacterController() { + reset(); + }; +}; + +struct CharacterEntity { + /// Render entity + Entity *entity = nullptr; + Vector3f position; + Vector3f velocity; + CharacterController controller; + + CharacterEntity (); + ~CharacterEntity (); + + void reset() { + position.setZero(); + velocity.setZero(); + controller.reset(); + } + + void update(float dt); +}; + +void ShowCharacterPropertiesWindow (CharacterEntity* character); diff --git a/src/modules/TestModule.cc b/src/modules/TestModule.cc index 04d02e4..fa43b55 100644 --- a/src/modules/TestModule.cc +++ b/src/modules/TestModule.cc @@ -1,6 +1,5 @@ #include "RuntimeModule.h" #include "Globals.h" -#include "modules/RenderModule.h" #include "3rdparty/ocornut-imgui/imgui.h" #include "imgui/imgui.h" #include @@ -12,6 +11,9 @@ #include "RuntimeModuleManager.h" #include "Serializer.h" +#include "modules/RenderModule.h" +#include "modules/CharacterModule.h" + #include #include @@ -23,90 +25,6 @@ bool fps_camera = true; // Boilerplate for the module reload stuff -struct CharacterController { - enum ControllerState { - ControlJump, - ControlStateLast - }; - - bool state[ControlStateLast]; - - Vector3f direction = Vector3f::Zero(); - - void reset() { - for (int i = 0; i < ControlStateLast; i++) { - state[i] = false; - } - - direction.setZero(); - } - - CharacterController() { - reset(); - }; -}; - -const float cJumpVelocity = 4.0f; -const float cVelocityDamping = 4.0f; -const float cGravity = 9.81f; -const float cGroundAcceleration = 30.0f; -const float cCharacterHeight = 1.8f; -const float cCharacterWidth = 1.f; - -struct CharacterEntity { - /// Render entity - Entity *entity; - Vector3f position; - Vector3f velocity; - CharacterController controller; - - void reset() { - position.setZero(); - velocity.setZero(); - controller.reset(); - } - - void update(float dt) { - Vector3f controller_acceleration ( - controller.direction[0] * cGroundAcceleration, - controller.direction[1] * cGroundAcceleration, - controller.direction[2] * cGroundAcceleration - ); - - Vector3f gravity (0.0f, -cGravity, 0.0f); - Vector3f damping ( - -velocity[0] * cVelocityDamping, - 0.0f, - -velocity[2] * cVelocityDamping - ); - - Vector3f acceleration = controller_acceleration + gravity + damping; - - velocity = velocity + acceleration * dt; - - if (position[1] == 0.0f - && controller.state[CharacterController::ControlJump]) { - velocity[1] = cJumpVelocity; - } - - // integrate position - position += velocity * dt; - - if (position[1] < 0.f) { - position[1] = 0.f; - velocity[1] = 0.0f; - } - - // apply transformation - entity->transform.translation.set( - position[0], - position[1], - position[2]); - - entity->mesh.updateMatrices(entity->transform.toMatrix()); - } -}; - struct module_state { bool fps_camera; float camera_theta; @@ -257,7 +175,7 @@ void handle_keyboard (struct module_state *state, float dt) { } if (glfwGetKey(gWindow, GLFW_KEY_SPACE) == GLFW_PRESS) { - controller.state[CharacterController::ControlJump] = true; + controller.state[CharacterController::ControlStateJump] = true; } } } @@ -288,6 +206,7 @@ static void module_serialize ( SerializeVec3(*serializer, "protot.TestModule.entity.velocity", state->character->velocity); SerializeBool(*serializer, "protot.TestModule.character_window.visible", state->character_properties_window_visible); SerializeBool(*serializer, "protot.TestModule.modules_window.visible", state->modules_window_visible); + SerializeBool(*serializer, "protot.TestModule.imgui_demo_window_visible", state->imgui_demo_window_visible); SerializeInt(*serializer, "protot.TestModule.modules_window.selection_index", state->modules_window_selected_index); } @@ -304,41 +223,6 @@ static void module_reload(struct module_state *state, void* read_serializer) { mouse_scroll_y = 0; cout << "Creating render entity ..." << endl; - state->character->entity = gRenderer->createEntity(); - state->character->position = Vector3f (0.f, 0.0f, 0.0f); - cout << "Creating render entity ... success!" << endl; - - cout << "Creating render entity mesh ..." << endl; - - // Build the snowman - state->character->entity->mesh.addMesh( - - 1, - Transform::fromTrans( - Vector3f (0.0f, 0.9 * 0.5f, 0.0f) - ), - bgfxutils::createUVSphere (45, 45, 0.9) - ); - - state->character->entity->mesh.addMesh( - 0, - Transform::fromTrans( - Vector3f (0.0f, 0.55f, 0.0f) - ), - bgfxutils::createUVSphere (45, 45, 0.7) - ); - - state->character->entity->mesh.addMesh( - 1, - Transform::fromTrans( - Vector3f (0.0f, 0.4f, 0.0f) - ), - bgfxutils::createUVSphere (45, 45, 0.5) - ); - -// state->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f); -// state->character->entity->mesh = bgfxutils::createCylinder (20); - cout << "Creating render entity mesh ... success!" << endl; - // load the state of the entity if (read_serializer != nullptr) { module_serialize(state, static_cast(read_serializer)); @@ -365,8 +249,6 @@ static void module_unload(struct module_state *state, void* write_serializer) { } state->character->entity = nullptr; - Vector3f bla (1.2f, 1.3f, 1.6f); - std::cout << "TestModule unloaded. State: " << state << std::endl; } @@ -426,100 +308,6 @@ void ShowModulesWindow(struct module_state *state) { ImGui::End(); } -// Returns a normalized vector where the value at the modified index -// is kept and only the other values are being modified so that the -// resulting vector is normalized. -bool DragFloat4Normalized(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f) -{ - float old_values[4]; - memcpy (old_values, v, sizeof(float) * 4); - - bool modified = ImGui::DragFloat4(label, v, v_speed, v_min, v_max, display_format, power); - if (modified) { - int mod_index = -1; - Vector3f other_values; - int other_index = 0; - - // determine the modified index and copy the unmodified values to - // other_values - for (int i = 0; i < 4; ++i) { - if (old_values[i] != v[i]) { - mod_index = i; - } else { - other_values[other_index] = v[i]; - other_index++; - } - } - - // normalize, but take zero length of other values into account and - // also modification of vectors with a single 1. - float other_length = other_values.norm(); - if (fabs(v[mod_index]) >= 1.0f - 1.0e-6f || other_length == 0.0f) { - other_values.setZero(); - v[mod_index] = 1.0f * v[mod_index] < 0.0f ? -1.0f : 1.0f; - } else { - // normalize other_values to have the remaining length - other_values = other_values * (1.f / other_length) * (sqrt(1.0f - v[mod_index] * v[mod_index])); - } - - // construct the new vector - other_index = 0; - for (int i = 0; i < 4; ++i) { - if (i != mod_index) { - v[i] = other_values[other_index]; - other_index++; - } - } - } - - return modified; -} - - - -void ShowCharacterPropertiesWindow (CharacterEntity* character) { - assert (character != nullptr); - ImGui::SetNextWindowSize (ImVec2(600.f, 300.0f), ImGuiSetCond_Once); - ImGui::SetNextWindowPos (ImVec2(400.f, 16.0f), ImGuiSetCond_Once); - ImGui::Begin("Character"); - - if (ImGui::Button ("Reset")) { - character->reset(); - } - - ImGui::DragFloat3 ("Position", character->position.data(), 0.01, -10.0f, 10.0f); - ImGui::DragFloat3 ("Velocity", character->velocity.data(), 0.01, -10.0f, 10.0f); - - - for (int i = 0; i < character->entity->mesh.meshes.size(); ++i) { - char buf[32]; - snprintf (buf, 32, "Mesh %d", i); - - ImGuiTreeNodeFlags node_flags = 0; - - bool node_open = ImGui::TreeNodeEx( - buf, - node_flags); - - if (node_open) { - Transform &transform = character->entity->mesh.localTransforms[i]; - - ImGui::DragFloat3 ("Position", transform.translation.data(), 0.01, -10.0f, 10.0f); - if (DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) { - if (isnan(transform.rotation.squaredNorm())) { - cout << "nan! " << transform.rotation.transpose() << endl; - abort(); - } - } - ImGui::DragFloat3 ("Scale", transform.scale.data(), 0.01, 0.001f, 10.0f); - - ImGui::TreePop(); - } - } - - ImGui::End(); -} - static bool module_step(struct module_state *state, float dt) { if (gRenderer == nullptr) return false; diff --git a/src/modules/imgui_protot_ext.h b/src/modules/imgui_protot_ext.h new file mode 100644 index 0000000..a0d1a5d --- /dev/null +++ b/src/modules/imgui_protot_ext.h @@ -0,0 +1,60 @@ +#pragma once + +#include "math_types.h" + +namespace ImGui { + +namespace Protot { + +// Returns a normalized vector where the value at the modified index +// is kept and only the other values are being modified so that the +// resulting vector is normalized. +bool DragFloat4Normalized(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f) +{ + float old_values[4]; + memcpy (old_values, v, sizeof(float) * 4); + + bool modified = ImGui::DragFloat4(label, v, v_speed, v_min, v_max, display_format, power); + if (modified) { + int mod_index = -1; + Vector3f other_values; + int other_index = 0; + + // determine the modified index and copy the unmodified values to + // other_values + for (int i = 0; i < 4; ++i) { + if (old_values[i] != v[i]) { + mod_index = i; + } else { + other_values[other_index] = v[i]; + other_index++; + } + } + + // normalize, but take zero length of other values into account and + // also modification of vectors with a single 1. + float other_length = other_values.norm(); + if (fabs(v[mod_index]) >= 1.0f - 1.0e-6f || other_length == 0.0f) { + other_values.setZero(); + v[mod_index] = 1.0f * v[mod_index] < 0.0f ? -1.0f : 1.0f; + } else { + // normalize other_values to have the remaining length + other_values = other_values * (1.f / other_length) * (sqrt(1.0f - v[mod_index] * v[mod_index])); + } + + // construct the new vector + other_index = 0; + for (int i = 0; i < 4; ++i) { + if (i != mod_index) { + v[i] = other_values[other_index]; + other_index++; + } + } + } + + return modified; +} + +} // Protot + +} // ImGui