티스토리 뷰

DirectXMath 벡터


DirectXMath 라이브러리의 벡터


Direct3D 응용 프로그램을 위한 표준적인 3차원 수학 라이브러리이다. 헤더 파일 DirectXMath.h를 포함시켜야(#include <DirectXMath.h> 하며, 추가적인 자료 형식들을 위해 DirectXPackedVector.h도 포함시켜야 할 수 있다.


DirectXMath.h의 코드는 DirectX 네임스페이스 안에 속하며, DirectXPackedVector.h의 코드는 DirectX::PackedVector 네임스페이스 안에 속한다. x86 플랫폼을 대상으로 할 때에는 SSE2를 활성화시켜야 한다(프로젝트 속성 > 구성 속성 > C/C++ > 코드 생성 > 고급 명령 집합 사용). x64 플랫폼에서는 모든 CPU가 SSE2를 지원하기 때문에 따로 활성화시켜줄 필요가 없다.


벡터 형식들


DirectXMath의 핵심 벡터 형식은 SIMD 하드웨어 레지스터에 대응되는 XMVECTOR이다. 이 128비트 크기의 형식은 32비트 부동소수점 값 네개로 구성되는데, SIMD 명령 하나로 네 값을 한꺼번에 처리할 수 있다. 이 형식은 다음과 같이 정의된다.


SIMD(Single Instruction Multiple Data)는 병렬 프로세서의 한 종류로, 하나의 명령어로 여러 개의 값을 동시에 계산하는 방식이다.

- 위키백과


typedef __m128 XMVECTOR;


여기서 __m128은 특별한 SIMD 형식이다. 벡터 계산 시 SIMD의 장점이 발휘되려면 벡터가 반드시 이 형식이여야 한다. 2차원, 3차원 벡터에서는 쓰이지 않는 성분들을 0으로 설정해서 무시하기만 하면 된다.


XMVECTOR는 16바이트 경계에 정합되어야 하는데, 지역 변수와 전역 변수에서는 그러한 정합이 자동으로 일어난다. 클래스 자료 멤버에는 이 형식 대신 XMFLOAT2, XMFLOAT3, XMFLOAT4를 사용하는 것이 권장된다. 이 구조체들의 정의는 다음과 같다.


struct XMFLOAT2 {

float x;

float y;


XMFLOAT2() {}

XMFLOAT2(float _x, float _y) : x(_x), y(_y) {}

// explict - 컴파일러가 XMFLOAT2의 생성자를 통해 XMFLOAT2 객체가 아닌 값이 들어왔을 때 생성자를 통해 자동으로 형변환 하는것을 막아줌

explicit XMFLOAT2(_In_reads_(2) const float* pArray) : 

x(pArray[0]), y(pArray[1]) {}


XMFLOAT3& operator=(const XMFLOAT3& Float3)

{ x = Float3.x; y = Float3.y; z = Float3.z; return *this; }

};


이 형식들을 계산에 직접 사용하면 SIMD의 장점을 취할 수 없기 때문에, SIMD를 활용하려면 이 형식들의 인스턴스를 XMVECTOR 형식으로 변환해야 한다. 다행히 DirectXMath가 제공하는 적재(load)함수를 이용해 그러한 변환을 할 수 있고, XMVECTOR의 자료를 XMFLOATn 형식들로 변환하는 저장(store) 함수도 제공한다.


1. 지역 변수나 전역 변수에는 XMVECTOR를 사용한다.

2. 클래스 자료 멤버에는 XMFLOAT2나 XMFLOAT3, XMFLOAT4를 사용한다.

3. 계산을 수행하기 전에 적재 함수들을 이용해서 XMFLOATn을 XMVECTOR로 변환한다.

4. XMVECTOR 인스턴스들로 계산을 수행한다.

5. 저장 함수들을 이용해서 XMVECTOR를 XMFLOATn으로 변환한다.


적재 및 저장 함수


적재 및 저장 함수의 목록은 다음과 같다.


XMVECTOR MX_CALLCONV XMLoadFloat2(const XMFLOAT2* pSource);

XMVECTOR MX_CALLCONV XMLoadFloat3(const XMFLOAT3* pSource);

XMVECTOR MX_CALLCONV XMLoadFloat4(const XMFLOAT4* pSource);


XMVECTOR의 자료를 XMFLOATn에 저장할 때에는 다음과 같은 함수를 사용한다.

void XM_CALLCONV XMStoreFloat2(const XMFLOAT2* pSource, FXMVECTOR v);
void XM_CALLCONV XMStoreFloat3(const XMFLOAT3* pSource, FXMVECTOR v);
void XM_CALLCONV XMStoreFloat4(const XMFLOAT4* pSource, FXMVECTOR v);

XMVECTOR의 특정 성분 하나만 읽거나 변경하고 싶을 때에는 다음 함수들을 사용한다.


float XM_CALLCONV XMVectorGetX(FMVECTOR V);

float XM_CALLCONV XMVectorGetY(FMVECTOR V);

float XM_CALLCONV XMVectorGetZ(FMVECTOR V);

float XM_CALLCONV XMVectorGetW(FMVECTOR V);


float XM_CALLCONV XMVectorSetX(FMVECTOR V. float x);

float XM_CALLCONV XMVectorSetY(FMVECTOR V. float y);

float XM_CALLCONV XMVectorSetZ(FMVECTOR V. float z);

float XM_CALLCONV XMVectorSetW(FMVECTOR V. float w);


매개변수 전달


XVECTOR 인스턴스를 인수로 해서 함수 호출할 때, 효율성을 위해서는 XMVECTOR같이 스택이 아니라 SSE/SSE2 레지스터를 통해서 함수에 전달되게 해야 한다. 플랫폼/컴파일러에 대한 의존성을 없애기 위해서는 XMVECTOR 매개변수에 대해 FXMVECTOR, GXMVECTOR, HXMVECTOR, CXMVECTOR이라는 형식들을 사용해야 하고, 레지스터 활용을 위한 규약의 의존성을 없애기 위해선 함수 이름 앞에 XM_CALLCONV라는 호출 규약 지시자를 붙여야 한다.


1. 처음 세 XMVECTOR 매개변수에는 반드시 FXMVECTOR 형식을 지정해야 한다.

2. 넷째 XMVECTOR 매개변수에는 반드시 GXMVECTOR 형식을 지정해야 한다.

3. 다섯째와 여섯째 XMVECTOR 매개변수에는 반드시 HXMVECTOR 형식을 지정해야 한다.

4. 그 이상의 XMVECTOR 매개변수들에는 반드시 CXMVECTOR 형식을 지정해야 한다.


32비트 Windows에서 __fastcall 호출 규약을 지원하는 컴파일러와 좀 더 최신의 __vectorcall 호출 규약을 지원하는 컴파일러는 이 형식들을 다음과 같이 지원한다.


32비트 Windows __fastcall

typedef const XMVECTOR FXMVECTOR;

typedef const XMVECTOR& GXMVECTOR;

typedef const XMVECTOR& HXMVECTOR;

typedef const XMVECTOR& CXMVECTOR;


32비트 Windows __vectorcall

typedef const XMVECTOR FXMVECTOR;

typedef const XMVECTOR GXMVECTOR;

typedef const XMVECTOR HXMVECTOR;

typedef const XMVECTOR& CXMVECTOR;


DirectXMath의 생성자에 대해서는 조금 다른 규칙이 적용된다. XMVECTOR 형식의 인수들을 받는 생성자를 작성할 때 처음 세 XMVECTOR 매개변수에는 FXMVECTOR를, 그 나머지에는 CXMVECTOR를 사용하라고 권한다. 또한, 생성자에는 XM_CALLCONV 호출 규약 지시자를 사용하지 말아야 한다.


DirectXMath 라이브러리 자체에서 뽑은 예이다.


inline XMMATRIX XM_CALLCONV XMMatrixTransformation(

FXMVECTOR ScalingOrigin,

FXMVECTOR ScalingOrientationQuaternion,

FXMVECTOR Scaling,

GXMVECTOR RotationOrigin,

HXMVECTOR RotationQuaternion,

HXMVECTOR Translation);


이 함수는 총 여섯 개의 XMVECTOR 매개변수를 받는다. 처음 세 매개변수에는 FMVECTOR를, 네 번째 매개변수에는 GMVECTOR를, 다섯째, 여섯째에는 HXMVECTOR를 사용한다. XMVECTOR 매개변수들 사이에 XMVECTOR가 아닌 매개변수가 끼어 있을 경우에는 XMVECTOR가 아닌 매개변수들은 무시하고 XMVECTOR 매개변수들만 세어서 앞의 규칙을 적용한다.


위와 같은 XMVECTOR 매개변수 전달 규칙은 입력 매개변수들에 적용된다. 출력 XMVECTOR 매개변수(XMVECTOR&, XMVECTOR*)는 SSE/SSE2 레지스터를 사용하지 않으므로 그냥 XMVECTOR가 아닌 매개변수들과 동일하게 취급한다.


상수 벡터


상수(const) XMVECTOR 인스턴스에는 반드시 XMVECTORF32 형식을 사용해야 한다. 다음은 DirectX SDK의 CascadedShadowMaps11 예제의 내용이다.


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

};


