Minor restructuring for tests, initial work for sync tracks.
parent
038f07de0a
commit
3e1c150345
|
@ -28,21 +28,19 @@ set(ozz_build_simd_ref OFF CACHE BOOL "")
|
|||
set(ozz_build_msvc_rt_dll OFF CACHE BOOL "")
|
||||
add_subdirectory(3rdparty/ozz-animation)
|
||||
|
||||
# Simulator Executable
|
||||
add_executable(AnimTestbed)
|
||||
target_include_directories(
|
||||
AnimTestbed
|
||||
set (ThirdPartyIncludeDeps
|
||||
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/Handmade-Math>
|
||||
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/vectorial/include>
|
||||
)
|
||||
target_link_libraries(AnimTestbed glfw ozz_base ozz_geometry ozz_animation ${OPENGL_LIBRARIES})
|
||||
|
||||
target_sources(AnimTestbed PRIVATE
|
||||
src/main.cc
|
||||
# Shared code by main executable and tests
|
||||
add_library(AnimTestbedCode OBJECT
|
||||
src/Camera.c
|
||||
src/SkinnedMesh.cc
|
||||
src/SkinnedMesh.h
|
||||
|
@ -51,11 +49,41 @@ target_sources(AnimTestbed PRIVATE
|
|||
src/AnimNodes/SpeedScaleNode.cc
|
||||
src/AnimNodes/BlendNode.cc
|
||||
src/AnimationController.cc
|
||||
3rdparty/glfw/deps/glad_gl.c
|
||||
3rdparty/imgui/imgui.cpp
|
||||
3rdparty/imgui/imgui_draw.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/backends/imgui_impl_glfw.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)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "AnimationController.h"
|
||||
#include "SkinnedMesh.h"
|
||||
|
||||
enum class AnimNodeType { Blend, SpeedScale, AnimSampler };
|
||||
|
||||
|
@ -27,6 +28,7 @@ struct AnimNode {
|
|||
bool m_is_time_synced;
|
||||
float m_current_time;
|
||||
float m_anim_duration;
|
||||
SyncTrack m_sync_track;
|
||||
|
||||
virtual void Reset() { m_current_time = 0.f; }
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ AnimationController::AnimationController(SkinnedMesh* skinned_mesh)
|
|||
blend_node->m_name = "Blend0";
|
||||
blend_node->m_input_A = speed_node;
|
||||
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);
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,10 @@ struct AnimationController {
|
|||
// Creates a list of nodes where for node at index i for all inputs holds index > i.
|
||||
void UpdateOrderedNodes();
|
||||
|
||||
void UpdateBlendLogic();
|
||||
|
||||
// Updates all nodes.
|
||||
void Update(float dt);
|
||||
void UpdateTime(float dt);
|
||||
|
||||
// Recursively evaluates all nodes.
|
||||
void Evaluate();
|
||||
|
|
|
@ -7,58 +7,6 @@
|
|||
#include <HandmadeMath.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() {
|
||||
while (m_animations.size() > 0) {
|
||||
|
@ -164,19 +112,7 @@ void SkinnedMesh::EvalAnimation(float in_time) {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -20,6 +20,40 @@
|
|||
#include "ozz/base/maths/soa_transform.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 {
|
||||
virtual ~SkinnedMesh();
|
||||
bool LoadSkeleton(const char* filename);
|
||||
|
@ -39,6 +73,7 @@ struct SkinnedMesh {
|
|||
|
||||
ozz::vector<ozz::animation::Animation*> m_animations;
|
||||
std::vector<std::string> m_animation_names;
|
||||
std::vector<SyncTrack> m_animation_sync_track;
|
||||
ozz::animation::Skeleton m_skeleton;
|
||||
ozz::animation::Animation* m_current_animation;
|
||||
ozz::animation::SamplingCache m_cache;
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -47,6 +47,7 @@ static void draw_imgui(ImDrawData*);
|
|||
#include <memory> // std::unique_ptr, std::make_unique
|
||||
|
||||
#include "AnimationController.h"
|
||||
#include "SkinnedMeshRenderer.h"
|
||||
#include "ozz/animation/runtime/animation.h"
|
||||
#include "ozz/animation/runtime/local_to_model_job.h"
|
||||
#include "ozz/animation/runtime/sampling_job.h"
|
||||
|
@ -418,7 +419,7 @@ int main() {
|
|||
sgl_load_matrix((const float*)&state.camera.mtxProj);
|
||||
sgl_matrix_mode_modelview();
|
||||
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()
|
||||
if (show_imgui_demo_window) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// Created by martin on 16.11.21.
|
||||
//
|
||||
|
||||
#include "catch.hpp"
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue