fix(renderer): mesh collider source positions in render space for skinned meshes
Skinned meshes keep vertices in raw mesh space (bakeTransform=false); rendering transforms them via bind palette (global(bone) x invBind, folds FBX unit scale). Physics MeshShape/ConvexHull and the mesh bounding sphere consumed the raw positions directly -> M1911 hull measured ~10x the visual size. ParseFromDisk now bakes bind-palette-skinned positions per vertex (same formula as the skinning shader) into ParsedMesh::cpuPositions; Mesh uses them for m_CpuPositions and bounds. GPU vertex data and rendering are untouched.
This commit is contained in:
@@ -25,7 +25,8 @@ namespace Engine
|
||||
Mesh::Mesh(Device& device, MemoryAllocator& allocator,
|
||||
const std::vector<Vertex>& vertices,
|
||||
const std::vector<std::vector<u32>>& lods,
|
||||
Material* material)
|
||||
Material* material,
|
||||
const std::vector<glm::vec3>* cpuPositions)
|
||||
: m_Material(material)
|
||||
, m_Slot(s_nextMeshSlot.fetch_add(1, std::memory_order_relaxed))
|
||||
{
|
||||
@@ -35,11 +36,19 @@ namespace Engine
|
||||
return;
|
||||
}
|
||||
|
||||
// 位置取数:蒙皮 mesh 用绑定姿态渲染空间副本(与视觉同源),
|
||||
// 否则用原始顶点位置
|
||||
const bool useBind = cpuPositions != nullptr &&
|
||||
cpuPositions->size() == vertices.size();
|
||||
auto posAt = [&](size_t i) -> const glm::vec3& {
|
||||
return useBind ? (*cpuPositions)[i] : vertices[i].position;
|
||||
};
|
||||
|
||||
// CPU 位置副本:物理 MeshShape/ConvexHull 数据源(GPU 上传后
|
||||
// 完整 Vertex 不再保留,见 Mesh.h)
|
||||
m_CpuPositions.reserve(vertices.size());
|
||||
for (const auto& v : vertices) {
|
||||
m_CpuPositions.push_back(v.position);
|
||||
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||
m_CpuPositions.push_back(posAt(i));
|
||||
}
|
||||
m_CpuIndices = lods[0];
|
||||
|
||||
@@ -78,18 +87,19 @@ namespace Engine
|
||||
}
|
||||
|
||||
// 局部空间包围球:顶点包围盒 → 中心 + 最大半径(视锥剔除用)
|
||||
// 蒙皮 mesh 用绑定姿态副本(原始空间包围球大一个数量级 = 剔除/拾取失真)
|
||||
{
|
||||
glm::vec3 mn(std::numeric_limits<f32>::max());
|
||||
glm::vec3 mx(std::numeric_limits<f32>::lowest());
|
||||
for (const auto& v : vertices) {
|
||||
mn = glm::min(mn, v.position);
|
||||
mx = glm::max(mx, v.position);
|
||||
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||
mn = glm::min(mn, posAt(i));
|
||||
mx = glm::max(mx, posAt(i));
|
||||
}
|
||||
m_Bounds.center = (mn + mx) * 0.5f;
|
||||
m_Bounds.radius = 0.0f;
|
||||
for (const auto& v : vertices) {
|
||||
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||
m_Bounds.radius = glm::max(m_Bounds.radius,
|
||||
glm::length(v.position - m_Bounds.center));
|
||||
glm::length(posAt(i) - m_Bounds.center));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user