将 "Spread" 值应用于 XMFLOAT4X4

Applying a "Spread" value to an XMFLOAT4X4

我正在尝试向 World Matrix 添加一个小值,以复制射击武器 [手枪、突击步枪] 的准确性

目前,我的世界矩阵位于父对象的位置,能够专门围绕 Y 轴旋转。

我已经在 Unity3D 中完成了此操作,运行 每当需要创建对象时 [每个]:

        var coneRotation = Quaternion.Euler(Random.Range(-spread, spread), Random.Range(-spread, spread), 0);
        var go = Instantiate(obj, parent.transform.position, transform.rotation * coneRotation) as GameObject;

并且正在尝试使用 Direct3D11 复制结果。

这个 lambda return 是目前 [-1.5, 1.5] 之间的随机值:

    auto randF = [&](float lower_bound, float uppder_bound) -> float
    {
        return lower_bound + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (uppder_bound - lower_bound)));
    };

我的第一个想法是在初始化时简单地将一个随机的 x && y 乘以对象的 forward 向量,并以这种方式移动它:position = position + forward * speed * dt; [speed1800],尽管旋转不正确(更不用说子弹发射了)。

我还尝试制作四元数 [如在 Unity3D 中]:XMVECTOR quaternion = XMVectorSet(random_x, random_y, 0) 并使用 XMMatrixRotationQuaternion.

创建旋转矩阵

之后我调用XMStoreFloat4x4(&world_matrix, XMLoadFloat4x4(&world_matrix) * rotation);,恢复矩阵的位置部分[访问world_matrix._41/._42/._43](world_matrix是[的矩阵=48=] 本身,而不是父级)。

[我也试过颠倒乘法的顺序]

我读到 XMMatrixRotationQuaternion 不 return 作为欧拉四元数,而 XMQuaternionToAxisAngle 是,尽管我不完全确定如何使用它。

完成这样的事情的正确方法是什么?

非常感谢!

您的代码 XMVECTOR quaternion = XMVectorSet(random_x, random_y, 0); 没有创建有效的四元数。首先,如果您没有将 w 组件设置为 1,那么 4 向量四元数实际上并不表示 3D 旋转。其次,四元数的向量分量不是欧拉角。

您想使用 XMQuaternionRotationRollPitchYaw 从欧拉角输入构造四元数旋转,或 XMQuaternionRotationRollPitchYawFromVector 将三个欧拉角作为向量。这些函数正在做 Unity 的 Quaternion.Euler 方法正在做的事情。

当然,如果你想要一个旋转矩阵而不是四元数,那么你可以XMMatrixRotationRollPitchYawXMMatrixRotationRollPitchYawFromVector直接从欧拉角构造一个4x4的旋转矩阵——实际上内部使用了四元数无论如何。根据您的代码片段,您似乎已经有了一个基本旋转作为四元数,您希望将其与扩展四元数连接起来,因此您可能不想在这种情况下使用此选项。

注意:你应该考虑使用 C++11 标准 <random> 而不是围绕糟糕的 C 编写的 lambda 包装器 rand功能。

类似于:

std::random_device rd;
std::mt19937 gen(rd());

// spread should be in radians here (not degrees which is what Unity uses)
std::uniform_real_distribution<float> dis(-spread, spread);
XMVECTOR coneRotation = XMQuaternionRotationRollPitchYaw( dis(gen), dis(gen), 0 );
XMVECTOR rot = XMQuaternionMultiply( parentRot, coneRotation );
XMMATRIX transform = XMMatrixAffineTransformation( g_XMOne, g_XMZero, rot, parentPos );

顺便说一句,如果您习惯使用 Unity 或 XNA Game Studio C# 数学库,您可能需要查看 SimpleMath wrapper for DirectXMath in DirectX Tool Kit