1.6 XNA MATH VECTORS
来源:互联网 发布:天猫盒子软件 编辑:程序博客网 时间:2024/05/20 23:35
1.6 XNA MATH VECTORS
1.6 XNA 数学库
In Direct3D9 and 10, the D3DX library shipped with a 3D math utility library that includedsupport for vectors among other core 3D math types required for doing 3Dgraphics. The D3DX library for version 11 no longer ships with 3D math code.Instead it ships with the XNA Math library, which is a vector math librarydeveloped separately from Direct3D that takes advantages of special hardwareregisters on Windows and XBox 360. OnWindows, the library uses the SSE2 (Streaming SIMD Extensions 2) instruction set. With 128-bit wide SIMD (single instruction multiple data) registers,SIMD instructions can operate on four 32-bit floats or ints with oneinstruction. This is very useful for vector calculations; for example, if youlook at vector addition:
在Direct3D 9和10中,D3DX数学库装载了实用3D数学库,其中包含对其他核心3D数学类型的向量支持。而在Direct3D 11不再沿用实用3D数学库,取而代之的XNA 数学库。这是个向量数学库,它独立与Direct3D。它可以利用window和XBOX360平台上的硬件寄存器。在window平台上,使用的是128 位宽的SIMD寄存器,每条SIMD指令可以操作4个32位整型或浮点型数据。这对向量计算是十分有用的。假定有如下向量加法:
u + v = (ux+ vx, uy + vy, uz + vz)
we see thatwe just add corresponding components. By using SIMD, we can do 4D vectoraddition with one SIMD instruction instead of 4 scalar instructions. If we areworking in 3D, we can still use SIMD, but we would just set the 4th componentto 0 and ignore it; likewise for 2D.
可以看到,我们只需要将各个分量相加。通过使用SIMD,我们可以仅使用一条SIMD指令而不是四条标量计算指令来计算4D向量。如果我们要计算3D向量,仍可用SIMD计算,只需将第四个分量设为0即可。2D计算也是类似的。
Our coverageof the XNA Math library is not comprehensive, and we only cover the key partsneeded for this book. For all the details, we recommend the onlinedocumentation [XNAMath2010]. For readers wishing to understand how an SIMDvector library might be developed optimally, and, perhaps, to gain some insightinto why the XNA Math library made some of the design decisions that it did, werecommend the article Designing Fast Cross-Platform SIMD Vector Libraries by[Oliveira2010].
本书并未涉及全部的XNA数学库,我们只是包含了本书所需的关键部分。如果想了解更多,我们推荐网络文档[XNAMath2010],对于想要深入了解XNA数学库的读者,我们推荐文档Designing Fast Cross-PlatformSIMD Vector Libraries by [Oliveira2010].
To use theXNA Math library, you only need to #include <xnamath.h>. There are noadditional library files, as all
the code isimplemented inline in the header file.
要使用XNA数学库,你只需要包含xnamath.h头文件,此外无需添加额外的库文件,所有的代码都在里面。
Note:There is nothing that stopsyou from including <d3dx10.h>, linking with d3dx10.lib, and using theD3DX10
Mathfunctions instead of the XNA math library.
注意:你仍旧可以使用d3dx10.h头文件,通过连接到d3dx10.lib使用D3DX10 Math的函数而不是XNA数学库。
1.6.1 Vector Types
1.6.1 向量类型
In XNA Math,the core vector type is XMVECTOR, which maps to SIMD hardware registers. Thisis a 128-bit type that can process four 32-bit floats with a single SIMDinstruction. When SSE2 is available, it is defined like so:
在XNA中,核心的向量类型是XMVECTOR,他被映射到了SIMD硬件寄存器。该寄存器宽128位,当SSE2可用时,它可以通过一条SIMD指令操作4个32位浮点型数据。
typedef __m128 XMVECTOR;
where __m128is a special SIMD type. When doing calculations, vectors must be of this typeto take advantage of SIMD. As already mentioned, we still use this type for 2Dand 3D vectors to take advantage of SIMD, but we just zero out the unusedcomponents and ignore them.
__128 是一种特殊的SIMD类型。计算时,向量必须指定为该类型才能利用SIMD来计算。如前所述,我们也可以使用该类型来表示2D和3D向量,只需将无用的分量设为0并忽略它既可。
XMVECTORneeds to be 16-byte aligned, and this is done automatically for local andglobal variables. For class data members, it is recommended to use XMFLOAT2(2D), XMFLOAT3 (3D), and XMFLOAT4 (4D) instead; these structures are definedbelow:
XMVECTOR需要16字节线性的,对于局部和全局变量它将自动完成。对于类的成员变量,建议使用XMFLOAT2(2D)、XMFLOAT3(3D)和XMFLOAT4(4D)。这些结构体的定义如下:
typedef struct _XMFLOAT2 {
FLOAT x;
FLOAT y;
} XMFLOAT2;
typedef struct _XMFLOAT3 {
FLOAT x;
FLOAT y;
FLOAT z;
} XMFLOAT3;
typedef struct _XMFLOAT4 {
FLOAT x;
FLOAT y;
FLOAT z;
FLOAT w;
} XMFLOAT4;
However, ifwe use these types directly for calculations, then we will not take advantageof SIMD. In order to use SIMD, we need to convert instances of these types intothe XMVECTOR type. This is done with the XNA Math loading functions.Conversely, XNA Math provides storage functions which are used to convert datafrom XMVECTOR into the XMFLOAT* types described previously.
然而,如果我们直接使用这些类型计算,我们将无法使用SIMD。为了使用SIMD,我们需要将这些类型的实例转换成XMVECTOR类型,此过程可使用XNA库封装的加载函数来完成。XNA数学库提供了内置函数来将XMVECTOR类型转换成之前提到的XMFLOAT* 类型。
Tosummarize,
1. UseXMVECTOR for local or global variables.
2. UseXMFLOAT2, XMFLOAT3, and XMFLOAT4 for class data members.
3. Useloading functions to convert from XMFLOAT* to XMVECTOR before doingcalculations.
4. Docalculations with XMVECTOR instances.
5. Usestorage functions to convert from XMVECTOR to XMFLOAT*.
小结:
1. 局部变量或全局变量可使用XMVECTOR
2. 使用XMFLOAT2, XMFLOAT3, 和 XMFLOAT4作为类的成员变量
3. 计算前,使用加载函数将XMFLOAT*类型转换成为XMVECTOR类型
4. 使用XMVECTOR类型的实例进行计算
5. 使用存储函数将XMVECTOR类型转换成XMFLOAT* 类型
1.6.2 Loading andStorage Methods
We use thefollowing methods to load data from XMFLOAT* into XMVECTOR:
我们使用下列方法将数据从XMFLOAT*类型加载到XMVECTOR类型
// Loads XMFLOAT2 into XMVECTOR 加载 XMFLOAT2 到 XMVECTOR
XMVECTOR XMLoadFloat2(CONST XMFLOAT2 *pSource);
// Loads XMFLOAT3 into XMVECTOR加载 XMFLOAT3 到 XMVECTOR
XMVECTOR XMLoadFloat3(CONST XMFLOAT3 *pSource);
// Loads XMFLOAT4 into XMVECTOR加载 XMFLOAT4 到 XMVECTOR
XMVECTOR XMLoadFloat4(CONST XMFLOAT4 *pSource);
NOTE:here are many moreloading methods used to load other data types into an XMVECTOR; the reader canview the XNA Math documentation for the complete list. Following are a few moreexamples:
注意:存在许多加载函数可以将其他数据类型转换到XMVECTOR类型,读者可以自己浏览XNA Math 文档查看完整地函数列表。下面给出少许例子:
// Loads 3-element UINT array into XMVECTOR 加载三元素无符号整型数组到XMVECTOR
XMVECTOR XMLoadInt3(CONST UINT* pSource);
// Loads XMCOLOR into XMVECTOR 加载XMCOLOR到XMVECTOR
XMVECTOR XMLoadColor(CONST XMCOLOR *pSource);
// Loads XMBYTE4 into XMVECTOR 加载XMBYTE4到XMVECTOR
XMVECTOR XMLoadByte4(CONST XMBYTE4 *pSource);
We use thefollowing methods to store data from XMVECTOR into XMFLOAT*:
我们使用下列函数将XMVECTOR类型数据存储为XMFLOAT*
// Loads XMVECTOR into XMFLOAT2 加载XMVECTOR到XMFLOAT2
VOID XMStoreFloat2(XMFLOAT2 *pDestination, FXMVECTOR V);
// Loads XMVECTOR into XMFLOAT3加载XMVECTOR到XMFLOAT3
VOID XMStoreFloat3(XMFLOAT3 *pDestination, FXMVECTOR V);
// Loads XMVECTOR into XMFLOAT4加载XMVECTOR到XMFLOAT4
VOID XMStoreFloat4(XMFLOAT4 *pDestination, FXMVECTOR V);
NOTE:There are many more storing methodsused to store XMVECTOR into other data types. Following is a small sampling;the reader can see the XNA Math documentation for the complete list.
注意:存在许多加载函数可以将XMVECTOR类型转换到其他数据类型,读者可以自己浏览XNA Math 文档查看完整地函数列表。下面给出少许例子:
// Loads XMVECTOR into 3 element UINT array
VOID XMStoreInt3(UINT* pDestination, FXMVECTOR V);
// Loads XMVECTOR into XMCOLOR
VOID XMStoreColor(XMCOLOR* pDestination, FXMVECTOR V);
// Loads XMVECTOR into XMBYTE4
VOID XMStoreByte4(XMBYTE4 *pDestination, FXMVECTOR V);
Sometimes wejust want to get or set one component of an XMVECTOR; the following getter andsetter functions facilitate this:
有时我们可能只希望设置或得到XMVECTOR的一个分量,下列的存取方法可以实现它:
FLOAT XMVectorGetX(FXMVECTOR V);
FLOAT XMVectorGetY(FXMVECTOR V);
FLOAT XMVectorGetZ(FXMVECTOR V);
FLOAT XMVectorGetW(FXMVECTOR V);
XMVECTOR XMVectorSetX(FXMVECTOR V, FLOAT x);
XMVECTOR XMVectorSetY(FXMVECTOR V, FLOAT y);
XMVECTOR XMVectorSetZ(FXMVECTOR V, FLOAT z);
XMVECTOR XMVectorSetW(FXMVECTOR V, FLOAT w);
1.6.3 Parameter Passing
To takeadvantage of SIMD, there are some rules for passing parameters to functions oftype XMVECTOR. These rules differ based on the platform; in particular, theydiffer between 32-bit Windows, 64-bit Windows, and XBox 360. To be platformindependent, we use the types CXMVECTOR and FXMVECTOR for passing XMVECTORparameters; these are defined to the right type based on the platform. ForWindows, these are defined as:
为了使用SIMD,我们必须遵循XMVECTOR的函数传递规则,这些规则基于不同的平台有所不同,尤其是在32 位window、64位window以及XBOX360上。为了使平台独立化,我们使用类型CXVECTOR和FXMVECTOR来传递XMVECTOR类型的参数,它们的具体类型定义取决于平台。在window中,其定义如下:
// 32-bit Windows
typedef const XMVECTOR FXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
// 64-bit Windows
typedef const XMVECTOR& FXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
Thedifference is whether we can pass a copy of XMVECTOR directly, or if we mustpass a reference. Now the rule for passing XMVECTOR parameters is as follows:
不同之处在于我们是否可以直接传递一个XMVECTOR的副本,或者我们必须传递一个引用变量。因此XMVECTOR类型的参数传递规则如下:
The first 3XMVECTOR parameters should be of type FXMVECTOR; any additional XMVECTORparameters should be of type CXMVECTOR. Here is an example:
前三个XMVECTOR参数的类型必须为FXMVECTOR;其余的XMVECTOR参数必须指定为CXMVECTOR类型。示例如下:
XMINLINE XMMATRIX XMMatrixTransformation( FXMVECTOR ScalingOrigin,
FXMVECTOR ScalingOrientationQuaternion, FXMVECTOR Scaling,
CXMVECTOR RotationOrigin,
CXMVECTOR RotationQuaternion,
CXMVECTOR Translation);
This function takes 6 XMVECTOR parameters, but following the parameter passing rules, it uses the FXMVECTOR and CXMVECTOR types. Thefirst three XMVECTOR parameters are of type FXMVECTOR and the additionalXMVECTOR parameters are of type CXMVECTOR. Note that you can have non-XMVECTORparameters between XMVECTOR parameters; the first 3 XMVECTOR parameters arestill typed as XMVECTOR, and additional XMVECTOR parameters are typed asCXMVECTOR:
此函数有6个XMVECTOR类型的参数,但仍遵循参数传递规则,它使用FXMVECTOR 和CXMVECTOR类型。前三个参数的类型为FXMVECTOR其余为CXMVECTOR。注意在任意两个XMVECTOR类型参数之间都可使用非XMVECTOR类型,但前三个XMVECTOR参数的类型必须为FXMVECTOR;其余的XMVECTOR参数必须指定为CXMVECTOR类型。
XMINLINE XMMATRIX XMMatrixTransformation2D( FXMVECTOR ScalingOrigin,
FLOAT ScalingOrientation,
FXMVECTOR Scaling,
FXMVECTOR RotationOrigin,
FLOAT Rotation,
CXMVECTOR Translation);
1.6.4 Constant Vectors
ConstantXMVECTOR instances should use the XMVECTORF32 type. Here are some examples fromthe DirectX SDK’s CascadedShadowMaps11 sample:
静态向量实例必须指定为XMVECTORF32类型,下列有一些来自CascadedShadowMaps1示例的代码示例:
static const XMVECTORF32 g_vHalfVector = { 0.5f, 0.5f, 0.5f, 0.5f };
static const XMVECTORF32 g_vZero = { 0.0f, 0.0f, 0.0f, 0.0f };
XMVECTORF32 vRightTop = {
vViewFrust.RightSlope,
vViewFrust.TopSlope,
1.0f,1.0f
};
XMVECTORF32 vLeftBottom = {
vViewFrust.LeftSlope,
vViewFrust.BottomSlope,
1.0f,1.0f
};
Essentially,we use XMVECTORF32 whenever we want to use initialization syntax. XMVECTORF32is a 16-byte aligned structure with aXMVECTOR conversion operator; it is defined as follows:
本质上,我们在初始化时使用XMVECTORF32。XMVECTORF32是使用XMVECTOR转换操作符的16字节线性结构体,其定义如下:
// Conversion types for constants 常量类型转换
typedef _DECLSPEC_ALIGN_16_ struct XMVECTORF32
{ union {
float f[4];
XMVECTOR v;
};
#if defined(__cplusplus)
inline operator XMVECTOR() const { return v; }
#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_)
inline operator __m128i() const
{ return reinterpret_cast<const __m128i *>(&v)[0]; }
inline operator __m128d() const
{ return reinterpret_cast<const __m128d *>(&v)[0]; } #endif
#endif // __cplusplus
} XMVECTORF32;
You can alsocreate a constant XMVECTOR of integer data using XMVECTORU32:
你也可以使用XMVECTORU32创建一个XMVECTOR类型的整型数据:
static const XMVECTORU32 vGrabY = {
0x00000000,0xFFFFFFFF,0x00000000,0x00000000
};
1.6.5 OverloadedOperators
1.6.5 重载操作
TheXMVECTOR has several overloaded operators for doing vector addition, subtraction, and scalar multiplication. Operator overloading can be disabled by defining XM_NO_OPERATOR_OVERLOADS. The reason some application would want to disable operator overloading is forperformance, as the function versions can be faster when forming complexexpressions (see [Oliveira2010]). We prefer the more intuitive syntax ofoperator overloading in this book and keep it enabled.
XMVECTOR中有许多加减及标量乘法的重载运算符。重载运算可通过定义XM_NO_OPERATOR_OVERLOADS来禁止,一些程序之所以禁用重载是为了使运算更高效,因为标准运算函数在复杂语句中运行更快。我们更倾向于随心所欲的重载,所以本书中将保持可重载。
// Vector operators
#if defined(__cplusplus) && !defined(XM_NO_OPERATOR_OVERLOADS)
XMVECTOR operator+ (FXMVECTOR V);
XMVECTOR operator- (FXMVECTOR V);
XMVECTOR& operator+= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR& operator-= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR& operator*= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR& operator/= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR& operator*= (XMVECTOR& V, FLOAT S);
XMVECTOR& operator/= (XMVECTOR& V, FLOAT S);
XMVECTOR operator+ (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR operator- (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR operator* (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR operator/ (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR operator* (FXMVECTOR V, FLOAT S);
XMVECTOR operator* (FLOAT S, FXMVECTOR V);
XMVECTOR operator/ (FXMVECTOR V, FLOAT S);
#endif // __cplusplus && !XM_NO_OPERATOR_OVERLOADS
1.6.6 Miscellaneous
The XNA Mathlibrary defined the following constants useful for approximating differentexpressions involving π:
XNA数学库定义了下列常量用来近似表示与π有关的参量
#define XM_PI 3.141592654f
#define XM_2PI 6.283185307f
#define XM_1DIVPI 0.318309886f
#define XM_1DIV2PI 0.159154943f
#define XM_PIDIV2 1.570796327f
#define XM_PIDIV4 0.785398163f
In addition,it defines the following inline functions for converting between radians anddegrees:
此外,还定义了下列内联函数用于将弧度和角度进行转换:
XMFINLINE FLOAT XMConvertToRadians(FLOAT fDegrees)
{
return fDegrees * (XM_PI / 180.0f);
}
XMFINLINE FLOAT XMConvertToDegrees(FLOAT fRadians)
{
return fRadians * (180.0f / XM_PI);
}
It alsodefines min/max macros:
#define XMMin(a, b) (((a) < (b)) ? (a) : (b))
#define XMMax(a, b) (((a) > (b)) ? (a) : (b))
1.6.7 Setter Functions
1.6.7 设置函数
XNA Mathprovides the following functions to set the contents of an XMVECTOR:
XNA数学库提供了下列函数来设置XMVECTOR的内容:
XMVECTOR XMVectorZero(); // Returns the zero vector 0 返回参数全零的向量
XMVECTOR XMVectorSplatOne(); // Returns the vector (1, 1, 1, 1)
XMVECTOR XMVectorSet( // Returns the vector (x, y, z, w)
FLOAT x, FLOAT y, FLOAT z, FLOAT w);
XMVECTOR XMVectorReplicate( // Returns the vector (s, s, s, s)FLOAT s);
XMVECTOR XMVectorSplatX( // Returns the vector (vx, vx, vx, vx)
FXMVECTOR V);
XMVECTOR XMVectorSplatY( // Returns the vector (vy, vy, vy, vy)
FXMVECTOR V);
XMVECTOR XMVectorSplatZ( // Returns the vector (vz, vz, vz, vz)
FXMVECTOR V);
Thefollowing program illustrates most of these functions:
下列的程序示例演示了如何使用他们:
#include <windows.h> // for FLOAT definition #include <xnamath.h>
#include <iostream>
using namespace std;
// Overload the "<<" operators so that we can use cout to// output XMVECTOR objects.
ostream& 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 << "xna math not supported" << endl; return 0;
}
XMVECTOR p = XMVectorZero();
XMVECTOR q = XMVectorSplatOne();
XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
XMVECTOR v = XMVectorReplicate(-2.0f);
XMVECTOR w = XMVectorSplatZ(u);
cout << "p = " << p << endl;
cout << "q = " << q << endl;
cout << "u = " << u << endl;
cout << "v = " << v << endl;
cout << "w = " << w << endl;
return 0;
}
1.6.8 Vector Functions
XNA Mathprovides the following functions to do various vector operations. We illustratewith the 3D versions, but there are analogous versions for 2D and 4D; the 2Dand 4D versions have the same names as the 3D versions, with the exception of a2 and 4 substituted for the 3, respectively.
XNA数学库提供了下列函数用于各种向量操作。此示例使用3D版本(即三维空间版本),但是其中仍有2D和4D的类型版本。2D和4D版本的函数名与3D相同,只不过把函数名中3换成2或4即可。
XMVECTOR XMVector3Length( // Returns || v ||
FXMVECTOR V); // Input v
XMVECTOR XMVector3LengthSq( // Returns || v ||
2FXMVECTOR V); // Input v
XMVECTOR XMVector3Dot( // Returns v1 • v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
XMVECTOR XMVector3Cross( // Returns v1 × v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
XMVECTOR XMVector3Normalize( // Returns v/|| v ||
FXMVECTOR V); // Input v
XMVECTOR XMVector3Orthogonal( // Returns a vector orthogonal to v
FXMVECTOR V); // Input v
XMVECTOR XMVector3AngleBetweenVectors( // Returns the angle between v1 and v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
VOID XMVector3ComponentsFromNormal(
XMVECTOR* pParallel, // Returns projn(v)
XMVECTOR* pPerpendicular, // Returns prepn(v)
FXMVECTOR V, // Input v
FXMVECTOR Normal); // Input n
BOOL XMVector3Equal( // Returns v1 = v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
BOOL XMVector3NotEqual( // Returns v1 ≠ v2
FXMVECTOR V1, // Input v1
FXMVECTOR V2); // Input v2
Note:Observe that thesefunctions return XMVECTORS even for operations that mathematically return ascalar (for example, the dot product k = v1 • v2). The scalar result is replicated in each component of the XMVECTOR. For example, for the dotproduct, the returned vector would be (v1 • v2, v1 • v2, v1 • v2, v1 • v2). One reason forthis is to minimize mixing of scalar and SIMD vector operations; it is moreefficient to keep everything SIMD until you are done with your calculations.
注意:观察到这些函数均返回XMVECTORS,即使是返回一个标量(例如,点积k = v1 • v2)。标量结果是把XMVECTOR的每个分量复制为相同量。例如,对于点积而言,结果向量应为v1 • v2, v1 • v2, v1 • v2, v1 • v2)。这样做的原因是避免将标量运算和SIMD的向量运算混淆。在你计算时,保持使用SIMD是非常必要的。
The following demo program shows how to use most of these functions, as well as some of the overloadedoperators:
下列示例演示了如何使用这些函数,其中也包含了许多重载操作
#include <windows.h> // for FLOAT definition #include <xnamath.h>
// Overload the "<<" operators so that we can use cout to // output XMVECTOR objects.
XMFLOAT3 dest;
XMStoreFloat3(&dest, v);
os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")";
return os;
}
cout.setf(ios_base::boolalpha);
// Check support for SSE2 (Pentium4, AMD K8, and above). if( !XMVerifyCPUSupport() )
{
cout << "xna math not supported" << endl; return 0;
}
XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f); // Vector addition: XMVECTOR operator +
XMVECTOR a = u + v;
// Scalar multiplication: XMVECTOR operator *
XMVECTOR c = 10.0f*u;
// ||u||
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;
}
Figure 1.19. Output for the above program.
NOTE:The XNA Math library alsoincludes some estimation methods, which are less accurate but faster tocompute. If you are willing to sacrifice some accuracy for speed, then use the estimatemethods. Here are two examples of estimate functions:
注意:XNA数学库也包含了许多近似计算函数,它们不太精确但计算速度快。如果你想牺牲精度而追求速度的话,你可以考虑使用近似计算。下面有2个近似计算函数的示例:
XMFINLINE XMVECTOR XMVector3LengthEst( // Returns estimated || v ||
FXMVECTOR V); // Input v
XMFINLINE XMVECTOR XMVector3NormalizeEst( // Returns estimated v/|| v ||
FXMVECTOR V); // Input v
1.6.9 Floating-PointError
1.6.9 浮点错误
Whileon the subject of working with vectors on a computer, we should be aware of thefollowing. When comparing
floating-pointnumbers, care must be taken due to floating-point imprecision. Two floating-pointnumbers that we expect to be equal may differ slightly. For example,mathematically, we’d expect a normalized vector to have a length of one, but ina computer program, the length will only be approximately one. Moreover, mathematically,1p = 1 for any real number p, but when we only have a numerical approximationfor , we see that the approximation raised to the th power increases the error;thus, numerical error also accumulates. The following short program illustratesthese ideas:
当在计算机中涉及到向量时,我们必须有下列意识。当比较两个浮点数时,一定要考虑浮点数的精度问题。两个我认为相等的浮点数可能略有不同。比如,在数学中,我们希望正规化一个向量使他长度为1,但在计算机程序中,这个长度只能是一个近似值。另外,在实际数学中,1的任意次方为1,但在计算机中我们只能得到一个近似值,这样就会导致计算错误,下列的简单代码演示了这种情况:
#include <windows.h> // for FLOAT definition
#include <xnamath.h>
#include <iostream>
using namespace std;
int main()
{
cout.precision(8);
// Check support for SSE2 (Pentium4, AMD K8, and above).
if( !XMVerifyCPUSupport() )
{
cout << "xna math not supported" << endl;
return 0;
}
XMVECTOR u = XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f);
XMVECTOR n = XMVector3Normalize(u);
float LU = XMVectorGetX(XMVector3Length(n));
// Mathematically, the length should be 1. Is it numerically?
cout << LU << endl;
if( LU == 1.0f )
cout << "Length 1" << endl;
else
cout << "Length not 1" << endl;
// Raising 1 to any power should still be 1. Is it?float powLU = powf(LU, 1.0e6f);
cout << "LU^(10^6) = " << powLU << endl;
}
Tocompensate for floating-point imprecision, we test if two floating-pointnumbers are approximately equal. We do
thisby defining an Epsilon constant, which is a very small value we use as a “buffer.” We say two values are
approximatelyequal if their distance is less than Epsilon. In other words, Epsilon gives ussome tolerance for
floating-pointimprecision. The following function illustrates how Epsilon can be used to testif two floating-point values are equal:
为了弥补浮点数不精确的问题,我们检测两个数是否近似相等。我们定义一个Epsilon常量,他的值非常小。当两个浮点数间的差值小于这个值时,我们认为这两个浮点数相等。换句话说,Epsilon允许一定的误差。下列函数示例用于测试两个浮点数是否近似相等:
const float Epsilon = 0.001f;
bool Equals(float lhs, float rhs)
{
// Is the distance between lhs and rhs less than EPSILON?
return fabs(lhs - rhs) < Epsilon ? true : false;
}
TheXNA Math library provides the XMVector3NearEqual function when testing theequality of vectors with an allowed tolerance Epsilon parameter:
XNA数学库提供了XMVector3NearEqual函数,用于测试两个向量在允许容差Epsilon内是否相等。
// Returns
// abs(U.x - V.x) <= Epsilon.x && // abs(U.y - V.y) <= Epsilon.y && // abs(U.z - V.z) <= Epsilon.z
XMFINLINE BOOL XMVector3NearEqual( FXMVECTOR U,
FXMVECTOR V,
FXMVECTOR Epsilon);
1.7 SUMMARY
- 1.6 XNA MATH VECTORS
- XNA Math Library 及 相关整理
- XNA Math Library 函数调用之参数传递分析
- XNA Math库 XMVECTOR与XMMATRIX使用规则
- XNA
- XNA
- C++ Vectors
- vectors.S
- term vectors
- C++ Vectors
- C++ Vectors
- Gradient Vectors
- C++ Vectors
- Vectors.dense()
- ARM64 vectors
- XNA游戏:Hello XNA
- diference between support vectors and boundary vectors.
- Math
- AVMediaServiceUtils::makePortPair
- java swing版考试系统
- 2017年5月20日软考考试报名开始啦
- 学习运维——配置电子邮件传输
- 让windowBackground也能用centerCrop
- 1.6 XNA MATH VECTORS
- Fighting_小银考呀考不过四级 (sdut oj)
- 芯片上电休眠或者JTAG禁用后怎么下载程序
- 小程序写倒计时
- Yolo的搭建和在Windows下封装以及工程应用
- 2017.3.13 反素数ant 失败总结
- 有哪些预付卡是全球游戏行业使用率非常高的?
- C输入输出
- ios升级