【问题标题】:How to normalize model size in DirectX?如何在 DirectX 中标准化模型大小?
【发布时间】:2012-12-14 05:24:42
【问题描述】:

我在 DirectX 中创建了一个简单的“引擎”,它可以从 .obj 文件加载和渲染模型。对于我创建的对象,它工作正常,例如坐标在 -1.0 到 1.0 范围内的简单立方体。然而,加载一个使用不同单位并且坐标在 -2k 到 2k 范围内的模型会导致一个巨大的东西甚至不完全适合深度缓冲区,所以我看到的是一条巨大的腿或类似的效果。

我记得在某处读到过有关它的信息,但最近我浏览了很多 DX 内容,我不记得它在哪里或是什么。所以我的问题是,假设我希望能够加载使用不同单位的不同模型,那么确保它们都具有相似尺寸并很好地适合屏幕的最佳方法是什么?

我可以尝试在加载对象时转换值,但也许还有更多使用转换矩阵或着色器的 DirectX 方式?

【问题讨论】:

  • 缩放通常以World Transform 的形式完成,其中顶点从模型空间转换到世界空间。然后将该矩阵与视图矩阵和投影矩阵相乘,形成最终的变换。
  • Tim 的回答是正确的,尽管他所说的规模差异会让他很快失去浮点精度。

标签: c++ 3d directx normalization wavefront


【解决方案1】:

最简单的方法是找出模型在哪个组件上包含最大范围,并使用该值统一缩放模型。要找到最大范围,请计算模型边界框(除非波前 obj. 文件已经提供它,但也许您还是想验证它),并使用框尺寸作为比较范围。这会将所有导入的模型缩小到单位范围。

例如,如果您有一个模型的边界框覆盖 374 * 820 * 512 个单位,最大的一个是 820 的 Y 轴,因此您只需将其缩小 820(将所有组件除以 820 )。这可以通过统一缩放矩阵方便地实现,如果我没记错的话,可以使用D3DXMatrixScaling 进行初始化。 假设边界框由 2 个向量(最大和最小顶点)给出,计算这些向量的差,然后选择最大值,并将其逆作为矩阵的缩放因子。

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
}

当然,如果您的视图覆盖的区域比单位框大(但显然这是您正在使用的),您可能需要使用一些缩放因子。

【讨论】:

  • 是的,这会起作用,但再考虑一下后,我想我会在 3D 软件中缩放我的模型,并暂时保留代码。
  • 我不是 D3D 用户,也许它显示在我提供的代码示例中,但如果您一次显示一个模型,我认为我的想法是正确的。如果你要显示很多,我想在加载模型后进行一次缩放会更有效,或者像你说的那样,使用外部软件。
猜你喜欢
  • 1970-01-01
  • 2019-11-20
  • 2015-06-10
  • 2021-12-20
  • 2020-11-30
  • 2013-10-18
  • 2023-03-12
  • 2016-12-21
  • 1970-01-01
相关资源
最近更新 更多