diff --git a/src/RuntimeModuleManager.cc b/src/RuntimeModuleManager.cc index 74ca25f..1f22dd0 100644 --- a/src/RuntimeModuleManager.cc +++ b/src/RuntimeModuleManager.cc @@ -65,7 +65,10 @@ void RuntimeModuleManager::LoadModule(RuntimeModule* module) { void RuntimeModuleManager::Update(float dt) { if (CheckModulesChanged()) { std::cout << "Detected module update. Unloading all modules." << std::endl; - for (int i = 0; i < mModules.size(); i++) { + + // We unload in reverse order so that dependencies are cleaned + // up properly. + for (int i = mModules.size() - 1; i >= 0; i--) { if (mModules[i]->handle) { std::cerr << "Unloading module " << mModules[i]->name << std::endl; mModules[i]->api.unload(mModules[i]->state); @@ -76,7 +79,7 @@ void RuntimeModuleManager::Update(float dt) { } // We need to sleep to make sure we load the new files - usleep(350000); + usleep(100000); } for (int i = 0; i < mModules.size(); i++) { diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index dee0b5b..c574cba 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -679,6 +679,7 @@ void Renderer::setupShaders() { int grid_size = 1024; int grid_border = 12; uint8_t grid_color_border [4] = {255, 255, 255, 255}; +// uint8_t grid_color_border [4] = {0, 0, 0, 0}; uint8_t grid_color_0[4] = {192, 192, 192, 255}; uint8_t grid_color_1[4] = {96, 96, 96, 255}; uint8_t* texture_data = NULL; @@ -1277,6 +1278,30 @@ Entity* Renderer::createEntity() { return result; } +bool Renderer::destroyEntity(Entity* entity) { + int i = 0; + for (i = 0; i < entities.size(); i++) { + if (entities[i] == entity) { + break; + } + } + + if (i != entities.size()) { + if (entity->mesh != nullptr) { + meshUnload (entity->mesh); + entity->mesh = nullptr; + } + + delete entity; + + entities.erase(entities.begin() + i); + + return true; + } + + return false; +} + bgfxutils::Mesh* Renderer::loadMesh(const char* filename) { MeshIdMap::iterator mesh_iter = meshIdMap.find (filename); bgfxutils::Mesh* result = NULL; diff --git a/src/modules/RenderModule.h b/src/modules/RenderModule.h index 28fbf5e..d843967 100644 --- a/src/modules/RenderModule.h +++ b/src/modules/RenderModule.h @@ -223,6 +223,8 @@ struct Renderer { void resize (int width, int height); Entity* createEntity(); + bool destroyEntity (Entity* entity); + bgfxutils::Mesh* loadMesh(const char* filename); }; diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index c9f01c7..7a412b3 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -23,6 +23,9 @@ namespace stl = tinystl; #include "RenderModule.h" #include "RenderUtils.h" //#include "MeshVBO.h" +#include "SimpleMath/SimpleMath.h" + +using namespace SimpleMath; void *load(const char *_filePath, uint32_t *_size = NULL); @@ -934,6 +937,94 @@ void mesh_load(Mesh* mesh, const void* _vertices, uint32_t _numVertices, const b // return result; // } +Mesh *createUVSphere (int rows, int segments) { + // work arrays that we fill with data + std::vector vertices; + std::vector normals; + std::vector colors; + + // fill arrays + float row_d = 1. / (rows); + float angle_d = 2 * M_PI / static_cast(segments); + + for (unsigned int j = 0; j < rows; j++) { + float alpha0 = j * row_d * M_PI; + float alpha1 = (j + 1) * row_d * M_PI; + + float r0 = sin (alpha0); + float r1 = sin (alpha1); + + float h0 = cos (alpha0); + float h1 = cos (alpha1); + + for (unsigned int i = 0; i < segments; i++) { + Vector3f v0, v1, v2, v3; + float a0 = (i - 0.5) * angle_d; + float a1 = (i + 0.5) * angle_d; + + v0 = Vector3f (r1 * cos(a0), h1, r1 * sin (a0)); + v1 = Vector3f (r1 * cos(a1), h1, r1 * sin (a1)); + v2 = Vector3f (r0 * cos(a1), h0, r0 * sin (a1)); + v3 = Vector3f (r0 * cos(a0), h0, r0 * sin (a0)); + + vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 0.f)); + normals.push_back (v0 * 1.f/ v0.norm()); + + vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 0.f)); + normals.push_back (v2 * 1.f/ v2.norm()); + + vertices.push_back (Vector4f(v1[0], v1[1], v1[2], 0.f)); + normals.push_back (v1 * 1.f/ v1.norm()); + + vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 0.f)); + normals.push_back (v0 * 1.f/ v0.norm()); + + vertices.push_back (Vector4f(v3[0], v3[1], v3[2], 0.f)); + normals.push_back (v3 * 1.f/ v3.norm()); + + vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 0.f)); + normals.push_back (v2 * 1.f/ v2.norm()); + } + } + + // create and copy the data into the actual mesh + Mesh* result = new Mesh(); + PosNormalColorVertex::init(); + bool have_normals = normals.size() > 0; + bool have_colors = colors.size() > 0; + + uint16_t stride = PosNormalColorVertex::ms_decl.getStride(); + const bgfx::Memory* vb_mem = bgfx::alloc (vertices.size() * stride); + PosNormalColorVertex* mesh_vb = (PosNormalColorVertex*) vb_mem; + + const bgfx::Memory* ib_mem = bgfx::alloc (sizeof(uint16_t) * vertices.size()); + uint16_t* mesh_ib = (uint16_t*) ib_mem; + + for (unsigned int i = 0; i < vertices.size(); i++) { + mesh_vb[i].m_x = vertices[i][0]; + mesh_vb[i].m_y = vertices[i][1]; + mesh_vb[i].m_z = vertices[i][2]; + + if (have_normals) { + mesh_vb[i].m_normal = packF4u (-normals[i][0], -normals[i][1], -normals[i][2]); + } else { + mesh_vb[i].m_normal = 0; + } + + if (have_colors) { + mesh_vb[i].m_rgba = packF4u (colors[i][0], colors[i][1], colors[i][2], colors[i][3]); + } else { + mesh_vb[i].m_rgba = packF4u (1.f, 1.f, 1.f, 1.f); + } + + mesh_ib[i] = i; + } + + mesh_load(result, mesh_vb, vertices.size(), PosNormalColorVertex::ms_decl, mesh_ib, vertices.size()); + + return result; +} + } diff --git a/src/modules/RenderUtils.h b/src/modules/RenderUtils.h index c30fb38..5a438f3 100644 --- a/src/modules/RenderUtils.h +++ b/src/modules/RenderUtils.h @@ -54,6 +54,8 @@ namespace bgfxutils { // Loads the mesh data from a VBO into a bgfx Mesh // Mesh *createMeshFromVBO (const MeshVBO& mesh_buffer); + + Mesh *createUVSphere (int rows, int segments); } #endif diff --git a/src/modules/TestModule.cc b/src/modules/TestModule.cc index 718fb7a..aa79b7d 100644 --- a/src/modules/TestModule.cc +++ b/src/modules/TestModule.cc @@ -29,14 +29,21 @@ bool fps_camera = true; // Boilerplate for the module reload stuff +struct CharacterEntity { + /// Render entity + Entity *entity; + Vector3f position; +}; + struct module_state { bool fps_camera; float camera_theta; float camera_phi; bool modules_window_visible = false; bool imgui_demo_window_visible = false; - int modules_window_selected_index = -1; + + CharacterEntity* character = nullptr; }; void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { @@ -145,6 +152,9 @@ void handle_keyboard (struct module_state *state) { static struct module_state *module_init() { std::cout << "Module init called" << std::endl; module_state *state = (module_state*) malloc(sizeof(*state)); + state->character = new CharacterEntity; + state->character->position = Vector3f (0.f, 0.f, 0.f); + state->modules_window_selected_index = -1; fps_camera = true; @@ -163,12 +173,30 @@ static void module_reload(struct module_state *state) { mouse_scroll_x = 0; mouse_scroll_y = 0; + cout << "Creating render entity ..." << endl; + state->character->entity = gRenderer->createEntity(); + cout << "Creating render entity ... success!" << endl; + + cout << "Creating render entity mesh ..." << endl; + state->character->entity->mesh = bgfxutils::createUVSphere (25, 25); + cout << "Creating render entity mesh ... success!" << endl; + glfwSetScrollCallback (gWindow, mouse_scroll_callback); } static void module_unload(struct module_state *state) { - std::cout << "TestModule unloaded. State: " << state << std::endl; glfwSetScrollCallback (gWindow, nullptr); + + cout << "destroying render entity " << state->character->entity << endl; + if (!gRenderer->destroyEntity (state->character->entity)) { + cerr << "Warning: could not destroy entity " << state->character->entity << endl; + } else { + cout << "Successfully destroyed entity " << state->character->entity << endl; + + } + state->character->entity = nullptr; + + std::cout << "TestModule unloaded. State: " << state << std::endl; } void ShowModulesWindow(struct module_state *state) {