diff --git a/Engine/BuiltInShaders/shaders/fs_vertex_weight.sc b/Engine/BuiltInShaders/shaders/fs_vertex_weight.sc new file mode 100644 index 00000000..dcd515cf --- /dev/null +++ b/Engine/BuiltInShaders/shaders/fs_vertex_weight.sc @@ -0,0 +1,87 @@ +$input v_worldPos, v_indices, v_weight + +#include "../common/common.sh" + +uniform vec4 u_debugBoneIndex[1]; + +vec3 evalSh(vec3 dir) { +# define k01 0.2820947918 // sqrt( 1/PI)/2 +# define k02 0.4886025119 // sqrt( 3/PI)/2 +# define k03 1.0925484306 // sqrt(15/PI)/2 +# define k04 0.3153915652 // sqrt( 5/PI)/4 +# define k05 0.5462742153 // sqrt(15/PI)/4 + + vec3 shEnv[9]; + shEnv[0] = vec3( 0.967757057878229854, 0.976516067990363390, 0.891218272348969998); /* Band 0 */ + shEnv[1] = vec3(-0.384163503608655643, -0.423492289131209787, -0.425532726148547868); /* Band 1 */ + shEnv[2] = vec3( 0.055906294587354334, 0.056627436881069373, 0.069969936396987467); + shEnv[3] = vec3( 0.120985157386215209, 0.119297994074027414, 0.117111965829213599); + shEnv[4] = vec3(-0.176711633774331106, -0.170331404095516392, -0.151345020570876621); /* Band 2 */ + shEnv[5] = vec3(-0.124682114349692147, -0.119340785411183953, -0.096300354204368860); + shEnv[6] = vec3( 0.001852378550138503, -0.032592784164597745, -0.088204495001329680); + shEnv[7] = vec3( 0.296365482782109446, 0.281268696656263029, 0.243328223888495510); + shEnv[8] = vec3(-0.079826665303240341, -0.109340956251195970, -0.157208859664677764); + + float sh[9]; + sh[0] = k01; + sh[1] = -k02 * dir.y; + sh[2] = k02 * dir.z; + sh[3] = -k02 * dir.x; + sh[4] = k03 * dir.y * dir.x; + sh[5] = -k03 * dir.y * dir.z; + sh[6] = k04 * (3.0 * dir.z * dir.z -1.0); + sh[7] = -k03 * dir.x * dir.z; + sh[8] = k05 * (dir.x * dir.x - dir.y * dir.y); + + vec3 rgb = vec3_splat(0.0); + rgb += shEnv[0] * sh[0] * 1.0; + rgb += shEnv[1] * sh[1] * 2.0 / 2.5; + rgb += shEnv[2] * sh[2] * 2.0 / 2.5; + rgb += shEnv[3] * sh[3] * 2.0 / 2.5; + rgb += shEnv[4] * sh[4] * 1.0 / 2.5; + rgb += shEnv[5] * sh[5] * 0.5; + rgb += shEnv[6] * sh[6] * 0.5; + rgb += shEnv[7] * sh[7] * 0.5; + rgb += shEnv[8] * sh[8] * 0.5; + + return rgb; +} + +void main() +{ + bool foundBoneWeights = false; + vec3 fragColor = vec3_splat(0.0); + for(int i = 0; i < 4; ++i) + { + if(v_indices[i] == u_debugBoneIndex[0].x) + { + if(v_weight[i] >= 0.7) + { + fragColor = vec3(1.0, 0.0, 0.0) * v_weight[i]; + } + else if(v_weight[i] >= 0.4 && v_weight[i] <= 0.6) + { + fragColor = vec3(0.0, 1.0, 0.0) * v_weight[i]; + } + else if(v_weight[i] >= 0.1) + { + fragColor = vec3(0.0, 0.0, 1.0) * v_weight[i]; + } + + foundBoneWeights = true; + break; + } + } + + if(foundBoneWeights) + { + // debug bone weights + gl_FragColor = vec4(fragColor, 1.0); + } + else + { + // Spherical Harmonics + vec3 flatNormal = normalize(cross(dFdx(v_worldPos), dFdy(v_worldPos))); + gl_FragColor = vec4(evalSh(flatNormal), 1.0); + } +} diff --git a/Engine/BuiltInShaders/shaders/vs_skeleton.sc b/Engine/BuiltInShaders/shaders/vs_skeleton.sc new file mode 100644 index 00000000..7b95f3bd --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_skeleton.sc @@ -0,0 +1,12 @@ +$input a_position, a_indices + +#include "../common/common.sh" + +uniform mat4 u_boneMatrices[128]; + +void main() +{ + mat4 boneTransform = u_boneMatrices[a_indices[0]]; + vec4 localPosition = mul(boneTransform, vec4(a_position, 1.0)); + gl_Position = mul(u_modelViewProj, localPosition); +} \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/vs_vertex_weight.sc b/Engine/BuiltInShaders/shaders/vs_vertex_weight.sc new file mode 100644 index 00000000..489ea28a --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_vertex_weight.sc @@ -0,0 +1,13 @@ +$input a_position, a_indices, a_weight +$output v_worldPos, v_indices, v_weight + +#include "../common/common.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0)); + + v_worldPos = mul(u_model[0], vec4(a_position, 1.0)).xyz; + v_indices = a_indices; + v_weight = a_weight; +} diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp index 22c998ab..0909542c 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp @@ -10,6 +10,7 @@ #include "Resources/ResourceBuilder.h" #include "Resources/ResourceLoader.h" #include "Resources/ShaderBuilder.h" +#include "Rendering/Utility/VertexLayoutUtility.h" #include "Scene/SceneDatabase.h" #include @@ -37,6 +38,52 @@ CD_FORCEINLINE bool IsMaterialTextureTypeValid(cd::MaterialTextureType type) return materialTextureTypeToShaderFeature.find(type) != materialTextureTypeToShaderFeature.end(); } +constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + +constexpr uint32_t indexDataSize = sizeof(uint16_t) * 4; + +constexpr size_t indexTypeSize = sizeof(uint16_t); + +void TraverseBone(const cd::Bone& bone, cd::Matrix4x4& totalDelta, cd::Matrix4x4& globalMatrix, const cd::SceneDatabase* pSceneDatabase, engine::SkinMeshComponent& skinmeshComponent, std::byte* currentDataPtr, + std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +{ + + for (auto& child : bone.GetChildIDs()) + { + cd::Matrix4x4 curGlobalMatrix = globalMatrix; + const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); + + int ID = child.Data(); + + curGlobalMatrix = curGlobalMatrix * currBone.GetTransform().GetMatrix(); + + uint16_t parentID = bone.GetID().Data(); + uint16_t currBoneID = currBone.GetID().Data(); + skinmeshComponent.SetBoneGlobalMatrix(currBoneID, curGlobalMatrix); + std::memcpy(¤tDataPtr[vertexOffset], curGlobalMatrix.GetTranslation().Begin(), posDataSize); + //std::memcpy(¤tDataPtr[vertexOffset], translate.Begin(), posDataSize); + vertexOffset += posDataSize; + + uint16_t boneID[4] = { currBoneID, 0, 0, 0 }; + std::memcpy(¤tDataPtr[vertexOffset], boneID, indexDataSize); + vertexOffset += indexDataSize; + + std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexTypeSize); + indexOffset += static_cast(indexTypeSize); + + std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexTypeSize); + indexOffset += static_cast(indexTypeSize); + + const cd::Matrix4x4& boneMatrix = currBone.GetOffset(); + //skinmeshComponent.SetBoneChangeMatrix(currBoneID, localTransform); + + const cd::Transform& boneTransform = currBone.GetTransform(); + //skinmeshComponent.SetBoneChangeMatrix(currBoneID, boneTransform.GetMatrix()); + + TraverseBone(currBone, totalDelta, curGlobalMatrix, pSceneDatabase, skinmeshComponent, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + } +} + } // namespace Detail ECWorldConsumer::ECWorldConsumer(engine::SceneWorld* pSceneWorld, engine::RenderContext* pRenderContext) : @@ -56,11 +103,15 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) { CD_WARN("[ECWorldConsumer] No valid meshes in the consumed SceneDatabase."); } - + static int animationCount = 0; auto ParseMesh = [&](cd::MeshID meshID, const cd::Transform& tranform) { + if (animationCount == 1) + { + return; + } engine::Entity meshEntity = m_pSceneWorld->GetWorld()->CreateEntity(); - AddTransform(meshEntity, tranform); + AddTransform(meshEntity, tranform); const auto& mesh = pSceneDatabase->GetMesh(meshID.Data()); @@ -80,8 +131,10 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) // TODO : Use a standalone .cdanim file to play animation. // Currently, we assume that imported SkinMesh will play animation automatically for testing. - AddAnimation(meshEntity, pSceneDatabase->GetAnimation(0), pSceneDatabase); AddMaterial(meshEntity, nullptr, pMaterialType, pSceneDatabase); + AddAnimation(meshEntity, pSceneDatabase->GetAnimation(animationCount), pSceneDatabase); + animationCount++; + AddSkeleton(meshEntity, pSceneDatabase); } }; @@ -167,6 +220,7 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) engine::Entity lightEntity = m_pSceneWorld->GetWorld()->CreateEntity(); AddLight(lightEntity, light); } + } void ECWorldConsumer::AddCamera(engine::Entity entity, const cd::Camera& camera) @@ -251,7 +305,6 @@ void ECWorldConsumer::AddAnimation(engine::Entity entity, const cd::Animation& a animationComponent.SetTrackData(pSceneDatabase->GetTracks().data()); animationComponent.SetDuration(animation.GetDuration()); animationComponent.SetTicksPerSecond(animation.GetTicksPerSecnod()); - bgfx::UniformHandle boneMatricesUniform = bgfx::createUniform("u_boneMatrices", bgfx::UniformType::Mat4, 128); animationComponent.SetBoneMatricesUniform(boneMatricesUniform.idx); } @@ -419,4 +472,59 @@ void ECWorldConsumer::AddMorphs(engine::Entity entity, const std::vectorGetWorld(); + engine::SkinMeshComponent& skinmeshComponent = pWorld->CreateComponent(entity); + const uint32_t boneCount = pSceneDatabase->GetBoneCount(); + if (0 == boneCount) + { + return; + } + + const cd::Bone& firstBone = pSceneDatabase->GetBone(0); + if (0 != firstBone.GetID().Data()) + { + CD_ENGINE_WARN("First BoneID is not 0"); + return; + } + static std::vector vertexBuffer; + static std::vector indexBuffer; + + cd::VertexFormat vertexFormat; + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::BoneIndex, cd::AttributeValueType::Int16, 4U); + + constexpr size_t indexTypeSize = sizeof(uint16_t); + indexBuffer.resize((boneCount - 1) * 2 * indexTypeSize); + vertexBuffer.resize(boneCount * vertexFormat.GetStride()); + skinmeshComponent.SetBoneMatricesSize(boneCount); + uint32_t currentVertexOffset = 0U; + uint32_t currentIndexOffset = 0U; + std::byte* pCurrentVertexBuffer = vertexBuffer.data(); + cd::Matrix4x4 globalMatrix = firstBone.GetOffset().Inverse(); + uint16_t BoneID = firstBone.GetID().Data(); + std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], globalMatrix.GetTranslation().Begin(), Detail::posDataSize); + currentVertexOffset += Detail::posDataSize; + + uint16_t currBoneID[4] = { BoneID, 0, 0, 0 }; + std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], currBoneID, Detail::indexDataSize); + currentVertexOffset += Detail::indexDataSize; + + skinmeshComponent.SetBoneGlobalMatrix(BoneID, globalMatrix); + cd::Matrix4x4 totalDelta = cd::Quaternion::FromAxisAngle(cd::Vec3f(0.0f, 1.0f, 1.0f), 30.0f).Identity().ToMatrix4x4(); + + Detail::TraverseBone(firstBone, totalDelta, globalMatrix, pSceneDatabase, skinmeshComponent, vertexBuffer.data(), indexBuffer.data(), currentVertexOffset, currentIndexOffset); + bgfx::VertexLayout vertexLayout; + engine::VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); + uint16_t boneVBH = bgfx::createVertexBuffer(bgfx::makeRef(vertexBuffer.data(), static_cast(vertexBuffer.size())), vertexLayout).idx; + uint16_t boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(indexBuffer.data(), static_cast(indexBuffer.size())), 0U).idx; + + skinmeshComponent.SetBoneVBH(boneVBH); + skinmeshComponent.SetBoneIBH(boneIBH); + + bgfx::UniformHandle boneMatricesUniform = bgfx::createUniform("u_boneMatrices", bgfx::UniformType::Mat4, 128); + skinmeshComponent.SetBoneMatricesUniform(boneMatricesUniform.idx); +} + } \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h index bd0ec9a0..a82ae0c3 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h @@ -63,6 +63,7 @@ class ECWorldConsumer final : public cdtools::IConsumer void AddLight(engine::Entity entity, const cd::Light& light); void AddTransform(engine::Entity entity, const cd::Transform& transform); void AddStaticMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); + void AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase); void AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); void AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase); void AddMaterial(engine::Entity entity, const cd::Material* pMaterial, engine::MaterialType* pMaterialType, const cd::SceneDatabase* pSceneDatabase); diff --git a/Engine/Source/Editor/UILayers/ImGuizmoView.cpp b/Engine/Source/Editor/UILayers/ImGuizmoView.cpp index 1bc954c0..c6a27c9f 100644 --- a/Engine/Source/Editor/UILayers/ImGuizmoView.cpp +++ b/Engine/Source/Editor/UILayers/ImGuizmoView.cpp @@ -15,65 +15,65 @@ namespace editor { -ImGuizmoView::~ImGuizmoView() -{ -} - -void ImGuizmoView::Init() -{ - ImGuizmo::SetGizmoSizeClipSpace(0.25f); -} - -void ImGuizmoView::Update() -{ - engine::SceneWorld* pSceneWorld = GetSceneWorld(); - engine::Entity selectedEntity = pSceneWorld->GetSelectedEntity(); - - if (engine::INVALID_ENTITY == selectedEntity) + ImGuizmoView::~ImGuizmoView() { - return; } - engine::TransformComponent* pTransformComponent = pSceneWorld->GetTransformComponent(selectedEntity); - if (!pTransformComponent) + void ImGuizmoView::Init() { - return; + ImGuizmo::SetGizmoSizeClipSpace(0.25f); } - ImGuizmo::OPERATION operation = m_pSceneView->GetImGuizmoOperation(); - const engine::CameraComponent* pCameraComponent = pSceneWorld->GetCameraComponent(pSceneWorld->GetMainCameraEntity()); - - ImGuizmo::BeginFrame(); - constexpr bool isPerspective = true; - ImGuizmo::SetOrthographic(!isPerspective); - ImGuiIO& io = ImGui::GetIO(); - ImGuizmo::SetRect(0.0f, 0.0f, ImGui::GetIO().DisplaySize.x, io.DisplaySize.y); - cd::Matrix4x4 worldMatrix = pTransformComponent->GetWorldMatrix(); - ImGuizmo::Manipulate(pCameraComponent->GetViewMatrix().Begin(), pCameraComponent->GetProjectionMatrix().Begin(), - operation, ImGuizmo::LOCAL, worldMatrix.Begin()); - - if (ImGuizmo::IsUsing()) + void ImGuizmoView::Update() { - if (ImGuizmo::OPERATION::TRANSLATE & operation) + engine::SceneWorld* pSceneWorld = GetSceneWorld(); + engine::Entity selectedEntity = pSceneWorld->GetSelectedEntity(); + + if (engine::INVALID_ENTITY == selectedEntity) { - pTransformComponent->GetTransform().SetTranslation(worldMatrix.GetTranslation()); - pTransformComponent->Dirty(); + return; } - - if (ImGuizmo::OPERATION::ROTATE & operation) + + engine::TransformComponent* pTransformComponent = pSceneWorld->GetTransformComponent(selectedEntity); + if (!pTransformComponent) { - pTransformComponent->GetTransform().SetRotation(cd::Quaternion::FromMatrix(worldMatrix.GetRotation())); - pTransformComponent->Dirty(); + return; } - if (ImGuizmo::OPERATION::SCALE & operation) + ImGuizmo::OPERATION operation = m_pSceneView->GetImGuizmoOperation(); + const engine::CameraComponent* pCameraComponent = pSceneWorld->GetCameraComponent(pSceneWorld->GetMainCameraEntity()); + + ImGuizmo::BeginFrame(); + constexpr bool isPerspective = true; + ImGuizmo::SetOrthographic(!isPerspective); + ImGuiIO& io = ImGui::GetIO(); + ImGuizmo::SetRect(0.0f, 0.0f, ImGui::GetIO().DisplaySize.x, io.DisplaySize.y); + cd::Matrix4x4 worldMatrix = pTransformComponent->GetWorldMatrix(); + ImGuizmo::Manipulate(pCameraComponent->GetViewMatrix().Begin(), pCameraComponent->GetProjectionMatrix().Begin(), + operation, ImGuizmo::LOCAL, worldMatrix.Begin()); + + if (ImGuizmo::IsUsing()) { - pTransformComponent->GetTransform().SetScale(worldMatrix.GetScale()); - pTransformComponent->Dirty(); - } + if (ImGuizmo::OPERATION::TRANSLATE & operation) + { + pTransformComponent->GetTransform().SetTranslation(worldMatrix.GetTranslation()); + pTransformComponent->Dirty(); + } + + if (ImGuizmo::OPERATION::ROTATE & operation) + { + pTransformComponent->GetTransform().SetRotation(cd::Quaternion::FromMatrix(worldMatrix.GetRotation())); + pTransformComponent->Dirty(); + } - pTransformComponent->Build(); + if (ImGuizmo::OPERATION::SCALE & operation) + { + pTransformComponent->GetTransform().SetScale(worldMatrix.GetScale()); + pTransformComponent->Dirty(); + } + + pTransformComponent->Build(); + } } -} } \ No newline at end of file diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 862c5ef6..6dcf9490 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -653,6 +653,30 @@ void UpdateComponentWidget(engine::Sc ImGui::PopStyleVar(); } +template<> +void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) +{ + auto* pAnimationComponent = pSceneWorld->GetAnimationComponent(entity); + if (!pAnimationComponent) + { + return; + } + + bool isOpen = ImGui::CollapsingHeader("Animation Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + + if (isOpen) + { + ImGui::Separator(); + ImGuiUtils::ImGuiBoolProperty("play", pAnimationComponent->GetIsPlaying()); + ImGuiUtils::ImGuiEnumProperty("AnimationClip", pAnimationComponent->GetAnimationClip()); + ImGuiUtils::ImGuiFloatProperty("Factor", pAnimationComponent->GetBlendFactor(),cd::Unit::None,0.0f,1.0f,false,0.01f); + ImGuiUtils::ImGuiFloatProperty("Time", pAnimationComponent->GetAnimationPlayTime(), cd::Unit::None, 0.0f); + } + ImGui::Separator(); + ImGui::PopStyleVar(); +} } namespace editor @@ -694,6 +718,7 @@ void Inspector::Update() details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); + details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); diff --git a/Engine/Source/Editor/UILayers/SceneView.cpp b/Engine/Source/Editor/UILayers/SceneView.cpp index 49120ac6..6cad47c9 100644 --- a/Engine/Source/Editor/UILayers/SceneView.cpp +++ b/Engine/Source/Editor/UILayers/SceneView.cpp @@ -310,7 +310,6 @@ void SceneView::Update() // Draw top menu buttons which include ImGuizmo operation modes, ViewCamera settings. UpdateToolMenuButtons(); - // Check if need to resize scene view. ImVec2 regionSize = ImGui::GetContentRegionAvail(); uint16_t regionWidth = static_cast(regionSize.x); diff --git a/Engine/Source/Editor/UILayers/SkeletonView.cpp b/Engine/Source/Editor/UILayers/SkeletonView.cpp index fc488cf6..150f92d9 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.cpp +++ b/Engine/Source/Editor/UILayers/SkeletonView.cpp @@ -1,5 +1,6 @@ #include "SkeletonView.h" +#include "Display/CameraController.h" #include "ECWorld/SceneWorld.h" #include #include @@ -13,11 +14,12 @@ SkeletonView::~SkeletonView() } void SkeletonView::Init() { - + } -void SkeletonView::DrawBone(cd::SceneDatabase* pSceneDatabase, const cd::Bone& Bone) +void SkeletonView::DrawBone(engine::SceneWorld* pSceneWorld, const cd::Bone& Bone) { + cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); if (Bone.GetChildIDs().empty()) { ImGui::Selectable(Bone.GetName()); @@ -26,15 +28,31 @@ void SkeletonView::DrawBone(cd::SceneDatabase* pSceneDatabase, const cd::Bone& B return; } - bool isOpen = ImGui::TreeNode(Bone.GetName()); + bool isOpen = ImGui::TreeNodeEx(Bone.GetName(), ImGuiTreeNodeFlags_OpenOnArrow); + if (ImGui::IsItemClicked()) + { + if (ImGui::IsMouseDoubleClicked(0)) + { + pSceneWorld->SetSelectedBoneID(Bone.GetID()); + if (auto* pSkinMeshComponent = pSceneWorld->GetSkinMeshComponent(pSceneWorld->GetSelectedEntity())) + { + if (m_pCameraController) + { + const cd::Vec3f& position = pSkinMeshComponent->GetBoneMatrix(pSceneWorld->GetSelectedBoneID().Data()).GetTranslation(); + + m_pCameraController->CameraFocus(); + } + } + } + } ImGui::SameLine(); ImGui::Text(reinterpret_cast(ICON_MDI_BONE)); - if(isOpen) + if (isOpen) { for (auto& child : Bone.GetChildIDs()) { const cd::Bone& bone = pSceneDatabase->GetBone(child.Data()); - DrawBone(pSceneDatabase, bone); + DrawBone(pSceneWorld, bone); } ImGui::TreePop(); @@ -49,13 +67,12 @@ void SkeletonView::DrawSkeleton(engine::SceneWorld* pSceneWorld) return; } const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - DrawBone(pSceneDatabase, rootBone); + DrawBone(pSceneWorld, rootBone); } void SkeletonView::Update() { - constexpr auto flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; - ImGui::Begin(GetName(), &m_isEnable, flags); + ImGui::Begin(GetName(), &m_isEnable); engine::SceneWorld* pSceneWorld = GetSceneWorld(); engine::Entity selectedEntity = pSceneWorld->GetSelectedEntity(); if (engine::INVALID_ENTITY == selectedEntity) @@ -63,9 +80,9 @@ void SkeletonView::Update() ImGui::End(); return; } - engine::AnimationComponent* pAnimationConponent = pSceneWorld->GetAnimationComponent(selectedEntity); - if (pAnimationConponent) - { + engine::SkinMeshComponent* pSkinMeshComponent = pSceneWorld->GetSkinMeshComponent(selectedEntity); + if (pSkinMeshComponent) + { DrawSkeleton(pSceneWorld); } diff --git a/Engine/Source/Editor/UILayers/SkeletonView.h b/Engine/Source/Editor/UILayers/SkeletonView.h index 21252484..d1a5d4b1 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.h +++ b/Engine/Source/Editor/UILayers/SkeletonView.h @@ -3,6 +3,13 @@ #include "Scene/Bone.h" #include "Scene/SceneDatabase.h" +namespace engine +{ + +class CameraController; + +} + namespace editor { @@ -15,8 +22,13 @@ class SkeletonView : public engine::ImGuiBaseLayer virtual void Init() override; virtual void Update() override; - void DrawBone(cd::SceneDatabase* pSceneDatabase,const cd::Bone& Bone); + void DrawBone(engine::SceneWorld* pSceneWorld, const cd::Bone& Bone); void DrawSkeleton(engine::SceneWorld* pSceneWorld); + + void SetCameraController(engine::CameraController* pCameraController) { m_pCameraController = pCameraController; } + +private: + engine::CameraController* m_pCameraController = nullptr; }; } diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index 912175e2..46ad28e4 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -12,6 +12,7 @@ #include "ECWorld/MaterialComponent.h" #include "ECWorld/NameComponent.h" #include "ECWorld/ShaderVariantCollectionsComponent.h" +#include "ECWorld/SkinMeshComponent.h" #include "ECWorld/SkyComponent.h" #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TerrainComponent.h" diff --git a/Engine/Source/Runtime/ECWorld/AnimationComponent.h b/Engine/Source/Runtime/ECWorld/AnimationComponent.h index 2430324a..f4ade711 100644 --- a/Engine/Source/Runtime/ECWorld/AnimationComponent.h +++ b/Engine/Source/Runtime/ECWorld/AnimationComponent.h @@ -16,6 +16,16 @@ class Track; namespace engine { +enum class AnimationClip +{ + Idel, + Walking, + Running, + + Blend, + Count, +}; + class AnimationComponent final { public: @@ -49,17 +59,36 @@ class AnimationComponent final void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } - void SetBoneMatrices(std::vector boneMatrices) { m_boneMatrices = cd::MoveTemp(boneMatrices); } - std::vector& GetBoneMatrices() { return m_boneMatrices; } - const std::vector& GetBoneMatrices() const { return m_boneMatrices; } + void SetAnimationPlayTime(float time) { m_animationPlayTime = time; } + float& GetAnimationPlayTime() { return m_animationPlayTime; } + + void SetAnimationPlaySpped(float time) { m_animationPlayTime = time; } + float& GetAnimationPlaySpeed() { return m_animationPlayTime; } + + void SetAnimationClip(AnimationClip crtClip) { m_clip = crtClip; } + AnimationClip& GetAnimationClip() { return m_clip; } + const AnimationClip& GeAnimationClip() const { return m_clip; } + + void SetBlendFactor(float factor) { m_blendFactor = factor; } + float& GetBlendFactor() { return m_blendFactor; } + const float& GetBlendFactor() const { return m_blendFactor; } + + bool& GetIsPlaying() { return m_playAnimation; } private: + AnimationClip m_clip = AnimationClip::Idel; const cd::Animation* m_pAnimation = nullptr; const cd::Track* m_pTrack = nullptr; + + float m_blendFactor = 0.0f; + bool m_playAnimation = false; + float m_animationPlaySpeed; + float m_animationPlayTime; float m_duration; float m_ticksPerSecond; uint16_t m_boneMatricesUniform; + uint16_t m_vertexMatricesUniform; std::vector m_boneMatrices; }; diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp index de096523..a0adc38b 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -34,6 +34,7 @@ SceneWorld::SceneWorld() m_pMaterialComponentStorage = m_pWorld->Register(); m_pNameComponentStorage = m_pWorld->Register(); m_pShaderVariantCollectionsComponentStorage = m_pWorld->Register(); + m_pSkinMeshComponentStorage = m_pWorld->Register(); m_pSkyComponentStorage = m_pWorld->Register(); m_pStaticMeshComponentStorage = m_pWorld->Register(); m_pParticleComponentStorage = m_pWorld->Register(); @@ -145,6 +146,11 @@ void SceneWorld::CreateTerrainMaterialType() m_pTerrainMaterialType->SetRequiredVertexFormat(cd::MoveTemp(terrainVertexFormat)); } +void SceneWorld::SetSelectedBoneID(cd::BoneID boneID) +{ + CD_TRACE("Select BoneID : {0}", boneID.Data()); + m_selectedBoneID = boneID; +} void SceneWorld::SetSelectedEntity(engine::Entity entity) { diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index 074b69a7..82aa0a95 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -39,6 +39,7 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Material); DEFINE_COMPONENT_STORAGE_WITH_APIS(Name); DEFINE_COMPONENT_STORAGE_WITH_APIS(ShaderVariantCollections); + DEFINE_COMPONENT_STORAGE_WITH_APIS(SkinMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(Particle); @@ -61,6 +62,9 @@ class SceneWorld void SetSelectedEntity(engine::Entity entity); CD_FORCEINLINE engine::Entity GetSelectedEntity() const { return m_selectedEntity; } + void SetSelectedBoneID(cd::BoneID boneID); + CD_FORCEINLINE cd::BoneID GetSelectedBoneID() const { return m_selectedBoneID; } + void SetMainCameraEntity(engine::Entity entity); CD_FORCEINLINE engine::Entity GetMainCameraEntity() const { return m_mainCameraEntity; } @@ -101,6 +105,7 @@ class SceneWorld DeleteMaterialComponent(entity); DeleteNameComponent(entity); DeleteShaderVariantCollectionsComponent(entity); + DeleteSkinMeshComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); DeleteParticleComponent(entity); @@ -143,6 +148,7 @@ class SceneWorld std::unique_ptr m_pDDGIMaterialType; // TODO : wrap them into another class? + cd::BoneID m_selectedBoneID = cd::BoneID::InvalidID; engine::Entity m_selectedEntity = engine::INVALID_ENTITY; engine::Entity m_mainCameraEntity = engine::INVALID_ENTITY; diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp index da1fdbf5..8e3a6223 100644 --- a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp @@ -16,4 +16,21 @@ void SkinMeshComponent::Build() } +void SkinMeshComponent::SetBoneMatricesSize(uint32_t boneCount) +{ + m_boneGlobalMatrices.resize(boneCount); + m_boneMatrices.resize(boneCount); + for (uint32_t i = 0; i < boneCount; ++i) + { + m_boneGlobalMatrices[i] = cd::Matrix4x4::Identity(); + m_boneMatrices[i] = cd::Matrix4x4::Identity(); + } +} + +void SkinMeshComponent::SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneChangeMatrix) +{ + m_boneGlobalMatrices[index] = boneChangeMatrix; + m_changeBoneIndex = index; +} + } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h index 67e4f7ed..fdc26998 100644 --- a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h @@ -31,18 +31,40 @@ class SkinMeshComponent final SkinMeshComponent& operator=(SkinMeshComponent&&) = default; ~SkinMeshComponent() = default; - uint16_t GetBonePositionBuffer() const { return m_boneVBH; } - uint16_t GetIndexBuffer() const { return m_boneIBH; } + void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } + uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } + + void SetBoneVBH(uint16_t boneVBH) { m_boneVBH = boneVBH; } + uint16_t GetBoneVBH() const { return m_boneVBH; } + + void SetBoneIBH(uint16_t boneIBH) { m_boneIBH = boneIBH; } + uint16_t GetBoneIBH() const { return m_boneIBH; } + + void SetBoneMatricesSize(uint32_t boneCount); + void SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneChangeMatrix); + const cd::Matrix4x4& GetBoneGlobalMatrix(uint32_t index) { return m_boneGlobalMatrices[index]; } + const std::vector& GetBoneGlobalMatrices() const { return m_boneGlobalMatrices; } + uint32_t GetChangeBoneIndex() const { return m_changeBoneIndex; } + void SetChangeBoneIndex(uint32_t index) {m_changeBoneIndex = index;} + void ResetChangeBoneIndex() { m_changeBoneIndex = engine::INVALID_ENTITY; } + + void SetBoneMatrix(uint32_t index, const cd::Matrix4x4& changeMatrix) { m_boneMatrices[index] = changeMatrix * m_boneMatrices[index]; } + const cd::Matrix4x4& GetBoneMatrix(uint32_t index) { return m_boneMatrices[index]; } void Reset(); void Build(); private: + //input + uint32_t m_changeBoneIndex = engine::INVALID_ENTITY; + //output - std::vector m_vertexBuffer; - std::vector m_indexBuffer; uint16_t m_boneVBH = UINT16_MAX; uint16_t m_boneIBH = UINT16_MAX; + uint16_t m_boneMatricesUniform; + + std::vector m_boneGlobalMatrices; + std::vector m_boneMatrices; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp index 8617c737..99b50303 100644 --- a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp @@ -6,10 +6,9 @@ #include "ECWorld/TransformComponent.h" #include "RenderContext.h" #include "Scene/Texture.h" - +#include "Log/Log.h" #include -//#include - +//#define VISUALIZE_BONE_WEIGHTS namespace engine { @@ -122,7 +121,7 @@ void CalculateBoneTransform(std::vector& boneMatrices, const cd:: } cd::Matrix4x4 globalTransform = parentBoneTransform * boneLocalTransform; - boneMatrices[bone.GetID().Data()] = globalInverse * globalTransform * bone.GetOffset(); + boneMatrices[bone.GetID().Data()] = bone.GetOffset() * globalTransform; for (cd::BoneID boneID : bone.GetChildIDs()) { @@ -131,13 +130,108 @@ void CalculateBoneTransform(std::vector& boneMatrices, const cd:: } }; +void CalculateVertexTransform(std::vector& vertexMatrices, const cd::SceneDatabase* pSceneDatabase, + float animationTime, const cd::Bone& bone) +{ + auto CalculateInterpolatedTranslation = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::Zero(); + }; + + auto CalculateInterpolatedRotation = [&animationTime](const cd::Track* pTrack) -> cd::Quaternion + { + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Quaternion::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + } + } + + return cd::Quaternion::Identity(); + }; + + auto CalculateInterpolatedScale = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::One(); + }; + + cd::Matrix4x4 vertexLocalTransform = cd::Matrix4x4::Identity(); + if (const cd::Track* pTrack = pSceneDatabase->GetTrackByName(bone.GetName())) + { + vertexLocalTransform = cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix() * bone.GetOffset(); + } + + vertexMatrices[bone.GetID().Data()] = vertexLocalTransform; + + for (cd::BoneID boneID : bone.GetChildIDs()) + { + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + CalculateVertexTransform(vertexMatrices, pSceneDatabase, animationTime, childBone); + } +} + } void AnimationRenderer::Init() { #ifdef VISUALIZE_BONE_WEIGHTS - m_pRenderContext->CreateUniform("u_debugBoneIndex", bgfx::UniformType::Vec4, 1); - m_pRenderContext->CreateProgram("AnimationProgram", "vs_visualize_bone_weight.bin", "fs_visualize_bone_weight.bin"); + GetRenderContext()->CreateUniform("u_debugBoneIndex", bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateProgram("AnimationProgram", "vs_visualize_bone_weight.bin", "fs_visualize_bone_weight.bin"); #else GetRenderContext()->CreateProgram("AnimationProgram", "vs_animation.bin", "fs_animation.bin"); #endif @@ -154,29 +248,16 @@ void AnimationRenderer::UpdateView(const float* pViewMatrix, const float* pProje void AnimationRenderer::Render(float deltaTime) { #ifdef VISUALIZE_BONE_WEIGHTS - constexpr float changeTime = 0.2f; - static float passedTime = 0.0f; - static float selectedBoneIndex[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - passedTime += deltaTime; - if (passedTime > changeTime) - { - selectedBoneIndex[0] = selectedBoneIndex[0] + 1.0f; - if (selectedBoneIndex[0] > 100.0f) - { - selectedBoneIndex[0] = 0.0f; - } - passedTime -= changeTime; - } - + float boneIndex = static_cast(m_pCurrentSceneWorld->GetSelectedBoneID().Data()); + float selectedBoneIndex[4] = { boneIndex, 0.0f, 0.0f, 0.0f }; constexpr StringCrc boneIndexUniform("u_debugBoneIndex"); - bgfx::setUniform(m_pRenderContext->GetUniform(boneIndexUniform), selectedBoneIndex, 1); + bgfx::setUniform(GetRenderContext()->GetUniform(boneIndexUniform), selectedBoneIndex, 1); #endif static float animationRunningTime = 0.0f; - animationRunningTime += deltaTime; const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) + for (Entity entity : m_pCurrentSceneWorld->GetSkinMeshEntities()) { StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(entity); if (!pMeshComponent) @@ -186,27 +267,7 @@ void AnimationRenderer::Render(float deltaTime) TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity); bgfx::setTransform(pTransformComponent->GetWorldMatrix().Begin()); - - AnimationComponent* pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); - - const cd::Animation* pAnimation = pAnimationComponent->GetAnimationData(); - float ticksPerSecond = pAnimation->GetTicksPerSecnod(); - assert(ticksPerSecond > 1.0f); - float animationTime = details::CustomFModf(animationRunningTime * ticksPerSecond, pAnimation->GetDuration()); - - static std::vector boneMatrices; - boneMatrices.clear(); - for (uint16_t boneIndex = 0; boneIndex < 128; ++boneIndex) - { - boneMatrices.push_back(cd::Matrix4x4::Identity()); - } - - const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - details::CalculateBoneTransform(boneMatrices, pSceneDatabase, animationTime, rootBone, - cd::Matrix4x4::Identity(), pTransformComponent->GetWorldMatrix().Inverse()); - bgfx::setUniform(bgfx::UniformHandle{pAnimationComponent->GetBoneMatrixsUniform()}, boneMatrices.data(), static_cast(boneMatrices.size())); - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{pMeshComponent->GetVertexBuffer()}); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{pMeshComponent->GetIndexBuffer()}); + UpdateStaticMeshComponent(pMeshComponent); constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; bgfx::setState(state); diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp index be0fb0af..c118f524 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp @@ -2,9 +2,10 @@ #include "Core/StringCrc.h" #include "ECWorld/SceneWorld.h" -#include "ECWorld/TransformComponent.h" +#include "ECWorld/SkinMeshComponent.h" #include "RenderContext.h" #include "Rendering/Utility/VertexLayoutUtility.h" +#include "Window/Input.h" namespace engine { @@ -12,51 +13,278 @@ namespace engine namespace details { -constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); +float CustomFMod(float dividend, float divisor) +{ + if (divisor == 0.0f) + { + return 0.0f; + } -constexpr size_t indexTypeSize = sizeof(uint16_t); + int quotient = static_cast(dividend / divisor); + float result = dividend - static_cast(quotient) * divisor; + + if (result == 0.0f && dividend != 0.0f) + { + result = 0.0f; + } + if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) + { + result = -result; + } + return result; +} -cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, const cd::SceneDatabase* pSceneDatabase) +cd::Matrix4x4 CalculateRootBoneTransform(const cd::SceneDatabase* pSceneDatabase, float animationTime, const char* clipName) { - const cd::Bone& parentBone = pSceneDatabase->GetBone(bone.GetParentID().Data()); - translate += parentBone.GetTransform().GetTranslation(); - if (0U != bone.GetParentID().Data()) + auto CalculateInterpolatedTranslation = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + const auto& Key = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedRotation = [&animationTime](const cd::Track* pTrack) -> cd::Quaternion + { + /* if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + } + }*/ + + return cd::Quaternion::Identity(); + }; + + auto CalculateInterpolatedScale = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (animationTime < nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::One(); + }; + + cd::Matrix4x4 boneLocalTransform = cd::Matrix4x4::Identity(); + if (const cd::Track* pTrack = pSceneDatabase->GetTrackByName((std::string(clipName) + pSceneDatabase->GetBone(0).GetName()).c_str())) { - CalculateBoneTranslate(parentBone, translate, pSceneDatabase); + boneLocalTransform = cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix() * pSceneDatabase->GetBone(0).GetOffset();; } - return translate; + + return boneLocalTransform; } -void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, - std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +void CalculateTransform(std::vector& boneMatrices, const cd::SceneDatabase* pSceneDatabase, + float animationTime, const cd::Bone& bone, const char* clipName, SkinMeshComponent* pSkinmeshConponent,cd::Matrix4x4& globalMatrix, const cd::Matrix4x4 rootBoonTransform) { - constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); - for (auto& child : bone.GetChildIDs()) + auto CalculateInterpolatedTranslation = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + + } + const auto& Key = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedRotation = [&animationTime](const cd::Track* pTrack) -> cd::Quaternion + { + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + } + } + const auto& Key = pTrack->GetRotationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedScale = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::One(); + }; + + cd::Matrix4x4 deltaTransform = cd::Matrix4x4::Identity(); + + if (const cd::Track* pTrack = pSceneDatabase->GetTrackByName((std::string(clipName) + bone.GetName()).c_str())) { - const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); - const cd::Bone& parent = pSceneDatabase->GetBone(currBone.GetParentID().Data()); - cd::Vec3f translate = currBone.GetOffset().GetTranslation(); - - //const cd::Vec3f position = details::CalculateBoneTranslate(currBone, translate, pSceneDatabase); - - uint16_t parentID = currBone.GetParentID().Data(); - uint16_t currBoneID = currBone.GetID().Data(); - std::memcpy(¤tDataPtr[vertexOffset], translate.Begin(), posDataSize); - vertexOffset += posDataSize; - std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); - std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); - - TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + if (0 == bone.GetID().Data()) + { + deltaTransform = pSkinmeshConponent->GetBoneGlobalMatrix(0).Inverse() * cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + } + else + { + cd::Matrix4x4 parent = pSkinmeshConponent->GetBoneGlobalMatrix(bone.GetParentID().Data()); + cd::Matrix4x4 curBoneGlobalMatrix = pSkinmeshConponent->GetBoneGlobalMatrix(bone.GetParentID().Data()) * cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + cd::Matrix4x4 local = cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + deltaTransform = pSkinmeshConponent->GetBoneGlobalMatrix(bone.GetID().Data()).Inverse() * curBoneGlobalMatrix; + } + } + cd::Matrix4x4 global = pSkinmeshConponent->GetBoneGlobalMatrix(bone.GetID().Data()) * deltaTransform; + pSkinmeshConponent->SetBoneGlobalMatrix(bone.GetID().Data(), global); + boneMatrices[bone.GetID().Data()] = deltaTransform; + + for (cd::BoneID boneID : bone.GetChildIDs()) + { + + cd::Matrix4x4 curGlobalMatrix = global; + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + CalculateTransform(boneMatrices, pSceneDatabase, animationTime, childBone, clipName, pSkinmeshConponent, curGlobalMatrix, rootBoonTransform); } } +void BlendTwoPos(std::vector& blendBoneMatrices, std::vector& BoneMatricesA, std::vector& BoneMatricesB, float animationRunningTime, float factor, const cd::SceneDatabase* pSceneDatabase) +{ + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration(); + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration(); + const float blendTime = clipATime + (clipBTime - clipATime) * factor; + float clipARunningTime = CustomFMod(animationRunningTime, clipATime); + float clipBRunningTime = CustomFMod(animationRunningTime, clipBTime); + float blendRunningTime = CustomFMod(animationRunningTime, blendTime); + float blendTimeProgress = animationRunningTime / blendTime; + + /*CalculateTransform(BoneMatricesA, pSceneDatabase, clipATime * blendTimeProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(0).GetName(), CalculateRootBoneTransform(pSceneDatabase, clipARunningTime, pSceneDatabase->GetAnimation(0).GetName())); + CalculateTransform(BoneMatricesB, pSceneDatabase, clipBTime * blendTimeProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(1).GetName(), CalculateRootBoneTransform(pSceneDatabase, clipBRunningTime, pSceneDatabase->GetAnimation(1).GetName()));*/ + //CalculateTransform(BoneMatricesA, pSceneDatabase, clipATime * blendTimeProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(0).GetName(), cd::Matrix4x4::Identity()); + //CalculateTransform(BoneMatricesB, pSceneDatabase, clipBTime * blendTimeProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(1).GetName(), cd::Matrix4x4::Identity()); + for (auto& bone : pSceneDatabase->GetBones()) + { + cd::Vec3f translationA = BoneMatricesA[bone.GetID().Data()].GetTranslation(); + cd::Quaternion rotationA = cd::Quaternion::FromMatrix(BoneMatricesA[bone.GetID().Data()].GetRotation()); + cd::Vec3f scaleA = BoneMatricesA[bone.GetID().Data()].GetScale(); + cd::Vec3f translationB = BoneMatricesB[bone.GetID().Data()].GetTranslation(); + cd::Quaternion rotationB = cd::Quaternion::FromMatrix(BoneMatricesB[bone.GetID().Data()].GetRotation()); + cd::Vec3f scaleB = BoneMatricesB[bone.GetID().Data()].GetScale(); + + cd::Transform transA = cd::Transform(translationA, rotationA, scaleA); + cd::Transform transB = cd::Transform(translationB, rotationB, scaleB); + cd::Vec3f blendTranslation = cd::Vec3f::Lerp(transA.GetTranslation(), transB.GetTranslation(), factor); + cd::Quaternion blendRotation = cd::Quaternion::Lerp(rotationA, rotationB, factor); + cd::Vec3f blendScale = cd::Vec3f::Lerp(transA.GetScale(), transB.GetScale(), factor); + cd::Vec3f blenda = blendRotation.ToEulerAngles(); + + cd::Matrix4x4 matrixA = BoneMatricesA[bone.GetID().Data()]; + cd::Matrix4x4 matrixB = BoneMatricesB[bone.GetID().Data()]; + cd::Vec4f col0 = matrixA.GetColumn(0) + (matrixB.GetColumn(0) - matrixA.GetColumn(0)) * factor; + cd::Vec4f col1 = matrixA.GetColumn(1) + (matrixB.GetColumn(1) - matrixA.GetColumn(1)) * factor; + cd::Vec4f col2 = matrixA.GetColumn(2) + (matrixB.GetColumn(2) - matrixA.GetColumn(2)) * factor; + cd::Vec4f col3 = matrixA.GetColumn(3) + (matrixB.GetColumn(3) - matrixA.GetColumn(3)) * factor; + cd::Matrix4x4 matrixBlend(col0,col1,col2,col3); + cd::Quaternion rotation = cd::Quaternion::FromMatrix(matrixBlend.GetRotation()); + cd::Vec3f blendb = rotation.ToEulerAngles(); + cd::Matrix4x4 boneLocalTranform = cd::Transform(blendTranslation, blendRotation, blendScale).GetMatrix(); + blendBoneMatrices[bone.GetID().Data()] = matrixBlend; + } +} + } void SkeletonRenderer::Init() { - GetRenderContext()->CreateProgram("SkeletonProgram", "vs_AABB.bin", "fs_AABB.bin"); + GetRenderContext()->CreateProgram("SkeletonProgram", "vs_skeleton.bin", "fs_AABB.bin"); bgfx::setViewName(GetViewID(), "SkeletonRenderer"); } @@ -66,69 +294,124 @@ void SkeletonRenderer::UpdateView(const float* pViewMatrix, const float* pProjec bgfx::setViewTransform(GetViewID(), pViewMatrix, pProjectionMatrix); } -void SkeletonRenderer::Build() +void SkeletonRenderer::Render(float deltaTime) { + static float animationRunningTime = 0.0f; + static float playTime = 0.0f;//for replay one animation + static cd::Matrix4x4 rootTransform = cd::Matrix4x4::Identity(); + static cd::Matrix4x4 deltaRootTransform = cd::Matrix4x4::Identity(); + cd::Matrix4x4 beforRootTransform = cd::Matrix4x4::Identity(); + cd::Matrix4x4 nowRootTransform = cd::Matrix4x4::Identity(); const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - - const uint32_t vertexCount = pSceneDatabase->GetBoneCount(); - if (0 == vertexCount) + for (Entity entity : m_pCurrentSceneWorld->GetSkinMeshEntities()) { - return; - } - - const cd::Bone& firstBone = pSceneDatabase->GetBone(0); - if (0 != firstBone.GetID().Data()) - { - CD_ENGINE_WARN("First BoneID is not 0"); - return; - } - - bgfx::setTransform(cd::Matrix4x4::Identity().Begin()); - cd::VertexFormat vertexFormat; - vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); - - constexpr size_t indexTypeSize = sizeof(uint16_t); - m_indexBuffer.resize((vertexCount - 1) * 2 * indexTypeSize); - m_vertexBuffer.resize(vertexCount * vertexFormat.GetStride()); - uint32_t currentVertexOffset = 0U; - uint32_t currentIndexOffset = 0U; - std::byte* pCurrentVertexBuffer = m_vertexBuffer.data(); - const cd::Point& position = firstBone.GetTransform().GetTranslation(); - std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], position.Begin(), details::posDataSize); - currentVertexOffset += details::posDataSize; - - details::TraverseBone(firstBone, pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), currentVertexOffset, currentIndexOffset); - bgfx::VertexLayout vertexLayout; - VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); - m_boneVBH = bgfx::createVertexBuffer(bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())), vertexLayout).idx; - m_boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(m_indexBuffer.data(), static_cast(m_indexBuffer.size())), 0U).idx; + auto pSkinMeshComponent = m_pCurrentSceneWorld->GetSkinMeshComponent(entity); + if (!pSkinMeshComponent) + { + continue; + } -} + AnimationComponent* pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); + TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity); + const char* clipName; + float ticksPerSecond = 0.0f; + float duration = 0.0f; + bool isLoopOut = false; + if (pAnimationComponent && pAnimationComponent->GetIsPlaying()) + { + animationRunningTime += deltaTime; + } + static std::vector globalDeltaBoneMatrix; + static std::vector boneMatrixA; + static std::vector boneMatrixB; + globalDeltaBoneMatrix.clear(); + boneMatrixA.clear(); + boneMatrixB.clear(); + for (uint16_t boneIndex = 0; boneIndex < 128; ++boneIndex) + { + globalDeltaBoneMatrix.push_back(cd::Matrix4x4::Identity()); + boneMatrixA.push_back(cd::Matrix4x4::Identity()); + boneMatrixB.push_back(cd::Matrix4x4::Identity()); + } + if (engine::AnimationClip::Idel == pAnimationComponent->GetAnimationClip()) + { + cd::Matrix4x4 rootBone = cd::Matrix4x4::Identity(); + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(0); + clipName = pSceneDatabase->GetAnimation(0).GetName(); + duration = pSceneDatabase->GetAnimation(0).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(0).GetTicksPerSecnod(); + + float animationTime = details::CustomFMod(animationRunningTime, duration); + pAnimationComponent->SetAnimationPlayTime(animationTime); + cd::Matrix4x4 curBoneGlobalMatrix = pSkinMeshComponent->GetBoneGlobalMatrix(0); + //if (animationTime >= playTime) + { + nowRootTransform = details::CalculateRootBoneTransform(pSceneDatabase, animationTime, clipName); + playTime = animationTime; + CD_INFO(animationTime); + details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, deltaRootTransform); + } + /* else + { + beforRootTransform = details::CalculateRootBoneTransform(pSceneDatabase, duration, clipName); + CD_INFO("loopTime"); + CD_INFO(playTime); + deltaRootTransform = beforRootTransform * deltaRootTransform; + playTime = animationTime; + details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, duration, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, deltaRootTransform); + }*/ + //pTransformComponent->SetTransform(cd::Transform(rootTransform.GetTranslation(), cd::Quaternion::FromMatrix(rootTransform.GetRotation()), rootTransform.GetScale())); + //details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, deltaRootTransform); -void SkeletonRenderer::Render(float delataTime) -{ - for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) - { - auto pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); - if (!pAnimationComponent) + } + else if (engine::AnimationClip::Walking == pAnimationComponent->GetAnimationClip()) { - continue; + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(1); + clipName = pSceneDatabase->GetAnimation(1).GetName(); + duration = pSceneDatabase->GetAnimation(1).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecnod(); + float animationTime = details::CustomFMod(animationRunningTime, duration); + cd::Matrix4x4 rootBoneInserve = details::CalculateRootBoneTransform(pSceneDatabase, animationTime, clipName); + //details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, rootBoneInserve); } - if (!hasBuilt) + else if (engine::AnimationClip::Running == pAnimationComponent->GetAnimationClip()) { - Build(); - hasBuilt = true; + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(2); + clipName = pSceneDatabase->GetAnimation(2).GetName(); + duration = pSceneDatabase->GetAnimation(2).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecnod(); + float animationTime = details::CustomFMod(animationRunningTime, duration); + cd::Matrix4x4 rootBoneInserve = details::CalculateRootBoneTransform(pSceneDatabase, animationTime, clipName); + //details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, cd::Matrix4x4::Identity()); } + else if (engine::AnimationClip::Blend == pAnimationComponent->GetAnimationClip()) + { + float factor = pAnimationComponent->GetBlendFactor(); + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration(); + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration(); + const float blendTime = clipATime + (clipBTime - clipATime) * factor; + float clipARunningTime = details::CustomFMod(animationRunningTime, clipATime); + float clipBRunningTime = details::CustomFMod(animationRunningTime, clipBTime); + float blendRunningTime = details::CustomFMod(animationRunningTime, blendTime); + float blendTimeProgress = blendRunningTime / blendTime; + details::BlendTwoPos(globalDeltaBoneMatrix, boneMatrixA, boneMatrixB, blendRunningTime, factor, pSceneDatabase); + } + + + //assert(ticksPerSecond > 1.0f); + float animationTime = details::CustomFMod(animationRunningTime, duration); - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ m_boneVBH }); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ m_boneIBH }); + bgfx::setUniform(bgfx::UniformHandle{ pSkinMeshComponent->GetBoneMatrixsUniform() }, globalDeltaBoneMatrix.data(), static_cast(globalDeltaBoneMatrix.size())); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pSkinMeshComponent->GetBoneVBH() }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pSkinMeshComponent->GetBoneIBH() }); - constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); constexpr StringCrc SkeletonProgram("SkeletonProgram"); bgfx::submit(GetViewID(), GetRenderContext()->GetProgram(SkeletonProgram)); + } } diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h index 81632f97..23ab26cc 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h @@ -16,17 +16,10 @@ class SkeletonRenderer final : public Renderer virtual void Init() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; - void Build(); void SetSceneWorld(SceneWorld* pSceneWorld) { m_pCurrentSceneWorld = pSceneWorld; } private: SceneWorld* m_pCurrentSceneWorld = nullptr; - std::vector m_vertexBuffer; - std::vector m_indexBuffer; - uint16_t m_boneVBH = UINT16_MAX; - uint16_t m_boneIBH = UINT16_MAX; - - bool hasBuilt = false; }; } \ No newline at end of file