Skip to content

Commit

Permalink
Isolates motion extraction sample code
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaumeblanc committed Mar 29, 2024
1 parent 92d3d38 commit 2868b2b
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 162 deletions.
2 changes: 1 addition & 1 deletion samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ add_subdirectory(blend)
add_subdirectory(foot_ik)
add_subdirectory(look_at)
add_subdirectory(millipede)
add_subdirectory(motion)
add_subdirectory(motion_extraction)
add_subdirectory(multithread)
add_subdirectory(optimize)
add_subdirectory(partial_blend)
Expand Down
45 changes: 0 additions & 45 deletions samples/motion/CMakeLists.txt

This file was deleted.

44 changes: 44 additions & 0 deletions samples/motion_extraction/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

add_custom_command(
DEPENDS $<$<BOOL:${ozz_build_fbx}>:BUILD_DATA>
"${CMAKE_CURRENT_LIST_DIR}/README.md"
"${ozz_media_directory}/bin/pab_skeleton.ozz"
"${ozz_media_directory}/bin/pab_atlas_raw.ozz"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/README.md"
"${CMAKE_CURRENT_BINARY_DIR}/media/skeleton.ozz"
"${CMAKE_CURRENT_BINARY_DIR}/media/raw_animation.ozz"
COMMAND ${CMAKE_COMMAND} -E make_directory media
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_LIST_DIR}/README.md" .
COMMAND ${CMAKE_COMMAND} -E copy "${ozz_media_directory}/bin/pab_skeleton.ozz" "./media/skeleton.ozz"
COMMAND ${CMAKE_COMMAND} -E copy "${ozz_media_directory}/bin/pab_atlas_raw.ozz" "./media/raw_animation.ozz"
VERBATIM)

add_executable(sample_motion_extraction
sample_motion_extraction.cc
"${CMAKE_CURRENT_BINARY_DIR}/README.md"
"${CMAKE_CURRENT_BINARY_DIR}/media/skeleton.ozz"
"${CMAKE_CURRENT_BINARY_DIR}/media/raw_animation.ozz")
target_link_libraries(sample_motion_extraction
sample_framework)
target_copy_shared_libraries(sample_motion_extraction)

set_target_properties(sample_motion_extraction
PROPERTIES FOLDER "samples")

if(EMSCRIPTEN)
# Resource files are embedded to the output file with emscripten
set_target_properties(sample_motion_extraction
PROPERTIES LINK_FLAGS "--embed-file media --embed-file README.md")

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/sample_motion_extraction.html
${CMAKE_CURRENT_BINARY_DIR}/sample_motion_extraction.js
${CMAKE_CURRENT_BINARY_DIR}/sample_motion_extraction.wasm
DESTINATION bin/samples/motion)
else()
install(TARGETS sample_motion_extraction DESTINATION bin/samples/motion_extraction)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/media DESTINATION bin/samples/motion_extraction)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/README.md DESTINATION bin/samples/motion_extraction)
endif(EMSCRIPTEN)

add_test(NAME sample_motion_extraction COMMAND sample_motion_extraction "--max_idle_loops=${ozz_sample_testing_loops}" $<$<BOOL:${ozz_run_tests_headless}>:--norender>)
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -60,63 +60,6 @@ OZZ_OPTIONS_DECLARE_STRING(animation,
"Path to the animation (ozz archive format).",
"media/raw_animation.ozz", false)

struct MotionAccumulator {
void Update(const ozz::math::Transform& _new) {
delta.translation = _new.translation - last.translation;
delta.rotation = Conjugate(last.rotation) * _new.rotation;
delta.scale = _new.scale / last.scale;
current.translation = current.translation + delta.translation;
current.rotation =
Normalize(current.rotation * // Avoid accumulating error that leads to
delta.rotation); // non-normalized quaternions.

current.scale = current.scale * delta.scale;

last = _new;
}

void Reset(const ozz::math::Transform& _new) {
origin = current;
delta = ozz::math::Transform::identity();
last = _new;
}

ozz::math::Transform origin = ozz::math::Transform::identity();
ozz::math::Transform last = ozz::math::Transform::identity();
ozz::math::Transform current = ozz::math::Transform::identity();
ozz::math::Transform delta = ozz::math::Transform::identity();
};

