From 6b9be0ee8e7827c3479d63d3eb3995d3d978bf8a Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Tue, 25 Feb 2014 17:05:25 +0100 Subject: [PATCH] Multi bone animation support internal legwork done --- Code/OysterGraphics/DllInterfaces/GFXAPI.cpp | 23 +- Code/OysterGraphics/DllInterfaces/GFXAPI.h | 2 +- Code/OysterGraphics/Model/Model.h | 4 +- Code/OysterGraphics/Model/ModelInfo.h | 3 + .../OysterGraphics/Render/DefaultRenderer.cpp | 653 +++++++++++------- 5 files changed, 422 insertions(+), 263 deletions(-) diff --git a/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp b/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp index ee3d9f8a..0369a3eb 100644 --- a/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp +++ b/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp @@ -171,7 +171,8 @@ namespace Oyster Model::Model* m = new Model::Model(); m->WorldMatrix = Oyster::Math::Float4x4::identity; m->Visible = true; - m->Animation.AnimationPlaying = NULL; + m->Animation[0].AnimationPlaying = nullptr; + m->Animation[1].AnimationPlaying = nullptr; m->Tint = Math::Float3(1); m->GlowTint = Math::Float3(1); m->Instanced = true; @@ -327,14 +328,20 @@ namespace Oyster Core::loader.ReleaseResource(tex); } - float API::PlayAnimation(Model::Model* m, std::wstring name,bool looping) + float API::PlayAnimation( Model::Model* m, const std::wstring &name, bool looping ) { - if(m==NULL) - return 0; - m->Animation.AnimationPlaying = &(*m->info->Animations.find(name)).second; - m->Animation.AnimationTime=0; - m->Animation.LoopAnimation = looping; - return (float)m->Animation.AnimationPlaying->duration; + if( m ) + { // nasty temp solution by Dan + static int fairSlotLooper = 0; + fairSlotLooper = (fairSlotLooper + 1) & 3; // same as n % 2 + + m->Animation[fairSlotLooper].AnimationPlaying = &(*m->info->Animations.find(name)).second; + m->Animation[fairSlotLooper].AnimationTime=0; + m->Animation[fairSlotLooper].LoopAnimation = looping; + + return (float)m->Animation[fairSlotLooper].AnimationPlaying->duration; + } + return 0; } void API::Update(float dt) diff --git a/Code/OysterGraphics/DllInterfaces/GFXAPI.h b/Code/OysterGraphics/DllInterfaces/GFXAPI.h index 7f338cce..9a99bbf5 100644 --- a/Code/OysterGraphics/DllInterfaces/GFXAPI.h +++ b/Code/OysterGraphics/DllInterfaces/GFXAPI.h @@ -111,7 +111,7 @@ namespace Oyster static Option GetOption(); //! @brief Starts an animation and returns the time of the animation - static float PlayAnimation(Model::Model* model, std::wstring name, bool looping = false); + static float PlayAnimation(Model::Model* model, const std::wstring &name, bool looping = false); //! @brief Moves all animating models forward the specified time; static void Update(float deltaTime); diff --git a/Code/OysterGraphics/Model/Model.h b/Code/OysterGraphics/Model/Model.h index 6d4e96f2..5fb2aa18 100644 --- a/Code/OysterGraphics/Model/Model.h +++ b/Code/OysterGraphics/Model/Model.h @@ -19,6 +19,7 @@ namespace Oyster float AnimationTime; bool LoopAnimation; }; + struct Model { ModelInfo* info; @@ -27,10 +28,9 @@ namespace Oyster Oyster::Math::Float3 GlowTint; bool Visible; bool Instanced; - AnimationData Animation; + AnimationData Animation[2]; }; } - }; }; diff --git a/Code/OysterGraphics/Model/ModelInfo.h b/Code/OysterGraphics/Model/ModelInfo.h index a53bcb23..7e737dbc 100644 --- a/Code/OysterGraphics/Model/ModelInfo.h +++ b/Code/OysterGraphics/Model/ModelInfo.h @@ -17,11 +17,13 @@ namespace Oyster Math::Matrix Absolute; int Parent; }; + struct Frame { Bone bone; double time; }; + struct Animation { int Bones; @@ -29,6 +31,7 @@ namespace Oyster Frame** Keyframes; //! @brief [Bone][Frame] double duration; }; + struct ModelInfo { std::vector Material; diff --git a/Code/OysterGraphics/Render/DefaultRenderer.cpp b/Code/OysterGraphics/Render/DefaultRenderer.cpp index 4b979be8..3a94c20e 100644 --- a/Code/OysterGraphics/Render/DefaultRenderer.cpp +++ b/Code/OysterGraphics/Render/DefaultRenderer.cpp @@ -12,278 +12,427 @@ namespace Oyster { namespace Render { - Definitions::Pointlight pl; + Definitions::Pointlight pl; - void DefaultRenderer::NewFrame(Oyster::Math::Float4x4 View, Oyster::Math::Float4x4 Projection, Definitions::Pointlight* Lights, int numLights) + /******************************************************** + * Private Prototype Methods + ********************************************************/ + void AnimateRelativeBones( const Model::ModelInfo &info, Model::AnimationData &anim, Math::Matrix relativeBuffer[] ); + void MergeAnimatedBones + ( + const Model::Bone raw[], int numBones, Math::Float interpolation, // comparable raw bone data and interpolation value + const Math::Matrix animatedBoneSourceA[], // relative bone animations + Math::Matrix animatedBoneSourceB_Target[] // relative bone animations and targetbuffer + ); + int AnimateAbsoluteBones + ( + const Model::ModelInfo &info, Math::Float deltaTime, + Model::AnimationData &anim, + Math::Matrix SkinTransformBuffer[], + Math::Matrix BoneAnimationBuffer_Relative[], + Math::Matrix BoneAnimationBuffer_Absolute[] + ); + int AnimateAbsoluteBones + ( + const Model::ModelInfo &info, Math::Float deltaTime, + Model::AnimationData anim[], int numAnimations, + Math::Matrix SkinTransformBuffer[], + Math::Matrix BoneAnimationBuffer_Relative[], + Math::Matrix BoneAnimationBuffer_Absolute[] + ); + + /******************************************************** + * Public Method Implementations + ********************************************************/ + + void DefaultRenderer::NewFrame(Oyster::Math::Float4x4 View, Oyster::Math::Float4x4 Projection, Definitions::Pointlight* Lights, int numLights) + { + Preparations::Basic::ClearBackBuffer(Oyster::Math::Float4(0,0,0,0)); + Preparations::Basic::ClearDepthStencil(Resources::Gui::depth); + Preparations::Basic::ClearRTV(Resources::GBufferRTV,Resources::GBufferSize,Math::Float4(0,0,0,0)); + Lights[1]; + + void* data; + + Definitions::LightConstants lc; + lc.InvProj = Projection.GetInverse(); + lc.Pixels = Core::resolution; + lc.Lights = numLights; + lc.View = View; + lc.Proj = Projection; + lc.SSAORadius = 3; + + data = Resources::Light::LightConstantsData.Map(); + memcpy(data, &lc, sizeof(Definitions::LightConstants)); + Resources::Light::LightConstantsData.Unmap(); + + data = Resources::Light::PointLightsData.Map(); + memcpy(data, Lights, sizeof(Definitions::Pointlight) * numLights); + Resources::Light::PointLightsData.Unmap(); + + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) { - Preparations::Basic::ClearBackBuffer(Oyster::Math::Float4(0,0,0,0)); - Preparations::Basic::ClearDepthStencil(Resources::Gui::depth); - Preparations::Basic::ClearRTV(Resources::GBufferRTV,Resources::GBufferSize,Math::Float4(0,0,0,0)); - Lights[1]; - - void* data; - - Definitions::LightConstants lc; - lc.InvProj = Projection.GetInverse(); - lc.Pixels = Core::resolution; - lc.Lights = numLights; - lc.View = View; - lc.Proj = Projection; - lc.SSAORadius = 3; - - data = Resources::Light::LightConstantsData.Map(); - memcpy(data, &lc, sizeof(Definitions::LightConstants)); - Resources::Light::LightConstantsData.Unmap(); - - data = Resources::Light::PointLightsData.Map(); - memcpy(data, Lights, sizeof(Definitions::Pointlight) * numLights); - Resources::Light::PointLightsData.Unmap(); - - for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) - { - (*i).second->Models=0; - } - - Core::PipelineManager::SetRenderPass(Resources::Gather::AnimatedPass); + (*i).second->Models=0; } - void DefaultRenderer::RenderScene(Model::Model* models, int count, Math::Matrix View, Math::Matrix Projection, float deltaTime) + Core::PipelineManager::SetRenderPass(Resources::Gather::AnimatedPass); + } + + void DefaultRenderer::RenderScene(Model::Model* models, int count, Math::Matrix View, Math::Matrix Projection, float deltaTime) + { + for(int i = 0; i < count; ++i) { - for(int i = 0; i < count; ++i) + if(&models[i] == NULL || !models[i].Visible) + continue; + + Model::ModelInfo* info = models[i].info; + if(!info->Animated && models[i].Instanced) { - if(&models[i] == NULL || !models[i].Visible) - continue; + Definitions::RenderInstanceData rid; + Math::Float3x3 normalTransform; + normalTransform = Math::Float3x3(models[i].WorldMatrix.v[0].xyz, models[i].WorldMatrix.v[1].xyz, models[i].WorldMatrix.v[2].xyz); + normalTransform.Transpose().Invert(); + Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); + rid.WV = View * m; + rid.WVP = Projection * View * models[i].WorldMatrix; - Model::ModelInfo* info = models[i].info; - if(!info->Animated && models[i].Instanced) - { - Definitions::RenderInstanceData rid; - Math::Float3x3 normalTransform; - normalTransform = Math::Float3x3(models[i].WorldMatrix.v[0].xyz, models[i].WorldMatrix.v[1].xyz, models[i].WorldMatrix.v[2].xyz); - normalTransform.Transpose().Invert(); - Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); - rid.WV = View * m; - rid.WVP = Projection * View * models[i].WorldMatrix; + rid.Tint = models[i].Tint; + rid.GTint = models[i].GlowTint; - rid.Tint = models[i].Tint; - rid.GTint = models[i].GlowTint; - - Resources::RenderData[info]->rid[Resources::RenderData[info]->Models++] = rid; - } - else - { - Definitions::PerModel pm; - Math::Float3x3 normalTransform; - normalTransform = Math::Float3x3(models[i].WorldMatrix.v[0].xyz, models[i].WorldMatrix.v[1].xyz, models[i].WorldMatrix.v[2].xyz); - normalTransform.Transpose().Invert(); - Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); - pm.WV = View * m; - pm.WVP = Projection * View * models[i].WorldMatrix; - - Model::ModelInfo* info = models[i].info; - - Definitions::AnimationData am; //final - if(info->Animated && models[i].Animation.AnimationPlaying != NULL) - { - models[i].Animation.AnimationTime += deltaTime; - ////store inverse absolut transform - Math::Matrix SkinTransform[100]; - Math::Matrix BoneAnimated[100]; - Math::Matrix BoneAbsAnimated[100]; - - - - for(int b = 0; b BoneCount; ++b) - { - Model::Bone Bone = info->bones[b]; - SkinTransform[b] = Bone.Absolute.GetInverse(); - BoneAnimated[b] = Bone.Relative; - BoneAbsAnimated[b] = Bone.Absolute; - } - int b = 0; - Model::Animation A = *models[i].Animation.AnimationPlaying; - while(models[i].Animation.AnimationTime>A.duration && models[i].Animation.LoopAnimation) - models[i].Animation.AnimationTime -= (float)A.duration; - - float position = models[i].Animation.AnimationTime; - for(int b = 0; b < A.Bones;++b) - { - //find current frame - int nrOfFrames = A.Frames[b]; - Model::Frame PFrame = A.Keyframes[b][nrOfFrames-1]; - Model::Frame NFrame = A.Keyframes[b][nrOfFrames-1]; - bool FrameFound = false; - for (int i = 0; i < nrOfFrames; i++) - { - if(position < A.Keyframes[b][i].time) - { - PFrame = A.Keyframes[b][i-1]; - NFrame = A.Keyframes[b][i]; - break; - } - } - float denominator = (float)(NFrame.time - PFrame.time); - if(denominator == 0) - { - BoneAnimated[PFrame.bone.Parent] = PFrame.bone.Relative; - continue; - } - float inter = (float)((position - PFrame.time) / denominator); - Math3D::InterpolateOrientation_UsingNonRigidNlerp(PFrame.bone.Relative,NFrame.bone.Relative,inter, BoneAnimated[PFrame.bone.Parent]); - } - - ////calculate Absolute Animation Transform - for(int b = 0; b < info->BoneCount; ++b) - { - BoneAbsAnimated[b] = BoneAbsAnimated[info->bones[b].Parent] * BoneAnimated[b]; - } - - //write data to am - for(int b = 0; b < info->BoneCount; ++b) - { - am.AnimatedData[b] = (BoneAbsAnimated[b] * SkinTransform[b]); - } - - - void *data = Resources::Gather::AnimationData.Map(); - memcpy(data,&am,sizeof(Definitions::AnimationData)); - Resources::Gather::AnimationData.Unmap(); - - pm.Animated = 1; - } - else - pm.Animated = 0; - - void* data = Resources::Gather::ModelData.Map(); - memcpy(data,&(pm),sizeof(pm)); - Resources::Gather::ModelData.Unmap(); - - Definitions::TintData td; - td.GlowTint = models[i].GlowTint; - td.Tint = models[i].Tint; - td.PAD = 0; - td.PAD2 = 0; - int s = sizeof(Definitions::TintData); - - data = Render::Resources::Color.Map(); - memcpy(data,&td,sizeof(Definitions::TintData)); - Render::Resources::Color.Unmap(); - - if(info->Material.size()) - { - Core::deviceContext->PSSetShaderResources(0,(UINT)info->Material.size(),&(info->Material[0])); - } - - - info->Vertices->Apply(); - if(info->Indexed) - { - info->Indecies->Apply(); - Oyster::Graphics::Core::deviceContext->DrawIndexed(info->IndexCount,0,0); - } - else - { - Oyster::Graphics::Core::deviceContext->Draw(info->VertexCount,0); - } - } - } - } - - void BlurGlow() - { - Definitions::BlurrData bd; - bd.BlurMask = Math::Float4(1,1,1,1); - bd.StopX = (UINT)Core::resolution.x/2; - bd.StopY = (UINT)Core::resolution.y; - bd.StartX = 0; - bd.StartY = (UINT)Core::resolution.y/2; - - void* data = Resources::Blur::Data.Map(); - memcpy(data,&bd,sizeof(Definitions::BlurrData)); - Resources::Blur::Data.Unmap(); - - Core::PipelineManager::SetRenderPass(Resources::Blur::HorPass); - Core::deviceContext->Dispatch((UINT)((Core::resolution.x/2 + 127U) / 128U), (UINT)(Core::resolution.y/2), 1); - - Core::PipelineManager::SetRenderPass(Resources::Blur::VertPass); - Core::deviceContext->Dispatch((UINT)(Core::resolution.x/2), (UINT)((Core::resolution.y/2 + 127U) / 128U), 1); - } - - void BlurSSAO() - { - Definitions::BlurrData bd; - bd.BlurMask = Math::Float4(0,0,0,1); - bd.StopX = (UINT)Core::resolution.x/2; - bd.StopY = (UINT)Core::resolution.y/2; - bd.StartX = 0; - bd.StartY = 0; - - void* data = Resources::Blur::Data.Map(); - memcpy(data,&bd,sizeof(Definitions::BlurrData)); - Resources::Blur::Data.Unmap(); - - Core::PipelineManager::SetRenderPass(Resources::Blur::HorPass); - Core::deviceContext->Dispatch((UINT)((Core::resolution.x/2 + 127U) / 128U), (UINT)(Core::resolution.y/2), 1); - - Core::PipelineManager::SetRenderPass(Resources::Blur::VertPass); - Core::deviceContext->Dispatch((UINT)(Core::resolution.x/2), (UINT)((Core::resolution.y/2 + 127U) / 128U), 1); - } - - void RenderModel(Model::ModelInfo* info, Definitions::RenderInstanceData* rid , int count) - { - if(count < 1) - return; - if(info->Material.size()) - { - Core::deviceContext->PSSetShaderResources(0,(UINT)info->Material.size(),&(info->Material[0])); - } - info->Vertices->Apply(); - if(info->Indexed) - { - info->Indecies->Apply(); - } - - void* data = Resources::Gather::InstancedData.Map(); - memcpy(data, rid, sizeof(Definitions::RenderInstanceData)*count); - Resources::Gather::InstancedData.Unmap(); - - if(info->Indexed) - { - Core::deviceContext->DrawIndexedInstanced(info->IndexCount,count,0,0,0); - //Core::deviceContext->DrawIndexed(info->IndexCount,0,0); + Resources::RenderData[info]->rid[Resources::RenderData[info]->Models++] = rid; } else { - Core::deviceContext->DrawInstanced(info->VertexCount,count,0,0); - //Core::deviceContext->Draw(info->VertexCount,0); + Definitions::PerModel pm; + Math::Float3x3 normalTransform; + normalTransform = Math::Float3x3(models[i].WorldMatrix.v[0].xyz, models[i].WorldMatrix.v[1].xyz, models[i].WorldMatrix.v[2].xyz); + normalTransform.Transpose().Invert(); + Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); + pm.WV = View * m; + pm.WVP = Projection * View * models[i].WorldMatrix; + + Model::ModelInfo* info = models[i].info; + + // Bone animation buffers + Math::Matrix SkinTransform[100]; + Math::Matrix BoneAnimated[100]; + Math::Matrix BoneAbsAnimated[100]; + + pm.Animated = AnimateAbsoluteBones + ( + *info, deltaTime, + models[i].Animation, + ::Utility::StaticArray::NumElementsOf( models[i].Animation ), + SkinTransform, BoneAnimated, BoneAbsAnimated + ); + + void* data = Resources::Gather::ModelData.Map(); + memcpy(data,&(pm),sizeof(pm)); + Resources::Gather::ModelData.Unmap(); + + Definitions::TintData td; + td.GlowTint = models[i].GlowTint; + td.Tint = models[i].Tint; + td.PAD = 0; + td.PAD2 = 0; + int s = sizeof(Definitions::TintData); + + data = Render::Resources::Color.Map(); + memcpy(data,&td,sizeof(Definitions::TintData)); + Render::Resources::Color.Unmap(); + + if(info->Material.size()) + { + Core::deviceContext->PSSetShaderResources(0,(UINT)info->Material.size(),&(info->Material[0])); + } + + + info->Vertices->Apply(); + if(info->Indexed) + { + info->Indecies->Apply(); + Oyster::Graphics::Core::deviceContext->DrawIndexed(info->IndexCount,0,0); + } + else + { + Oyster::Graphics::Core::deviceContext->Draw(info->VertexCount,0); + } } - } + } + } + void BlurGlow() + { + Definitions::BlurrData bd; + bd.BlurMask = Math::Float4(1,1,1,1); + bd.StopX = (UINT)Core::resolution.x/2; + bd.StopY = (UINT)Core::resolution.y; + bd.StartX = 0; + bd.StartY = (UINT)Core::resolution.y/2; + + void* data = Resources::Blur::Data.Map(); + memcpy(data,&bd,sizeof(Definitions::BlurrData)); + Resources::Blur::Data.Unmap(); - void DefaultRenderer::EndFrame() + Core::PipelineManager::SetRenderPass(Resources::Blur::HorPass); + Core::deviceContext->Dispatch((UINT)((Core::resolution.x/2 + 127U) / 128U), (UINT)(Core::resolution.y/2), 1); + + Core::PipelineManager::SetRenderPass(Resources::Blur::VertPass); + Core::deviceContext->Dispatch((UINT)(Core::resolution.x/2), (UINT)((Core::resolution.y/2 + 127U) / 128U), 1); + } + + void BlurSSAO() + { + Definitions::BlurrData bd; + bd.BlurMask = Math::Float4(0,0,0,1); + bd.StopX = (UINT)Core::resolution.x/2; + bd.StopY = (UINT)Core::resolution.y/2; + bd.StartX = 0; + bd.StartY = 0; + + void* data = Resources::Blur::Data.Map(); + memcpy(data,&bd,sizeof(Definitions::BlurrData)); + Resources::Blur::Data.Unmap(); + + Core::PipelineManager::SetRenderPass(Resources::Blur::HorPass); + Core::deviceContext->Dispatch((UINT)((Core::resolution.x/2 + 127U) / 128U), (UINT)(Core::resolution.y/2), 1); + + Core::PipelineManager::SetRenderPass(Resources::Blur::VertPass); + Core::deviceContext->Dispatch((UINT)(Core::resolution.x/2), (UINT)((Core::resolution.y/2 + 127U) / 128U), 1); + } + + void RenderModel(Model::ModelInfo* info, Definitions::RenderInstanceData* rid , int count) + { + if(count < 1) + return; + if(info->Material.size()) { - Core::PipelineManager::SetRenderPass(Graphics::Render::Resources::Gather::InstancedPass); - Resources::Gather::InstancedData.Apply(1); + Core::deviceContext->PSSetShaderResources(0,(UINT)info->Material.size(),&(info->Material[0])); + } + info->Vertices->Apply(); + if(info->Indexed) + { + info->Indecies->Apply(); + } - for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + void* data = Resources::Gather::InstancedData.Map(); + memcpy(data, rid, sizeof(Definitions::RenderInstanceData)*count); + Resources::Gather::InstancedData.Unmap(); + + if(info->Indexed) + { + Core::deviceContext->DrawIndexedInstanced(info->IndexCount,count,0,0,0); + //Core::deviceContext->DrawIndexed(info->IndexCount,0,0); + } + else + { + Core::deviceContext->DrawInstanced(info->VertexCount,count,0,0); + //Core::deviceContext->Draw(info->VertexCount,0); + } + } + + + void DefaultRenderer::EndFrame() + { + Core::PipelineManager::SetRenderPass(Graphics::Render::Resources::Gather::InstancedPass); + Resources::Gather::InstancedData.Apply(1); + + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + { + RenderModel((*i).first,(*i).second->rid, (*i).second->Models); + } + + Core::PipelineManager::SetRenderPass(Resources::Light::Pass); + + Core::deviceContext->Dispatch((UINT)((Core::resolution.x + 15U) / 16U), (UINT)((Core::resolution.y + 15U) / 16U), 1); + + BlurGlow(); + + BlurSSAO(); + + Core::PipelineManager::SetRenderPass(Resources::Post::Pass); + + Core::deviceContext->Dispatch((UINT)((Core::resolution.x + 15U) / 16U), (UINT)((Core::resolution.y + 15U) / 16U), 1); + + Core::swapChain->Present(0,0); + } + + /******************************************************** + * Private Prototype Method Implementations + ********************************************************/ + + void AnimateRelativeBones( const Model::ModelInfo &info, Model::AnimationData &anim, Math::Matrix relativeBuffer[] ) + { + for( int i = 0; i < info.BoneCount; ++i ) + { + Model::Bone Bone = info.bones[i]; + relativeBuffer[i] = Bone.Relative; + } + + const Model::Animation &A = *anim.AnimationPlaying; + + while( anim.AnimationTime > A.duration && anim.LoopAnimation ) + anim.AnimationTime -= (float)A.duration; + + float position = anim.AnimationTime; + for( int i = 0; i < A.Bones; ++i ) + { + //find current frame + int nrOfFrames = A.Frames[i]; + Model::Frame PFrame = A.Keyframes[i][nrOfFrames-1]; + Model::Frame NFrame = A.Keyframes[i][nrOfFrames-1]; + bool FrameFound = false; + + for (int j = 0; j < nrOfFrames; j++) { - RenderModel((*i).first,(*i).second->rid, (*i).second->Models); + if(position < A.Keyframes[i][j].time) + { + PFrame = A.Keyframes[i][j-1]; + NFrame = A.Keyframes[i][j]; + break; + } } - Core::PipelineManager::SetRenderPass(Resources::Light::Pass); - - Core::deviceContext->Dispatch((UINT)((Core::resolution.x + 15U) / 16U), (UINT)((Core::resolution.y + 15U) / 16U), 1); - - BlurGlow(); - - BlurSSAO(); - - Core::PipelineManager::SetRenderPass(Resources::Post::Pass); - - Core::deviceContext->Dispatch((UINT)((Core::resolution.x + 15U) / 16U), (UINT)((Core::resolution.y + 15U) / 16U), 1); - - Core::swapChain->Present(0,0); + float denominator = (float)(NFrame.time - PFrame.time); + + if( denominator != 0.0f ) + { + float inter = (float)((position - PFrame.time) / denominator); + Math3D::InterpolateOrientation_UsingNonRigidNlerp( PFrame.bone.Relative,NFrame.bone.Relative, inter, relativeBuffer[PFrame.bone.Parent] ); + } + else + { + relativeBuffer[PFrame.bone.Parent] = PFrame.bone.Relative; + } } + } + + enum Conflict + { + Conflict_detected, + Conflict_useA, + Conflict_useB + }; + + Conflict DetectBoneAnimationConflict( const Model::Bone &raw, const Math::Matrix &animBoneA, const Math::Matrix &animBoneB ); + + void MergeAnimatedBones( const Model::Bone raw[], int numBones, Math::Float interpolation, const Math::Matrix *animatedBoneSourceA, Math::Matrix animatedBoneSourceB_Target[] ) + { + for( int i = 0; i < numBones; ++i ) + { + switch( DetectBoneAnimationConflict(raw[i], animatedBoneSourceA[i], animatedBoneSourceB_Target[i]) ) + { + case Conflict_detected: + Math3D::InterpolateOrientation_UsingNonRigidNlerp( animatedBoneSourceA[i], animatedBoneSourceB_Target[i], interpolation, animatedBoneSourceB_Target[i] ); + break; + case Conflict_useA: + animatedBoneSourceB_Target[i] = animatedBoneSourceA[i]; + break; + default: case Conflict_useB: break; + } + } + } + + Conflict DetectBoneAnimationConflict( const Model::Bone &raw, const Math::Matrix &animBoneA, const Math::Matrix &animBoneB ) + { + if( animBoneA == raw.Relative ) + return Conflict_useB; + + if( animBoneB == raw.Relative ) + return Conflict_useA; + + return Conflict_detected; + } + + int AnimateAbsoluteBones( const Model::ModelInfo &info, Math::Float deltaTime, Model::AnimationData &anim, Math::Matrix SkinTransformBuffer[], Math::Matrix BoneAnimationBuffer_Relative[], Math::Matrix BoneAnimationBuffer_Absolute[] ) + { + if( !info.Animated || (anim.AnimationPlaying == nullptr) ) + { // no animation + return 0; + } + + anim.AnimationTime += deltaTime; + AnimateRelativeBones( info, anim, BoneAnimationBuffer_Relative ); + + for( int i = 0; i < info.BoneCount; ++i ) + { + Model::Bone Bone = info.bones[i]; + SkinTransformBuffer[i] = Bone.Absolute.GetInverse(); + BoneAnimationBuffer_Absolute[i] = Bone.Absolute; + } + + Definitions::AnimationData am; + + for( int i = 0; i < info.BoneCount; ++i ) + { + //calculate Absolute Animation Transform + BoneAnimationBuffer_Absolute[i] = BoneAnimationBuffer_Absolute[info.bones[i].Parent] * BoneAnimationBuffer_Relative[i]; + + //write data to am + am.AnimatedData[i] = (BoneAnimationBuffer_Absolute[i] * SkinTransformBuffer[i]); + } + + void *data = Resources::Gather::AnimationData.Map(); + memcpy( data, &am, sizeof(Definitions::AnimationData) ); + Resources::Gather::AnimationData.Unmap(); + + return 1; + } + + int AnimateAbsoluteBones( const Model::ModelInfo &info, Math::Float deltaTime, Model::AnimationData anim[], int numAnimations, Math::Matrix SkinTransformBuffer[], Math::Matrix BoneAnimationBuffer_Relative[], Math::Matrix BoneAnimationBuffer_Absolute[] ) + { + if( !info.Animated || (numAnimations < 1) ) + { // no animation + return 0; + } + int isAnimated = 0; + + // for each animation + for( int i = 0; i < numAnimations; ++i ) + { + if( anim[i].AnimationPlaying != nullptr ) + { + anim[i].AnimationTime += deltaTime; + if( isAnimated ) + { + AnimateRelativeBones( info, anim[i], BoneAnimationBuffer_Absolute ); // Borrowing BoneAnimationBuffer_Absolute as interim buffer + MergeAnimatedBones( info.bones, info.BoneCount, 0.5f, BoneAnimationBuffer_Absolute, BoneAnimationBuffer_Relative ); + } + else + { + isAnimated = 1; + AnimateRelativeBones( info, anim[i], BoneAnimationBuffer_Relative ); + } + } + } + + if( isAnimated ) + { + for( int i = 0; i < info.BoneCount; ++i ) + { + Model::Bone Bone = info.bones[i]; + SkinTransformBuffer[i] = Bone.Absolute.GetInverse(); + BoneAnimationBuffer_Absolute[i] = Bone.Absolute; + } + + Definitions::AnimationData am; + + for( int i = 0; i < info.BoneCount; ++i ) + { + //calculate Absolute Animation Transform + BoneAnimationBuffer_Absolute[i] = BoneAnimationBuffer_Absolute[info.bones[i].Parent] * BoneAnimationBuffer_Relative[i]; + + //write data to am + am.AnimatedData[i] = (BoneAnimationBuffer_Absolute[i] * SkinTransformBuffer[i]); + } + + void *data = Resources::Gather::AnimationData.Map(); + memcpy( data, &am, sizeof(Definitions::AnimationData) ); + Resources::Gather::AnimationData.Unmap(); + } + + return isAnimated; + } } } } \ No newline at end of file