2021-11-11 21:22:24 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
// //
|
|
|
|
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
|
|
|
// and distributed under the MIT License (MIT). //
|
|
|
|
// //
|
|
|
|
// Copyright (c) Guillaume Blanc //
|
|
|
|
// //
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a //
|
|
|
|
// copy of this software and associated documentation files (the "Software"), //
|
|
|
|
// to deal in the Software without restriction, including without limitation //
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the //
|
|
|
|
// Software is furnished to do so, subject to the following conditions: //
|
|
|
|
// //
|
|
|
|
// The above copyright notice and this permission notice shall be included in //
|
|
|
|
// all copies or substantial portions of the Software. //
|
|
|
|
// //
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
|
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
|
|
|
// DEALINGS IN THE SOFTWARE. //
|
|
|
|
// //
|
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2023-03-26 11:44:29 +02:00
|
|
|
#include "framework/application.h"
|
|
|
|
#include "framework/imgui.h"
|
|
|
|
#include "framework/renderer.h"
|
|
|
|
#include "framework/utils.h"
|
2021-11-11 21:22:24 +01:00
|
|
|
#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/log.h"
|
|
|
|
#include "ozz/base/maths/box.h"
|
|
|
|
#include "ozz/base/maths/simd_math.h"
|
|
|
|
#include "ozz/base/maths/soa_transform.h"
|
|
|
|
#include "ozz/base/maths/vec_float.h"
|
|
|
|
#include "ozz/options/options.h"
|
|
|
|
|
|
|
|
// Skeleton archive can be specified as an option.
|
|
|
|
OZZ_OPTIONS_DECLARE_STRING(skeleton,
|
|
|
|
"Path to the skeleton (ozz archive format).",
|
|
|
|
"media/skeleton.ozz", false)
|
|
|
|
|
|
|
|
// Animation archive can be specified as an option.
|
|
|
|
OZZ_OPTIONS_DECLARE_STRING(animation,
|
|
|
|
"Path to the animation (ozz archive format).",
|
|
|
|
"media/animation.ozz", false)
|
|
|
|
|
|
|
|
class BakedSampleApplication : public ozz::sample::Application {
|
|
|
|
public:
|
|
|
|
BakedSampleApplication() : camera_index_(-1) {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Updates current animation time and skeleton pose.
|
|
|
|
virtual bool OnUpdate(float _dt, float) {
|
|
|
|
// Updates current animation time.
|
|
|
|
controller_.Update(animation_, _dt);
|
|
|
|
|
|
|
|
// Samples optimized animation at t = animation_time_.
|
|
|
|
ozz::animation::SamplingJob sampling_job;
|
|
|
|
sampling_job.animation = &animation_;
|
2023-03-26 11:44:29 +02:00
|
|
|
sampling_job.context = &context_;
|
2021-11-11 21:22:24 +01:00
|
|
|
sampling_job.ratio = controller_.time_ratio();
|
|
|
|
sampling_job.output = make_span(locals_);
|
|
|
|
if (!sampling_job.Run()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Converts from local space to model space matrices.
|
|
|
|
ozz::animation::LocalToModelJob ltm_job;
|
|
|
|
ltm_job.skeleton = &skeleton_;
|
|
|
|
ltm_job.input = make_span(locals_);
|
|
|
|
ltm_job.output = make_span(models_);
|
|
|
|
if (!ltm_job.Run()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool OnInitialize() {
|
|
|
|
// Reading skeleton.
|
|
|
|
if (!ozz::sample::LoadSkeleton(OPTIONS_skeleton, &skeleton_)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reading animation.
|
|
|
|
if (!ozz::sample::LoadAnimation(OPTIONS_animation, &animation_)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocates runtime buffers.
|
|
|
|
const int num_joints = skeleton_.num_joints();
|
|
|
|
const int num_soa_joints = skeleton_.num_soa_joints();
|
|
|
|
locals_.resize(num_soa_joints);
|
|
|
|
models_.resize(num_joints);
|
|
|
|
|
2023-03-26 11:44:29 +02:00
|
|
|
// Allocates a context that matches animation requirements.
|
|
|
|
context_.Resize(num_joints);
|
2021-11-11 21:22:24 +01:00
|
|
|
|
|
|
|
// Look for a "camera" joint.
|
|
|
|
for (int i = 0; i < num_joints; i++) {
|
|
|
|
if (std::strstr(skeleton_.joint_names()[i], "camera")) {
|
|
|
|
camera_index_ = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void OnDestroy() {}
|
|
|
|
|
|
|
|
// Samples animation, transforms to model space and renders.
|
|
|
|
virtual bool OnDisplay(ozz::sample::Renderer* _renderer) {
|
|
|
|
// Render a 1m size boxes for every joint. The scale of each box come from
|
|
|
|
// the animation.
|
|
|
|
const float size = .5f;
|
|
|
|
const ozz::math::Box box(ozz::math::Float3(-size), ozz::math::Float3(size));
|
|
|
|
return _renderer->DrawBoxShaded(box, make_span(models_),
|
|
|
|
ozz::sample::kWhite);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool OnGui(ozz::sample::ImGui* _im_gui) {
|
|
|
|
// Exposes animation runtime playback controls.
|
|
|
|
{
|
|
|
|
static bool open = true;
|
|
|
|
ozz::sample::ImGui::OpenClose oc(_im_gui, "Animation control", &open);
|
|
|
|
if (open) {
|
|
|
|
controller_.OnGui(animation_, _im_gui);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool GetCameraOverride(ozz::math::Float4x4* _transform) const {
|
|
|
|
// Early out if no camera joint was found.
|
|
|
|
if (camera_index_ == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*_transform = models_[camera_index_];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void GetSceneBounds(ozz::math::Box* _bound) const {
|
|
|
|
ozz::sample::ComputePostureBounds(make_span(models_), _bound);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Playback animation controller. This is a utility class that helps with
|
|
|
|
// controlling animation playback time.
|
|
|
|
ozz::sample::PlaybackController controller_;
|
|
|
|
|
|
|
|
// Runtime skeleton.
|
|
|
|
ozz::animation::Skeleton skeleton_;
|
|
|
|
|
|
|
|
// Runtime animation.
|
|
|
|
ozz::animation::Animation animation_;
|
|
|
|
|
2023-03-26 11:44:29 +02:00
|
|
|
// Sampling context.
|
|
|
|
ozz::animation::SamplingJob::Context context_;
|
2021-11-11 21:22:24 +01:00
|
|
|
|
|
|
|
// Buffer of local transforms as sampled from animation_.
|
|
|
|
ozz::vector<ozz::math::SoaTransform> locals_;
|
|
|
|
|
|
|
|
// Buffer of model space matrices.
|
|
|
|
ozz::vector<ozz::math::Float4x4> models_;
|
|
|
|
|
|
|
|
// Camera joint index. -1 if not found.
|
|
|
|
int camera_index_;
|
|
|
|
};
|
|
|
|
|
|
|
|
int main(int _argc, const char** _argv) {
|
|
|
|
const char* title = "Ozz-animation sample: Baked rigid bodies";
|
|
|
|
return BakedSampleApplication().Run(_argc, _argv, "1.0", title);
|
|
|
|
}
|