Started working on the animation player widget.

AnimGraphEditor
Martin Felis 2023-03-26 15:01:44 +02:00
parent 7152fa74e1
commit 80ea25483b
2 changed files with 102 additions and 21 deletions

View File

@ -105,7 +105,7 @@ void SkinnedMeshResource::createInstance(SkinnedMesh& skinnedMesh) const {
skinnedMesh.LoadSkeleton(m_skeleton_file.c_str());
for (int i = 0; i < m_animation_files.size(); i++) {
skinnedMesh.LoadAnimation(m_animation_files[i].c_str());
skinnedMesh.m_animation_sync_track.push_back(m_sync_tracks[i]);
skinnedMesh.m_animation_sync_track.back() = m_sync_tracks[i];
}
}

View File

@ -61,18 +61,12 @@ static void draw_imgui(ImDrawData*);
#include "ozz/base/maths/soa_transform.h"
#include "ozz/base/maths/vec_float.h"
// wrapper struct for managed ozz-animation C++ objects, mUST BE DEleted
// before shutdown, otherwise ozz-animation will report a memory leak
typedef struct {
ozz::animation::Skeleton skeleton;
ozz::animation::Animation animation;
ozz::animation::SamplingJob::Context sampling_context;
ozz::vector<ozz::math::SoaTransform> local_matrices;
ozz::vector<ozz::math::Float4x4> model_matrices;
} ozz_t;
static struct {
std::unique_ptr<ozz_t> ozz;
struct {
ozz::animation::Animation* animation = nullptr;
ozz::animation::SamplingJob sampling_job;
ozz::animation::SamplingJob::Context* m_sampling_context = nullptr;
} ozz;
sg_pass_action pass_action;
Camera camera;
struct {
@ -82,7 +76,7 @@ static struct {
} loaded;
struct {
double frame;
double absolute;
float absolute;
uint64_t laptime;
float factor;
float anim_ratio;
@ -124,7 +118,14 @@ struct ApplicationConfig {
int size[2] = {800, 500};
};
SkinnedMeshWidget skinned_mesh_widget;
struct AnimationPlayerWidget {
bool visible = false;
int position[2] = {20, 20};
int size[2] = {800, 500};
};
AnimationPlayerWidget animation_player_widget;
bool show_imgui_demo_window = false;
bool show_another_window = false;
bool show_camera_widget = false;
@ -151,7 +152,13 @@ void to_json(nlohmann::json& j, const ApplicationConfig& config) {
j["skinned_mesh_widget"]["position"][1] = config.skinned_mesh_widget.position[1];
j["skinned_mesh_widget"]["size"][0] = config.skinned_mesh_widget.size[0];
j["skinned_mesh_widget"]["size"][1] = config.skinned_mesh_widget.size[1];
j["animation_player_widget"]["visible"] = config.animation_player_widget.visible;
j["animation_player_widget"]["position"][0] = config.animation_player_widget.position[0];
j["animation_player_widget"]["position"][1] = config.animation_player_widget.position[1];
j["animation_player_widget"]["size"][0] = config.animation_player_widget.size[0];
j["animation_player_widget"]["size"][1] = config.animation_player_widget.size[1];
j["camera_widget"]["visible"] = config.show_camera_widget;
}
@ -188,12 +195,11 @@ void from_json(const nlohmann::json& j, ApplicationConfig& config) {
}
}
if (j.contains("skinned_mesh_widget")) {
if (j["skinned_mesh_widget"].contains("visible")) {
config.skinned_mesh_widget.visible = j["skinned_mesh_widget"]["visible"];
}
if (j["skinned_mesh_widget"].contains("position") and j["skinned_mesh_widget"]["position"].size() == 2) {
config.skinned_mesh_widget.position[0] = j["skinned_mesh_widget"]["position"].at(0);
config.skinned_mesh_widget.position[1] = j["skinned_mesh_widget"]["position"].at(1);
@ -204,7 +210,23 @@ void from_json(const nlohmann::json& j, ApplicationConfig& config) {
config.skinned_mesh_widget.size[1] = j["skinned_mesh_widget"]["size"].at(1);
}
}
if (j.contains("animation_player_widget")) {
if (j["animation_player_widget"].contains("visible")) {
config.animation_player_widget.visible = j["animation_player_widget"]["visible"];
}
if (j["animation_player_widget"].contains("position") and j["animation_player_widget"]["position"].size() == 2) {
config.animation_player_widget.position[0] = j["animation_player_widget"]["position"].at(0);
config.animation_player_widget.position[1] = j["animation_player_widget"]["position"].at(1);
}
if (j["animation_player_widget"].contains("size") and j["animation_player_widget"]["size"].size() == 2) {
config.animation_player_widget.size[0] = j["animation_player_widget"]["size"].at(0);
config.animation_player_widget.size[1] = j["animation_player_widget"]["size"].at(1);
}
}
if (j.contains("camera_widget") and j["camera_widget"].contains("visible")) {
config.show_camera_widget = j["camera_widget"]["visible"];
}
@ -480,10 +502,16 @@ int main() {
&gApplicationConfig.window_size[0],
&gApplicationConfig.window_size[1]);
state.time.frame = stm_sec(
stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime)));
if (!state.time.paused) {
state.time.frame = stm_sec(
stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime)));
state.time.absolute += state.time.frame * state.time.factor;
state.time.absolute += state.time.frame * state.time.factor;
if (state.ozz.animation != nullptr) {
state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration());
}
}
int cur_width, cur_height;
glfwGetFramebufferSize(w, &cur_width, &cur_height);
@ -571,6 +599,10 @@ int main() {
ImGui::Checkbox(
"Skinned Mesh",
&gApplicationConfig.skinned_mesh_widget.visible);
ImGui::Checkbox(
"Animation Player",
&gApplicationConfig.animation_player_widget.visible);
ImGui::Separator();
ImGui::Checkbox(
"ImGui Demo",
@ -621,6 +653,55 @@ int main() {
ImGui::End();
}
if (gApplicationConfig.animation_player_widget.visible) {
ImGui::SetNextWindowPos(ImVec2(gApplicationConfig.animation_player_widget.position[0], gApplicationConfig.skinned_mesh_widget.position[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(gApplicationConfig.animation_player_widget.size[0], gApplicationConfig.skinned_mesh_widget.size[1]), ImGuiCond_FirstUseEver);
ImGui::Begin("Animation Player", &gApplicationConfig.animation_player_widget.visible);
ImVec2 animation_player_widget_position = ImGui::GetWindowPos();
gApplicationConfig.animation_player_widget.position[0] = animation_player_widget_position.x;
gApplicationConfig.animation_player_widget.position[1] = animation_player_widget_position.y;
ImVec2 animation_player_widget_size = ImGui::GetWindowSize();
gApplicationConfig.animation_player_widget.size[0] = animation_player_widget_size.x;
gApplicationConfig.animation_player_widget.size[1] = animation_player_widget_size.y;
ImGui::Text("Animation");
const char* items[255] = {0};
static int selected = -1;
for (int i = 0; i < skinned_mesh.m_animations.size(); i++) {
items[i] = skinned_mesh.m_animation_names[i].c_str();
}
if (ImGui::Combo("Animation", &selected, items, skinned_mesh.m_animations.size())) {
state.ozz.animation = skinned_mesh.m_animations[selected];
}
if (state.time.paused) {
if (ImGui::Button("Play")) {
state.time.paused = false;
}
} else {
if (ImGui::Button("Pause")) {
state.time.paused = true;
}
}
if (state.ozz.animation != nullptr) {
ImGui::SliderFloat(
"Time",
&state.time.absolute,
0,
state.ozz.animation->duration(),
"%.3f",
0);
}
ImGui::End();
}
// TODO: add AnimGraph to calculate pose
// skinned_mesh.CalcModelMatrices();