Minor restructuring for tests, initial work for sync tracks.

AnimGraphEditor
Martin Felis 2021-11-16 18:15:56 +01:00
parent 038f07de0a
commit 3e1c150345
12 changed files with 18144 additions and 77 deletions

View File

@ -28,21 +28,19 @@ set(ozz_build_simd_ref OFF CACHE BOOL "")
set(ozz_build_msvc_rt_dll OFF CACHE BOOL "") set(ozz_build_msvc_rt_dll OFF CACHE BOOL "")
add_subdirectory(3rdparty/ozz-animation) add_subdirectory(3rdparty/ozz-animation)
# Simulator Executable set (ThirdPartyIncludeDeps
add_executable(AnimTestbed)
target_include_directories(
AnimTestbed
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/glfw/deps> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/glfw/deps>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/glfw/deps>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Handmade-Math> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Handmade-Math>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/imgui> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/imgui>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ozz-animation/include>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sokol> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sokol>
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vectorial/include> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vectorial/include>
) )
target_link_libraries(AnimTestbed glfw ozz_base ozz_geometry ozz_animation ${OPENGL_LIBRARIES})
target_sources(AnimTestbed PRIVATE # Shared code by main executable and tests
src/main.cc add_library(AnimTestbedCode OBJECT
src/Camera.c src/Camera.c
src/SkinnedMesh.cc src/SkinnedMesh.cc
src/SkinnedMesh.h src/SkinnedMesh.h
@ -51,11 +49,41 @@ target_sources(AnimTestbed PRIVATE
src/AnimNodes/SpeedScaleNode.cc src/AnimNodes/SpeedScaleNode.cc
src/AnimNodes/BlendNode.cc src/AnimNodes/BlendNode.cc
src/AnimationController.cc src/AnimationController.cc
3rdparty/glfw/deps/glad_gl.c
3rdparty/imgui/imgui.cpp 3rdparty/imgui/imgui.cpp
3rdparty/imgui/imgui_draw.cpp 3rdparty/imgui/imgui_draw.cpp
3rdparty/imgui/imgui_widgets.cpp 3rdparty/imgui/imgui_widgets.cpp
)
target_include_directories(
AnimTestbedCode
${ThirdPartyIncludeDeps}
)
# AnimTestbed Executable
add_executable(AnimTestbed)
target_include_directories(
AnimTestbed
${ThirdPartyIncludeDeps}
)
target_sources(AnimTestbed PRIVATE
src/main.cc
src/SkinnedMeshRenderer.cc
3rdparty/glfw/deps/glad_gl.c
3rdparty/imgui/imgui_demo.cpp 3rdparty/imgui/imgui_demo.cpp
3rdparty/imgui/backends/imgui_impl_glfw.cpp 3rdparty/imgui/backends/imgui_impl_glfw.cpp
3rdparty/imgui/backends/imgui_impl_opengl3.cpp 3rdparty/imgui/backends/imgui_impl_opengl3.cpp
) )
target_link_libraries(AnimTestbed AnimTestbedCode glfw ozz_base ozz_geometry ozz_animation ${OPENGL_LIBRARIES})
# Tests
add_executable(runtests)
target_sources(runtests PRIVATE tests/main.cc tests/SyncTrackTests.cc)
target_include_directories(
runtests
${ThirdPartyIncludeDeps}
)
target_link_libraries(runtests AnimTestbedCode glfw ozz_base ozz_geometry ozz_animation)

View File

@ -8,6 +8,7 @@
#include <string> #include <string>
#include "AnimationController.h" #include "AnimationController.h"
#include "SkinnedMesh.h"
enum class AnimNodeType { Blend, SpeedScale, AnimSampler }; enum class AnimNodeType { Blend, SpeedScale, AnimSampler };
@ -27,6 +28,7 @@ struct AnimNode {
bool m_is_time_synced; bool m_is_time_synced;
float m_current_time; float m_current_time;
float m_anim_duration; float m_anim_duration;
SyncTrack m_sync_track;
virtual void Reset() { m_current_time = 0.f; } virtual void Reset() { m_current_time = 0.f; }

View File

@ -46,7 +46,7 @@ AnimationController::AnimationController(SkinnedMesh* skinned_mesh)
blend_node->m_name = "Blend0"; blend_node->m_name = "Blend0";
blend_node->m_input_A = speed_node; blend_node->m_input_A = speed_node;
blend_node->m_input_B = sampler_node1; blend_node->m_input_B = sampler_node1;
blend_node->m_sync_inputs = true; blend_node->m_sync_inputs = false;
m_anim_nodes.push_back(blend_node); m_anim_nodes.push_back(blend_node);
SpeedScaleNode* speed_node1 = new SpeedScaleNode(this); SpeedScaleNode* speed_node1 = new SpeedScaleNode(this);
@ -97,7 +97,11 @@ void AnimationController::UpdateOrderedNodes() {
} }
} }
void AnimationController::Update(float dt) { void AnimationController::UpdateBlendLogic() {
}
void AnimationController::UpdateTime(float dt) {
if (m_output_node == nullptr) { if (m_output_node == nullptr) {
return; return;
} }

View File

@ -23,8 +23,10 @@ struct AnimationController {
// Creates a list of nodes where for node at index i for all inputs holds index > i. // Creates a list of nodes where for node at index i for all inputs holds index > i.
void UpdateOrderedNodes(); void UpdateOrderedNodes();
void UpdateBlendLogic();
// Updates all nodes. // Updates all nodes.
void Update(float dt); void UpdateTime(float dt);
// Recursively evaluates all nodes. // Recursively evaluates all nodes.
void Evaluate(); void Evaluate();

View File

@ -7,58 +7,6 @@
#include <HandmadeMath.h> #include <HandmadeMath.h>
#include <imgui.h> #include <imgui.h>
#include "sokol_gfx.h"
#include "util/sokol_gl.h"
static void draw_vec(const ozz::math::SimdFloat4& vec) {
sgl_v3f(ozz::math::GetX(vec), ozz::math::GetY(vec), ozz::math::GetZ(vec));
}
static void draw_line(
const ozz::math::SimdFloat4& v0,
const ozz::math::SimdFloat4& v1) {
draw_vec(v0);
draw_vec(v1);
}
// this draws a wireframe 3d rhombus between the current and parent joints
void SkinnedMesh::DrawJoint(int joint_index, int parent_joint_index) {
if (parent_joint_index < 0) {
return;
}
using namespace ozz::math;
const Float4x4& m0 = m_model_matrices[joint_index];
const Float4x4& m1 = m_model_matrices[parent_joint_index];
const SimdFloat4 p0 = m0.cols[3];
const SimdFloat4 p1 = m1.cols[3];
const SimdFloat4 ny = m1.cols[1];
const SimdFloat4 nz = m1.cols[2];
const SimdFloat4 len = SplatX(Length3(p1 - p0)) * simd_float4::Load1(0.1f);
const SimdFloat4 pmid = p0 + (p1 - p0) * simd_float4::Load1(0.66f);
const SimdFloat4 p2 = pmid + ny * len;
const SimdFloat4 p3 = pmid + nz * len;
const SimdFloat4 p4 = pmid - ny * len;
const SimdFloat4 p5 = pmid - nz * len;
sgl_c3f(1.0f, 1.0f, 0.0f);
draw_line(p0, p2);
draw_line(p0, p3);
draw_line(p0, p4);
draw_line(p0, p5);
draw_line(p1, p2);
draw_line(p1, p3);
draw_line(p1, p4);
draw_line(p1, p5);
draw_line(p2, p3);
draw_line(p3, p4);
draw_line(p4, p5);
draw_line(p5, p2);
}
SkinnedMesh::~SkinnedMesh() { SkinnedMesh::~SkinnedMesh() {
while (m_animations.size() > 0) { while (m_animations.size() > 0) {
@ -164,19 +112,7 @@ void SkinnedMesh::EvalAnimation(float in_time) {
} }
void SkinnedMesh::DrawSkeleton() { void SkinnedMesh::DrawSkeleton() {
sgl_matrix_mode_modelview();
sgl_push_matrix();
hmm_mat4 scale_mat = HMM_Scale(HMM_Vec3(0.01f, 0.01f, 0.01f));
sgl_mult_matrix((const float*)&scale_mat);
const int num_joints = m_skeleton.num_joints();
ozz::span<const int16_t> joint_parents = m_skeleton.joint_parents();
sgl_begin_lines();
for (int joint_index = 0; joint_index < num_joints; joint_index++) {
DrawJoint(joint_index, joint_parents[joint_index]);
}
sgl_end();
sgl_pop_matrix();
} }
void SkinnedMesh::DrawDebugUi() { void SkinnedMesh::DrawDebugUi() {

View File

@ -20,6 +20,40 @@
#include "ozz/base/maths/soa_transform.h" #include "ozz/base/maths/soa_transform.h"
#include "ozz/base/maths/vec_float.h" #include "ozz/base/maths/vec_float.h"
constexpr int cSyncTrackMaxIntervals = 8;
struct SyncTrack {
float m_duration;
int m_num_intervals;
float m_interval_durations[cSyncTrackMaxIntervals];
float ConvertAbsTimeToSyncTime (float abs_time) {
float sync_time = fmodf (abs_time, m_duration) / m_duration;
int interval_index = 0;
while (sync_time < m_interval_durations[interval_index]) {
sync_time -= m_interval_durations[interval_index];
interval_index ++;
}
}
static SyncTrack Blend(float weight, const SyncTrack& track_A, const SyncTrack& track_B) {
SyncTrack result;
assert (track_A.m_num_intervals == track_B.m_num_intervals);
result.m_num_intervals = track_A.m_num_intervals;
result.m_duration = (1.0f - weight) * track_A.m_duration + weight * track_B.m_duration;
for (int i = 0; i < result.m_num_intervals; i++) {
result.m_interval_durations[i] = (1.0f - weight) * track_A.m_interval_durations[i] + weight * track_B.m_interval_durations[i];
}
return result;
}
};
struct SkinnedMesh { struct SkinnedMesh {
virtual ~SkinnedMesh(); virtual ~SkinnedMesh();
bool LoadSkeleton(const char* filename); bool LoadSkeleton(const char* filename);
@ -39,6 +73,7 @@ struct SkinnedMesh {
ozz::vector<ozz::animation::Animation*> m_animations; ozz::vector<ozz::animation::Animation*> m_animations;
std::vector<std::string> m_animation_names; std::vector<std::string> m_animation_names;
std::vector<SyncTrack> m_animation_sync_track;
ozz::animation::Skeleton m_skeleton; ozz::animation::Skeleton m_skeleton;
ozz::animation::Animation* m_current_animation; ozz::animation::Animation* m_current_animation;
ozz::animation::SamplingCache m_cache; ozz::animation::SamplingCache m_cache;

View File

@ -0,0 +1,75 @@
//
// Created by martin on 16.11.21.
//
#include "SkinnedMeshRenderer.h"
#include "sokol_gfx.h"
#include "util/sokol_gl.h"
#include "HandmadeMath.h"
static void draw_vec(const ozz::math::SimdFloat4& vec) {
sgl_v3f(ozz::math::GetX(vec), ozz::math::GetY(vec), ozz::math::GetZ(vec));
}
static void draw_line(
const ozz::math::SimdFloat4& v0,
const ozz::math::SimdFloat4& v1) {
draw_vec(v0);
draw_vec(v1);
}
// this draws a wireframe 3d rhombus between the current and parent joints
void draw_joint (const SkinnedMesh& skinned_mesh, int joint_index, int parent_joint_index) {
if (parent_joint_index < 0) {
return;
}
using namespace ozz::math;
const Float4x4& m0 = skinned_mesh.m_model_matrices[joint_index];
const Float4x4& m1 = skinned_mesh.m_model_matrices[parent_joint_index];
const SimdFloat4 p0 = m0.cols[3];
const SimdFloat4 p1 = m1.cols[3];
const SimdFloat4 ny = m1.cols[1];
const SimdFloat4 nz = m1.cols[2];
const SimdFloat4 len = SplatX(Length3(p1 - p0)) * simd_float4::Load1(0.1f);
const SimdFloat4 pmid = p0 + (p1 - p0) * simd_float4::Load1(0.66f);
const SimdFloat4 p2 = pmid + ny * len;
const SimdFloat4 p3 = pmid + nz * len;
const SimdFloat4 p4 = pmid - ny * len;
const SimdFloat4 p5 = pmid - nz * len;
sgl_c3f(1.0f, 1.0f, 0.0f);
draw_line(p0, p2);
draw_line(p0, p3);
draw_line(p0, p4);
draw_line(p0, p5);
draw_line(p1, p2);
draw_line(p1, p3);
draw_line(p1, p4);
draw_line(p1, p5);
draw_line(p2, p3);
draw_line(p3, p4);
draw_line(p4, p5);
draw_line(p5, p2);
}
void RenderSkinnedMesh (const SkinnedMesh& skinned_mesh) {
sgl_matrix_mode_modelview();
sgl_push_matrix();
hmm_mat4 scale_mat = HMM_Scale(HMM_Vec3(0.01f, 0.01f, 0.01f));
sgl_mult_matrix((const float*)&scale_mat);
const int num_joints = skinned_mesh.m_skeleton.num_joints();
ozz::span<const int16_t> joint_parents = skinned_mesh.m_skeleton.joint_parents();
sgl_begin_lines();
for (int joint_index = 0; joint_index < num_joints; joint_index++) {
draw_joint(skinned_mesh, joint_index, joint_parents[joint_index]);
}
sgl_end();
sgl_pop_matrix();
}

12
src/SkinnedMeshRenderer.h Normal file
View File

@ -0,0 +1,12 @@
//
// Created by martin on 16.11.21.
//
#ifndef ANIMTESTBED_SKINNEDMESHRENDERER_H
#define ANIMTESTBED_SKINNEDMESHRENDERER_H
#include "SkinnedMesh.h"
void RenderSkinnedMesh (const SkinnedMesh& skinned_mesh);
#endif //ANIMTESTBED_SKINNEDMESHRENDERER_H

View File

@ -47,6 +47,7 @@ static void draw_imgui(ImDrawData*);
#include <memory> // std::unique_ptr, std::make_unique #include <memory> // std::unique_ptr, std::make_unique
#include "AnimationController.h" #include "AnimationController.h"
#include "SkinnedMeshRenderer.h"
#include "ozz/animation/runtime/animation.h" #include "ozz/animation/runtime/animation.h"
#include "ozz/animation/runtime/local_to_model_job.h" #include "ozz/animation/runtime/local_to_model_job.h"
#include "ozz/animation/runtime/sampling_job.h" #include "ozz/animation/runtime/sampling_job.h"
@ -418,7 +419,7 @@ int main() {
sgl_load_matrix((const float*)&state.camera.mtxProj); sgl_load_matrix((const float*)&state.camera.mtxProj);
sgl_matrix_mode_modelview(); sgl_matrix_mode_modelview();
sgl_load_matrix((const float*)&state.camera.mtxView); sgl_load_matrix((const float*)&state.camera.mtxView);
skinned_mesh.DrawSkeleton(); RenderSkinnedMesh(skinned_mesh);
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowDemoWindow() // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowDemoWindow()
if (show_imgui_demo_window) { if (show_imgui_demo_window) {

5
tests/SyncTrackTests.cc Normal file
View File

@ -0,0 +1,5 @@
//
// Created by martin on 16.11.21.
//
#include "catch.hpp"

17959
tests/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

8
tests/main.cc Normal file
View File

@ -0,0 +1,8 @@
#define CATCH_CONFIG_RUNNER // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
int main (int argc, char* argv[]) {
int result = Catch::Session().run(argc, argv);
return result;
}