矩阵堆栈 (Direct3D 9)

注意

D3DX 实用工具库已弃用。 建议改用 DirectXMath 以及 gitHub 此标头。

D3DX 实用工具库提供 ID3DXMATRIXStack 接口。 它提供一种机制,使矩阵能够被推送到矩阵堆栈上并弹出。 实现矩阵堆栈是一种在遍历转换层次结构时跟踪矩阵的有效方法。

D3DX 实用工具库使用矩阵堆栈将转换存储为矩阵。 ID3DXMATRIXStack 接口的各种方法处理当前矩阵或位于堆栈顶部的矩阵。 可以使用 ID3DXMATRIXStack::LoadIdentity 方法清除当前矩阵。 若要显式指定要加载为当前转换矩阵的特定矩阵,请使用 ID3DXMATRIXStack::LoadMatrix 方法。 然后,可以调用 ID3DXMATRIXStack::MultMatrix 方法或 ID3DXMATRIXStack::MultMatrixLocal 方法将当前矩阵乘以指定的矩阵。

ID3DXMATRIXStack::P op 方法使你能够返回到以前的转换矩阵,ID3DXMATRIXStack::P ush 方法向堆栈中添加转换矩阵。

矩阵堆栈上的单个矩阵表示为 4x4 同质矩阵,由 D3DX 实用工具库 D3DXMATRIX 结构定义。

D3DX 实用工具库通过组件对象模型 (COM) 对象提供矩阵堆栈。

实现场景层次结构

矩阵堆栈简化了分层模型的构造,其中复杂对象是从一系列更简单的对象构造的。

场景或转换层次结构通常由树数据结构表示。 树数据结构中的每个节点都包含一个矩阵。 特定矩阵表示从节点的父级到节点的坐标系的变化。 例如,如果要对人臂进行建模,则可以实现下图所示的层次结构。

人臂层次结构的 图

在此层次结构中,Body 矩阵将正文置于世界。 UpperArm 矩阵包含肩部的旋转,LowerArm 矩阵包含肘部的旋转,手部矩阵包含手腕的旋转。 若要确定手相对于世界的位置,请将所有矩阵从身体向下乘以手。

上一个层次结构过于简单,因为每个节点只有一个子级。 如果开始更详细地对手进行建模,可能会添加手指和拇指。 每个数字都可以作为 Hand 的子级添加到层次结构中,如下图所示。

人工手图

如果按深度优先顺序遍历手臂的完整图-在转到下一个路径之前遍历一条路径-绘制场景,则执行分段呈现序列。 例如,若要呈现手和手指,请实现以下模式。

  1. 将手部矩阵推送到矩阵堆栈上。
  2. 绘制手。
  3. 将 Thumb 矩阵推送到矩阵堆栈。
  4. 绘制拇指。
  5. 从堆栈中弹出 Thumb 矩阵。
  6. 将手指 1 矩阵推到矩阵堆栈上。
  7. 绘制第一根手指。
  8. 从堆栈中弹出手指 1 矩阵。
  9. 将手指 2 矩阵推到矩阵堆栈上。 以这种方式继续,直到呈现所有手指和拇指。

完成手指呈现后,会从堆栈中弹出手部矩阵。

可以使用以下示例在代码中遵循此基本过程。 在深入搜索树数据结构期间遇到节点时,将矩阵推送到矩阵堆栈的顶部。

MatrixStack->Push();

MatrixStack->MultMatrix(pNode->matrix);

使用节点完成后,将矩阵从矩阵堆栈的顶部弹出。

MatrixStack->Pop();

这样,堆栈顶部的矩阵始终表示当前节点的世界转换。 因此,在绘制每个节点之前,应设置 Direct3D 矩阵。

pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(0), *MatrixStack->GetTop());

有关可以在 D3DX 矩阵堆栈上执行的特定方法的详细信息,请参阅 ID3DXMATRIXStack 参考主题。

顶点管道