一、向量运算
点乘:a * b = |a| |b| cosα
投影
叉乘:|a X b| = |a| |b| sinα 向量计算: x =y1*z2 - z1*y2; y = z1*x2 - x1*z2; z = x1*y2 - y1*x2;
...
二、设计决策
- 这里用float类型。当今的处理器处理浮点数能在处理整数的周期内完成,并且还提供向量处理器来执行浮点向量运算,所以不用担心浮点类型的计算效率。
- 关于返回类型,一般来说,返回类型是一个引用会提高效率(因为少调用构造函数)。但是在一些情况下(如+等重载运算)则需要返回类实例,这里的处理是在return时直接构造,显式构造临时对象。但是这还是会造成性能下降(因为还是需要调用构造函数)。然而,我们似乎可以使用对象池以减少这种效率问题,但是除了轻微的性能提升,提高了巨大的代码复杂性。所以这里还是使用了return时直接构造。
- 在设计代码时,时刻牢记效率问题。保持类的精简,同时也不要为了轻微的性能优化付出很大的代码复杂性。
三、向量类
/***************************************************************
*
* vector3类:简单的3D向量类
*
****************************************************************/
#include <math.h>
class Vector3 {
public:
float x, y, z;
/**************构造函数****************************/
//默认初始化函数
Vector3(){}
/****与构造函数体内赋值不一样 赋值是先调用无参构造,再调用赋值 初始化是直接调用带参构造***/
//构造函数初始化表 传入为一个Vector3实例
Vector3(const Vector3 &v) : x(v.x), y(v.y), z(v.z) {}
//构造函数 传入为三个分量
Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
/***************标准对象操作***********************/
//赋值重载 返回引用
Vector3 &operator = (const Vector3 &v) {
x = v.x; y = v.y; z = v.z;
return *this;
}
/****(这里的const表明此函数不会对数据成员进行更改)*/
//重载比较算符
bool operator ==(const Vector3 &v) const {
return x==v.x && y==v.y && z==v.z;
}
bool operator !=(const Vector3 &v) const {
return x!=v.x || y!=v.y || z!=v.z;
}
/***************向量运算***************************/
//置为零向量
void zero() { x = y = z = 0.0f; }
//重载 取负 运算符
Vector3 operator - () const { return Vector3(-x,-y,-z); }
//重载 +,- 运算符
Vector3 operator + (const Vector3 &v) const {
return Vector3(x + v.x, y + v.y, z + v.z);
}
Vector3 operator - (const Vector3 &v) const {
return Vector3(x - v.x, y - v.y, z - v.z);
}
//与标量的乘、除法
Vector3 operator *(float k) const {
return Vector3(x*k, y*k, z*k);
}
Vector3 operator /(float k) const {
float oneOverK = 1.0f / k; //这里不对零进行检查
return Vector3(x*oneOverK, y*oneOverK, z*oneOverK);
}
//自运算 算符
Vector3 &operator +=(const Vector3 &v) {
x += v.x; y += v.y; z += v.z;
return *this;
}
Vector3 &operator -=(const Vector3 &v) {
x -= v.x; y -= v.y; z -= v.z;
return *this;
}
Vector3 &operator *=(float k) {
x *= k; y *= k; z *= k;
return *this;
}
Vector3 operator /=(float k) {
float oneOverK = 1.0f / k; //这里不对零进行检查
x *= oneOverK; y *= oneOverK; z *= oneOverK;
return *this;
}
//向量标准化
void normalize() {
float magSq = x*x + y*y + z*z;
if (magSq > 0.0f) { //检查除零
float oneOverMag = 1.0 / sqrt(magSq);
x *= oneOverMag;
y *= oneOverMag;
z *= oneOverMag;
}
}
//向量点乘
float operator *(const Vector3 &v) const {
return x*v.x + y*v.y + z*v.z;
}
};
/***************************************************************
*
* 非成员函数
*
****************************************************************/
//向量求模
inline float vectorMag(const Vector3 &v) {
return sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
}
//计算向量叉乘
inline Vector3 crossProduct(const Vector3 &v1, const Vector3 &v2) {
return Vector3(
v1.y*v2.z - v1.z*v2.y,
v1.z*v2.x - v1.x*v2.z,
v1.x*v2.y - v1.y*v2.x
);
}
//实现标量左乘
inline Vector3 operator *(float k, const Vector3 &v) {
return Vector3(k*v.x, k*v.y, k*v.z);
}
//计算两点距离
inline float distance(const Vector3 &a, const Vector3 &b) {
float dx = a.x - b.x;
float dy = a.y - b.y;
float dz = a.z - b.z;
return sqrt(dx*dx + dy*dy + dz*dz);
}
/***************************************************************
*
* 全局变量
*
****************************************************************/
//全局零向量
extern const Vector3 zeroVector;