Skip to content

Commit

Permalink
skeleton can be edited
Browse files Browse the repository at this point in the history
  • Loading branch information
VTui22 committed Sep 11, 2023
1 parent 93fc8a9 commit 040f6e1
Show file tree
Hide file tree
Showing 14 changed files with 270 additions and 117 deletions.
13 changes: 13 additions & 0 deletions Engine/BuiltInShaders/shaders/vs_skeleton.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
$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);
}
107 changes: 107 additions & 0 deletions Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <algorithm>
Expand Down Expand Up @@ -37,6 +38,56 @@ 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);

cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, const cd::SceneDatabase* pSceneDatabase)
{
const cd::Bone& parentBone = pSceneDatabase->GetBone(bone.GetParentID().Data());
translate += parentBone.GetTransform().GetTranslation();
if (0U != bone.GetParentID().Data())
{
CalculateBoneTranslate(parentBone, translate, pSceneDatabase);
}
return translate;
}

void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, engine::SkinMeshComponent& skinmeshComponent, std::byte* currentDataPtr,
std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset)
{
for (auto& child : bone.GetChildIDs())
{
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(&currentDataPtr[vertexOffset], translate.Begin(), posDataSize);
vertexOffset += posDataSize;

uint16_t boneID[4] = { currBoneID, 0, 0, 0 };
std::memcpy(&currentDataPtr[vertexOffset], boneID, indexDataSize);
vertexOffset += indexDataSize;

std::memcpy(&currentIndexPtr[indexOffset], &parentID, indexTypeSize);
indexOffset += static_cast<uint32_t>(indexTypeSize);

std::memcpy(&currentIndexPtr[indexOffset], &currBoneID, indexTypeSize);
indexOffset += static_cast<uint32_t>(indexTypeSize);

const cd::Matrix4x4& boneMatrix = currBone.GetOffset();
skinmeshComponent.SetBoneMatrix(currBoneID, boneMatrix);

TraverseBone(currBone, pSceneDatabase, skinmeshComponent, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset);
}
}

} // namespace Detail

ECWorldConsumer::ECWorldConsumer(engine::SceneWorld* pSceneWorld, engine::RenderContext* pRenderContext) :
Expand Down Expand Up @@ -82,6 +133,7 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase)
// Currently, we assume that imported SkinMesh will play animation automatically for testing.
AddAnimation(meshEntity, pSceneDatabase->GetAnimation(0), pSceneDatabase);
AddMaterial(meshEntity, nullptr, pMaterialType, pSceneDatabase);
AddSkeleton(meshEntity, pSceneDatabase);
}
};

Expand Down Expand Up @@ -372,4 +424,59 @@ void ECWorldConsumer::AddMaterial(engine::Entity entity, const cd::Material* pMa
materialComponent.Build();
}

void ECWorldConsumer::AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase)
{
engine::World* pWorld = m_pSceneWorld->GetWorld();
engine::SkinMeshComponent& skinmeshComponent = pWorld->CreateComponent<engine::SkinMeshComponent>(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<std::byte> vertexBuffer;
static std::vector<std::byte> 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();
const cd::Point& position = firstBone.GetOffset().GetTranslation();
uint16_t BoneID = firstBone.GetID().Data();
std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], position.Begin(), Detail::posDataSize);
currentVertexOffset += Detail::posDataSize;

uint16_t currBoneID[4] = { BoneID, 0, 0, 0 };
std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], currBoneID, Detail::indexDataSize);
currentVertexOffset += Detail::indexDataSize;

const cd::Matrix4x4& boneMatrix = firstBone.GetOffset();
skinmeshComponent.SetBoneMatrix(BoneID, boneMatrix);

Detail::TraverseBone(firstBone, 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<uint32_t>(vertexBuffer.size())), vertexLayout).idx;
uint16_t boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(indexBuffer.data(), static_cast<uint32_t>(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);
}

}
1 change: 1 addition & 0 deletions Engine/Source/Editor/ECWorld/ECWorldConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,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);
Expand Down
5 changes: 4 additions & 1 deletion Engine/Source/Editor/EditorApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,11 @@ void EditorApp::InitEditorUILayers()
pSceneView->SetAABBRenderer(m_pAABBRenderer);
m_pEditorImGuiContext->AddDynamicLayer(cd::MoveTemp(pSceneView));

auto pSkeletonView = std::make_unique<SkeletonView>("SkeletonView");
pSkeletonView->SetCameraController(m_pViewportCameraController.get());
m_pEditorImGuiContext->AddDynamicLayer(cd::MoveTemp(pSkeletonView));

m_pEditorImGuiContext->AddDynamicLayer(std::make_unique<Inspector>("Inspector"));
m_pEditorImGuiContext->AddDynamicLayer(std::make_unique<SkeletonView>("SkeletonView"));