위와 같이 중괄호 초기화 구문을 사용할 때는 XMVECTORF32를 사용해야 한다. XMVECTORF32는 16바이트 경계에 정합되는 구조체로, XMVECTOR로의 변환 연산자들을 제공한다. 구조체와 연산자들의 정의는 다음과 같다.


// 상수를 위한 변환 형식

__declspec(align(16)) struct XMVECTORF32 {

union {

float f[4];

XMVECTOR v;

};


inline operator XMVECTOR() const { return v; }

inline operator const float*() const { return f; }


#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SEE_INTRINSICS_)

inline operator __m128i() const { return _mm_castps_si128(v); }

inline operator __m128d() const { return _mm_castps_pd(v) }

#endif

};


정수 자료를 담은 상수 XMVECTOR를 생성하고 싶으면 XMVECTORU32를 사용하면 된다.


static const XMVECTORU32 vGrabY = {

0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000

};


중복적재된 연산자들


XMVECTOR에는 벡터 덧셈, 뺄셈, 스칼라 곱셈을 위해 중복적재(overloading)된 여러 연산자가 있다.


XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V);

XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V);


XMVECTORXM_CALLCONV operator+= (XMVECTOR& V1, FXMVECTOR V2);

XMVECTORXM_CALLCONV operator-= (XMVECTOR& V1, FXMVECTOR V2);