struct MotionTracks {
ozz::animation::Float3Track position;
ozz::animation::QuaternionTrack rotation;
};

bool SampleMotion(const MotionTracks& _tracks, float _ratio,
ozz::math::Transform* _transform) {
// Get position from motion track
ozz::animation::Float3TrackSamplingJob position_sampler;
position_sampler.track = &_tracks.position;
position_sampler.result = &_transform->translation;
position_sampler.ratio = _ratio;
if (!position_sampler.Run()) {
return false;
}

// Get rotation from motion track
ozz::animation::QuaternionTrackSamplingJob rotation_sampler;
rotation_sampler.track = &_tracks.rotation;
rotation_sampler.result = &_transform->rotation;
rotation_sampler.ratio = _ratio;
if (!rotation_sampler.Run()) {
return false;
}

_transform->scale = ozz::math::Float3::one();

return true;
}

class MotionSampleApplication : public ozz::sample::Application {
public:
MotionSampleApplication() {}
Expand All @@ -125,45 +68,43 @@ class MotionSampleApplication : public ozz::sample::Application {
// Updates current animation time and skeleton pose.
virtual bool OnUpdate(float _dt, float) {
// Updates current animation time.
int loops = controller_.Update(animation_, _dt);

ozz::math::Transform motion_transform;
for (; loops; loops > 0 ? --loops : ++loops) {
if (!SampleMotion(motion_tracks_, loops > 0 ? 1.f : 0.f,
&motion_transform)) {
controller_.Update(animation_, _dt);

// Reset character transform
transform_ = ozz::math::Float4x4::identity();

// Get position from motion track
if (apply_motion_position_) {
ozz::math::Float3 position;
ozz::animation::Float3TrackSamplingJob position_sampler;
position_sampler.track = &position_track_;
position_sampler.result = &position;
position_sampler.ratio = controller_.time_ratio();
if (!position_sampler.Run()) {
return false;
}
motion_accumulator_.Update(motion_transform);

if (!SampleMotion(motion_tracks_, loops > 0 ? 0.f : 1.f,
&motion_transform)) {
return false;
}
motion_accumulator_.Reset(motion_transform);
}

if (!SampleMotion(motion_tracks_, controller_.time_ratio(),
&motion_transform)) {
return false;
transform_ = // Apply motion position to character transform
transform_ * ozz::math::Float4x4::Translation(
ozz::math::simd_float4::Load3PtrU(&position.x));
}
motion_accumulator_.Update(motion_transform);

if (!apply_motion_position_) {
}
// Get rotation from motion track
if (apply_motion_rotation_) {
ozz::math::Quaternion rotation;
ozz::animation::QuaternionTrackSamplingJob rotation_sampler;
rotation_sampler.track = &rotation_track_;
rotation_sampler.result = &rotation;
rotation_sampler.ratio = controller_.time_ratio();
if (!rotation_sampler.Run()) {
return false;
}

if (!apply_motion_rotation_) {
transform_ = // Apply motion rotation to character transform
transform_ * ozz::math::Float4x4::FromQuaternion(
ozz::math::simd_float4::LoadPtrU(&rotation.x));
}

motion_accumulator_.Update(motion_transform);

transform_ = ozz::math::Float4x4::FromAffine(
ozz::math::simd_float4::Load3PtrU(
&motion_accumulator_.current.translation.x),
ozz::math::simd_float4::LoadPtrU(
&motion_accumulator_.current.rotation.x),
ozz::math::simd_float4::Load3PtrU(
&motion_accumulator_.current.scale.x));

// Samples optimized animation at t = animation_time_.
ozz::animation::SamplingJob sampling_job;
sampling_job.animation = &animation_;
Expand Down Expand Up @@ -197,38 +138,26 @@ class MotionSampleApplication : public ozz::sample::Application {
ozz::math::Float3(.3f, 1.8f, .2f)),
transform_, ozz::sample::kWhite);

const auto origin = ozz::math::Float4x4::FromAffine(
ozz::math::simd_float4::Load3PtrU(
&motion_accumulator_.origin.translation.x),
ozz::math::simd_float4::LoadPtrU(
&motion_accumulator_.origin.rotation.x),
ozz::math::simd_float4::Load3PtrU(&motion_accumulator_.origin.scale.x));
const float at = controller_.time_ratio();
const float step = 1.f / (animation_.duration() * 30.f);
success &= DrawMotion(_renderer, motion_tracks_.position, 0.f, at, step,
ozz::sample::kGreen, origin);
success &= DrawMotion(_renderer, motion_tracks_.position, at, 1.f, step,
ozz::sample::kRed, origin);
success &= DrawMotion(_renderer, position_track_, 0.f, at, step,
ozz::sample::kGreen, ozz::math::Float4x4::identity());
success &= DrawMotion(_renderer, position_track_, at, 1.f, step,
ozz::sample::kRed, ozz::math::Float4x4::identity());
return success;
}

bool ExtractMotion() {
// Position
// Raw motion tracks extraction
ozz::animation::offline::RawFloat3Track raw_motion_position;
raw_motion_position.name = "motion_position";

// Rotation
ozz::animation::offline::RawQuaternionTrack raw_motion_rotation;
raw_motion_rotation.name = "motion_rotation";

ozz::animation::offline::RawAnimation baked_animation;
if (!motion_extractor_(raw_animation_, skeleton_, &raw_motion_position,
&raw_motion_rotation, &baked_animation)) {
return false;
}

// Track optimization and runtime bulding
{
{ // Track optimization and runtime building
ozz::animation::offline::TrackOptimizer optimizer;
ozz::animation::offline::RawFloat3Track raw_track_position_opt;
if (!optimizer(raw_motion_position, &raw_track_position_opt)) {
Expand All @@ -249,12 +178,11 @@ class MotionSampleApplication : public ozz::sample::Application {
if (!motion_p || !motion_r) {
return false;
}
motion_tracks_.position = std::move(*motion_p);
motion_tracks_.rotation = std::move(*motion_r);
position_track_ = std::move(*motion_p);
rotation_track_ = std::move(*motion_r);
}

// Track optimization and runtime bulding
{
{ // Track optimization and runtime building
ozz::animation::offline::RawAnimation baked_animation_opt;
ozz::animation::offline::AnimationOptimizer optimizer;
if (!optimizer(baked_animation, skeleton_, &baked_animation_opt)) {
Expand Down Expand Up @@ -423,7 +351,6 @@ class MotionSampleApplication : public ozz::sample::Application {
ozz::sample::PlaybackController controller_;

// Store extractor to expose parameters to GUI.
// In a real use case, no need to store it.
ozz::animation::offline::MotionExtractor motion_extractor_;

// Runtime skeleton.
Expand All @@ -435,15 +362,13 @@ class MotionSampleApplication : public ozz::sample::Application {
// Runtime animation.
ozz::animation::Animation animation_;

// Runtime motion track
MotionTracks motion_tracks_;
// Runtime motion tracks.
ozz::animation::Float3Track position_track_;
ozz::animation::QuaternionTrack rotation_track_;

// Sampling context.
ozz::animation::SamplingJob::Context context_;

// Character motion accumulator.
MotionAccumulator motion_accumulator_;

// Character transform.
ozz::math::Float4x4 transform_;

Expand All @@ -453,6 +378,7 @@ class MotionSampleApplication : public ozz::sample::Application {
// Buffer of model space matrices.
ozz::vector<ozz::math::Float4x4> models_;

// GUI options to apply root motion.
bool apply_motion_position_ = true;
bool apply_motion_rotation_ = true;
};
Expand Down

0 comments on commit 2868b2b

Please sign in to comment.