Split up MeshHierarchy into Skeleton and SkeletonMeshes, minor code style cleanup

master
Martin Felis 2017-02-23 15:19:26 +01:00
parent d1ada7f3a4
commit 6573a36c90
5 changed files with 158 additions and 77 deletions

View File

@ -64,31 +64,54 @@ CharacterEntity::CharacterEntity() {
// base_mesh->Update(); // base_mesh->Update();
// delete quad; // delete quad;
int bone_index;
// Build the snowman // Build the snowman
entity->mesh.addMesh(
- 1, // bottom sphere
bone_index = entity->mSkeleton.AddBone(
-1,
Transform::fromTrans( Transform::fromTrans(
Vector3f (0.0f, 0.9 * 0.5f, 0.0f) Vector3f (0.0f, 0.9 * 0.5f, 0.0f)
), )
// base_mesh
Mesh::sCreateUVSphere(45, 45, 0.9)
); );
entity->mSkeletonMeshes.AddMesh (
Mesh::sCreateUVSphere(45, 45, 0.9),
bone_index
);
gLog ("Now have %d bones, bone_index %d",
entity->mSkeleton.Length(),
bone_index);
entity->mesh.addMesh( // middle sphere
0, bone_index = entity->mSkeleton.AddBone(
bone_index,
Transform::fromTrans( Transform::fromTrans(
Vector3f (0.0f, 0.55f, 0.0f) Vector3f (0.0f, 0.55f, 0.0f)
), )
Mesh::sCreateUVSphere (45, 45, 0.7)
); );
entity->mSkeletonMeshes.AddMesh (
Mesh::sCreateUVSphere (45, 45, 0.7),
bone_index
);
gLog ("Now have %d bones, bone_index %d",
entity->mSkeleton.Length(),
bone_index);
entity->mesh.addMesh( // top sphere
1, bone_index = entity->mSkeleton.AddBone(
bone_index,
Transform::fromTrans( Transform::fromTrans(
Vector3f (0.0f, 0.4f, 0.0f) Vector3f (0.0f, 0.4f, 0.0f)
), )
Mesh::sCreateUVSphere (45, 45, 0.5)
); );
entity->mSkeletonMeshes.AddMesh (
Mesh::sCreateUVSphere (45, 45, 0.5),
bone_index
);
gLog ("Now have %d bones, bone_index %d",
entity->mSkeleton.Length(),
bone_index);
// mState->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f); // mState->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f);
// mState->character->entity->mesh = bgfxutils::createCylinder (20); // mState->character->entity->mesh = bgfxutils::createCylinder (20);
@ -208,7 +231,7 @@ void CharacterEntity::Update(float dt) {
} }
// apply transformation // apply transformation
entity->transform.translation.set( entity->mTransform.translation.set(
mPosition[0], mPosition[0],
mPosition[1], mPosition[1],
mPosition[2]); mPosition[2]);
@ -219,10 +242,10 @@ void CharacterEntity::Update(float dt) {
Quaternion quat (-cos(cur_time), 0.0f, 0.0f * sin(cur_time), 1.0f); Quaternion quat (-cos(cur_time), 0.0f, 0.0f * sin(cur_time), 1.0f);
quat.normalize(); quat.normalize();
entity->mesh.localTransforms[0].rotation = quat; entity->mTransform.rotation = quat;
// update matrices // update matrices
entity->mesh.updateMatrices(entity->transform.toMatrix()); entity->mSkeleton.UpdateMatrices(entity->mTransform.toMatrix());
cur_time += dt; cur_time += dt;
} }
@ -240,8 +263,7 @@ void ShowCharacterPropertiesWindow (CharacterEntity* character) {
ImGui::DragFloat3 ("Position", character->mPosition.data(), 0.01, -10.0f, 10.0f); ImGui::DragFloat3 ("Position", character->mPosition.data(), 0.01, -10.0f, 10.0f);
ImGui::DragFloat3 ("Velocity", character->mVelocity.data(), 0.01, -10.0f, 10.0f); ImGui::DragFloat3 ("Velocity", character->mVelocity.data(), 0.01, -10.0f, 10.0f);
for (int i = 0; i < character->entity->mSkeleton.Length(); ++i) {
for (int i = 0; i < character->entity->mesh.meshes.size(); ++i) {
char buf[32]; char buf[32];
snprintf (buf, 32, "Mesh %d", i); snprintf (buf, 32, "Mesh %d", i);
@ -252,7 +274,7 @@ void ShowCharacterPropertiesWindow (CharacterEntity* character) {
node_flags); node_flags);
if (node_open) { if (node_open) {
Transform &transform = character->entity->mesh.localTransforms[i]; Transform &transform = character->entity->mSkeleton.mLocalTransforms[i];
ImGui::DragFloat3 ("Position", transform.translation.data(), 0.01, -10.0f, 10.0f); ImGui::DragFloat3 ("Position", transform.translation.data(), 0.01, -10.0f, 10.0f);
if (ImGui::Protot::DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) { if (ImGui::Protot::DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) {

View File

@ -145,23 +145,17 @@ const struct module_api MODULE_API = {
}; };
} }
void MeshHierarchy::updateMatrices(const Matrix44f &world_transform) { void Skeleton::UpdateMatrices(const Matrix44f &world_transform) {
for (uint32_t i = 0; i < meshes.size(); ++i) { for (uint32_t i = 0; i < mBoneMatrices.size(); ++i) {
Matrix44f parent_matrix (world_transform); Matrix44f parent_matrix (world_transform);
if (parent[i] != -1) { if (mParent[i] != -1) {
parent_matrix = meshMatrices[parent[i]]; parent_matrix = mBoneMatrices[mParent[i]];
} }
meshMatrices[i] = localTransforms[i].toMatrix() * parent_matrix; mBoneMatrices[i] = mLocalTransforms[i].toMatrix() * parent_matrix;
} }
} }
void MeshHierarchy::submit(const RenderState *state) {
for (uint32_t i = 0; i < meshes.size(); ++i) {
bgfxutils::meshSubmit (meshes[i]->mBgfxMesh, state, 1, meshMatrices[i].data());
}
};
// BGFX globals // BGFX globals
bgfx::VertexBufferHandle cube_vbh; bgfx::VertexBufferHandle cube_vbh;
bgfx::IndexBufferHandle cube_ibh; bgfx::IndexBufferHandle cube_ibh;
@ -1515,45 +1509,66 @@ void Renderer::paintGL() {
float light_pos_world[3]; float light_pos_world[3];
// shadow map pass // shadow map pass
for (uint32_t j = 0; j < entities[i]->mesh.meshes.size(); ++j) { for (uint32_t j = 0; j < entities[i]->mSkeletonMeshes.Length(); ++j) {
bx::mtxMul( bx::mtxMul(
lightMtx, lightMtx,
entities[i]->mesh.meshMatrices[j].data(), entities[i]->mSkeletonMeshes.GetBoneMatrix(j).data(),
lights[0].mtxShadow lights[0].mtxShadow
); );
bgfx::setUniform(lights[0].u_lightMtx, lightMtx); bgfx::setUniform(lights[0].u_lightMtx, lightMtx);
bgfxutils::meshSubmit ( entities[i]->mSkeletonMeshes.GetMesh(j)->Submit(
entities[i]->mesh.meshes[j]->mBgfxMesh,
&s_renderStates[RenderState::ShadowMap], &s_renderStates[RenderState::ShadowMap],
1, entities[i]->mSkeletonMeshes.GetBoneMatrix(j).data()
entities[i]->mesh.meshMatrices[j].data()
); );
} }
// scene pass // scene pass
for (uint32_t j = 0; j < entities[i]->mesh.meshes.size(); ++j) { for (uint32_t j = 0; j < entities[i]->mSkeletonMeshes.Length(); ++j) {
bx::mtxMul( bx::mtxMul(
lightMtx, lightMtx,
entities[i]->mesh.meshMatrices[j].data(), entities[i]->mSkeletonMeshes.GetBoneMatrix(j).data(),
lights[0].mtxShadow lights[0].mtxShadow
); );
// compute world position of the light // compute world position of the light
Vector4f light_pos = Vector4f light_pos =
entities[i]->mesh.meshMatrices[j] entities[i]->mSkeletonMeshes.GetBoneMatrix(j)
* SimpleMath::Map<Vector4f>(lights[0].pos, 4, 1); * SimpleMath::Map<Vector4f>(lights[0].pos, 4, 1);
bgfx::setUniform(lights[0].u_lightPos, light_pos.data()); bgfx::setUniform(lights[0].u_lightPos, light_pos.data());
bgfx::setUniform(lights[0].u_lightMtx, lightMtx);
bgfx::setUniform(u_color, entities[i]->color); bgfx::setUniform(u_color, entities[i]->color);
bgfxutils::meshSubmit ( bgfx::setUniform(lights[0].u_lightMtx, lightMtx);
entities[i]->mesh.meshes[j]->mBgfxMesh, entities[i]->mSkeletonMeshes.GetMesh(j)->Submit(
&s_renderStates[RenderState::Scene], &s_renderStates[RenderState::Scene],
1, entities[i]->mSkeletonMeshes.GetBoneMatrix(j).data()
entities[i]->mesh.meshMatrices[j].data()
); );
} }
//
//
//
// for (uint32_t j = 0; j < entities[i]->mesh.meshes.size(); ++j) {
// bx::mtxMul(
// lightMtx,
// entities[i]->mesh.meshMatrices[j].data(),
// lights[0].mtxShadow
// );
//
// // compute world position of the light
// Vector4f light_pos =
// entities[i]->mesh.meshMatrices[j]
// * SimpleMath::Map<Vector4f>(lights[0].pos, 4, 1);
//
// bgfx::setUniform(lights[0].u_lightPos, light_pos.data());
// bgfx::setUniform(lights[0].u_lightMtx, lightMtx);
// bgfxutils::meshSubmit (
// entities[i]->mesh.meshes[j]->mBgfxMesh,
// &s_renderStates[RenderState::Scene],
// 1,
// entities[i]->mesh.meshMatrices[j].data()
// );
//
// }
} }
// render debug information // render debug information

View File

@ -9,6 +9,7 @@
#include <bgfx/bgfx.h> #include <bgfx/bgfx.h>
#include "Globals.h"
#include "RenderUtils.h" #include "RenderUtils.h"
struct Entity; struct Entity;
@ -230,49 +231,82 @@ struct Transform {
} }
}; };
struct MeshHierarchy { struct Skeleton {
~MeshHierarchy() /// index of the mParent. Children must have higher indices than heir
{ // mParents
for (Mesh* mesh : meshes) { std::vector<int> mParent;
delete mesh; /// Transforms relative to their mParents.
} std::vector<Transform> mLocalTransforms;
}
std::vector<Mesh*> meshes;
/// index of the parent. Children must have higher indices than heir
// parents
std::vector<int> parent;
/// Transforms relative to their parents.
std::vector<Transform> localTransforms;
/// Absolute transforms. /// Absolute transforms.
std::vector<Matrix44f> meshMatrices; std::vector<Matrix44f> mBoneMatrices;
void addMesh( int AddBone(
const int parent_idx, const int parent_index,
const Transform& transform, const Transform& transform
Mesh* mesh) { ) {
assert (parent_idx == -1 || parent_idx < parent.size()); assert (parent_index == -1 || parent_index < mParent.size());
parent.push_back(parent_idx); mParent.push_back(parent_index);
localTransforms.push_back(transform); mLocalTransforms.push_back(transform);
meshes.push_back(mesh);
if (parent_idx != -1) { if (parent_index != -1) {
meshMatrices.push_back(transform.toMatrix() * meshMatrices[parent_idx]); mBoneMatrices.push_back(transform.toMatrix() * mBoneMatrices[parent_index]);
} else { } else {
meshMatrices.push_back(transform.toMatrix()); mBoneMatrices.push_back(transform.toMatrix());
}
return mBoneMatrices.size() - 1;
}
void UpdateMatrices(const Matrix44f &world_transform);
int Length() const {
return mBoneMatrices.size();
}
};
struct SkeletonMeshes {
Skeleton& mSkeleton;
typedef std::pair<Mesh*, int> MeshBoneIndex;
std::vector<MeshBoneIndex> mMeshBoneIndices;
SkeletonMeshes(Skeleton &skeleton) :
mSkeleton(skeleton)
{}
~SkeletonMeshes() {
for(MeshBoneIndex& mesh_bone : mMeshBoneIndices) {
delete mesh_bone.first;
} }
} }
void updateMatrices(const Matrix44f &world_transform);
void submit(const RenderState *state); void AddMesh (Mesh* mesh, int bone_index) {
mMeshBoneIndices.push_back (MeshBoneIndex (mesh, bone_index));
}
const Matrix44f GetBoneMatrix(int index) const {
assert (index >= 0 && index < Length());
assert (mMeshBoneIndices[index].second < mSkeleton.mBoneMatrices.size());
return mSkeleton.mBoneMatrices[mMeshBoneIndices[index].second];
}
const Mesh* GetMesh(int index) const {
assert (index >= 0 && index < Length());
return mMeshBoneIndices[index].first;
}
int Length() const {
return mMeshBoneIndices.size();
}
}; };
struct Entity { struct Entity {
Transform transform; Transform mTransform;
float color[4]; Vector4f mColor;
MeshHierarchy mesh; Skeleton mSkeleton;
SkeletonMeshes mSkeletonMeshes;
Entity() : Entity() :
color { 1.f, 1.f, 1.f, 1.f } mColor (1.f, 1.f, 1.f, 1.f ),
mSkeletonMeshes(mSkeleton)
{} {}
}; };

View File

@ -920,6 +920,15 @@ void Mesh::Merge (const Mesh& other, const Matrix44f &transform) {
} }
} }
void Mesh::Submit (const RenderState *state, const float* matrix) const {
bgfxutils::meshSubmit (
mBgfxMesh,
state,
1,
matrix);
}
Mesh* Mesh::sCreateCuboid (float width, float height, float depth) { Mesh* Mesh::sCreateCuboid (float width, float height, float depth) {
Mesh* result = new Mesh(); Mesh* result = new Mesh();

View File

@ -22,6 +22,7 @@ struct Mesh {
~Mesh(); ~Mesh();
void Update(); void Update();
void Merge (const Mesh& other, const Matrix44f &mat = Matrix44f::Identity()); void Merge (const Mesh& other, const Matrix44f &mat = Matrix44f::Identity());
void Submit (const RenderState *state, const float* matrix) const;
static Mesh *sCreateCuboid (float width, float height, float depth); static Mesh *sCreateCuboid (float width, float height, float depth);
static Mesh *sCreateUVSphere (int rows, int segments, float radius = 1.0f); static Mesh *sCreateUVSphere (int rows, int segments, float radius = 1.0f);