Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skeleton can be edited #383

Closed
wants to merge 19 commits into from
87 changes: 87 additions & 0 deletions Engine/BuiltInShaders/shaders/fs_vertex_weight.sc
Original file line number Diff line number Diff line change
@@ -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);
}
}
12 changes: 12 additions & 0 deletions Engine/BuiltInShaders/shaders/vs_skeleton.sc
Original file line number Diff line number Diff line change
@@ -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);
}
13 changes: 13 additions & 0 deletions Engine/BuiltInShaders/shaders/vs_vertex_weight.sc
Original file line number Diff line number Diff line change
@@ -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;
}
116 changes: 112 additions & 4 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,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(&currentDataPtr[vertexOffset], curGlobalMatrix.GetTranslation().Begin(), posDataSize);
//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.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) :
Expand All @@ -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());

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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -419,4 +472,59 @@ void ECWorldConsumer::AddMorphs(engine::Entity entity, const std::vector<cd::Mor
blendShapeComponent.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();
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<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 @@ -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);
Expand Down
Loading