遊戲建模-矢量運算

遊戲建模-矢量運算

矢量(VECTOR)也稱『向量』其實是抽象『量』它在遊戲世界被頂義為『位置』『速度』『磨擦』『方向』『點』等等. 矢量通常有3種

矢量 分量 簡序
2D矢量 x,y 2D空間
3D矢量 x,y,z 3D空間
4D矢量 x,y,z,w 3D空間w總是為1.用於方陣運算

首先定義3D矢量結構:

typedef struct VECTOR3D_TYP{

float x,y,z;

}VECTOR3D,*VECTOR3D_PTR;

下面是3D矢量(VECTOR)運算函式庫.

 

計算3D矢量長度,矢量長度也稱為範數(norm).將其理解為原點(0,0,0)到矢量(x,y,z)之距離

float Length_VECTOR3D(VECTOR3D_PTR va){

return( (float)sqrtf(va->xva->x + va->yva->y + va->z*va->z) );

}

 

3D矢量進行歸一化(normalize),也就使其長度縮放為1,但同時方向保持不變.它通常被用於無需理會長度之運算如『方向』

void Normalize_VECTOR3D(VECTOR3D_PTR va){

// 1.首先計算長度

float length = sqrtf(va->xva->x + va->yva->y + va->z*va->z);

//2.矢量除以長度得到歸一化矢量

va->x= va->x/length;

va->y= va->y/length;

va->z= va->z/length;

}

 

3D矢量點積運算可以理解為矢量乘法.先將各分量相乘後再相加得到一個標量

float operator%(VECTOR3D va, VECTOR3D vb){

return((va.x * vb.x) + (va.y * vb.y) + (va.z * vb.z));

}

float Dot_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return( (va->x * vb->x) + (va->y * vb->y) + (va->z * vb->z) );

}

叉積是另一種矢量乘法,叉積運算最小要有3個分量才有效.

VECTOR3D operator^(VECTOR3D va, VECTOR3D vb){

VECTOR3D vn;

vn.x = ((va.y * vb.z) – (va.z * vb.y));

vn.y = -((va.x * vb.z) – (va.z * vb.x));

vn.z = ((va.x * vb.y) – (va.y * vb.x));

return(vn);

}

VECTOR3D Cross_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

VECTOR3D vn;

vn.x =  ( (va->y * vb->z) – (va->z * vb->y) );

vn.y = -( (va->x * vb->z) – (va->z * vb->x) );

vn.z =  ( (va->x * vb->y) – (va->y * vb->x) );

return(vn);

}

 

計算兩個3D矢量va和vb之間夾角余弦值

float CosTh_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return(Dot_VECTOR3D(va,vb)/(Length_VECTOR3D(va)*Length_VECTOR3D(vb)));

}

 

 

計算三角形法線

void Normal_VECTOR3D(VECTOR3D_PTR normal,VECTOR3D_PTR va, VECTOR3D_PTR vb, VECTOR3D_PTR vc){

VECTOR3D u, v, n;

float length;

u = *vb – *va;

v = *vc – *va;

n = u^v;//Cross_VECTOR3D(&u, &v, &n);// 計算叉積

length = sqrtf(n.xn.x + n.yn.y + n.z*n.z);

normal->x = n.x/length;

normal->y = n.y/length;

normal->z = n.z/length;

}

 

將兩個3D矢量相加(va + vb),如用於位置移動

VECTOR3D operator+(VECTOR3D va, VECTOR3D vb){

VECTOR3D vsum;

vsum.x = va.x + vb.x;

vsum.y = va.y + vb.y;

vsum.z = va.z + vb.z;

return (vsum);//返回相加結果!

}

 

將兩個3D矢量相減(va – vb),如用於位置移動

VECTOR3D operator-(VECTOR3D va, VECTOR3D vb){

VECTOR3D vdiff;

vdiff.x = va.x – vb.x;

vdiff.y = va.y – vb.y;

vdiff.z = va.z – vb.z;

return(vdiff);     //返回相減向量!

}

 

3D矢量反數,如返轉方向

VECTOR3D operator-(VECTOR3D v){

VECTOR3D negation;

negation.x = -v.x ;

negation.y = -v.y ;

negation.z = -v.z ;

return(negation);     //返回反數向量!

}

 

使用縮放因子k對3D矢量進行縮放如:位置=位置+速度*時間

VECTOR3D operator*(VECTOR3D va, float k){

VECTOR3D vscaled;

vscaled.x = k * va.x;

vscaled.y = k * va.y;

vscaled.z = k * va.z;

return vscaled;// 返回縮放後向量

}

 

3D矢量賦值

void Init_VECTOR3D(VECTOR3D_PTR v, float x,float y,float z) {

v->x = x;  v->y = y; v->z = z;

}

 

3D矢量拷貝

Copy_VECTOR3D(VECTOR3D_PTR vdst, VECTOR3D_PTR vsrc){

vdst->x = vsrc->x;  vdst->y = vsrc->y; vdst->z = vsrc->z;

}

 

3D矢量比較

bool operator==(VECTOR3D vdst, VECTOR3D vsrc){

if (vdst.x == vsrc.x && vdst.y == vsrc.y && vdst.z == vsrc.z)

return true;

else

return false;

}

 

3D向量不等比較

bool operator!=(VECTOR3D vdst, VECTOR3D vsrc)

{

if (vdst.x != vsrc.x ||         vdst.y != vsrc.y ||vdst.z != vsrc.z)

return true;

else

return false;

}

 

向量歸零(3D向量)無方向,無距離,代表位於原點

void Zero_VECTOR3D(VECTOR3D_PTR v) {

v->x = v->y = v->z = 0.0f;

}

計算兩矢量之間夾角

float Angle_VECTOR3D(VECTOR3D_PTR va, VECTOR3D_PTR vb){

return acosf(*va % *vb);

}

角度轉弧度

#define DEG_TO_RAD(ang) ((ang)*PI/180.0)

弧度轉角度

#define RAD_TO_DEG(rads) ((rads)*180.0/PI)

隨機數 x:下限,  y:上限.

#define RAND_RANGE(x,y) ( (x) + (rand()%((y)-(x)+1)))

隨機數: -1.0 ~ 1.0

#define FRAND_RANGE1()   (((float)rand()-(float)rand())/RAND_MAX)

隨機數 0~1

#define FRAND_RANGE() ((float)rand() / (float)RAND_MAX)

評論