XMVECTORXM_CALLCONV operator*= (XMVECTOR& V1, FXMVECTOR V2);

XMVECTORXM_CALLCONV operator/= (XMVECTOR& V1, FXMVECTOR V2);


XMVECTORoperator*= (XMVECTOR& V, float S);

XMVECTORoperator/= (XMVECTOR& V, float S);


XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V1, FXMVECTOR V2);

XMVECTOR XM_CALLCONV operator- (FXMVECTOR V1, FXMVECTOR V2);

XMVECTOR XM_CALLCONV operator* (FXMVECTOR V1, FXMVECTOR V2);

XMVECTOR XM_CALLCONV operator/ (FXMVECTOR V1, FXMVECTOR V2);

XMVECTOR XM_CALLCONV operator* (FXMVECTOR V, float S);

XMVECTOR XM_CALLCONV operator* (float S, FXMVECTOR V);

XMVECTOR XM_CALLCONV operator/ (FXMVECTOR V, float S);


기타 상수 및 함수


const float XM_PI = 3.14592654f;

const float XM_2PI = 6.283185307f;

const float XM_1DVPI = 0.318309886f;

const float XM_1DV2PI = 0.1591543f;

const float XM_PIDIV2 = 1.570796327f;

const float XM_PIDV4 = 0.785398163f;


또한, DirectXMath는 라디안 단위 각도와 도(degree) 단위 각도 사이의 변환을 위한 다음과 같은 인라인 함수들도 제공한다.


inline float XMConvertToRadians(float fDegrees) {

return fDegrees * (XM_PI / 180.0f);

}

inline float XMConvertToDegrees(float fRadians) {

return fRadians * (180.0f / XM_PI);

}


최솟값/최댓값 함수는 다음과 같다.


template<class T> inline T XMMin(T a, T b) { return (a < b) ? a : b; }

