Wrapped animation into SkinnedMesh object.
parent
886a510fcd
commit
551bcca478
|
@ -44,6 +44,8 @@ target_link_libraries(AnimTestbed glfw ozz_base ozz_geometry ozz_animation ${OPE
|
||||||
target_sources(AnimTestbed PRIVATE
|
target_sources(AnimTestbed PRIVATE
|
||||||
src/main.cc
|
src/main.cc
|
||||||
src/Camera.c
|
src/Camera.c
|
||||||
|
src/SkinnedMesh.cc
|
||||||
|
src/SkinnedMesh.h
|
||||||
3rdparty/glfw/deps/glad_gl.c
|
3rdparty/glfw/deps/glad_gl.c
|
||||||
3rdparty/imgui/imgui.cpp
|
3rdparty/imgui/imgui.cpp
|
||||||
3rdparty/imgui/imgui_draw.cpp
|
3rdparty/imgui/imgui_draw.cpp
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
//
|
||||||
|
// Created by martin on 12.11.21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SkinnedMesh.h"
|
||||||
|
|
||||||
|
#include <HandmadeMath.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <util/sokol_gl.h>
|
||||||
|
|
||||||
|
#include "sokol_gfx.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) {
|
||||||
|
ozz::animation::Animation* animation_ptr =
|
||||||
|
m_animations[m_animations.size() - 1];
|
||||||
|
delete animation_ptr;
|
||||||
|
m_animations.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkinnedMesh::LoadSkeleton(const char* filename) {
|
||||||
|
// const char* skeleton_file = "../media/skeleton.ozz";
|
||||||
|
const char* skeleton_file = "../media/MixamoYBot-skeleton.ozz";
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
ozz::log::Out() << "Loading skeleton archive " << filename << "."
|
||||||
|
<< std::endl;
|
||||||
|
ozz::io::File file(filename, "rb");
|
||||||
|
if (!file.opened()) {
|
||||||
|
ozz::log::Err() << "Failed to open skeleton file " << filename << "."
|
||||||
|
<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ozz::io::IArchive archive(&file);
|
||||||
|
if (!archive.TestTag<ozz::animation::Skeleton>()) {
|
||||||
|
ozz::log::Err() << "Failed to load skeleton instance from file " << filename
|
||||||
|
<< "." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the tag is validated, reading cannot fail.
|
||||||
|
archive >> m_skeleton;
|
||||||
|
|
||||||
|
const int num_soa_joints = m_skeleton.num_soa_joints();
|
||||||
|
const int num_joints = m_skeleton.num_joints();
|
||||||
|
m_local_matrices.resize(num_soa_joints);
|
||||||
|
m_model_matrices.resize(num_joints);
|
||||||
|
m_cache.Resize(num_joints);
|
||||||
|
std::cout << "Successfully loaded " << skeleton_file
|
||||||
|
<< " (soa: " << num_soa_joints << ", joints: " << num_joints << ")"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkinnedMesh::LoadAnimation(const char* filename) {
|
||||||
|
ozz::animation::Animation* animation_ptr = new ozz::animation::Animation();
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
ozz::log::Out() << "Loading animation archive: " << filename << "."
|
||||||
|
<< std::endl;
|
||||||
|
ozz::io::File file(filename, "rb");
|
||||||
|
if (!file.opened()) {
|
||||||
|
ozz::log::Err() << "Failed to open animation file " << filename << "."
|
||||||
|
<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ozz::io::IArchive archive(&file);
|
||||||
|
if (!archive.TestTag<ozz::animation::Animation>()) {
|
||||||
|
ozz::log::Err() << "Failed to load animation instance from file "
|
||||||
|
<< filename << "." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the tag is validated, reading cannot fail.
|
||||||
|
archive >> *animation_ptr;
|
||||||
|
|
||||||
|
m_animations.push_back(animation_ptr);
|
||||||
|
m_animation_names.push_back(filename);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SkinnedMesh::SetCurrentAnimation(int index)
|
||||||
|
{
|
||||||
|
if (index <= 0 || index >= m_animations.size()) {
|
||||||
|
ozz::log::Err() << "Invalid animation index " << index << " valid range: ["
|
||||||
|
<< 0 << ", " << m_animations.size() << "]'" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_current_animation = m_animations[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//bool LoadMesh (const char* filename);
|
||||||
|
|
||||||
|
void SkinnedMesh::EvalAnimation(float in_time) {
|
||||||
|
const float anim_duration = m_current_animation->duration();
|
||||||
|
float anim_ratio = fmodf((float)in_time / anim_duration, 1.0f);
|
||||||
|
|
||||||
|
// sample animation
|
||||||
|
ozz::animation::SamplingJob sampling_job;
|
||||||
|
sampling_job.animation = m_current_animation;
|
||||||
|
sampling_job.cache = &m_cache;
|
||||||
|
sampling_job.ratio = anim_ratio;
|
||||||
|
sampling_job.output = make_span(m_local_matrices);
|
||||||
|
sampling_job.Run();
|
||||||
|
|
||||||
|
// convert joint matrices from local to model space
|
||||||
|
ozz::animation::LocalToModelJob ltm_job;
|
||||||
|
ltm_job.skeleton = &m_skeleton;
|
||||||
|
ltm_job.input = make_span(m_local_matrices);
|
||||||
|
ltm_job.output = make_span(m_model_matrices);
|
||||||
|
ltm_job.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
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::DrawUi() {
|
||||||
|
ImGui::Begin("SkinnedMesh");
|
||||||
|
|
||||||
|
ImGui::Checkbox("Time override", &state.time.anim_ratio_ui_override);
|
||||||
|
|
||||||
|
// const float anim_duration = state.ozz->animation.duration();
|
||||||
|
// if (!state.time.anim_ratio_ui_override) {
|
||||||
|
// state.time.anim_ratio =
|
||||||
|
// fmodf((float)state.time.absolute / anim_duration, 1.0f);
|
||||||
|
// }
|
||||||
|
// ImGui::SliderFloat("Time", &state.time.anim_ratio, 0.f, 1.f);
|
||||||
|
|
||||||
|
ImGui::Text(
|
||||||
|
"Application average %.3f ms/frame (%.1f FPS)",
|
||||||
|
1000.0f / ImGui::GetIO().Framerate,
|
||||||
|
ImGui::GetIO().Framerate);
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// Created by martin on 12.11.21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ANIMTESTBED_SKINNEDMESH_H
|
||||||
|
#define ANIMTESTBED_SKINNEDMESH_H
|
||||||
|
|
||||||
|
// ozz-animation headers
|
||||||
|
#include <cmath> // fmodf
|
||||||
|
#include <memory> // std::unique_ptr, std::make_unique
|
||||||
|
|
||||||
|
#include "ozz/animation/runtime/animation.h"
|
||||||
|
#include "ozz/animation/runtime/local_to_model_job.h"
|
||||||
|
#include "ozz/animation/runtime/sampling_job.h"
|
||||||
|
#include "ozz/animation/runtime/skeleton.h"
|
||||||
|
#include "ozz/base/containers/vector.h"
|
||||||
|
#include "ozz/base/io/archive.h"
|
||||||
|
#include "ozz/base/io/stream.h"
|
||||||
|
#include "ozz/base/log.h"
|
||||||
|
#include "ozz/base/maths/soa_transform.h"
|
||||||
|
#include "ozz/base/maths/vec_float.h"
|
||||||
|
|
||||||
|
struct SkinnedMesh {
|
||||||
|
virtual ~SkinnedMesh();
|
||||||
|
bool LoadSkeleton(const char* filename);
|
||||||
|
bool LoadAnimation(const char* filename);
|
||||||
|
//bool LoadMesh (const char* filename);
|
||||||
|
|
||||||
|
void SetCurrentAnimation(int index);
|
||||||
|
const ozz::animation::Animation* GetCurrentAnimation() {return m_current_animation; };
|
||||||
|
float GetCurrentAnimationDuration() {return m_current_animation->duration(); };
|
||||||
|
|
||||||
|
void EvalAnimation(float in_time);
|
||||||
|
void DrawSkeleton();
|
||||||
|
void DrawJoint(int joint_index, int parent_joint_index);
|
||||||
|
|
||||||
|
void DrawUi();
|
||||||
|
// void DrawSkinnedMesh();
|
||||||
|
|
||||||
|
ozz::vector<ozz::animation::Animation*> m_animations;
|
||||||
|
std::vector<std::string> m_animation_names;
|
||||||
|
ozz::animation::Skeleton m_skeleton;
|
||||||
|
ozz::animation::Animation* m_current_animation;
|
||||||
|
ozz::animation::SamplingCache m_cache;
|
||||||
|
ozz::vector<ozz::math::SoaTransform> m_local_matrices;
|
||||||
|
ozz::vector<ozz::math::Float4x4> m_model_matrices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //ANIMTESTBED_SKINNEDMESH_H
|
148
src/main.cc
148
src/main.cc
|
@ -15,6 +15,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
#include "SkinnedMesh.h"
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
const int Width = 1024;
|
const int Width = 1024;
|
||||||
|
@ -109,10 +110,6 @@ ControlMode gControlMode = ControlMode::ControlModeNone;
|
||||||
static uint8_t skel_data_buffer[4 * 1024];
|
static uint8_t skel_data_buffer[4 * 1024];
|
||||||
static uint8_t anim_data_buffer[32 * 1024];
|
static uint8_t anim_data_buffer[32 * 1024];
|
||||||
|
|
||||||
static void load_skeleton(void);
|
|
||||||
static void load_animation(void);
|
|
||||||
static void eval_animation(void);
|
|
||||||
static void draw_skeleton(void);
|
|
||||||
static void draw_grid(void);
|
static void draw_grid(void);
|
||||||
static void draw_ui(void);
|
static void draw_ui(void);
|
||||||
// static void skeleton_data_loaded(const sfetch_response_t* response);
|
// static void skeleton_data_loaded(const sfetch_response_t* response);
|
||||||
|
@ -196,7 +193,16 @@ int main() {
|
||||||
sgldesc.sample_count = 0;
|
sgldesc.sample_count = 0;
|
||||||
sgl_setup(&sgldesc);
|
sgl_setup(&sgldesc);
|
||||||
|
|
||||||
state.ozz = std::make_unique<ozz_t>();
|
printf ("default allocator: 0x%p\n", (void*)ozz::memory::default_allocator());
|
||||||
|
SkinnedMesh gSkinnedMesh;
|
||||||
|
gSkinnedMesh.LoadSkeleton("../media/MixamoYBot-skeleton.ozz");
|
||||||
|
gSkinnedMesh.LoadAnimation("../media/Idle-loop.ozz");
|
||||||
|
gSkinnedMesh.LoadAnimation("../media/Walking-loop.ozz");
|
||||||
|
gSkinnedMesh.LoadAnimation("../media/RunningSlow-loop.ozz");
|
||||||
|
gSkinnedMesh.LoadAnimation("../media/RunningFast-loop.ozz");
|
||||||
|
gSkinnedMesh.SetCurrentAnimation(0);
|
||||||
|
|
||||||
|
// state.ozz = std::make_unique<ozz_t>();
|
||||||
state.time.factor = 1.0f;
|
state.time.factor = 1.0f;
|
||||||
|
|
||||||
Camera_Init(&state.camera);
|
Camera_Init(&state.camera);
|
||||||
|
@ -303,9 +309,6 @@ int main() {
|
||||||
pass_action.colors[0].action = SG_ACTION_CLEAR;
|
pass_action.colors[0].action = SG_ACTION_CLEAR;
|
||||||
pass_action.colors[0].value = {0.1f, 0.1f, 0.1f, 1.0f};
|
pass_action.colors[0].value = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||||
|
|
||||||
load_skeleton();
|
|
||||||
load_animation();
|
|
||||||
|
|
||||||
// draw loop
|
// draw loop
|
||||||
while (!glfwWindowShouldClose(w)) {
|
while (!glfwWindowShouldClose(w)) {
|
||||||
state.time.frame = stm_sec(
|
state.time.frame = stm_sec(
|
||||||
|
@ -395,8 +398,18 @@ int main() {
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
frame();
|
draw_grid();
|
||||||
draw_ui();
|
gSkinnedMesh.DrawUi();
|
||||||
|
|
||||||
|
state.time.absolute += state.time.frame * state.time.factor;
|
||||||
|
gSkinnedMesh.EvalAnimation(state.time.absolute);
|
||||||
|
|
||||||
|
sgl_defaults();
|
||||||
|
sgl_matrix_mode_projection();
|
||||||
|
sgl_load_matrix((const float*)&state.camera.mtxProj);
|
||||||
|
sgl_matrix_mode_modelview();
|
||||||
|
sgl_load_matrix((const float*)&state.camera.mtxView);
|
||||||
|
gSkinnedMesh.DrawSkeleton();
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -416,7 +429,7 @@ int main() {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.ozz = nullptr;
|
// state.ozz = nullptr;
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
@ -505,64 +518,6 @@ static void load_animation(void) {
|
||||||
std::cout << "Successfully loade " << anim_file << std::endl;
|
std::cout << "Successfully loade " << anim_file << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_ui() {
|
|
||||||
// 1. Show a simple window
|
|
||||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
|
||||||
ImGui::Begin("Animation");
|
|
||||||
|
|
||||||
ImGui::Checkbox("Time override", &state.time.anim_ratio_ui_override);
|
|
||||||
|
|
||||||
const float anim_duration = state.ozz->animation.duration();
|
|
||||||
if (!state.time.anim_ratio_ui_override) {
|
|
||||||
state.time.anim_ratio =
|
|
||||||
fmodf((float)state.time.absolute / anim_duration, 1.0f);
|
|
||||||
}
|
|
||||||
ImGui::SliderFloat("Time", &state.time.anim_ratio, 0.f, 1.f);
|
|
||||||
|
|
||||||
ImGui::Text(
|
|
||||||
"Application average %.3f ms/frame (%.1f FPS)",
|
|
||||||
1000.0f / ImGui::GetIO().Framerate,
|
|
||||||
ImGui::GetIO().Framerate);
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void frame() {
|
|
||||||
draw_grid();
|
|
||||||
|
|
||||||
if (state.loaded.animation && state.loaded.skeleton) {
|
|
||||||
if (!state.time.paused) {
|
|
||||||
state.time.absolute += state.time.frame * state.time.factor;
|
|
||||||
}
|
|
||||||
eval_animation();
|
|
||||||
draw_skeleton();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void eval_animation() {
|
|
||||||
// convert current time to animation ration (0.0 .. 1.0)
|
|
||||||
const float anim_duration = state.ozz->animation.duration();
|
|
||||||
if (!state.time.anim_ratio_ui_override) {
|
|
||||||
state.time.anim_ratio =
|
|
||||||
fmodf((float)state.time.absolute / anim_duration, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sample animation
|
|
||||||
ozz::animation::SamplingJob sampling_job;
|
|
||||||
sampling_job.animation = &state.ozz->animation;
|
|
||||||
sampling_job.cache = &state.ozz->cache;
|
|
||||||
sampling_job.ratio = state.time.anim_ratio;
|
|
||||||
sampling_job.output = make_span(state.ozz->local_matrices);
|
|
||||||
sampling_job.Run();
|
|
||||||
|
|
||||||
// convert joint matrices from local to model space
|
|
||||||
ozz::animation::LocalToModelJob ltm_job;
|
|
||||||
ltm_job.skeleton = &state.ozz->skeleton;
|
|
||||||
ltm_job.input = make_span(state.ozz->local_matrices);
|
|
||||||
ltm_job.output = make_span(state.ozz->model_matrices);
|
|
||||||
ltm_job.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_vec(const ozz::math::SimdFloat4& vec) {
|
static void draw_vec(const ozz::math::SimdFloat4& vec) {
|
||||||
sgl_v3f(ozz::math::GetX(vec), ozz::math::GetY(vec), ozz::math::GetZ(vec));
|
sgl_v3f(ozz::math::GetX(vec), ozz::math::GetY(vec), ozz::math::GetZ(vec));
|
||||||
}
|
}
|
||||||
|
@ -574,44 +529,6 @@ static void draw_line(
|
||||||
draw_vec(v1);
|
draw_vec(v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this draws a wireframe 3d rhombus between the current and parent joints
|
|
||||||
static void draw_joint(int joint_index, int parent_joint_index) {
|
|
||||||
if (parent_joint_index < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace ozz::math;
|
|
||||||
|
|
||||||
const Float4x4& m0 = state.ozz->model_matrices[joint_index];
|
|
||||||
const Float4x4& m1 = state.ozz->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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_grid(void) {
|
static void draw_grid(void) {
|
||||||
sgl_defaults();
|
sgl_defaults();
|
||||||
|
@ -649,23 +566,6 @@ static void draw_grid(void) {
|
||||||
sgl_end();
|
sgl_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_skeleton(void) {
|
|
||||||
sgl_defaults();
|
|
||||||
sgl_matrix_mode_projection();
|
|
||||||
sgl_load_matrix((const float*)&state.camera.mtxProj);
|
|
||||||
sgl_matrix_mode_modelview();
|
|
||||||
hmm_mat4 scale_mat = HMM_Scale(HMM_Vec3(0.01f, 0.01f, 0.01f));
|
|
||||||
sgl_load_matrix((const float*)&state.camera.mtxView);
|
|
||||||
sgl_mult_matrix((const float*)&scale_mat);
|
|
||||||
|
|
||||||
const int num_joints = state.ozz->skeleton.num_joints();
|
|
||||||
ozz::span<const int16_t> joint_parents = state.ozz->skeleton.joint_parents();
|
|
||||||
sgl_begin_lines();
|
|
||||||
for (int joint_index = 0; joint_index < num_joints; joint_index++) {
|
|
||||||
draw_joint(joint_index, joint_parents[joint_index]);
|
|
||||||
}
|
|
||||||
sgl_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw ImGui draw lists via sokol-gfx
|
// draw ImGui draw lists via sokol-gfx
|
||||||
void draw_imgui(ImDrawData* draw_data) {
|
void draw_imgui(ImDrawData* draw_data) {
|
||||||
|
|
Loading…
Reference in New Issue