1 #include <Engine/Scene/SkeletonBasedAnimationSystem.hpp>
5 #include <Core/Asset/FileData.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>
11 #include <Engine/Data/Texture.hpp>
12 #include <Engine/Data/TextureManager.hpp>
13 #include <Engine/FrameInfo.hpp>
14 #include <Engine/RadiumEngine.hpp>
15 #include <Engine/Scene/SkeletonComponent.hpp>
16 #include <Engine/Scene/SkinningComponent.hpp>
18 using namespace Ra::Core::Animation;
24 SkeletonBasedAnimationSystem::SkeletonBasedAnimationSystem() :
System(), m_xrayOn( false ) {
27 auto* engine = RadiumEngine::getInstance();
28 auto* texMngr = engine->getTextureManager();
30 auto& heatmapData = texMngr->addTexture(
"Engine:Skinning:weights", 1, 128,
nullptr );
32 heatmapData.name = *resourceDir +
"/Textures/heatmap.png";
33 texMngr->loadTextureImage( heatmapData );
35 heatmapData.name =
"Engine:Skinning:weights";
39 SkeletonBasedAnimationSystem::~SkeletonBasedAnimationSystem() {
40 SkeletonComponent::s_boneMesh.reset();
41 SkeletonComponent::s_boneMaterial.reset();
42 SkeletonComponent::s_boneRenderTechnique.reset();
56 auto animTask = std::make_unique<Core::FunctionTask>(
57 animFunc,
"AnimatorTask_" + animComp->getSkeleton()->getName() );
63 auto animTask = std::make_unique<Core::FunctionTask>(
64 animFunc,
"AnimatorTask_" + animComp->getSkeleton()->getName() );
69 else if (
auto skinComp =
dynamic_cast<SkinningComponent*
>( compEntry.second ) ) {
71 auto skinTask = std::make_unique<Core::FunctionTask>(
72 skinFunc,
"SkinnerTask_" + skinComp->getMeshName() );
74 auto endTask = std::make_unique<Core::FunctionTask>(
75 endFunc,
"SkinnerEndTask_" + skinComp->getMeshName() );
77 auto skinTaskId = taskQueue->
registerTask( std::move( skinTask ) );
78 auto endTaskId = taskQueue->
registerTask( std::move( endTask ) );
89 const Core::Asset::FileData* fileData ) {
90 auto skelData = fileData->getHandleData();
91 auto animData = fileData->getAnimationData();
94 Scalar startTime = std::numeric_limits<Scalar>::max();
96 for (
const auto& skel : skelData ) {
98 component->handleSkeletonLoading( skel );
99 component->handleAnimationLoading( animData );
100 auto [s, e] = component->getAnimationTimeInterval();
101 startTime = std::min( startTime, s );
102 endTime = std::max( endTime, e );
103 component->setXray( m_xrayOn );
107 auto engine = RadiumEngine::getInstance();
108 engine->setStartTime( startTime );
109 engine->setEndTime( endTime );
112 auto geomData = fileData->getGeometryData();
113 if ( geomData.size() > 0 && skelData.size() > 0 ) {
114 for (
const auto& geom : geomData ) {
117 auto it = std::find_if( skelData.begin(), skelData.end(), [&geom](
const auto& skel ) {
118 return std::find_if( skel->getBindMeshes().begin(),
119 skel->getBindMeshes().end(),
120 [&geom]( const auto& meshName ) {
121 return meshName == geom->getName();
122 } ) != skel->getBindMeshes().end();
124 if ( it != skelData.end() ) {
125 const auto& skel = *it;
137 void SkeletonBasedAnimationSystem::setXray(
bool on ) {
139 for (
const auto& comp : m_components ) {
141 animComp->setXray( on );
146 bool SkeletonBasedAnimationSystem::isXrayOn() {
150 void SkeletonBasedAnimationSystem::toggleSkeleton(
const bool status ) {
151 for (
const auto& comp : m_components ) {
153 animComp->toggleSkeleton( status );
void addPendingDependency(const std::string &predecessors, TaskId successor)
void addDependency(TaskId predecessor, TaskId successor)
TaskId registerTask(std::unique_ptr< Task > task)
An entity is an scene element. It ties together components with a transform.
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)
@ LBS
Linear Blend Skinning.
void skin()
Apply the Skinning Method and update the SkinningFrameData.
std::vector< std::pair< const Entity *, Component * > > m_components
List of active components.
virtual void registerComponent(const Entity *entity, Component *component)
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.
optional< std::string > getRadiumResourcesPath()
Get the path of Radium internal resources.
Structure passed to each system before they fill the task queue.
Scalar m_animationTime
The current animation time.