矢量(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)