点和向量的数学基础

来源:互联网 发布:java英文参考文献 编辑:程序博客网 时间:2024/06/05 18:42

计算机图形学数学基础译自 ScratchaPixel 网站,数学基础部分共八篇,本篇为第一篇,感兴趣的同学可以参考我的 GitBook 镜像。

向量长度 Vector Length

向量可以被看作是一个箭头从一个点出发到另外一个点结束。向量不仅可以看作为从A点到B点的方向,还可以看作A点到B点的距离。下列是计算向量长度的公式:

vector_length

在几何学中,复纵线(||V||)表示矢量V的长度。向量长度通常被称为 模(norm)大小(magnitude)
在C++中可以表示为:

template <typename T>class Vec3 {public:  // length can be a method from the class  T length() {    return sqrt(x * x + y * y + z * z);  }}

标准化向量 Normalizing a Vector

一个 标准化的(normalised) 向量,是指一个向量的长度为1。这种向量也被称为 单位向量(unit vector),标准化向量非常简单,我们先计算出向量的长度,然后用向量在每个轴的坐标乘以这个长度。公式为:

vector_normalize

需要注意在C++代码里除法是可以优化的,首先计算向量的长度len,如果大于0,然后计算出长度len的倒数invLen,最后用向量在每个轴上的坐标乘以invLen。这样做的原因是程序设计中乘法的开销要小于除法,尤其是在 渲染(renderer) 过程中,标准化向量极为常见,这个过程会有成百上千甚至百万个向量。在这种级别,任何可能的优化都会直接影响渲染的时间。(需要支持有的编译器会自动将乘法优化为除法)。

template <typename T>class Vec3 {public:  // as a method of the class Vec3  Vec3<T> & normalize() {    T len = length();    if (len > 0) {      T invLen = 1 / len;      x *= invLen;      y *= invLen;      z *= invLen;    }    return *this;  }}

几何学中常定义 norm 函数来为向量的长度或距离赋值,这里定义的函数被称为 欧几里得范数(Euclidean norm).

点积 Dot Product

点积(dot product)数积(scalar product),需要两个向量A和B,可以被看作一个向量在另一个向量上的 投影(projection)。点积的结果是一个实数(float或double类型)。A和B的点积被记为: (有时也会被记为<A,B>)。

dot_product

点积由A向量的每个元素乘以B向量每个元素并求和。在3D的场景下,向量有三个 系数(coefficients)元素(elemment),即x,y和z。公式为:

需要指出的是这与我们计算向量长度的方法十分相似,如果我们取两个相等向量(A=B)的点积的平方根
然后就可以得到向量的长度。可以写做:

这可以被用于标准化方法:

template<typename T>class Vec3 {public:  ...  T dot(const Vec3<T> &v) const {    return x * v.x + y * v.y + z * v.z;  }  Vec3<T> & normalize() {    T len2 = dot(*this);    if (len2 > 0) {      T invLen = 1 / sqrt(len2);      x *= invLen;      y *= invLen;      z *= invLen;    }    return *this;  }  ...};

两个向量的点积在3D程序中非常常见,因为点积的结果是两个向量夹角的余弦值。
+ 如果B是单位向量,则可以得到。如果得到的点积结果为负,表示A和B的方向相反,这被称为A在B上的标投影。
+ 当A和B都不是单位向量时,可以写作,因为B作为一个单位向量是
+ 当两个向量都标准化后,通过计算点积的反余弦可以得到两个向量的夹角:
或者:
(在几何学中,表示cos的反函数,在计算机图形学中,这个函数通常记为acos()).

dot_product

点积在3D场景中用途非常广泛:
+ 测试向量的正交性。当两个向量(A,B)相互垂直时,A和B的点积为0,当两个向量(A,C)为反方向时,A和C的点积为-1,当两个向量(A,D)为相同方向时,A和D的点积为1.
+ 计算两向量间的夹角或向量和坐标轴之间的夹角(在坐标轴转化为球形坐标时非常有用)。

叉积 Cross Product

叉积同样是两个向量的间操作,与点积不同的是,叉积返回的是一个向量。由叉积产生的向量C垂直于产生叉积的向量A和B,如图:

cross_product

叉积的表达为: C = A x B,为了计算叉积需要如下公式:

叉积产生的向量是垂直于产生叉积的两个向量。向量A和B的叉积记为A x B。两个向量A和B决定一个平面,叉积向量C垂直于这个平面。向量A和B不需要相互垂直,但是在A和B是单位向量时A,B,C可以形成笛卡尔坐标系(Cartesian Coordinate System).这个特性在创建本地坐标系时非常有用。

template<typename T>class Vec3 {public:  ...  // as a method of the class  Vec3<T> cross(cosnt Vec3<T> &v) const {    return Vec3<T>(y * v.z - z * v.y,                   z * v.x - x * v.z,                   x * v.y - y * v.x);  }  ...};// or a utility functiontemplate<typename T>Vec3<T> cross(const Vec3<T> &a, const Vec3<T> &b) {  return Vec3<T>(    a.y * b.z - a.z * b.y,     a.z * b.x - a.x * b.z,     a.x * b.y - a.y * b.x  );}

需要指出的是,向量A和B的顺序会直接影响叉积的值,如A x B = (1,0,0) x (0,1,0) = (0,0,1)
B x A = (0,1,0) x (1,0,0) = (0,0,-1).我们常说叉积是反交换率的(anticommutative),因为AxB=C而BxA=-C。

handness

在几何学中,叉积的结果被称为 伪向量(pseudo vector),计算叉积的向量的顺序可以直接影响曲面法线(surface normals)的方向。依据这个顺序,叉积的结果可以是指向 曲面内部(inward-pointing normal) 或者 指向 外部(outward-pointing normal)

0 0
原创粉丝点击