zoukankan      html  css  js  c++  java
  • XNA数学库

    XNA Math Vectors

    在direct3D 9 和10中,包含3D数学库的D3DX库支持向量和其他核心类型的计算。在direct11中,D3DX库不在包含3D数学库,取而代之的是XNA数学库。XNA利用的是特殊的硬件寄存器。在windows环境中,XNA
    数学库使用SSE2(Streaming SIMD Extension 2)指令集。它使用128-bits大小的SIMD(single instruction multiple data)寄存器,可以用一个指令操作4个32-bits浮点型数据或整型数据。
    例如:u + v = (ux + vx, uy + vy, uz + vz)
    我们用3个加法指令将每个分量加起来。但通过使用SIMD,我们可以只用一个SIMD指令做4D向量加法,而不是用4个标量指令。如果你操作3D向量,我们仍然可以使用SIMD,
    我们只需将向量的第四个分量置为0并且忽略它。在2D中类似。
    为了使用XNA数学库,我们只需添加头文件#include<xnamath.h> 。当然,你也可以通过包含头文件#include<d3dx10.h>,并且链接静态库d3dx10.lib使用D3DX10数学库。


    在XNA数学库中,关键的向量类型是XMVECTOR. 它是一个128-bits类型,可以被单个SIMD指令处理。
    它被这样定义:

    1 typedef __m128 XMVECTOR;

    这里,__m128是一个特殊的SIMD类型。对于类数据成员,最好使用XMFLOAT2,XMFLOAT3,XMFLAOT4。它们被如下定义:

    1 typedef struct _XMFLOAT4
    2 {
    3     FLOAT x;
    4     FLOAT y;
    5     FLOAT z;
    6     FLOAT w;
    7 }XMFLOAT4;

    然而,如果我们直接使用这些类型进行计算,将不能利用SIMD硬件。我们需要将这些类型的实例转化为XMFLOAT类型。这些是XNA载入函数(loading functions)的工作。相反地,XNA还提供存储函数(storage functions)将
    XMVECTOR转化为XMFLOAT*类型。

    Loading 和 Storage 函数

    Loading函数:

    1 XMVECTOR XMLoadFloat2(CONST XMFLOAT2 *pSource); // 将XMFLOAT2转化为XMVECTOR类型
    2 XMVECTOR XMLoadFloat3(CONST XMFLOAT3 *pSource); // 将XMFLOAT3转化为XMVECTOR类型
    3 XMVECTOR XMLoadFloat4(CONST XMFLOAT4 *pSource); // 将XMFLOAT4转化为XMVECTOR类型

    还有很多方法将其他类型转化为XMVECTOR类型,下面是一些例子:

    1 XMVECTOR XMLoadInt3(CONST UINT* pSource);    // Loads 3-element UINT array into XMVECTOR
    2 XMVECTOR XMLoadColor(CONST XMCOLOR *pSource);    // Loads XMCOLOR into XMVECTOR
    3 XMVECTOR XMLoadByte4(CONST XMBYTE4 *pSource);    // Loads XMBYTE4 into XMVECTOR

    Storage函数:

    1 VOID XMStoreFloat2(XMFLOAT2 *pDestination,FXMVECTOR V); // 将XMVECTOR转化为XMFLOAT2类型

    还有很多方法将XMVECTOR转化为其他类型,下面是一些例子:

    1 VOID XMStoreInt3(UINT* pDestination, FXMVECTOR V);
    2 VOID XMStoreColor(XMCOLOR* pDestination, FXMVECTOR V);
    3 VOID XMStoreByte4(XMBYTE4 *pDestination, FXMVECTOR V);

    有时,我们只想获取或者设置XMVECTOR的一个分量,可以使用下面的函数完成:

    1 FLOAT XMVectorGetX(FXMVECTOR V);
    2 XMVECTOR XMVectorSetX(FXMVECTOR V,Float x);

    传递参数的规则

    为了利用SIMD,将参数传递给XMVECTOR类型的函数有一些规则需要遵守,这些规则根据平台的不同而不同。尤其是32-bit Windows、64-bit Windows和XBOX 360. 为了独立于平台,
    我们使用类型CXMVECTOR和FXMVECTOR传递XMVECTOR的参数。对于Windows,它们被定义如下:

    1 // 32-bit Windows
    2 typedef const XMVECTOR FXMVECTOR;
    3 typedef const XMVECTOR& CXMVECTOR;
    4 // 64-bit Windows
    5 typedef const XMVECTOR& FXMVECTOR;
    6 typedef const XMVECTOR& CXMVECTOR;

    它们的不同点是,我们可以直接传递XMVECTOR的副本还是我们必须传递一个引用。现在,传递XMVECTOR参数的规则如下:
    前三个XMVECTOR参数应该是FXMVECTOR类型,后面的为CXMVECTOR类型。

    1 XMINLINE XMMATRIX XMMatrixTransformation(
    2     FXMVECTOR ScalingOrigin,
    3     FXMVECTOR ScalingOrientationQuaternion,
    4     FXMVECTOR Scaling,
    5     CXMVECTOR RotationOrigin,
    6     CXMVECTOR RotationQuaternion,
    7     CXMVECTOR Translation);

    注意,你可以拥有非XMVECTOR类型的参数,前面的规则仍然有效:

    1 XMINLINE XMMATRIX XMMatrixTransformation2D(
    2 FXMVECTOR ScalingOrigin,
    3 FLOAT ScalingOrientation, // FLOAT类型
    4 FXMVECTOR Scaling,
    5 FXMVECTOR RotationOrigin,
    6 FLOAT Rotation, // FLOAT类型
    7 CXMVECTOR Translation);

    对于常量XMVECTOR实例,我们应该使用XMVECTORF32类型存储浮点型向量。这儿有一些例子:

    1 static const XMVECTORF32 g_vZero = { 0.0f, 0.0f, 0.0f, 0.0f };
    2 
    3 XMVECTORF32 vRightTop = {
    4 vViewFrust.RightSlope,
    5 vViewFrust.TopSlope,
    6 1.0f,1.0f
    7 };

    使用XMVECTORU32存储整型向量:

    1 static const XMVECTORU32 vGrabY = {
    2 0x00000000,0xFFFFFFFF,0x00000000,0x00000000
    3 };

    XNA数学库定义了一些与PI有关的常量:

    1 #defineXM_PI 3.141592654f
    2 #defineXM_2PI 6.283185307f
    3 #defineXM_1DIVPI 0.318309886f // 1/PI
    4 #defineXM_1DIV2PI 0.159154943f // 1/2PI
    5 #defineXM_PIDIV2 1.570796327f // PI/2
    6 #defineXM_PIDIV4 0.785398163f // PI/4

    它还定义了如下内联函数用来在角度和弧度之间进行转换:

    1 XMFINLINE FLOAT XMConvertToRadians(FLOAT fDegrees)
    2 {
    3     return fDegrees*(XM_PI/180.0f);
    4 }
    5 
    6 XMFINLINE FLOAT XMConvertToDegrees(FLOAT fRadians)
    7 {
    8     return fRadians*(180.0f/XM_PI);
    9 }

    它也定义了最大最小宏:

    1 #define XMMin(a,b) (((a) < (b)) ? (a) : (b))
    2 #define XMMax(a, b) (((a) > (b)) ? (a) : (b))

    XNA数学库提供了下列函数来设置XMVECTOR的内容:

    1 XMVECTOR XMVectorZero(); // 返回0向量(0,0,0,0)
    2 XMVECTOR XMVectorSplatOne(); // 返回向量(1, 1, 1, 1)
    3 XMVECTOR XMVectorSet(FLOAT x, FLOAT y, FLOAT z,FLOAT w); // 返回向量(x, y, z, w)
    4 XMVECTOR XMVectorReplicate(FLOAT s); // 返回向量(s, s, s, s)
    5 XMVECTOR XMVectorSplatX(FXMVECTOR V);// 返回向量(vx, vx, vx,vx)
    6 XMVECTOR XMVectorSplatY(FXMVECTOR V);// 返回向量(vy, vy, vy,vy)
    7 XMVECTOR XMVectorSplatZ(FXMVECTOR V);// 返回向量(vz, vz, vz,vz)

    一些向量计算的函数:(下面为3D的例子,2D,4D同理,只需将函数名中的3替换为2、4)

     1 XMVECTOR XMVector3Length(FXMVECTOR V);    // Returns || v ||
     2 XMVECTOR XMVector3LengthSq(FXMVECTOR V); // Returns || v ||的二次方
     3 XMVECTOR XMVector3Dot(FXMVECTOR V1, FXMVECTOR V2);    // Returns v1 • v2
     4 XMVECTOR XMVector3Cross(FXMVECTOR V1, FXMVECTOR V2);    //Returns v1 × v2
     5 XMVECTOR XMVector3Normalize(FXMVECTOR V);    // Returns v/|| v ||
     6 XMVECTOR XMVector3Orthogonal(FXMVECTOR V);    // Returns a vector orthogonal to v
     7 XMVector3AngleBetweenVectors(FXMVECTOR V1, FXMVECTOR V2);    // Returns the angle between v1 and v2
     8 VOID XMVector3ComponentsFromNormal(XMVECTOR* pParallel,XMVECTOR* pPerpendicular, FXMVECTOR V, FXMVECTORNormal);    // Returns projn(v)// Returns prepn(v)
     9 BOOL XMVector3Equal(FXMVECTOR V1, FXMVECTOR V2);    // Returns v1 = v2
    10 BOOL XMVector3NotEqual(FXMVECTOR V1, FXMVECTOR V2);    // Returns v1 ≠ v2

    还有一些估算方法,如果你不在乎精确度,而在乎速度,可以使用如下函数:

    MFINLINE XMVECTOR XMVector3LengthEst(XMVECTOR V); // Returns estimated || v ||
    MFINLINE XMVECTOR XMVector3NormalizeEst(XMVECTOR V); // Returns estimated v/|| v ||

    众所周知,浮点数的操作结果是不精确的。
    可以定义一个阙值来解决:

    1 const float Epsilon = 0.001f;
    2 bool Equals(float lhs, float rhs)
    3 {
    4 return fabs(lhs - rhs) < Epsilon ? true : false;
    5 }

    在XNA数学库中有类似的函数:XMVector3NearEqual()

    1 // Returns
    2 // abs(U.x – V.x) <= Epsilon.x &&
    3 // abs(U.y – V.y) <= Epsilon.y &&
    4 // abs(U.z – V.z) <= Epsilon.z
    5 XMFINLINE BOOL XMVector3NearEqual(
    6 FXMVECTOR U,
    7 FXMVECTOR V,
    8 FXMVECTOR Epsilon);

    为了在XNA数学库中表示4x4矩阵,我们使用XMMATRIX类,它被这样定义:

     1 union
     2 {    
     3     XMVECTOR r[4];
     4 struct
     5 {
     6     FLOAT _11, _12, _13, _14;
     7     FLOAT _21, _22, _23, _24;
     8     FLOAT _31, _32, _33, _34;
     9     FLOAT _41, _42, _43, _44;
    10 };
    11     FLOAT m[4][4];
    12 };

    正如上面定义的,XMMATRIX被用4个使用SIMD的XMVECTOR实例表示。
    除了使用各种各样的构造函数,XMMATRIX还可以通过XMMatrixSet函数创建:

    1 XMMATRIX XMMatrixSet(
    2 FLOAT m00,FLOAT m01,FLOAT m02,FLOAT m03,
    3 FLOAT m10,FLOAt m11,FLOAT m12,FLOAT m13,
    4 FLOAt m20,FLOAt m21,FLOAT m22,FLOAT m23,
    5 FLOAT m30,FLOAT m31,FLOAT m32,FLOAT m33);

    正如前面讲过的,我们在类数据成员的表示中,通常被推荐使用XMFLOAT2,XMFLOAT3,XMFLOAT4,同样,在表示类数据成员时,我们被推荐使用XMFLOAT4x4类型存储矩阵。


    XNA数学库中包括下面与矩阵有关的函数:

    1 XMMATRIX XMMatrixIdentitu();    // 返回单位矩阵 I
    2 Bool XMMatrixIsIdentity(CXMMATRIX M);    // 如果M为单位矩阵,返回true
    3 XMMATRIX XMMatrixMultiply(CXMMATRIX A,CXMMATRIX B);    // 返回 矩阵A,B的乘积
    4 XMMATRIX XMMatrixTranspose(CXMMATRIX M);    // 返回矩阵M的转置矩阵
    5 XMVECTOR XMMatrixDeterminant(CXMMATRIX M);    // 返回向量(det M,det M,det M,det M)
    6 XMMATRIX XMMatrixInverse(XMVECTOR* pDeterminant,CXMMATRIX M);    // 返回矩阵M的逆矩阵

    XMMATRIX参数的类型应该为CXMAATRIX,这将保证XMMATRIX参数在Windows和Xbox平台上被正确传递。

    XNA中的变换函数:

     1 XMMATRIX XMMatrixScaling(
     2 FLOAT ScaleX,
     3 FLOAT ScaleY,
     4 FLOAT ScaleZ); // 缩放函数
     5 XMMATRIX XMMatrixScalingFromVector(
     6 FXMVECTOR Scale); // //Constructs a scaling matrix from components in vector
     7 XMMATRIX XMMatrixRotationX(
     8 FLOAT Angle); // 绕X轴旋转
     9 XMMATRIX XMMatrixRotationY(
    10 FLOAT Angle); // 绕Y轴旋转
    11 XMMATRIX XMMatrixRotationZ(
    12 FLOAT Angle); // 绕Z轴旋转
    13 XMMATRIX XMMatrixRotationAxis(
    14 FXMVECTOR Axis,
    15 FLOAT Angle); // 绕任意轴n旋转
    16 XMMATRIX XMMatrixTranslation(
    17 FLOAT OffsetX,
    18 FLOAT OffsetY,
    19 FLOAT OffsetZ); // 平移矩阵
    20 XMMATRIX XMMatrixTranslationFromVector(
    21 FXMVECTOR Offset); // Constructs a translation matrix from components in a vector
    22 XMVECTOR XMVector3Transform(
    23 FXMVECTOR V,
    24 CXMMATRIX M); //计算向量V和矩阵M的积
    25 XMVECTOR XMVector3TransformCoord(
    26 FXMVECTOR V,
    27 CXMMATRIX M); //Computes the vector-matrix product vM where vw = 1 for transforming points
    28 XMVECTOR XMVector3TransformNormal(
    29 FXMVECTOR V,
    30 CXMMATRIX M); //Computes the vector-matrix product vM where vw = 0 for transforming vectors

    注意:最后两个函数XMVector3TransformCoord()和XMVector3TransformNormal(),你不需要明确地指定vw=1 或者 vw =0,因为函数会自动完成。

  • 相关阅读:
    算法之字符串
    linux环境无界面运行selenium
    用猴子补丁的方式解决 python unittest按定义的顺序执行用例
    adb命令行执行uiautomator2
    uiautomator2环境搭建
    jenkins安装
    python unittest自动化数据驱动demo
    uiautomator1与2的区别
    HttpRunnerManager学习
    接口测试
  • 原文地址:https://www.cnblogs.com/ll-10/p/5503380.html
Copyright © 2011-2022 走看看