auto pAssetBrowser = std::make_unique<AssetBrowser>("AssetBrowser");
pAssetBrowser->SetSceneRenderer(m_pSceneRenderer);
Expand Down
43 changes: 32 additions & 11 deletions Engine/Source/Editor/UILayers/ImGuizmoView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "ECWorld/CameraComponent.h"
#include "ECWorld/SceneWorld.h"
#include "ECWorld/SkinMeshComponent.h"
#include "ECWorld/StaticMeshComponent.h"
#include "ECWorld/TransformComponent.h"
#include "ImGui/ImGuiContextInstance.h"
Expand All @@ -27,18 +28,19 @@ void ImGuizmoView::Init()
void ImGuizmoView::Update()
{
engine::SceneWorld* pSceneWorld = GetSceneWorld();
cd::SceneDatabase* pSceneDatabese = pSceneWorld->GetSceneDatabase();
engine::Entity selectedEntity = pSceneWorld->GetSelectedEntity();
cd::BoneID selectedBoneID = pSceneWorld->GetSelectedBoneID();

if (engine::INVALID_ENTITY == selectedEntity)
if (engine::INVALID_ENTITY == selectedEntity && cd::BoneID::InvalidID == selectedBoneID)
{
return;
}

cd::Matrix4x4 worldMatrix = cd::Matrix4x4::Identity();
cd::Matrix4x4 deltaMatrix = cd::Matrix4x4::Identity();
engine::TransformComponent* pTransformComponent = pSceneWorld->GetTransformComponent(selectedEntity);
if (!pTransformComponent)
{
return;
}
engine::SkinMeshComponent* pSkinMeshComponent = pSceneWorld->GetSkinMeshComponent(selectedEntity);

ImGuizmo::OPERATION operation = m_pSceneView->GetImGuizmoOperation();
const engine::CameraComponent* pCameraComponent = pSceneWorld->GetCameraComponent(pSceneWorld->GetMainCameraEntity());
Expand All @@ -48,18 +50,32 @@ void ImGuizmoView::Update()
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 (engine::INVALID_ENTITY != selectedEntity && pTransformComponent)
{
cd::Matrix4x4 worldMatrix = pTransformComponent->GetWorldMatrix();
ImGuizmo::Manipulate(pCameraComponent->GetViewMatrix().Begin(), pCameraComponent->GetProjectionMatrix().Begin(),
operation, ImGuizmo::LOCAL, worldMatrix.Begin());
}
if (cd::BoneID::InvalidID != selectedBoneID && pSkinMeshComponent)
{
uint32_t index = selectedBoneID.Data();
auto matrices = pSkinMeshComponent->GetBoneChangeMatrices();
cd::Matrix4x4 worldMatrix = pSkinMeshComponent->GetBoneMatrix(index);
ImGuizmo::Manipulate(pCameraComponent->GetViewMatrix().Begin(), pCameraComponent->GetProjectionMatrix().Begin(),
operation, ImGuizmo::LOCAL, worldMatrix.Begin(), deltaMatrix.Begin());
}

if (ImGuizmo::IsUsing())
{
if (ImGuizmo::OPERATION::TRANSLATE & operation)
{
pTransformComponent->GetTransform().SetTranslation(worldMatrix.GetTranslation());
pTransformComponent->Dirty();
if (pTransformComponent)
{
pTransformComponent->GetTransform().SetTranslation(worldMatrix.GetTranslation());
pTransformComponent->Dirty();
}
}

if (ImGuizmo::OPERATION::ROTATE & operation)
{
pTransformComponent->GetTransform().SetRotation(cd::Quaternion::FromMatrix(worldMatrix.GetRotation()));
Expand All @@ -73,6 +89,11 @@ void ImGuizmoView::Update()
}

pTransformComponent->Build();
if (pSkinMeshComponent)
{
//pSkinMeshComponent->SetBoneMatrix(selectedBoneID.Data(), worldMatrix);
pSkinMeshComponent->SetBoneChangeMatrix(selectedBoneID.Data(), deltaMatrix);
}
}
}

Expand Down
34 changes: 25 additions & 9 deletions Engine/Source/Editor/UILayers/SkeletonView.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "SkeletonView.h"

#include "Display/CameraController.h"
#include "ECWorld/SceneWorld.h"
#include <imgui/imgui.h>
#include <ImGui/IconFont/IconsMaterialDesignIcons.h>
Expand All @@ -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());
Expand All @@ -26,15 +28,30 @@ 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(position);
}
}
}
}
ImGui::SameLine();
ImGui::Text(reinterpret_cast<const char*>(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();
Expand All @@ -49,13 +66,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)
Expand All @@ -65,7 +81,7 @@ void SkeletonView::Update()
}
engine::AnimationComponent* pAnimationConponent = pSceneWorld->GetAnimationComponent(selectedEntity);
if (pAnimationConponent)
{
{
DrawSkeleton(pSceneWorld);
}

Expand Down
14 changes: 13 additions & 1 deletion Engine/Source/Editor/UILayers/SkeletonView.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
#include "Scene/Bone.h"
#include "Scene/SceneDatabase.h"

namespace engine
{

class CameraController;

}

namespace editor
{

Expand All @@ -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;
};

}
Expand Down
1 change: 1 addition & 0 deletions Engine/Source/Runtime/ECWorld/AllComponentsHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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"
Expand Down
6 changes: 6 additions & 0 deletions Engine/Source/Runtime/ECWorld/SceneWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ SceneWorld::SceneWorld()
m_pMaterialComponentStorage = m_pWorld->Register<engine::MaterialComponent>();
m_pNameComponentStorage = m_pWorld->Register<engine::NameComponent>();
m_pShaderVariantCollectionsComponentStorage = m_pWorld->Register<engine::ShaderVariantCollectionsComponent>();
m_pSkinMeshComponentStorage = m_pWorld->Register<engine::SkinMeshComponent>();
m_pSkyComponentStorage = m_pWorld->Register<engine::SkyComponent>();
m_pStaticMeshComponentStorage = m_pWorld->Register<engine::StaticMeshComponent>();
m_pParticleComponentStorage = m_pWorld->Register<engine::ParticleComponent>();
Expand Down Expand Up @@ -144,6 +145,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)
{
Expand Down
Loading

0 comments on commit 040f6e1

Please sign in to comment.