template<calss T> inline T XMMax(T a, T b) { return (a < b) ? a : b; }


설정 함수


DirectXMath 라이브러리는 XMVECTOR 객체의 내용을 설정하는 용도로 다음과 같은 함수들을 제공한다.


영벡터를 반환

XMVECTOR XM_CALLCONV XMVectorZero();


벡터 (1, 1, 1, 1) 반환

XMVECTOR XM_CALLCONV XMVectorSplatOne();


벡터 (x, y, z, w) 반환

XMVECTOR XM_CALLCONV XMVectorSet(float x, float y, float z, float w);


벡터 (s, s, s, s) 반환

XMVECTOR XM_CALLCONV XMVectorReplicate(float Value);


벡터 (vx, vx, vx, vx) 반환

XMVECTOR XM_CALLCONV XMVectorSplatX(FMVECTOR V);


벡터 (vy, vy, vy, vy) 반환

XMVECTOR XM_CALLCONV XMVectorSplatY(FMVECTOR V);


벡터 (vz, vz, vz, vz) 반환

XMVECTOR XM_CALLCONV XMVectorSplatZ(FMVECTOR V);


다음은 이 함수들 대부분의 용법을 보여주는 예제 프로그램이다.


#include <Windows.h> // XMVerifyCPUSupport에 필요함

#include <DirectXMath.h>

#include <DirectXPackedVector.h>

#include <iostream>


using namespace std;

using namespace DirectX;

using namespace DirectX::PackedVector;


// XMVECTOR 객체를 cout으로 출력하기 위해 << 연산자를 중복적재한다.


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.self(ios_base::boolalpha);


// SSE2를 지원하는지 확인한다

if(!XMVerifyCPUSupport()) {

cout << "DirectXMath를 지원하지 않음" << 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;

}


벡터 함수들


DirectXMath 라이브러리는 다양한 함수들을 제공한다. 다음은 그중 3차원 벡터를 위한 함수들이다. 2차원 벡터나 4차원 벡터일 때는 함수 이름에 3 대신 2나 4가 쓰인다.


벡터의 길이 반환

XMVECTOR XM_CALLCONV XMVector3Length(

FXMVECTOR V);


벡터의 길이의 제곱 반환

XMVECTOR XM_CALLCONV XMVector3LengthSq(

FXMVECTOR V);


V1과 V2의 내적 반환

XMVECTOR XM_CALLCONV XMVector3Dot(

FXMVECTOR V1,

FXMVECTOR V2);


V1과 V2의 외적 반환

XMVECTOR XM_CALLCONV XMVector3Cross(

FXMVECTOR V1,

FXMVECTOR V2);


V 정규화

XMVECTOR XM_CALLCONV XMVector3Normalize(

FXMVECTOR V);


V에 수직인 벡터 반환

XMVECTOR XM_CALLCONV XmVector30rthgonal(

FXMVECTOR V);


V1과 V2 사이의 각도 반환

XMVECTOR XM_CALLCONV XMVector3AngleBetweenVectors(

FXMVECTOR V1,

FXMVECTOR V2);


void XM_CALLCONV XMVector3ComponentsFromNormal(

XMVECTOR* pParallel,  // proj_n(v) 저장 - 직교투영(정사영)

XMVECTOR* pPerpendicular,  // perp_n(v) 저장 - 수직인 벡터

FXMVECTOR V, // 입력 v

FXMVECTOR Normal); // 입력 n


V1 == V2 반환

bool XM_CALLCONV XMVector3Equal(

FXMVECTOR V1,

FXMVECTOR V2);


V1 != V2 반환

bool XM_CALLCONV XMVECTOR3NotEqual(

FXMVECTOR V1,

FXMVECTOR V2);


내적처럼 결과가 스칼라값인 연산이라도 이 함수들은 XMVECTOR를 반환한다. 스칼라 결과는 XMVECTOR의 모든 성분에 복사되어 있다. 이런 방식을 사용하는 이유 중 하나는 스칼라 연산과 SIMD 벡터 연산의 전환을 최소화한다는 것이다. 계산 도중 최대한 모든 것을 SIMD로 유지하는 것이 좀 더 효율적이다.


다음 예제 프로그램은 이 함수들 대부분의 용법을 보여준다.


