neco to dela
This commit is contained in:
parent
3f33390ad7
commit
87db261a10
@ -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<AnimationComponent>(ent);
|
||||
else
|
||||
reg.erase<AnimationComponent>(ent);
|
||||
//if (comp.model->HasAnimations())
|
||||
// reg.emplace_or_replace<AnimationComponent>(ent);
|
||||
//else
|
||||
// reg.erase<AnimationComponent>(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<ModelComponent>(ent);
|
||||
reg.erase<AnimationComponent>(ent);
|
||||
//reg.erase<AnimationComponent>(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<ModelComponent>(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<AnimationComponent, ModelComponent>();
|
||||
for (auto [ent, model] : v.each()) {
|
||||
auto v = Game::Registry().view<ModelComponent, TransformComponent>();
|
||||
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<ModelComponent, TransformComponent>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ namespace TSR {
|
||||
struct ModelComponent {
|
||||
AssetPtr<Model> model;
|
||||
TSR::DrawCtx ctx;
|
||||
Transform trans[2];
|
||||
std::vector<glm::mat4> bone_transforms_mat;
|
||||
std::vector<BoneTransform> bone_transforms[2];
|
||||
std::map<AnimationId, ModelAnimation> 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();
|
||||
|
||||
161
src/tsr/game.cpp
161
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;
|
||||
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<TransformComponent>(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<TransformComponent>(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<std::chrono::milliseconds>(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();
|
||||
|
||||
}
|
||||
|
||||
@ -5,13 +5,10 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <memory>
|
||||
#include <entt/entt.hpp>
|
||||
#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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -104,32 +104,34 @@ Model::Model(const std::string& name) {
|
||||
m_part_names.insert({ part_json.at("name").get<std::string>(), 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<std::string>(), 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<std::string>(), idx });
|
||||
|
||||
if (anim_json.contains("skel")) {
|
||||
if (!m_skeleton) Throw("Skeletal animation in a model with no skeleton");
|
||||
anim.skel = AssetMap::Get<SkAnim>(anim_json.at("skel").get<std::string>());
|
||||
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<SkAnim>(anim_json.at("skel").get<std::string>());
|
||||
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<float>();
|
||||
anim.tps = anim_json.at("tps").get<float>();
|
||||
}
|
||||
anim.duration = anim.skel->Duration();
|
||||
anim.tps = anim.skel->TPS();
|
||||
}
|
||||
else {
|
||||
anim.duration = anim_json.at("duration").get<float>();
|
||||
anim.tps = anim_json.at("tps").get<float>();
|
||||
}
|
||||
|
||||
anim.is_cyclic = false;
|
||||
if (anim_json.contains("cyclic"))
|
||||
anim.is_cyclic = anim_json.at("cyclic").get<bool>();
|
||||
anim.is_cyclic = false;
|
||||
if (anim_json.contains("cyclic"))
|
||||
anim.is_cyclic = anim_json.at("cyclic").get<bool>();
|
||||
|
||||
// events
|
||||
// events
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (nlohmann::json::exception ex) {
|
||||
|
||||
23
src/tsr/transform.hpp
Normal file
23
src/tsr/transform.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
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);
|
||||
}
|
||||
109
src/tsr/worldmap.cpp
Normal file
109
src/tsr/worldmap.cpp
Normal file
@ -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<std::string>();
|
||||
|
||||
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>();
|
||||
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<Model>(models.first);
|
||||
|
||||
if (models.second.m_contexts.size() > 4) {
|
||||
MapObject obj;
|
||||
obj.m_model = s;
|
||||
obj.m_ctx.ssbo = std::make_unique<InstancedSSBO>(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;
|
||||
|
||||
|
||||
}
|
||||
59
src/tsr/worldmap.hpp
Normal file
59
src/tsr/worldmap.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#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<BasicDrawCtx> m_contexts;
|
||||
};
|
||||
|
||||
using LoadingObjData = std::map<std::string, ModelInstances>;
|
||||
|
||||
LoadingObjData m_loading_obj_data;
|
||||
LoadingObjData::const_iterator m_loading_iter;
|
||||
int m_loaded_models;
|
||||
|
||||
// final
|
||||
struct MapObject {
|
||||
DrawCtx m_ctx;
|
||||
AssetPtr<Model> m_model;
|
||||
};
|
||||
|
||||
std::vector<MapObject> m_objects;
|
||||
std::vector<MapObject> 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
115
src/tsrecs.cpp
115
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 <windows.h>
|
||||
|
||||
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<Model>("models/test_skeletal.mdl.json");
|
||||
|
||||
DrawCtx draw_ctx;
|
||||
draw_ctx.model_matrix = glm::mat4(1.0f);
|
||||
|
||||
std::vector<glm::mat4> 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();
|
||||
|
||||
|
||||
@ -139,6 +139,7 @@
|
||||
<ClCompile Include="src\tsr\renderer.cpp" />
|
||||
<ClCompile Include="src\tsr\window.cpp" />
|
||||
<ClCompile Include="src\tsrecs.cpp" />
|
||||
<ClCompile Include="src\tsr\worldmap.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\tsr\camera.hpp" />
|
||||
@ -150,8 +151,10 @@
|
||||
<ClInclude Include="src\tsr\filesystem.hpp" />
|
||||
<ClInclude Include="src\tsr\ia.hpp" />
|
||||
<ClInclude Include="src\tsr\renderer.hpp" />
|
||||
<ClInclude Include="src\tsr\transform.hpp" />
|
||||
<ClInclude Include="src\tsr\tsr.hpp" />
|
||||
<ClInclude Include="src\tsr\window.hpp" />
|
||||
<ClInclude Include="src\tsr\worldmap.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@ -45,6 +45,9 @@
|
||||
<ClCompile Include="src\tsr\camera.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\tsr\worldmap.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\tsr\window.hpp">
|
||||
@ -80,5 +83,11 @@
|
||||
<ClInclude Include="src\tsr\camera.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\tsr\transform.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\tsr\worldmap.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user