From 298e553aab77cfe7770194c98a58467d89d74ab3 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Wed, 11 Oct 2023 18:09:17 +0300 Subject: [PATCH] Engine: SkinnedMeshRender should have customizable bounding volume #564 --- engine/includes/components/armature.h | 3 - .../includes/components/skinnedmeshrender.h | 10 +++ engine/src/components/armature.cpp | 85 +++++++------------ engine/src/components/skinnedmeshrender.cpp | 37 +++++--- thirdparty/next/src/math/aabb.cpp | 2 +- worldeditor/bin/editor/meshes/bone.fbx.set | 2 +- 6 files changed, 66 insertions(+), 73 deletions(-) diff --git a/engine/includes/components/armature.h b/engine/includes/components/armature.h index 21279f07d..a853e079c 100644 --- a/engine/includes/components/armature.h +++ b/engine/includes/components/armature.h @@ -21,8 +21,6 @@ class ENGINE_EXPORT Armature : public NativeBehaviour { Pose *bindPose() const; void setBindPose(Pose *pose); - AABBox recalcBounds(const AABBox &aabb) const; - Texture *texture() const; private: @@ -39,7 +37,6 @@ class ENGINE_EXPORT Armature : public NativeBehaviour { private: vector m_invertTransform; - vector m_transform; vector m_bones; Pose *m_bindPose; diff --git a/engine/includes/components/skinnedmeshrender.h b/engine/includes/components/skinnedmeshrender.h index 23c246d53..8767a1ea2 100644 --- a/engine/includes/components/skinnedmeshrender.h +++ b/engine/includes/components/skinnedmeshrender.h @@ -12,6 +12,8 @@ class ENGINE_EXPORT SkinnedMeshRender : public Renderable { A_REGISTER(SkinnedMeshRender, Renderable, Components/3D); A_PROPERTIES( + A_PROPERTY(Vector3, boundsCenter, SkinnedMeshRender::boundsCenter, SkinnedMeshRender::setBoundsCenter), + A_PROPERTY(Vector3, boundsExtent, SkinnedMeshRender::boundsExtent, SkinnedMeshRender::setBoundsExtent), A_PROPERTYEX(Armature *, armature, SkinnedMeshRender::armature, SkinnedMeshRender::setArmature, "editor=Component"), A_PROPERTYEX(MeshGroup *, mesh, SkinnedMeshRender::mesh, SkinnedMeshRender::setMesh, "editor=Asset"), A_PROPERTYEX(Material *, material, SkinnedMeshRender::material, SkinnedMeshRender::setMaterial, "editor=Asset") @@ -21,6 +23,12 @@ class ENGINE_EXPORT SkinnedMeshRender : public Renderable { public: SkinnedMeshRender(); + Vector3 boundsCenter() const; + void setBoundsCenter(Vector3 center); + + Vector3 boundsExtent() const; + void setBoundsExtent(Vector3 extent); + Mesh *mesh() const; void setMesh(Mesh *mesh); @@ -43,6 +51,8 @@ class ENGINE_EXPORT SkinnedMeshRender : public Renderable { void drawGizmosSelected() override; private: + AABBox m_bounds; + Mesh *m_mesh; MaterialInstance *m_material; diff --git a/engine/src/components/armature.cpp b/engine/src/components/armature.cpp index c78d60213..62d7eb4ae 100644 --- a/engine/src/components/armature.cpp +++ b/engine/src/components/armature.cpp @@ -3,6 +3,7 @@ #include "components/transform.h" #include "components/actor.h" +#include "resources/mesh.h" #include "resources/pose.h" #include "resources/texture.h" @@ -68,15 +69,15 @@ void Armature::update() { for(uint32_t i = 0; i < m_bones.size(); i++) { if(i < m_invertTransform.size() && m_bones[i]) { - m_transform[i] = m_bones[i]->worldTransform() * m_invertTransform[i]; - } - // Compress data - Matrix4 t = m_transform[i]; - t[3] = t[12]; - t[7] = t[13]; - t[11] = t[14]; + Matrix4 t(m_bones[i]->worldTransform() * m_invertTransform[i]); - memcpy(&data[i * M4X3_SIZE], t.mat, M4X3_SIZE); + // Compress data + t[3] = t[12]; + t[7] = t[13]; + t[11] = t[14]; + + memcpy(&data[i * M4X3_SIZE], t.mat, M4X3_SIZE); + } } m_cache->setDirty(); } @@ -110,47 +111,12 @@ Texture *Armature::texture() const { /*! \internal */ -AABBox Armature::recalcBounds(const AABBox &aabb) const { - Vector3 v0, v1; - aabb.box(v0, v1); - - Vector3 min( FLT_MAX); - Vector3 max(-FLT_MAX); - for(uint32_t b = 0; b < m_bones.size(); b++) { - Vector3 t0 = m_transform[b] * v0; - Vector3 t1 = m_transform[b] * v1; - - min.x = MIN(min.x, t0.x); - min.y = MIN(min.y, t0.y); - min.z = MIN(min.z, t0.z); - - min.x = MIN(min.x, t1.x); - min.y = MIN(min.y, t1.y); - min.z = MIN(min.z, t1.z); - - max.x = MAX(max.x, t0.x); - max.y = MAX(max.y, t0.y); - max.z = MAX(max.z, t0.z); - - max.x = MAX(max.x, t1.x); - max.y = MAX(max.y, t1.y); - max.z = MAX(max.z, t1.z); - } - AABBox result; - result.setBox(min, max); - - return result; -} -/*! - \internal -*/ void Armature::loadUserData(const VariantMap &data) { Component::loadUserData(data); - { - auto it = data.find(POSE); - if(it != data.end()) { - setBindPose(Engine::loadResource((*it).second.toString())); - } + + auto it = data.find(POSE); + if(it != data.end()) { + setBindPose(Engine::loadResource((*it).second.toString())); } } /*! @@ -158,18 +124,28 @@ void Armature::loadUserData(const VariantMap &data) { */ VariantMap Armature::saveUserData() const { VariantMap result = Component::saveUserData(); - { - string ref = Engine::reference(bindPose()); - if(!ref.empty()) { - result[POSE] = ref; - } + + string ref = Engine::reference(bindPose()); + if(!ref.empty()) { + result[POSE] = ref; } + return result; } void Armature::drawGizmosSelected() { - for(auto it : m_bones) { - //Handles::drawBone(it->parentTransform(), it); + static Mesh *bone = nullptr; + if(bone == nullptr) { + bone = Engine::loadResource(".embedded/bone.fbx/Bone"); + } + + if(bone) { + Vector4 color(0.0f, 1.0f, 0.0f, 0.1f); + for(auto it : m_bones) { + Transform *p = it->parentTransform(); + Vector3 parent(p->worldPosition()); + Gizmos::drawMesh(*bone, color, Matrix4(parent, p->worldQuaternion(), Vector3((it->worldPosition() - parent).length()))); + } } } @@ -180,7 +156,6 @@ void Armature::cleanDirty(Actor *actor) { uint32_t count = m_bindPose->boneCount(); m_bones.resize(count); m_invertTransform.resize(count); - m_transform.resize(count); for(uint32_t c = 0; c < count; c++) { const Bone *b = m_bindPose->bone(c); diff --git a/engine/src/components/skinnedmeshrender.cpp b/engine/src/components/skinnedmeshrender.cpp index 466a2ff41..d58105f6e 100644 --- a/engine/src/components/skinnedmeshrender.cpp +++ b/engine/src/components/skinnedmeshrender.cpp @@ -28,10 +28,11 @@ const char *gMatrices = "skinMatrices"; */ SkinnedMeshRender::SkinnedMeshRender() : - m_mesh(nullptr), - m_material(nullptr), - m_armature(nullptr) { + m_mesh(nullptr), + m_material(nullptr), + m_armature(nullptr) { + m_bounds.radius = 0.0f; } /*! \internal @@ -50,14 +51,21 @@ void SkinnedMeshRender::draw(CommandBuffer &buffer, uint32_t layer) { \internal */ AABBox SkinnedMeshRender::localBound() const { - AABBox result; - if(m_mesh) { - result = m_mesh->bound(); - } - if(m_armature) { - result = m_armature->recalcBounds(result); - } - return result; + return m_bounds; +} + +Vector3 SkinnedMeshRender::boundsCenter() const { + return m_bounds.center; +} +void SkinnedMeshRender::setBoundsCenter(Vector3 center) { + m_bounds.center = center; +} + +Vector3 SkinnedMeshRender::boundsExtent() const { + return m_bounds.extent; +} +void SkinnedMeshRender::setBoundsExtent(Vector3 extent) { + m_bounds.extent = extent; } /*! Returns a Mesh assigned to this component. @@ -72,6 +80,10 @@ void SkinnedMeshRender::setMesh(Mesh *mesh) { m_mesh = mesh; if(m_mesh) { setMaterial(m_mesh->material()); + + if(!m_bounds.isValid()) { + m_bounds = m_mesh->bound(); + } } } /*! @@ -112,8 +124,7 @@ void SkinnedMeshRender::setArmature(Armature *armature) { if(m_armature) { connect(m_armature, _SIGNAL(destroyed()), this, _SLOT(onReferenceDestroyed())); if(m_material) { - Texture *t = m_armature->texture(); - m_material->setTexture(gMatrices, t); + m_material->setTexture(gMatrices, m_armature->texture()); } } } diff --git a/thirdparty/next/src/math/aabb.cpp b/thirdparty/next/src/math/aabb.cpp index d0b0454af..bd5a3f5b2 100644 --- a/thirdparty/next/src/math/aabb.cpp +++ b/thirdparty/next/src/math/aabb.cpp @@ -35,7 +35,7 @@ AABBox::AABBox(const Vector3 ¢er, const Vector3 &extent) : Returns true in case of AABBox is valid; otherwise returns false. */ bool AABBox::isValid() const { - return (extent.x >= 0.0f) && (extent.y >= 0.0f) && (extent.z >= 0.0f); + return radius > 0.0f; } /*! Grow the AABBox to encapsulate a spehere with \a position and \a radius. diff --git a/worldeditor/bin/editor/meshes/bone.fbx.set b/worldeditor/bin/editor/meshes/bone.fbx.set index ffa9d7957..6ebc19e3b 100644 --- a/worldeditor/bin/editor/meshes/bone.fbx.set +++ b/worldeditor/bin/editor/meshes/bone.fbx.set @@ -3,7 +3,7 @@ "md5": "{58357402-cd2a-3d6e-d117-2110431833c4}", "settings": { "Compress_Animation": 1, - "Custom_Scale": 1, + "Custom_Scale": 0.1, "Import_Animation": false, "Import_Color": true, "Import_Normals": true,