#include <Windows.h> // XMVerifyCPUSupport에 필요함

#include <DirectXMath.h>

#include <DirectXPackedVector.h>

#include <iostream>


using namespace std;

using namespace DirectX;

using namespace DirectX::PackedVector;


int main() {

cout.setf(ios_base::boolalpha);


// SSE2를 지원하는지 확인

if(!XMVerifyCPUSupport) {

cout << "DirectXMath를 지원하지 않음" << 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);


// XMVECTOR operator

XMVECTOR a = u + v;

XMVECTOR b = u - v;

XMVECTOR c = 10.0f * u;


// 길이

XMVECTOR L = XMVector3Length(u);


// 정규화

XMVECTOR d = XMVector3Normalize(u);


// 내적

XMVECTOR s = XMVector3Dot(u, v);


// 외적

XMVECTOR e = XMVector3Cross(u, v);


// proj_n(w)와 perp_n(w)

XMVECTOR projW;

XMVECTOR perpW;

XMVECTOR3ComponentsFromNormal(&projW, &perpW, w, n);


// projW + perpW = w인가?

bool equal = XMVector3Equal(projW + perpW, w) != 0;

bool notEqual = XMVector3NotEqual(projW + perpW, w) != 0;


// projW와 perpW 사이의 각도는 반드시 90도여야 한다

XMVECTOR angleVec = XMVector3AngleBetweenVectors(projW, perpW);

float angleRadians = XMVectorGetX(angleVec);

float angleDegrees = XMConvertToDegrees(angleRadians);


return 0;

}


DirectXMath 라이브러리는 계산이 덜 정확하지만 더 빠른 추정(estimation) 함수들도 제공한다. 속도를 위해 정확성을 조금 희생할 수 있는 상황이라면 이런 추정 함수들을 사용해 보는 것도 좋다.


추정된 벡터의 길이 반환

XMVECTOR XM_CALLCONV XMVector3LengthEst(FXMVECTOR V);


추정된 벡터 정규화

XMVECTOR XM_CALLCONV XMVector3NormalizeEst(FXMVECTOR V);


부동소수점 오차

컴퓨터에서 벡터를 다룰 때에는 부동소수점의 부정확함을 반드시 고려해야 한다는 점이다. 정규화된 벡터의 크기는 정확히 1이여야 하지만, 프로그램 안에서 그 길이는 근사적으로만 1이다. 또한, 임의의 실수 p에 대해 1^p = 1이 성립하지만, 근삿값으로만 표현되는 부동소수점 연산에서는 거듭제곱 과정에서 오차가 증가한다. 즉, 수치 오차가 누적되는 것이다.


#include <Windows.h> // XMVerifyCPUSupport에 필요함

#include <DirectXMath.h>

#include <DirectXPackedVector.h>

#include <iostream>


using namespace std;

using namespace DirectX;

using namespace DirectX::PackedVector;


int main() {

cout.precision(8);


// SSE2를 지원하는지 확인

if(!XMVerifyCPUSupport) {

cout << "DirectXMath를 지원하지 않음" << endl;

return 0;

}


XMVECTOR u = XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f);

XMVECTOR n = XMVector3Normalize(u);


float LU = XMVectorGetX(XMVector3Length(n));


// 수학적으로는 길이가 반드시 1이어야 한다

cout << LU << endl;


if(LU == 1.0f) {

cout << "길이 1" << endl;

else

cout << "길이 1이 아님" << endl;


// 1을 임의의 지수로 거듭제곱해도 여전히 1이어야 한다

float powLU = powf(LU, 1.0e6f);

cout << "LU^(10^6) = " << powLU << endl;


return 0;

}


이러한 부동소수점의 부정확함 때문에 부동소수점 간의 상등을 판정할 때에는 두 수가 근사적으로 같은지를 보아야 한다. 이를 위해 허용 오차로 사용할 아주 작은 수인 엡실론을 정하고, 그 값을 이를테면 Epsilon이라는 상수로 코드 안에 정의해 둔다. 두 수가 같은지 판정할 때에는 두 수의 거리(차이의 절댓값)가 그 Epsilon보다 작은지 본다. 만일 거리가 Epsilon보다 작으면 두 수는 근사적으로 상등인 것이다.


