我正在查看DirectX SDK中的教程。教程 5 工作正常,但是在我将代码复制并分离到我自己的类后,我在启动应用程序时遇到了奇怪的错误。
该行是:
g_World1 = XMMatrixIdentity();
因此,我在运算符=中遇到了错误 xnamathmatrix.int 看起来像这样:
XMFINLINE _XMMATRIX& _XMMATRIX::operator=
(
CONST _XMMATRIX& M
)
{
r[0] = M.r[0];
r[1] = M.r[1];
r[2] = M.r[2];
r[3] = M.r[3];
return *this;
}
错误消息是:
Access violation reading location 0xffffffff
我在某处读到它可能是由与XMFLOAT4X4/XMmatrix相关的内容引起的:
您是否考虑过使用 XMFLOAT4X4 来存储矩阵,并且只使用 XMMATRIX?
但我想我已经使用了XMMATRIX。
MyClass.h:
private:
XMMATRIX g_World1;
我的类.cpp:
void init(){
g_World1 = XMMatrixIdentity();
}
我认为我不应该将 XMMATRIX g_World1; 更改为 XMFLOAT4X4 g_World1,因为它会产生以下错误:
错误 C2679:二进制"=":未找到采用类型为"XMMATRIX"的右侧操作数的运算符(或者没有可接受的转换)
由于 XMMATRIX 表示一个 16 字节对齐的 4x4 矩阵,因此未对齐的g_World1分配会导致访问冲突(简单地说,g_World1 的地址不能被 16 整除)。
解决方案:使结构成员对齐 16 个字节(让 MyClass 具有"就位"g_World1)。但是,您仍然必须确保MyClass实例驻留在可被16整除的地址上。
您可以使用放置"new"运算符来分配 MyClass 对象。
关于对齐方式,请参见此处:如何对齐指针
XMVECTOR和XMMATRIX是"寄存器代理"类型。您可以安全地将它们用作 Xbox 360、Xbox One 和 Windows x64 平台的类型,因为它们在堆栈上的数据本机都具有 16 字节对齐方式,并在堆上分配。
将它们用于Windows 32位或Windows RT/ARM需要花费更多的精力,因为本机对齐方式超过16字节。一种方法是 DirectX 工具包使用的技术...它使用 pImpl 惯用法,并且 pImpl 内部类显式分配了 16 字节对齐方式,这是直接使用 XMVECTOR 和 XMMATRIX 类型的地方。另一种方法是使用所有各种"存储"类型,如XMFLOAT4和XMFLOAT4X4。
注意:DirectXMath程序员指南涵盖了这一点。这不是一个很长的文档,它包含了很多提示和建议。
PS:MSDN Code Gallery上有一个版本的Win32桌面标准Direct3D教程,不需要DirectX SDK...它只使用VS 2012或VS 2013附带的Windows 8.x SDK。
谢谢。
最后,我决定使用 XMLoadFloat4x4() 和 XMStoreFloat4x4() 函数。我将类的成员存储为 Float4x4,并将它们临时转换为 XMMATRIX 每个 render() 循环。但。。。这是一个快速还是愚蠢的解决方案?
在"Frank D. Luna"的"Introduction to 3D Game Programming with Directx 11"一书中说:
不要将 XMMATRIX 用作类或结构的成员。始终使用 XMFloat4x4 并在需要时加载和存储。