From dcc3f8a26cd33d2a1cbdd54631a06b6586ce8e68 Mon Sep 17 00:00:00 2001 From: Lveyou <1339484752@qq.com> Date: Tue, 19 May 2026 11:55:29 +0800 Subject: [PATCH] =?UTF-8?q?*=20=E7=89=A9=E7=90=86=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E7=BB=98=E5=9B=BE=E3=80=81=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=8C=85=E5=9B=B4=E7=9B=92=E8=AE=A1=E7=AE=97=E3=80=81=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=8C=85=E5=9B=B4=E7=9B=92=E5=BD=A2=E7=8A=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dl/math/dl_physics.cpp | 78 +++++++++++++++++++++--------- dl/math/dl_physics.h | 15 +++++- dl/math/dl_rigid_body.cpp | 7 +++ dl/math/dl_rigid_body.h | 1 + dl/render/dl_actor.cpp | 31 ++++++++++-- dl/render/dl_model.h | 2 +- dl/render/dl_model_data.cpp | 37 ++++++++------ dl/render/dl_model_data.h | 41 ++++++++++------ dl/render/dl_model_loader.cpp | 60 +++++------------------ project/dl_test/res/model/box.glb | Bin 0 -> 1936 bytes res/dl/default.model | Bin 691 -> 702 bytes res/dl/shader/3d_bone_frag.spv | Bin 33852 -> 33852 bytes res/dl/shader/3d_frag.spv | Bin 33852 -> 33852 bytes shader/3d.frag | 4 +- 14 files changed, 167 insertions(+), 109 deletions(-) create mode 100644 project/dl_test/res/model/box.glb diff --git a/dl/math/dl_physics.cpp b/dl/math/dl_physics.cpp index bd228829..cbc4a363 100644 --- a/dl/math/dl_physics.cpp +++ b/dl/math/dl_physics.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "dl_rigid_body.h" #include "base/dl_color.h" @@ -41,15 +42,8 @@ static Position3 to_pos3(const RVec3& pos) struct RigidBodyShape { - std::vector _vecSetting; // 不同缩放使用不同形状 - std::unordered_map _mapRef; - - ~RigidBodyShape() - { - for (auto& iter : _vecSetting) - delete iter; - } + std::unordered_map _mapRef; }; @@ -240,6 +234,11 @@ public: } }; +inline Color to_color(JPH::Color& color) +{ + return createColor(color.r, color.g, color.b, color.a); +} + class MyDebugRenderer : public JPH::DebugRendererSimple { public: @@ -248,7 +247,7 @@ public: { auto p0 = to_pos3(inFrom); auto p1 = to_pos3(inTo); - Color color = createColor(inColor.GetUInt32()); + Color color = to_color(inColor); g_gfx->SetColor(color); g_gfx->Line(p0, p1); } @@ -260,7 +259,7 @@ public: auto p0 = to_pos3(v1); auto p1 = to_pos3(v2); auto p2 = to_pos3(v3); - Color color = createColor(col.GetUInt32()); + Color color = to_color(col); g_gfx->SetColor(color); g_gfx->Triangle(p0, p1, p2); } @@ -373,12 +372,33 @@ dl::RigidBody* Physics::CreateRigidBody(JPH::ShapeRefC* ref, dl::RigidBody* Physics::CreateRigidBodyDefault(Transform* trans) { - auto ref = CreateShapeBox(0, { 1,1,1 }, { 1,1,1 }); + auto ref = CreateShapeBox(0, { 1,1,1 }); return CreateRigidBody(ref, {}, {}, RigidBodyType::DYNAMIC, true); } +inline uint64_t hash3f_64(const Position3& pos) +{ + auto ux = *(uint32_t*)(&pos.x); + auto uy = *(uint32_t*)(&pos.y); + auto uz = *(uint32_t*)(&pos.z); -JPH::ShapeRefC* Physics::CreateShapeBox(size_t shape_id, const Position3& box, const Position3& scale) + uint64_t h = ( + (uint64_t)ux * 0x123456789 + + (uint64_t)uy * 0x987654321 + + (uint64_t)uz * 0x555555555 + ); + + h ^= h >> 32; + h *= 0x9E3779B97F4A7C15; // 黄金比例常数 + h ^= h >> 32; + return h; +} + +JPH::ShapeRefC* Physics::CreateShapeBox(size_t shape_id, + const Position3& box, + const Position3& scale, + const Position3& position, + const Position3& rotate) { RigidBodyShape* shape; @@ -391,26 +411,40 @@ JPH::ShapeRefC* Physics::CreateShapeBox(size_t shape_id, const Position3& box, c else shape = iter->second; - float step = 10000.0f; - assert(scale.x < step && scale.y < step && scale.z < step); + uint64_t s_index = hash3f_64(scale); - float s = scale.x + scale.y * step + scale.z * step * step; - auto iter1 = shape->_mapRef.find(s); + auto iter1 = shape->_mapRef.find(s_index); if (iter1 == shape->_mapRef.end()) { Vec3 vec{ box.x * scale.x, box.y * scale.y, box.z * scale.z }; - BoxShapeSettings* setting = new BoxShapeSettings(vec); - shape->_vecSetting.push_back(setting); + BoxShapeSettings setting{ vec }; - ShapeSettings::ShapeResult result = setting->Create(); + ShapeSettings::ShapeResult result = setting.Create(); if (result.HasError()) - log_err("JPH: {}", result.GetError()); + log_err("JPH Shape: {}", result.GetError()); + ShapeRefC ref = result.Get(); - shape->_mapRef[s] = result.Get(); - return &shape->_mapRef[s]; + + // 偏移,旋转 + if (!Every::Zero(position) + || !Every::Zero(scale)) + { + RotatedTranslatedShapeSettings setting{ + to_rvec3(position), + JPH::Quat::sEulerAngles(to_rvec3(rotate)), + ref + }; + + ShapeSettings::ShapeResult result = setting.Create(); + if (result.HasError()) + log_err("JPH Shape: {}", result.GetError()); + ref = result.Get(); + } + shape->_mapRef[s_index] = ref; + return &shape->_mapRef[s_index]; } else return &iter1->second; diff --git a/dl/math/dl_physics.h b/dl/math/dl_physics.h index 5aa9b59c..1a695e2a 100644 --- a/dl/math/dl_physics.h +++ b/dl/math/dl_physics.h @@ -57,13 +57,24 @@ public: RigidBody* CreateRigidBodyDefault(Transform* trans); // 创建(取得)形状 box - // 一般来说一个模型拥有固定的 形状和物理属性 + // 一般来说一个模型拥有固定的 形状和物理属性() // shape_id 等价模型id // box 大小 // scale 缩放 + + /** + * @brief 创建(取得)形状 box + * @param[in] shape_id 形状id + * @param[in] box 轴对称包围盒 + * @param[in] offset 偏移 + * @param[in] rotate 旋转 + * @param[in] scale 缩放 + */ JPH::ShapeRefC* CreateShapeBox(size_t shape_id, const Position3& box, - const Position3& scale); + const Position3& scale = {1.0f, 1.0f, 1.0f}, + const Position3& offset = {}, + const Position3& rotate = {}); void Update(); void RenderDebug(); diff --git a/dl/math/dl_rigid_body.cpp b/dl/math/dl_rigid_body.cpp index 51c1df92..abe8ff77 100644 --- a/dl/math/dl_rigid_body.cpp +++ b/dl/math/dl_rigid_body.cpp @@ -31,4 +31,11 @@ dl::Position3 RigidBody::GetPosition() return { pos.GetX(), pos.GetY(), pos.GetZ() }; } +dl::Position3 RigidBody::GetRotate() +{ + auto quat = _body->GetRotation(); + auto vec = quat.GetEulerAngles(); + return { vec.GetX(), vec.GetY(), vec.GetZ() }; +} + } \ No newline at end of file diff --git a/dl/math/dl_rigid_body.h b/dl/math/dl_rigid_body.h index 46fa97ad..442dd363 100644 --- a/dl/math/dl_rigid_body.h +++ b/dl/math/dl_rigid_body.h @@ -33,6 +33,7 @@ class RigidBody friend class Physics; public: Position3 GetPosition(); + Position3 GetRotate(); ~RigidBody(); private: diff --git a/dl/render/dl_actor.cpp b/dl/render/dl_actor.cpp index 948e2563..800a4a1b 100644 --- a/dl/render/dl_actor.cpp +++ b/dl/render/dl_actor.cpp @@ -30,10 +30,15 @@ void Actor::Render() if (_rigidBody) { _trans->SetPosition(_rigidBody->GetPosition()); + _trans->SetRotate(_rigidBody->GetRotate()); } //--------------------render------------- - assert(_idModel < g_vk->GetMulModelSize()); + if (_idModel >= g_vk->GetMulModelSize()) + { + log_warn("错误的Actor!"); + return; + } std::vector& mul_model = g_vk->GetMulModel(_idModel); //ub骨骼id @@ -110,11 +115,31 @@ void Actor::CreateRigidBody(RigidBodyType type, bool active) } std::vector& mul_model = g_vk->GetMulModel(_idModel); - assert(mul_model.size() == 1); + + BoundingBox aabb; + for (auto& iter : mul_model) + { + for (auto& iter1 : iter->_treeNode) + { + if (iter1._aabb._vaild) + { + Matrix4 mat_to_world; + if (_modelAnimationInstance) + mat_to_world = iter1.GetMatrixWorld(_modelAnimationInstance); + else + mat_to_world = iter1.GetMatrixLocal(); + aabb.Add(iter1._aabb.getAABB(mat_to_world)); + } + } + } + // 没有包围盒,创建一个默认的 + if (!aabb._vaild) + aabb = BoundingBox({ -1.0f, -1.0f, -1.0f }, { 1.0f, 1.0f, 1.0f }); + Position3 aabb_center = (aabb._max + aabb._min) / 2.0f; // JPH::ShapeRefC* ref = g_physics->CreateShapeBox( - _idModel, {1, 1, 1}, _trans->GetScale()); + _idModel, aabb._max - aabb_center, _trans->GetScale(), aabb_center); // _rigidBody = g_physics->CreateRigidBody(ref, _trans->GetPosition(), diff --git a/dl/render/dl_model.h b/dl/render/dl_model.h index bec5281e..ec7ec47b 100644 --- a/dl/render/dl_model.h +++ b/dl/render/dl_model.h @@ -44,7 +44,7 @@ private: std::vector _treeNodeParent; std::vector _allAnimation; // 动画 std::vector _allSkin; // 骨骼 - std::vector _allSub; // 网格 + std::vector _allSub; // 网格 std::vector _mulInstance; // 实例(每个actor有一个) }; diff --git a/dl/render/dl_model_data.cpp b/dl/render/dl_model_data.cpp index 87c0711f..8aca3902 100644 --- a/dl/render/dl_model_data.cpp +++ b/dl/render/dl_model_data.cpp @@ -13,6 +13,7 @@ namespace dl s.Write(&_indexSkin); s.Write(&_indexParent); s.Write(&_trans2Parent); + s.Write(&_aabb); } void ModelNodeRt::Load(StreamInput& s) @@ -21,6 +22,7 @@ namespace dl s.Read(&_indexSkin); s.Read(&_indexParent); s.Read(&_trans2Parent); + s.Read(&_aabb); } dl::Matrix4 ModelNodeRt::GetMatrixLocal() @@ -89,16 +91,21 @@ namespace dl // 2.骨骼空间 -> 世界空间 } - BoundingBox::BoundingBox() + void BoundingBox::Add(const BoundingBox& b) { - - } - - BoundingBox::BoundingBox(Position3 imin, Position3 imax): - min{imin}, - max{imax} - { - + if (!b._vaild) + return; + if (!_vaild) + { + _min = b._min; + _max = b._max; + _vaild = b._vaild; + } + else + { + _min = Each::Min(_min, b._min); + _max = Each::Max(_max, b._max); + } } BoundingBox BoundingBox::getAABB(Matrix4 m) @@ -108,20 +115,20 @@ namespace dl Position3 v0, v1; Position3 right = toShorter(m[0]); - v0 = right * this->min[0]; - v1 = right * this->max[0]; + v0 = right * this->_min[0]; + v1 = right * this->_max[0]; min += Each::Min(v0, v1); max += Each::Max(v0, v1); Position3 up = toShorter(m[1]); - v0 = up * this->min[1]; - v1 = up * this->max[1]; + v0 = up * this->_min[1]; + v1 = up * this->_max[1]; min += Each::Min(v0, v1); max += Each::Max(v0, v1); Position3 back = toShorter(m[2]); - v0 = back * this->min[2]; - v1 = back * this->max[2]; + v0 = back * this->_min[2]; + v1 = back * this->_max[2]; min += Each::Min(v0, v1); max += Each::Max(v0, v1); diff --git a/dl/render/dl_model_data.h b/dl/render/dl_model_data.h index bf56f4f1..baf2b226 100644 --- a/dl/render/dl_model_data.h +++ b/dl/render/dl_model_data.h @@ -48,6 +48,28 @@ struct ModelNodeTransform }; +// +struct BoundingBox +{ + Position3 _min; + Position3 _max; + bool _vaild; +public: + BoundingBox() : + _vaild{ false } + { + } + BoundingBox(Position3 min, Position3 max) : + _min{ min }, + _max{ max }, + _vaild{ true } + { + } + + void Add(const BoundingBox& b); + + BoundingBox getAABB(Matrix4 m); +}; // 模型节点子网格 struct ModelDrawCall @@ -61,16 +83,6 @@ struct ModelDrawCall } }; -// -struct BoundingBox -{ - Position3 min; - Position3 max; - bool valid = false; - BoundingBox(); - BoundingBox(Position3 min, Position3 max); - BoundingBox getAABB(Matrix4 m); -}; struct ModelPrimitive { uint32_t _indexBeg; @@ -78,15 +90,15 @@ struct ModelPrimitive uint32_t _vertexIndex; uint32_t _vertexCount; uint32_t _indexMaterial; - BoundingBox bb; - bool hasIndices; + BoundingBox _aabb; + bool _bHasIndices; }; // 模型网格 struct ModelMesh { - std::vector primitives; - BoundingBox bb; + std::vector _primitives; + BoundingBox _aabb; }; struct ModelSkin; @@ -116,6 +128,7 @@ struct ModelNodeRt int _indexSkin; // 整个骨骼是在一个节点上 int _indexParent; // 父节点索引 ModelNodeTransform _trans2Parent; // 到父节点的变换(具有初始值,动画只改变srt) + BoundingBox _aabb; bool _bNeedUpdateMatrixWorld; bool _bNeedUpdateMatrixLocal; diff --git a/dl/render/dl_model_loader.cpp b/dl/render/dl_model_loader.cpp index ca53ca0f..d6987f52 100644 --- a/dl/render/dl_model_loader.cpp +++ b/dl/render/dl_model_loader.cpp @@ -210,6 +210,7 @@ ModelObject* ModelLoader::_create_model_object(ModelData& data) node_rt._index = node->_index; node_rt._indexSkin = node->_indexSkin; node_rt._trans2Parent = node->_trans2Parent; + node_rt._aabb = node->_mesh._aabb; // parent_id 重映射 if (!node->_parent) node_rt._indexParent = -1; @@ -260,39 +261,16 @@ std::vector ModelLoader::_load_gltf( log_info("子模型数:{}", model.meshes.size()); log_info("材质数:{}", model.materials.size()); - // 只生成一个ModelObject(animation可能是节点动画,暂不支持) - bool has_skin = !model.skins.empty(); - - /*std::vector ret; - ModelObject* model_object = new ModelObject; - std::vector& mo_vertices = model_object->_allVertex; - std::vector& mo_vertices_bone = model_object->_allVertexBone; - std::vector& mo_indices = model_object->_allIndex; - std::vector& mo_material = model_object->_allMaterial; - ret.push_back(model_object);*/ ModelData model_data; _gltf_load_material(model, res_name, model_data._allMaterial); _gltf_load_scene(model, model_data); - - - /*if (!has_bone) - { - assert(mo_vertices_bone.empty()); - } - else - { - assert(mo_vertices.empty()); - }*/ - ModelObject* obj = _create_model_object(model_data); std::vector ret; ret.push_back(obj); - /*log_msg("解析gltf模型完成:v_{},i_{}", - !has_bone ? mo_vertices.size() : mo_vertices_bone.size(), - mo_indices.size());*/ + return ret; } @@ -472,9 +450,8 @@ void ModelLoader::_gltf_load_scene(const tinygltf::Model& model, ModelData& data mat_n.Transpose(); Matrix3 mat_t = Mat::ToMatrix3(mat_world); - for (auto& pri : node->_mesh.primitives) + for (auto& pri : node->_mesh._primitives) { - //mat_world.Dump(); // 是否多个pri会引用同一个顶点,有待验证 for (size_t i = pri._vertexIndex; i < pri._vertexIndex + pri._vertexCount; ++i) { @@ -491,7 +468,7 @@ void ModelLoader::_gltf_load_scene(const tinygltf::Model& model, ModelData& data // pri -> all_sub for (auto& iter : data._allNode) { - for (ModelPrimitive& pri : iter->GetValue()->_mesh.primitives) + for (ModelPrimitive& pri : iter->GetValue()->_mesh._primitives) { ModelDrawCall sub; sub._indexMaterial = pri._indexMaterial; @@ -569,15 +546,8 @@ void ModelLoader::_gltf_load_node(const tinygltf::Model& model, int node, { model_node->_trans2Parent._mat = _mat4_cast(nn.matrix); } - // gltf R(up:+y forward:+z) -> dl R(up:+z forward:+x) - - //if (model_node_parent == nullptr) - //{ - // //data._matRoot = model_node->_trans2Parent.GetMatrix(); - // data._matRoot = Mat::CreateRotation(AXIS_X, Math::PI(1, 2))* data._matRoot; - // data._matRoot = Mat::CreateRotation(AXIS_Z, Math::PI(1, 2))* data._matRoot; - //} - + // gltf R(up:+y forward:+z) + // dl R(up:+z forward:+x) // 构建树 data._allNode.Add(model_node, model_node_parent); @@ -816,22 +786,14 @@ void ModelLoader::_gltf_load_node(const tinygltf::Model& model, int node, model_primitive._vertexIndex = vertex_start; model_primitive._vertexCount = vertex_count; model_primitive._indexMaterial = primitive.material; - model_primitive.hasIndices = index_count > 0; - model_primitive.bb.min = pos_min; - model_primitive.bb.max = pos_max; - model_primitive.bb.valid = true; - model_mesh.primitives.push_back(model_primitive); + model_primitive._bHasIndices = index_count > 0; + model_primitive._aabb = BoundingBox(pos_min, pos_max); + model_mesh._primitives.push_back(model_primitive); } // Mesh BB from BBs of primitives - for (ModelPrimitive& p : model_mesh.primitives) + for (ModelPrimitive& p : model_mesh._primitives) { - if (p.bb.valid && !model_mesh.bb.valid) - { - model_mesh.bb = p.bb; - model_mesh.bb.valid = true; - } - model_mesh.bb.min = Each::Min(model_mesh.bb.min, p.bb.min); - model_mesh.bb.max = Each::Max(model_mesh.bb.max, p.bb.max); + model_mesh._aabb.Add(p._aabb); } model_node->_mesh = model_mesh; } diff --git a/project/dl_test/res/model/box.glb b/project/dl_test/res/model/box.glb new file mode 100644 index 0000000000000000000000000000000000000000..3ae897e9ca947f758997c11dc9d184f28192d296 GIT binary patch literal 1936 zcmb7E+fLg+5FIWp&lit!-KqMdB0s zNA0I|W^IFOLV!)YvpajvnVs3S2VQq~765)P04VbSUpr=N#H=vn5i>??z&k<_EKMUM*{7tW&XCpS`;i;si_(p7VMv$Quap78CqSgyy+v6R#$9v3(M9fhm z39z5yaARk-*yoYud9KqA;=!rULu8MbZH2rMc!Aip9GT^jTCSv~XsMUimrIHKu@eK$MJZqsbZsnF%bQcj zecq)$jjlh0uHT4`mADyQI%RGZOf!w%X>9FnwdF;--hRGVvQYL##P_&Ai13Q)wVJ}n zVfOp-y}^@@EHR*0sIpdH$0Nx~aW_|r-ItA5^#91!4NBymu{R3jjdjc;Pp;5aO^T2f zAeVJ*jV{!eIe_hE3%?+jn-6&Y_nYun8I2Xd!kMnBabN&AD^QA z`!VqsE#WS4t!N2H{-Qm}>3>S&kcFH+&51|$1Rv5V5e6ICOB$n({Dh-Mmi*6P1!pVp w7@oiatYW_kZ{Z!hhGp!R;T61qIatDe3EsdXn1w~`7vU+qgy%4W{S3^*KMF3+>Hq)$ literal 0 HcmV?d00001 diff --git a/res/dl/default.model b/res/dl/default.model index 02747fc9bf644f7f466d9660d2c8417f68e5ca65..809339a619d3b66da8bcc5d6ffd1441075fb5e29 100644 GIT binary patch delta 297 zcmWlUu}Z^W6ot>Z{ZrEt{6lNht%_9(Vo`K(G95CB2%>|dN(Udnv0w&4$A&K1d-bHR~lqn)v7_6$wYJ2kaq#4ePb?<4a{dn< CvN=5f delta 269 zcmWlUze~e#5XC=t-=xM8NK7qMDE?MDs6^@>hmKtY2L-_h4lZu_1G3q%C5wNAn}eHG zaOmLR;GdwIgR6^rS>D}y_uhkh^zZ%g;d#Hzq`*sPDC7i&F@Z;DOSi^o5f^-e5^ws5 z$tn9~_WMS>`VJmWkuTQzdo#A5{yg-6Fd!Nrt=;bAVPknL+=}t7=#@@1qG7YGLuJN# zIi37mXyK|eSvpOoJ-E`CT>TMr;6!v-SG6gerB<3Fngg`NNW=@8D?3>I{H4a3xj)1% kbLKIv{wS0vbqm$Aw36CosnjJJh-Z%D>QipyuDaHve`<&@jsO4v diff --git a/res/dl/shader/3d_bone_frag.spv b/res/dl/shader/3d_bone_frag.spv index e9fef79ece865b1b732efe750aa8efc9ce4f1b94..d8f495a39c0cada7514080c7360bad7c16390813 100644 GIT binary patch delta 16 Xcmdnf!L+A?X~P9KMwZPN-Lh=~Jq-rR delta 16 Xcmdnf!L+A?X~P9KM%T?3-Lh=~K9dIv diff --git a/res/dl/shader/3d_frag.spv b/res/dl/shader/3d_frag.spv index e9fef79ece865b1b732efe750aa8efc9ce4f1b94..d8f495a39c0cada7514080c7360bad7c16390813 100644 GIT binary patch delta 16 Xcmdnf!L+A?X~P9KMwZPN-Lh=~Jq-rR delta 16 Xcmdnf!L+A?X~P9KM%T?3-Lh=~K9dIv diff --git a/shader/3d.frag b/shader/3d.frag index eac37022..0005e930 100644 --- a/shader/3d.frag +++ b/shader/3d.frag @@ -355,8 +355,6 @@ void main() //-------------------------------------------------------------------------- // 1. 获取最终表面法线(纹理法线 / 模型法线) vec3 n = (material.normalTextureSet > -1) ? getNormal() : normalize(inNormal); - //n.y *= -1.0f; - // 2. 计算PBR核心方向向量 vec3 v = normalize(ubo.camPos - inPosition); // 点 -> 相机 vec3 l = normalize(-pass.light[0].direction); // 点 -> 光源(平行光需要取反) @@ -463,7 +461,7 @@ void main() outColor.rgba = material.baseColorTextureSet > -1 ? texture(diffuseMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1) : vec4(1.0f); break; case 2: - outColor.rgb = (material.normalTextureSet > -1) ? texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).rgb : normalize(inNormal); + outColor.rgb = (material.normalTextureSet > -1) ? texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).rgb : abs(inNormal); break; case 3: outColor.rgb = (material.occlusionTextureSet > -1) ? texture(aoMap, material.occlusionTextureSet == 0 ? inUV0 : inUV1).rrr : vec3(0.0f);