const float Epsilon = 0.001f;

bool Equals(float lhs, float rhs) {

return fabs(lhs - rhs) < Epsilon ? true : false;

}


DirectXMath 라이브러리에는 두 벡터의 상등을 판정하는 XMVector3NearEqual이라는 함수가 있다. 매개변수 Epsilon은 앞에서 말한 허용 오차이다.


XMFINLINE bool XM_CALLCONV XMVector3NearEqual(

FXMVECTOR U,

FXMVECTOR V,

FXMVECTOR Epsilon);


요약

1. 벡터는 크기와 방향을 모두 가진 물리적 수량을 나타내는 데 쓰인다. 기하학적으로는 벡터를 지향 선분으로 표현한다. 꼬리가 원점과 일치하도록 이동된 벡터를 가리켜서 표준 위치에 있다고 말한다. 표준 위치에 있는 벡터는 좌표계에 상대적인 그 머리의 좌표성분을 이용해 수치적으로 서술할 수 있다.


2. 벡터 u = (ux, uy, uz)와 v = (vx, vy, vz)에 대해 다음과 같은 벡터 연산들이 정의된다.

(a) 덧셈: u + v = (ux + vx, uy + vy, uz + vz)


(b) 뺄셈: u - v = (ux - vx, uy +- vy, uz - vz)


(c) 스칼라 곱셈: ku = (kux , kuy, kuz)


(d) 길이: u =


(e) 정규화: u = u/u∥ = (ux/u∥, uy/u∥, uz/u∥)


(f) 내적: u · v = uv∥cosθ = uxvx + uyvy + uzvz


(g) 외적: u × v = (uyvz - uzvy, uzvx - uxvz, uxvy - uyvx)


(g-2) 2차원 유사 외적: u(x, y) = v(-uy, ux) (u⊥v, u⊥-v)


3. 코드에서 벡터를 효율적으로 다루기 위해 DirectXMath 라이브러리의 XMVECTOR 형식을 사용한다. 이 형식은 SIMD 연산들을 이용해서 벡터를 효율적으로 처리한다. 클래스 자료 멤버에는 XMFLOAT2, XMFLOAT3, XMFLOAT4 클래스를 사용하되, 필요에 따라 적재 함수들을 이용해서 XMVECTOR로의 변환하고 저장 함수들을 이용해서 다시 XMFLOATn으로 변환한다. 초기화 구문을 이용해서 상수 벡터를 정의할 때에는 XMVECTORF32 형식을 사용해야 한다.


4. XMVECTOR 인스턴스를 인수로 해서 함수를 호출할 때, 효율성을 위해서는 XMVECTOR값이 스택이 아니라 SSE/SSE2 레지스터를 통해서 함수에 전달되게 해야 한다. 이를 플랫폼 독립적인 방식으로 처리하기 위해, 함수의 XMVECTOR 매개변수에 처음 세 매개변수에는 FXMVECTOR 형식을, 넷째 XMVECTOR에는 GXMVECTOR 형식을, 다섯째와 여섯째 XMVECTOR에는 HXMVECTOR를, 그 이상에는 반드시 CXMVECTOR 형식을 지정한다는 규칙을 따라야 한다.


5. DirectXMath 라이브러리는 XMVECTOR를 이용한 벡터 덧셈, 뺄셈, 스칼라 곱셈을 위해 중복적재된 연산자들을 제공한다. 더 나아가서, DirectXMath 라이브러리는 벡터의 길이 및 제곱 계산, 두 벡터의 내적과 외적 계산, 벡터 정규화를 위한 편의용 함수들도 제공한다.


6. 부동소수점의 부정확함을 고려해 두 부동소수점 형식의 상등을 구할 때에는, 허용 오차로 사용할 아주 작은 수인 앱실론을 정하고 두 수의 차이의 절댓값이 그 앱실론보다 작은지 비교하는 방법을 사용해야 한다.




'공부 > 프레임워크, 엔진' 카테고리의 다른 글

의존성 주입과 Zenject  (1) 2023.07.17
[GMS] repeat는 나머지 연산이 아니다.  (0) 2019.02.11
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함