我在 DirectX 中创建了一个简单的“引擎”,它可以从 .obj 文件加载和渲染模型。对于我创建的对象,它工作正常,例如坐标在 -1.0 到 1.0 范围内的简单立方体。然而,加载一个使用不同单位且坐标在 -2k 到 2k 范围内的模型会导致一个巨大的东西甚至不能完全适合深度缓冲区,所以我看到像一条巨大的腿或类似的效果。
我记得在某处读过有关它的内容,但最近我浏览了很多 DX 的东西,我不记得它在哪里或是什么。所以我的问题是,假设我希望能够加载使用不同单位的不同模型,确保它们都具有相似大小并很好地适合屏幕的最佳方法是什么?
我可以尝试在加载对象时转换值,但也许还有更多使用转换矩阵或着色器的 DirectX 方式?
最佳答案
最简单的方法是找到模型在哪个组件上包含最大范围,并使用该值统一缩放模型。要找到最大范围,请计算模型边界框(除非 wavefront obj.files 已经提供了它,但也许您无论如何都想验证它),并使用框尺寸作为要比较的范围。这会将所有导入的模型缩小到单位范围。
例如,如果您有一个边界框覆盖 374 * 820 * 512 个单位的模型,最大的是 Y 轴 820,因此您只需将其缩小 820(将所有组件除以 820 ).这可以通过统一缩放矩阵方便地实现,如果我没记错的话,可以使用 D3DXMatrixScaling
对其进行初始化。
假设边界框由 2 个 vector (最大和最小顶点)给出,计算这些 vector 的差值,然后选择最大值,并将其倒数用作矩阵的缩放因子。
D3DMatrix mScale;
D3DVector mx, mn;
obj->getBoundingBox(&mn,&mx);
float scale = 1.0 / max(mx.x - mn.x, max(mx.y - mn.y, mx.z -mn.z));
D3DXMatrixScaling( &mScale, scale, scale,scale);
剩下要做的就是将矩阵插入渲染管道。
关于边界框的计算,在模型的所有顶点上进行一个简单的循环,保持最小和最大分量(彼此独立),应该可以做到。
D3DVector mn, mx;
mn.x = mn.y = mn.z = MAX_FLOAT;
mx.x = mx.y = mx.z = - MAX_FLOAT;
for (int i = 0; i < numVertices ; i++) {
mn.x = min(mn.x, vertex[i].x);
mn.y = min(mn.y, vertex[i].y);
mn.z = min(mn.z, vertex[i].z);
// same for mx using max
}
当然,如果您的 View 覆盖的区域比单位框大(但显然这是您正在使用的),您可能需要使用一些比例因子。
关于c++ - 如何在 DirectX 中标准化模型大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14078093/