* 物理引擎调试绘图、模型包围盒计算、使用包围盒形状
This commit is contained in:
+56
-22
@@ -17,6 +17,7 @@
|
||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||
#include <Jolt/Physics/Body/Body.h>
|
||||
#include <Jolt/Renderer/DebugRendererSimple.h>
|
||||
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
|
||||
|
||||
#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<JPH::BoxShapeSettings*> _vecSetting;
|
||||
// 不同缩放使用不同形状
|
||||
std::unordered_map<float, JPH::ShapeRefC> _mapRef;
|
||||
|
||||
~RigidBodyShape()
|
||||
{
|
||||
for (auto& iter : _vecSetting)
|
||||
delete iter;
|
||||
}
|
||||
std::unordered_map<uint64_t, JPH::ShapeRefC> _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;
|
||||
|
||||
+13
-2
@@ -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();
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,6 +33,7 @@ class RigidBody
|
||||
friend class Physics;
|
||||
public:
|
||||
Position3 GetPosition();
|
||||
Position3 GetRotate();
|
||||
|
||||
~RigidBody();
|
||||
private:
|
||||
|
||||
+28
-3
@@ -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<Model*>& mul_model = g_vk->GetMulModel(_idModel);
|
||||
|
||||
//ub骨骼id
|
||||
@@ -110,11 +115,31 @@ void Actor::CreateRigidBody(RigidBodyType type, bool active)
|
||||
}
|
||||
|
||||
std::vector<Model*>& 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(),
|
||||
|
||||
@@ -44,7 +44,7 @@ private:
|
||||
std::vector<int> _treeNodeParent;
|
||||
std::vector<ModelAnimation> _allAnimation; // 动画
|
||||
std::vector<ModelSkin> _allSkin; // 骨骼
|
||||
std::vector<ModelDrawCall> _allSub; // 网格
|
||||
std::vector<ModelDrawCall> _allSub; // 网格
|
||||
|
||||
std::vector<Instance> _mulInstance; // 实例(每个actor有一个)
|
||||
};
|
||||
|
||||
+22
-15
@@ -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);
|
||||
|
||||
|
||||
+27
-14
@@ -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<ModelPrimitive> primitives;
|
||||
BoundingBox bb;
|
||||
std::vector<ModelPrimitive> _primitives;
|
||||
BoundingBox _aabb;
|
||||
};
|
||||
|
||||
struct ModelSkin;
|
||||
@@ -116,6 +128,7 @@ struct ModelNodeRt
|
||||
int _indexSkin; // 整个骨骼是在一个节点上
|
||||
int _indexParent; // 父节点索引
|
||||
ModelNodeTransform _trans2Parent; // 到父节点的变换(具有初始值,动画只改变srt)
|
||||
BoundingBox _aabb;
|
||||
|
||||
bool _bNeedUpdateMatrixWorld;
|
||||
bool _bNeedUpdateMatrixLocal;
|
||||
|
||||
@@ -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<ModelObject*> ModelLoader::_load_gltf(
|
||||
log_info("子模型数:{}", model.meshes.size());
|
||||
log_info("材质数:{}", model.materials.size());
|
||||
|
||||
// 只生成一个ModelObject(animation可能是节点动画,暂不支持)
|
||||
bool has_skin = !model.skins.empty();
|
||||
|
||||
/*std::vector<ModelObject*> ret;
|
||||
ModelObject* model_object = new ModelObject;
|
||||
std::vector<Vertex>& mo_vertices = model_object->_allVertex;
|
||||
std::vector<VertexBone>& mo_vertices_bone = model_object->_allVertexBone;
|
||||
std::vector<uint32_t>& mo_indices = model_object->_allIndex;
|
||||
std::vector<ModelObjectMaterial>& 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<ModelObject*> 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;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-3
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user