From 87db261a10fa149bba339921eb4ffebf6deeeac2 Mon Sep 17 00:00:00 2001 From: det-fys Date: Fri, 22 Dec 2023 16:10:48 +0100 Subject: [PATCH] neco to dela --- src/tsr/entity_model.cpp | 158 +++++++++++++++++++++++++++++++++----- src/tsr/entity_model.hpp | 3 +- src/tsr/game.cpp | 161 ++++++++++++++++++++++++++++++++++++++- src/tsr/game.hpp | 11 +-- src/tsr/ia.hpp | 8 +- src/tsr/model.cpp | 46 +++++------ src/tsr/transform.hpp | 23 ++++++ src/tsr/worldmap.cpp | 109 ++++++++++++++++++++++++++ src/tsr/worldmap.hpp | 59 ++++++++++++++ src/tsrecs.cpp | 115 +--------------------------- tsrecs.vcxproj | 3 + tsrecs.vcxproj.filters | 9 +++ 12 files changed, 536 insertions(+), 169 deletions(-) create mode 100644 src/tsr/transform.hpp create mode 100644 src/tsr/worldmap.cpp create mode 100644 src/tsr/worldmap.hpp diff --git a/src/tsr/entity_model.cpp b/src/tsr/entity_model.cpp index 7cb554a..a622a9b 100644 --- a/src/tsr/entity_model.cpp +++ b/src/tsr/entity_model.cpp @@ -1,4 +1,5 @@ #include "entity_model.hpp" +#include "window.hpp" using namespace TSR; @@ -14,36 +15,45 @@ void ModelSystem::AddModel(entt::entity ent, const std::string& name) { comp.bone_transforms[1].resize(num_bones); } - if (comp.model->HasAnimations()) - reg.emplace_or_replace(ent); - else - reg.erase(ent); + //if (comp.model->HasAnimations()) + // reg.emplace_or_replace(ent); + //else + // reg.erase(ent); + + comp.ctx.model_matrix = glm::mat4(1.0f); for (int i = 0; i < TSR_NUM_COLORS; ++i) comp.ctx.colors[i] = glm::vec4(1.0f); comp.spawned_at = Game::FrameNum(); - auto& bone_transforms = comp.bone_transforms[Game::FrameNum() % 2]; - for (auto& t : bone_transforms) { - t.pos = glm::vec3(0.0f); - t.rot = glm::quat(glm::mat4(1.0f)); - t.scl = glm::vec3(1.0f); + //auto& bone_transforms = comp.bone_transforms[1 - (Game::FrameNum() % 2)]; + for (auto& t : comp.bone_transforms[0]) + IdentityTransform(t); + + for (auto& t : comp.bone_transforms[1]) + IdentityTransform(t); + + IdentityTransform(comp.trans[0]); + IdentityTransform(comp.trans[1]); + + for (auto& mat : comp.bone_transforms_mat) { + mat = glm::mat4(1.0f); } } void TSR::ModelSystem::RemoveModel(entt::entity ent) { auto& reg = Game::Registry(); reg.erase(ent); - reg.erase(ent); + //reg.erase(ent); } -void ModelSystem::Anim(entt::entity ent, const std::string& anim_name) { +void ModelSystem::Anim(entt::entity ent, const std::string& anim_name, float t) { auto& comp = Game::Registry().get(ent); auto id = comp.model->GetAnimId(anim_name); auto& anim = comp.animations[id]; - anim.t = 0.0f; + anim.t = t; } @@ -59,10 +69,17 @@ void ModelSystem::Animate() { float frame_time = 1.0f / (float)Game::TPS(); - auto v = Game::Registry().view(); - for (auto [ent, model] : v.each()) { + auto v = Game::Registry().view(); + for (auto [ent, model, trans] : v.each()) { + model.trans[frame_idx] = trans.trans; + auto& anims = model.animations; auto& bone_transforms = model.bone_transforms[frame_idx]; + auto& bone_transforms_prev = model.bone_transforms[1 - frame_idx]; + + for (int i = 0; i < bone_transforms.size(); ++i) { + bone_transforms[i] = bone_transforms_prev[i]; + } for (auto it = anims.begin(); it != anims.end(); ) { bool remove = false; @@ -81,6 +98,8 @@ void ModelSystem::Animate() { } } + // events + if (anim.skel) { auto& skel_anim = *anim.skel; @@ -93,10 +112,12 @@ void ModelSystem::Animate() { const auto& frame1 = anim.skel->Channels()[i].frames[fr1]; const auto& frame2 = anim.skel->Channels()[i].frames[fr2]; - auto& trans = bone_transforms[anim.bone_ids[i]]; - trans.pos = glm::mix(frame1.pos, frame2.pos, t); - trans.rot = glm::slerp(frame1.rot, frame2.rot, t); - trans.scl = glm::mix(frame1.scl, frame2.scl, t); + //auto& trans = bone_transforms[anim.bone_ids[i]]; + //trans.pos = glm::mix(frame1.pos, frame2.pos, t); + //trans.rot = glm::slerp(frame1.rot, frame2.rot, t); + //trans.scl = glm::mix(frame1.scl, frame2.scl, t); + + bone_transforms[anim.bone_ids[i]] = MixTransforms(frame1, frame2, t); } } @@ -106,9 +127,55 @@ void ModelSystem::Animate() { ++it; } - } +} +static void CreateTransMatFast(glm::mat4& trans_mat, const Transform& trans) { + //glm::mat4 trans_mat(1.0f); + + float x = trans.rot.x; + float y = trans.rot.y; + float z = trans.rot.z; + float w = trans.rot.w; + + float x2 = x + x; + float y2 = y + y; + float z2 = z + z; + float xx = x * x2; + float xy = x * y2; + float xz = x * z2; + float yy = y * y2; + float yz = y * z2; + float zz = z * z2; + float wx = w * x2; + float wy = w * y2; + float wz = w * z2; + + float sx = trans.scl.x; + float sy = trans.scl.y; + float sz = trans.scl.z; + + trans_mat[0][0] = (1.0f - (yy + zz)) * sx; + trans_mat[0][1] = (xy + wz) * sx; + trans_mat[0][2] = (xz - wy) * sx; + //trans_mat[0][2] = 0.0f; + + trans_mat[1][0] = (xy - wz) * sy; + trans_mat[1][1] = (1.0f - (xx + zz)) * sy; + trans_mat[1][2] = (yz + wx) * sy; + //trans_mat[1][3] = 0.0f; + + trans_mat[2][0] = (xz + wy) * sz; + trans_mat[2][1] = (yz - wx) * sz; + trans_mat[2][2] = (1.0f - (xx + yy)) * sz; + //trans_mat[2][3] = 0.0f; + + trans_mat[3][0] = trans.pos.x; + trans_mat[3][1] = trans.pos.y; + trans_mat[3][2] = trans.pos.z; + //trans_mat[3][3] = 1.0f; + + //return trans_mat; } void ModelSystem::Render(TSR::Renderer& renderer) { @@ -124,12 +191,61 @@ void ModelSystem::Render(TSR::Renderer& renderer) { //} auto frame_t = Game::FrameT(); - auto frame_idx1 = Game::FrameNum() % 2; - auto frame_idx0 = 1 - frame_idx1; + auto frame_idx0 = Game::FrameNum() % 2; + auto frame_idx1 = 1 - frame_idx0; + + //glm::mat4 identity(1.0f); auto v = Game::Registry().view(); for (auto [ent, model, trans] : v.each()) { + + // no second buffer + if (model.spawned_at >= Game::FrameNum() - 1) + continue; + + //auto translation = glm::translate(glm::mat4(1.0f), glm::mix(trans.pos[frame_idx0], trans.pos[frame_idx1], frame_t)); + //auto rotation = glm::toMat4(glm::normalize(glm::slerp(trans.rot[frame_idx0], trans.rot[frame_idx1], frame_t))); + //model.ctx.model_matrix = translation * rotation; + const auto& trans1 = model.trans[frame_idx0]; + const auto& trans2 = model.trans[frame_idx1]; + + CreateTransMatFast(model.ctx.model_matrix, MixTransforms(trans1, trans2, frame_t)); + + if (model.model->IsSkeletal() && !Window::KeyDown(GLFW_KEY_V)) { + + auto& sk_bones = model.model->GetSkeleton().Bones(); + auto& bone_transforms0 = model.bone_transforms[frame_idx0]; + auto& bone_transforms1 = model.bone_transforms[frame_idx1]; + + for (int i = 0; i < model.bone_transforms_mat.size(); ++i) { + const auto& frame1 = bone_transforms0[i]; + const auto& frame2 = bone_transforms1[i]; + + //auto pos = glm::mix(frame1.pos, frame2.pos, frame_t); + //auto rot = glm::slerp(frame1.rot, frame2.rot, frame_t); + //auto scl = glm::mix(frame1.scl, frame2.scl, frame_t); + + //auto translation = glm::translate(glm::mat4(1.0f), glm::mix(frame1.pos, frame2.pos, frame_t)); + //auto rotation = glm::toMat4(glm::normalize(glm::slerp(frame1.rot, frame2.rot, frame_t))); + //auto scale = glm::scale(glm::mat4(1.0f), glm::mix(frame1.scl, frame2.scl, frame_t)); + + //model.bone_transforms_mat[i] = translation * rotation * scale; + + //model.bone_transforms_mat[i] = glm::translate(identity, pos) * glm::mat4_cast(glm::normalize(rot)) * glm::scale(identity, scl); + //model.bone_transforms_mat[i] = CreateTransMatFast(pos, rot, scl); + CreateTransMatFast(model.bone_transforms_mat[i], MixTransforms(frame1, frame2, frame_t)); + + if (sk_bones[i].parent_idx != TSR_NO_BONE) + model.bone_transforms_mat[i] = model.bone_transforms_mat[sk_bones[i].parent_idx] * model.bone_transforms_mat[i]; + } + + } + + model.ctx.bone_transforms = model.bone_transforms_mat.data(); + + if (!Window::KeyDown(GLFW_KEY_X)) + model.model->Draw(renderer, &model.ctx); } diff --git a/src/tsr/entity_model.hpp b/src/tsr/entity_model.hpp index 7eb4f7f..3186d94 100644 --- a/src/tsr/entity_model.hpp +++ b/src/tsr/entity_model.hpp @@ -14,6 +14,7 @@ namespace TSR { struct ModelComponent { AssetPtr model; TSR::DrawCtx ctx; + Transform trans[2]; std::vector bone_transforms_mat; std::vector bone_transforms[2]; std::map animations; @@ -26,7 +27,7 @@ namespace TSR { public: static void AddModel(entt::entity ent, const std::string& name); static void RemoveModel(entt::entity ent); - static void Anim(entt::entity ent, const std::string& anim_name); + static void Anim(entt::entity ent, const std::string& anim_name, float t = 0.0f); static void StopAnim(entt::entity ent, const std::string& anim_name); static void Animate(); diff --git a/src/tsr/game.cpp b/src/tsr/game.cpp index 478835e..a6e9531 100644 --- a/src/tsr/game.cpp +++ b/src/tsr/game.cpp @@ -1,8 +1,165 @@ #include "game.hpp" +#include "entity_model.hpp" +#include "window.hpp" +#include "camera.hpp" +#include "worldmap.hpp" using namespace TSR; entt::registry Game::s_registry; uint64_t Game::s_sv_frame = 0; - float Game::s_frame_t = 0.0f; - int Game::s_tps = 50; \ No newline at end of file +float Game::s_frame_t = 0.0f; +int Game::s_tps = 50; + +static Camera cam; + +static entt::entity ent1; + +static WorldMap* s_map; + +void Game::Run() { + + Filesystem::Init("main"); + WindowWrapper ww("TSR test", 640, 480); + ////Audio::Init(); + + Renderer renderer; + + WorldMap map("maps/kalbatest1.mapproject.json"); + + while (!map.Loaded()) + map.LoadNext(); + + s_map = ↦ + + for (int i = 0; i < 20; ++i) { + auto ent = Game::Registry().create(); + ModelSystem::AddModel(ent, "models/test_skeletal.mdl.json"); + ModelSystem::Anim(ent, "init"); + ModelSystem::Anim(ent, "ruce"); + + glm::vec3 pos(2.0f * (i / 10), 0.0f, 2.0f * (i % 10)); + + auto& trans = Registry().emplace_or_replace(ent); + trans.trans.pos = pos; + trans.trans.rot = glm::quat(glm::vec3(0.0f)); + trans.trans.scl = glm::vec3(1.0f); + + } + + ent1 = Game::Registry().create(); + ModelSystem::AddModel(ent1, "models/skrin.mdl.json"); + ModelSystem::Anim(ent1, "init"); + ModelSystem::Anim(ent1, "open_left"); + ModelSystem::Anim(ent1, "open_right"); + auto& trans = Registry().emplace_or_replace(ent1); + glm::vec3 pos(0.0f, 5.0f, 0.0f); + trans.trans.pos = pos; + trans.trans.rot = glm::quat(glm::vec3(0.0f)); + trans.trans.scl = glm::vec3(1.0f); + + Window::SetInputMode(GLFW_CURSOR, GLFW_CURSOR_DISABLED); + Window::SetCursorPosCallback([](GLFWwindow* window, double xpos, double ypos) { + + static float last_mouse_x = 0.0f, last_mouse_y = 0.0f; + + + double xoffset = xpos - last_mouse_x; + double yoffset = last_mouse_y - ypos; // reversed since y-coordinates range from bottom to top + + cam.ProcessMouse(xoffset, yoffset); + + last_mouse_x = xpos; + last_mouse_y = ypos; + }); + + Window::SetKeyCallback([](GLFWwindow* window, int key, int scancode, int action, int mods) { + if (action == GLFW_PRESS) { + switch (key) { + case GLFW_KEY_E: + ModelSystem::Anim(ent1, "open_left"); + ModelSystem::Anim(ent1, "open_right"); + break; + + case GLFW_KEY_Q: + ModelSystem::Anim(ent1, "close_left"); + ModelSystem::Anim(ent1, "close_right"); + break; + } + + + + } + + }); + + cam.movement_speed *= 0.1f; + + Window::Show(); + + auto start_t = std::chrono::steady_clock::now(); + uint32_t time = 0U; + uint32_t real_time = 0U; + + uint32_t frame_time_ms = 1000U / s_tps; + + glfwSwapInterval(0); + + while (!Window::ShouldClose()) { + + auto diff = std::chrono::steady_clock::now() - start_t; + real_time = std::chrono::duration_cast(diff).count(); + + if (!Window::KeyDown(GLFW_KEY_C)) { + while (time < real_time) { + SvFrame(); + time += frame_time_ms; + } + + } + + s_frame_t = (float)(real_time - time + frame_time_ms) / (float)frame_time_ms; + + ClFrame(renderer, 0.0f); + } +} + +void Game::SvFrame() { + ModelSystem::Animate(); + ++s_sv_frame; + + float time = 1.0f / (float)s_tps; + + if (Window::KeyDown(GLFW_KEY_W)) + cam.ProcessMovement(Camera::Movement::FORWARD, time); + if (Window::KeyDown(GLFW_KEY_S)) + cam.ProcessMovement(Camera::Movement::BACKWARD, time); + if (Window::KeyDown(GLFW_KEY_A)) + cam.ProcessMovement(Camera::Movement::LEFT, time); + if (Window::KeyDown(GLFW_KEY_D)) + cam.ProcessMovement(Camera::Movement::RIGHT, time); + if (Window::KeyDown(GLFW_KEY_SPACE)) + cam.ProcessMovement(Camera::Movement::UP, time); + if (Window::KeyDown(GLFW_KEY_LEFT_SHIFT)) + cam.ProcessMovement(Camera::Movement::DOWN, time); +} + +void Game::ClFrame(Renderer& renderer, float frame_t) { + + + + int w, h; + Window::GetFramebufferSize(w, h); + renderer.SetProjection((float)w / (float)h, 90.0f, 0.1f, 1000.0f); + //r.SetViewMatrix(glm::lookAt(glm::vec3(-1.0f, 2.0f, 2.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f))); + renderer.SetViewMatrix(cam.GetViewMatrix()); + //r.SetViewMatrix(glm::lookAt(glm::vec3(10.0f, 5.0f, 3.0f), glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f))); + + ModelSystem::Render(renderer); + s_map->Draw(renderer); + renderer.Render(w, h); + + Window::PollEvents(); + Window::SwapBuffers(); + +} diff --git a/src/tsr/game.hpp b/src/tsr/game.hpp index c094448..670829c 100644 --- a/src/tsr/game.hpp +++ b/src/tsr/game.hpp @@ -5,13 +5,10 @@ #include #include #include +#include "renderer.hpp" namespace TSR { - struct TransformComponent { - glm::vec3 pos[2]; - glm::quat rot[2]; - }; class Game { static entt::registry s_registry; @@ -20,8 +17,9 @@ namespace TSR { static int s_tps; public: + static void Run(); static void SvFrame(); - static void ClFrame(float frame_t); + static void ClFrame(Renderer& renderer, float frame_t); static entt::registry& Registry() { return s_registry; } static uint64_t FrameNum() { return s_sv_frame; } @@ -29,6 +27,9 @@ namespace TSR { static int TPS() { return s_tps; } }; + struct TransformComponent { + Transform trans; + }; } diff --git a/src/tsr/ia.hpp b/src/tsr/ia.hpp index 2bf0414..5353a54 100644 --- a/src/tsr/ia.hpp +++ b/src/tsr/ia.hpp @@ -1,7 +1,7 @@ #pragma once #include "tsr.hpp" - +#include "transform.hpp" // PARSERS namespace TSR { @@ -22,11 +22,7 @@ namespace TSR { glm::mat4 offset; }; - struct BoneTransform { - glm::vec3 pos; - glm::quat rot; - glm::vec3 scl; - }; + using BoneTransform = Transform; struct SkAnimChannel { std::string name; diff --git a/src/tsr/model.cpp b/src/tsr/model.cpp index cb0e8b8..e97436c 100644 --- a/src/tsr/model.cpp +++ b/src/tsr/model.cpp @@ -104,32 +104,34 @@ Model::Model(const std::string& name) { m_part_names.insert({ part_json.at("name").get(), m_parts.size() - 1 }); } - const auto& anims_json = model_json.at("animations"); - for (const auto& anim_json : anims_json) { - m_animations.push_back(Animation()); - auto idx = m_animations.size() - 1; - auto& anim = m_animations[idx]; - m_anim_names.insert({ anim_json.at("name").get(), idx }); + if (model_json.contains("animations")) { + const auto& anims_json = model_json.at("animations"); + for (const auto& anim_json : anims_json) { + m_animations.push_back(Animation()); + auto idx = m_animations.size() - 1; + auto& anim = m_animations[idx]; + m_anim_names.insert({ anim_json.at("name").get(), idx }); - if (anim_json.contains("skel")) { - if (!m_skeleton) Throw("Skeletal animation in a model with no skeleton"); - anim.skel = AssetMap::Get(anim_json.at("skel").get()); - for (const auto& chan : anim.skel->Channels()) - anim.bone_ids.push_back(m_skeleton->GetBoneIdByName(chan.name)); + if (anim_json.contains("skel")) { + if (!m_skeleton) Throw("Skeletal animation in a model with no skeleton"); + anim.skel = AssetMap::Get(anim_json.at("skel").get()); + for (const auto& chan : anim.skel->Channels()) + anim.bone_ids.push_back(m_skeleton->GetBoneIdByName(chan.name)); - anim.duration = anim.skel->Duration(); - anim.tps = anim.skel->TPS(); - } - else { - anim.duration = anim_json.at("duration").get(); - anim.tps = anim_json.at("tps").get(); - } + anim.duration = anim.skel->Duration(); + anim.tps = anim.skel->TPS(); + } + else { + anim.duration = anim_json.at("duration").get(); + anim.tps = anim_json.at("tps").get(); + } - anim.is_cyclic = false; - if (anim_json.contains("cyclic")) - anim.is_cyclic = anim_json.at("cyclic").get(); + anim.is_cyclic = false; + if (anim_json.contains("cyclic")) + anim.is_cyclic = anim_json.at("cyclic").get(); - // events + // events + } } } catch (nlohmann::json::exception ex) { diff --git a/src/tsr/transform.hpp b/src/tsr/transform.hpp new file mode 100644 index 0000000..55f1d78 --- /dev/null +++ b/src/tsr/transform.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +struct Transform { + glm::vec3 pos; + glm::quat rot; + glm::vec3 scl; +}; + +inline Transform MixTransforms(const Transform& t1, const Transform& t2, float t) { + Transform ret; + ret.pos = glm::mix(t1.pos, t2.pos, t); + ret.rot = glm::slerp(t1.rot, t2.rot, t); + ret.scl = glm::mix(t1.scl, t2.scl, t); + return ret; +} + +inline void IdentityTransform(Transform& t) { + t.pos = glm::vec3(0.0f); + t.rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); + t.scl = glm::vec3(1.0f); +} \ No newline at end of file diff --git a/src/tsr/worldmap.cpp b/src/tsr/worldmap.cpp new file mode 100644 index 0000000..ad952e9 --- /dev/null +++ b/src/tsr/worldmap.cpp @@ -0,0 +1,109 @@ +#include "worldmap.hpp" + +using namespace TSR; + +static const char* color_strs[] = { "color1", "color2", "color3", "color4" }; + +WorldMap::WorldMap(const std::string& map_path) : m_loading_phase(LoadingPhase::FIRST), m_map_path(map_path), m_loaded_models(0) {} + +int WorldMap::LoadNext() { + switch (m_loading_phase) { + + case LoadingPhase::FIRST: + m_loading_phase = LoadingPhase::PARSE; + return 0; + break; + + case LoadingPhase::PARSE: + { + auto j_map = nlohmann::json::parse(Filesystem::Read(m_map_path)); + + //if (j_map.contains("")) + + auto j_objects = j_map.at("objects"); + + for (const auto& j_object : j_objects) { + + auto model_name = j_object.at("model").get(); + + auto& model_instances = m_loading_obj_data[model_name]; + + //MapObject obj; + //obj.m_model = s; + + BasicDrawCtx ctx; + + auto pos = JsonGetVec<3>(j_object.at("pos")); + auto rot = j_object.at("angle").get(); + float scale = 1.0f; + + if (j_object.contains("scale")) + j_object.at("scale").get_to(scale); + + ctx.model_matrix = glm::scale(glm::rotate(glm::translate(glm::mat4(1.0f), pos), glm::radians(rot), glm::vec3(0.0f, 1.0f, 0.0f)), glm::vec3(scale)); + + for (int i = 0; i < 4; ++i) { + auto& cns = color_strs[i]; + if (j_object.contains(cns)) + ctx.colors[i] = JsonGetVec<4>(j_object.at(cns)); + } + + model_instances.m_contexts.push_back(ctx); + + } + + m_loading_iter = m_loading_obj_data.cbegin(); + m_loading_phase = LoadingPhase::MODELS; + return 10; + + break; + } + + + case LoadingPhase::MODELS: + { + if (m_loading_iter == m_loading_obj_data.cend()) { + m_loading_phase = LoadingPhase::FINISHED; + m_loading_obj_data.clear(); + return 100; + } + + const auto& models = *(m_loading_iter++); + ++m_loaded_models; + + auto s = AssetMap::Get(models.first); + + if (models.second.m_contexts.size() > 4) { + MapObject obj; + obj.m_model = s; + obj.m_ctx.ssbo = std::make_unique(models.second.m_contexts); + + m_objects_instanced.push_back(std::move(obj)); + + } + else { + for (const auto& instance : models.second.m_contexts) { + MapObject obj; + obj.m_model = s; + obj.m_ctx.model_matrix = instance.model_matrix; + for (int i = 0; i < 4; i++) + obj.m_ctx.colors[i] = instance.colors[i]; + + m_objects.push_back(std::move(obj)); + } + + } + return 10 + (90 * m_loaded_models / m_loading_obj_data.size()); + + break; + } + + case LoadingPhase::FINISHED: + return 100; + break; + } + + return 0; + + +} diff --git a/src/tsr/worldmap.hpp b/src/tsr/worldmap.hpp new file mode 100644 index 0000000..017e17a --- /dev/null +++ b/src/tsr/worldmap.hpp @@ -0,0 +1,59 @@ +#pragma once +#include +#include "model.hpp" +//#include "audio.hpp" +#include "window.hpp" +#include "tsr.hpp" + +namespace TSR { + + class WorldMap { + // general + std::string m_map_path; + + // loading + enum class LoadingPhase { + FIRST, + PARSE, + MODELS, + FINISHED, + } m_loading_phase; + + struct ModelInstances { + std::vector m_contexts; + }; + + using LoadingObjData = std::map; + + LoadingObjData m_loading_obj_data; + LoadingObjData::const_iterator m_loading_iter; + int m_loaded_models; + + // final + struct MapObject { + DrawCtx m_ctx; + AssetPtr m_model; + }; + + std::vector m_objects; + std::vector m_objects_instanced; + + public: + WorldMap(const std::string& map_path); + + bool Loaded() const { return m_loading_phase == LoadingPhase::FINISHED; } + const std::string& Name() { return m_map_path; } + + int LoadNext(); + + void Draw(Renderer& r) const { + for (const auto& obj : m_objects) + obj.m_model->Draw(r, &obj.m_ctx); + + for (const auto& obj : m_objects_instanced) + obj.m_model->DrawInstanced(r, &obj.m_ctx); + } + }; + + +} \ No newline at end of file diff --git a/src/tsrecs.cpp b/src/tsrecs.cpp index 1999b3d..e73437a 100644 --- a/src/tsrecs.cpp +++ b/src/tsrecs.cpp @@ -5,6 +5,8 @@ #include "tsr/renderer.hpp" #include "tsr/model.hpp" #include "tsr/camera.hpp" +#include "tsr/game.hpp" +#include "tsr/entity_model.hpp" #include using namespace TSR; @@ -14,118 +16,7 @@ int main() { TsrPrintf("Hello (client)\n"); try { - Filesystem::Init("main"); - WindowWrapper ww("TSR test", 640, 480); - ////Audio::Init(); - - Renderer r; - - auto model = AssetMap::Get("models/test_skeletal.mdl.json"); - - DrawCtx draw_ctx; - draw_ctx.model_matrix = glm::mat4(1.0f); - - std::vector bone_transforms; - bone_transforms.resize(model->GetSkeleton().Bones().size()); - - draw_ctx.bone_transforms = &bone_transforms[0]; - - auto anim_id = model->GetAnimId("ruce"); - const auto& anim = model->GetAnim(anim_id); - - const auto& skel = model->GetSkeleton(); - const auto& sk_bones = skel.Bones(); - - //glfwSwapInterval(0); - - Window::SetInputMode(GLFW_CURSOR, GLFW_CURSOR_DISABLED); - Window::SetCursorPosCallback([](GLFWwindow* window, double xpos, double ypos) { - - static float last_mouse_x = 0.0f, last_mouse_y = 0.0f; - - - double xoffset = xpos - last_mouse_x; - double yoffset = last_mouse_y - ypos; // reversed since y-coordinates range from bottom to top - - cam.ProcessMouse(xoffset, yoffset); - - last_mouse_x = xpos; - last_mouse_y = ypos; - }); - - cam.movement_speed *= 0.1f; - - Window::Show(); - while (!Window::ShouldClose()) { - float time = 1.0f / 75.0f; - - if (Window::KeyDown(GLFW_KEY_W)) - cam.ProcessMovement(Camera::Movement::FORWARD, time); - if (Window::KeyDown(GLFW_KEY_S)) - cam.ProcessMovement(Camera::Movement::BACKWARD, time); - if (Window::KeyDown(GLFW_KEY_A)) - cam.ProcessMovement(Camera::Movement::LEFT, time); - if (Window::KeyDown(GLFW_KEY_D)) - cam.ProcessMovement(Camera::Movement::RIGHT, time); - if (Window::KeyDown(GLFW_KEY_SPACE)) - cam.ProcessMovement(Camera::Movement::UP, time); - if (Window::KeyDown(GLFW_KEY_LEFT_SHIFT)) - cam.ProcessMovement(Camera::Movement::DOWN, time); - - - int w, h; - Window::GetFramebufferSize(w, h); - r.SetProjection((float)w / (float)h, 90.0f, 0.1f, 1000.0f); - //r.SetViewMatrix(glm::lookAt(glm::vec3(-1.0f, 2.0f, 2.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f))); - r.SetViewMatrix(cam.GetViewMatrix()); - //r.SetViewMatrix(glm::lookAt(glm::vec3(10.0f, 5.0f, 3.0f), glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f))); - - - // reset bones - for (int i = 0; i < bone_transforms.size(); ++i) { - bone_transforms[i] = sk_bones[i].transform; - } - - // animation - float cur_frame = glm::mod((float)(glfwGetTime() * anim.skel->TPS()), (float)anim.skel->Duration()); - //float cur_frame = glm::mod(1.0f, 3.0f); - - for (int i = 0; i < anim.skel->Channels().size(); ++i) { - - int fr1 = glm::floor(cur_frame); - int fr2 = glm::ceil(cur_frame); - float t = glm::fract(cur_frame); - - const auto& frame1 = anim.skel->Channels()[i].frames[fr1]; - const auto& frame2 = anim.skel->Channels()[i].frames[fr2]; - - auto translation = glm::translate(glm::mat4(1.0f), glm::mix(frame1.pos, frame2.pos, t)); - auto rotation = glm::toMat4(glm::normalize(glm::slerp(frame1.rot, frame2.rot, t))); - auto scale = glm::scale(glm::mat4(1.0f), glm::mix(frame1.scl, frame2.scl, t)); - - bone_transforms[anim.bone_ids[i]] = translation * rotation * scale; - - } - - // apply parents - for (int i = 0; i < bone_transforms.size(); ++i) { - if (sk_bones[i].parent_idx != TSR_NO_BONE) - bone_transforms[i] = bone_transforms[sk_bones[i].parent_idx] * bone_transforms[i]; - } - - - - model->Draw(r, &draw_ctx); - - r.Render(w, h); - - Window::PollEvents(); - Window::SwapBuffers(); - - - - - } + Game::Run(); //Client::Run(); diff --git a/tsrecs.vcxproj b/tsrecs.vcxproj index 90d39ba..4e3fe83 100644 --- a/tsrecs.vcxproj +++ b/tsrecs.vcxproj @@ -139,6 +139,7 @@ + @@ -150,8 +151,10 @@ + + diff --git a/tsrecs.vcxproj.filters b/tsrecs.vcxproj.filters index 8df5ece..e005b41 100644 --- a/tsrecs.vcxproj.filters +++ b/tsrecs.vcxproj.filters @@ -45,6 +45,9 @@ Source Files + + Source Files + @@ -80,5 +83,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file