Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkeletonBasedAnimationSystem.cpp
1#include <Core/Animation/KeyFramedValue.hpp>
2#include <Core/Animation/Skeleton.hpp>
3#include <Core/Asset/FileData.hpp>
4#include <Core/Asset/GeometryData.hpp>
5#include <Core/Asset/HandleData.hpp>
6#include <Core/Math/Math.hpp>
7#include <Core/Resources/Resources.hpp>
8#include <Core/Tasks/Task.hpp>
9#include <Core/Tasks/TaskQueue.hpp>
10#include <Engine/Data/Texture.hpp>
11#include <Engine/Data/TextureManager.hpp>
12#include <Engine/FrameInfo.hpp>
13#include <Engine/RadiumEngine.hpp>
14#include <Engine/Scene/Component.hpp>
15#include <Engine/Scene/SkeletonBasedAnimationSystem.hpp>
16#include <Engine/Scene/SkeletonComponent.hpp>
17#include <Engine/Scene/SkinningComponent.hpp>
18#include <algorithm>
19#include <functional>
20#include <limits>
21#include <map>
22#include <memory>
23#include <optional>
24#include <string>
25#include <utility>
26#include <vector>
27
28namespace Ra {
29namespace Engine {
30namespace Scene {
31class Entity;
32} // namespace Scene
33} // namespace Engine
34} // namespace Ra
35
36using namespace Ra::Core::Animation;
37
38namespace Ra {
39namespace Engine {
40namespace Scene {
41
43 auto resourceDir { Core::Resources::getRadiumResourcesPath() };
44 if ( resourceDir ) {
45 auto* engine = RadiumEngine::getInstance();
46 auto* texMngr = engine->getTextureManager();
47 // Register an entry into the texture manager
48 // load the texture image without OpenGL initialization
49 auto image = texMngr->loadTextureImage( *resourceDir + "/Textures/heatmap.png" );
50 Data::TextureParameters heatMapTexturePamameters = { "Engine:Skinning:weights", {}, image };
51 m_heatMapTextureHandle = texMngr->addTexture( heatMapTexturePamameters );
52 }
53}
54
55SkeletonBasedAnimationSystem::~SkeletonBasedAnimationSystem() {
56 SkeletonComponent::s_boneMesh.reset();
57 SkeletonComponent::s_boneMaterial.reset();
58 SkeletonComponent::s_boneRenderTechnique.reset();
59}
60
61// System Interface
62
64 const FrameInfo& frameInfo ) {
65 for ( auto compEntry : m_components ) {
66 // deal with AnimationComponents
67 if ( auto animComp = dynamic_cast<SkeletonComponent*>( compEntry.second ) ) {
68 if ( !Core::Math::areApproxEqual( m_time, frameInfo.m_animationTime ) ) {
69 // here we update the skeleton w.r.t. the animation
70 auto animFunc =
72 auto animTask = std::make_unique<Core::FunctionTask>(
73 animFunc, "AnimatorTask_" + animComp->getSkeleton()->getName() );
74 taskQueue->registerTask( std::move( animTask ) );
75 }
76 else {
77 // here we update the skeleton w.r.t. the manipulation
78 auto animFunc = std::bind( &SkeletonComponent::updateDisplay, animComp );
79 auto animTask = std::make_unique<Core::FunctionTask>(
80 animFunc, "AnimatorTask_" + animComp->getSkeleton()->getName() );
81 taskQueue->registerTask( std::move( animTask ) );
82 }
83 }
84 // deal with SkinningComponents
85 else if ( auto skinComp = dynamic_cast<SkinningComponent*>( compEntry.second ) ) {
86 auto skinFunc = std::bind( &SkinningComponent::skin, skinComp );
87 auto skinTask = std::make_unique<Core::FunctionTask>(
88 skinFunc, "SkinnerTask_" + skinComp->getMeshName() );
89 auto endFunc = std::bind( &SkinningComponent::endSkinning, skinComp );
90 auto endTask = std::make_unique<Core::FunctionTask>(
91 endFunc, "SkinnerEndTask_" + skinComp->getMeshName() );
92
93 auto skinTaskId = taskQueue->registerTask( std::move( skinTask ) );
94 auto endTaskId = taskQueue->registerTask( std::move( endTask ) );
95 taskQueue->addPendingDependency( "AnimatorTask_" + skinComp->getSkeletonName(),
96 skinTaskId );
97 taskQueue->addDependency( skinTaskId, endTaskId );
98 }
99 }
100
101 m_time = frameInfo.m_animationTime;
102}
103
105 const Core::Asset::FileData* fileData ) {
106 auto skelData = fileData->getHandleData();
107 auto animData = fileData->getAnimationData();
108
109 // deal with AnimationComponents
110 Scalar startTime = std::numeric_limits<Scalar>::max();
111 Scalar endTime = 0;
112 for ( const auto& skel : skelData ) {
113 auto component = new SkeletonComponent( "AC_" + skel->getName(), entity );
114 component->handleSkeletonLoading( skel );
115 component->handleAnimationLoading( animData );
116 auto [s, e] = component->getAnimationTimeInterval();
117 startTime = std::min( startTime, s );
118 endTime = std::max( endTime, e );
119 component->setXray( m_xrayOn );
120 registerComponent( entity, component );
121 }
122 // configure the time on the Engine
123 auto engine = RadiumEngine::getInstance();
124 engine->setStartTime( startTime );
125 engine->setEndTime( endTime );
126
127 // deal with SkinningComponents
128 auto geomData = fileData->getGeometryData();
129 if ( geomData.size() > 0 && skelData.size() > 0 ) {
130 for ( const auto& geom : geomData ) {
131 // look for a skeleton skinning this mesh
132 // warning: there should be at most one such skeleton!
133 auto it = std::find_if( skelData.begin(), skelData.end(), [&geom]( const auto& skel ) {
134 return std::find_if( skel->getBindMeshes().begin(),
135 skel->getBindMeshes().end(),
136 [&geom]( const auto& meshName ) {
137 return meshName == geom->getName();
138 } ) != skel->getBindMeshes().end();
139 } );
140 if ( it != skelData.end() ) {
141 const auto& skel = *it;
142 SkinningComponent* component = new SkinningComponent(
143 "SkC_" + geom->getName(), SkinningComponent::LBS, entity );
144 component->handleSkinDataLoading( skel, geom->getName() );
145 registerComponent( entity, component );
146 }
147 }
148 }
149}
150
151// Skeleton display
152
153void SkeletonBasedAnimationSystem::setXray( bool on ) {
154 m_xrayOn = on;
155 for ( const auto& comp : m_components ) {
156 if ( auto animComp = dynamic_cast<SkeletonComponent*>( comp.second ) ) {
157 animComp->setXray( on );
158 }
159 }
160}
161
162bool SkeletonBasedAnimationSystem::isXrayOn() {
163 return m_xrayOn;
164}
165
166void SkeletonBasedAnimationSystem::toggleSkeleton( const bool status ) {
167 for ( const auto& comp : m_components ) {
168 if ( auto animComp = dynamic_cast<SkeletonComponent*>( comp.second ) ) {
169 animComp->toggleSkeleton( status );
170 }
171 }
172}
173
174} // namespace Scene
175} // namespace Engine
176} // namespace Ra
T bind(T... args)
This class allows tasks to be registered and then executed in parallel on separate threads.
Definition TaskQueue.hpp:50
void addPendingDependency(const std::string &predecessors, TaskId successor)
void addDependency(TaskId predecessor, TaskId successor)
Definition TaskQueue.cpp:84
TaskId registerTask(std::unique_ptr< Task > task)
Definition TaskQueue.cpp:40
An entity is an scene element. It ties together components with a transform.
Definition Entity.hpp:23
void handleAssetLoading(Entity *entity, const Core::Asset::FileData *fileData) override
Loads Skeletons and Animations from a file data into the givn Entity.
void generateTasks(Core::TaskQueue *taskQueue, const FrameInfo &frameInfo) override
Creates a task for each AnimationComponent to update skeleton display.
void update(Scalar time)
Updates the skeleton pose as the pose corresponding to time time.
void updateDisplay()
Updates the skeleton display.
The SkinningComponent class is responsible for applying Geometric Skinning Methods on an animated obj...
void endSkinning()
Update internal data and update the skinned mesh.
void handleSkinDataLoading(const Core::Asset::HandleData *data, const std::string &meshName)
void skin()
Apply the Skinning Method and update the SkinningFrameData.
std::vector< std::pair< const Entity *, Component * > > m_components
List of active components.
Definition System.hpp:103
virtual void registerComponent(const Entity *entity, Component *component)
Definition System.cpp:10
T find_if(T... args)
T max(T... args)
T min(T... args)
T move(T... args)
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type areApproxEqual(T x, T y, T espilonBoostFactor=T(10))
Compare two numbers such that |x-y| < espilon*epsilonBoostFactor.
Definition Math.hpp:42
optional< std::string > getRadiumResourcesPath()
Get the path of Radium internal resources.
Definition Resources.cpp:33
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4
Describes the sampler and image of a texture.
Definition Texture.hpp:99
Structure passed to each system before they fill the task queue.
Definition FrameInfo.hpp:8
Scalar m_animationTime
The current animation time.
Definition FrameInfo.hpp:10