1.6.8矢量函数
DirectX Math提供以下功能来执行各种矢量操作。 我们用3D版本来说明,但是2D和4D有类似的版本; 2D和4D版本与3D版本具有相同的名称,除了2和4分别替代3。
XMVECTOR XM_CALLCONV XMVector3Length( // Returns||v||
FXMVECTOR V); // Input v
XMVECTOR XM_CALLCONV XMVector3LengthSq( // Returns||v||2
FXMVECTOR V); // Input v
XMVECTOR XM_CALLCONV XMVector3Dot( // Returns v1·v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
XMVECTOR XM_CALLCONV XMVector3Cross( // Returns v1 ×v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
XMVECTOR XM_CALLCONV XMVector3Normalize( // Returns v/||v||
FXMVECTOR V); // Input v
XMVECTOR XM_CALLCONV XMVector3Orthogonal( // Returns a vector orthogonal to v
FXMVECTOR V); // Input v
XMVECTOR XM_CALLCONV XMVector3AngleBetweenVectors( // Returns the angle between v1 and v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
void XM_CALLCONV XMVector3ComponentsFromNormal(XMVECTOR* pParallel, // Returns projn(v)
XMVECTOR* pPerpendicular, // Returns perpn(v)
FXMVECTOR V, // Input v
FXMVECTOR Normal); // Input n
bool XM_CALLCONV XMVector3Equal( // Returns v1 = v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
bool XM_CALLCONV XMVector3NotEqual( // Returns v1 ≠ v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
请注意,即使对数学运算返回标量的操作(例如点积k = v1·v2),这些函数也会返回XMVECTOR。 标量结果被复制到XMVECTOR的每个组件中。 例如,对于点积,返回的矢量将是(v1·v2,v1·v2,v1·v2,v1·v2)。 其中一个原因是最小化标量和SIMD向量操作的混合;在您完成计算之前,保持SIMD的一切都更为有效。
下面的演示程序演示了如何使用大多数这些函数以及一些重载操作符:
#include <windows.h> // for XMVerifyCPUSupport
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <iostream>
using namespace std;
using namespace DirectX;
using namespace DirectX::PackedVector;
// Overload the "<<" operators so that we can use cout to
// output XMVECTOR objects.
ostream& XM_CALLCONV operator << (ostream& os, FXMVECTOR v)
{
XMFLOAT3 dest;
XMStoreFloat3(&dest, v);
os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")";
return os;
}
int main()
{
cout.setf(ios_base::boolalpha);
// Check support for SSE2 (Pentium4, AMD K8, and above).
if (!XMVerifyCPUSupport())
{
cout << "directx math not supported" << endl;
return 0;
}
XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);
XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);
// Vector addition: XMVECTOR operator +
XMVECTOR a = u + v;
// Vector subtraction: XMVECTOR operator -
XMVECTOR b = u - v;
// Scalar multiplication: XMVECTOR operator *
XMVECTOR c = 10.0f*u;
// ||u||
XMVECTOR L = XMVector3Length(u);
// d = u / ||u||
XMVECTOR d = XMVector3Normalize(u);
// s = u dot v
XMVECTOR s = XMVector3Dot(u, v);
// e = u x v
XMVECTOR e = XMVector3Cross(u, v);
// Find proj_n(w) and perp_n(w)
XMVECTOR projW;
XMVECTOR perpW;
XMVector3ComponentsFromNormal(&projW, &perpW, w, n);
// Does projW + perpW == w?
bool equal = XMVector3Equal(projW + perpW, w) != 0;
bool notEqual = XMVector3NotEqual(projW + perpW, w) != 0;
// The angle between projW and perpW should be 90 degrees.
XMVECTOR angleVec = XMVector3AngleBetweenVectors(projW, perpW);
float angleRadians = XMVectorGetX(angleVec);
float angleDegrees = XMConvertToDegrees(angleRadians);
cout << "u = " << u << endl;
cout << "v = " << v << endl;
cout << "w = " << w << endl;
cout << "n = " << n << endl;
cout << "a = u + v = " << a << endl;
cout << "b = u - v = " << b << endl;
cout << "c = 10 * u = " << c << endl;
cout << "d = u / ||u|| = " << d << endl;
cout << "e = u x v = " << e << endl;
cout << "L = ||u|| = " << L << endl;
cout << "s = u.v = " << s << endl;
cout << "projW = " << projW << endl;
cout << "perpW = " << perpW << endl;
cout << "projW + perpW == w = " << equal << endl;
cout << "projW + perpW != w = " << notEqual << endl;
cout << "angle = " << angleDegrees << endl;
return 0;
}
DirectX Math库还包含一些估算方法,这些方法精确度较低但计算速度较快。 如果你愿意牺牲一些速度的准确性,那么就使用估计方法。 以下是两个估算函数的例子:
XMVECTOR XM_CALLCONV XMVector3LengthEst( // Returnsestimated ||v||
FXMVECTOR V); // Input v
XMVECTOR XM_CALLCONV XMVector3NormalizeEst( //Returns estimated v/||v||
FXMVECTOR V); // Input v