向量
1、什么是向量
表示一个有大小的方向,一个向量无论如何平移,都表示同一个向量。
向量的长度称为向量的模,记做:∣ a ⃗ ∣ |\vec{a}| ∣ a ∣ 。
1 2 const magnitude = Cartesian3 .magnitude (a);
图形学中常说的向量通常表示的是单位向量a ^ \hat{a} a ^ ,也就是长度为1的向量,那么这时这个向量可以看做仅表示方向,记做:a ^ = a ⃗ ∣ a ⃗ ∣ \hat{a}=\frac{\vec{a}}{|\vec{a}|} a ^ = ∣ a ∣ a 。
1 2 const normalizeA = Cartesian3 .normalize (a, new Cartesian3 ());
2、向量的基本运算
2.1、向量的加法
向量的加法满足:平行四边形法则/三角形法则。
在数学上向量的加法就是向量的各个分量相加
1 2 const AB = Cartesian3 .add (a, b, new Cartesian3 ());
2.2、向量的点乘
向量的点乘:a ⃗ ⋅ b ⃗ = ∣ a ⃗ ∣ ∣ b ⃗ ∣ cos θ \vec{a} \cdot \vec{b} = |\vec{a}||\vec{b}|\cos{\theta} a ⋅ b = ∣ a ∣ ∣ b ∣ cos θ
可以推导出两个向量之间的夹角余弦:cos θ = a ⃗ ⋅ b ⃗ ∣ a ⃗ ∣ ∣ b ⃗ ∣ \cos{\theta} = \frac{\vec{a} \cdot \vec{b}} {|\vec{a}||\vec{b}|} cos θ = ∣ a ∣ ∣ b ∣ a ⋅ b
而如果 a ⃗ \vec{a} a 和 b ⃗ \vec{b} b 恰巧是单位向量,那么此时夹角余弦等于 cos θ = a ^ ⋅ b ^ \cos{\theta} = \hat{a} \cdot \hat{b} cos θ = a ^ ⋅ b ^
2.2.1、向量的点乘在图形学上的作用
上面说到两个向量之间的夹角余弦可以通过点乘的方式进行计算。
而在图形学中点乘最大的作用也是找到两个向量之间的夹角,或者说夹角余弦 。
特别是在做光照模型的时候,光的方向、法线方向、相机看的方向等等这些向量,他们之间的夹角和他们的关系都是通过点乘去计算的。
也经常用于计算一个向量到另一个向量上的投影 。
cos θ = a ^ ⋅ b ^ \cos{\theta} = \hat{a} \cdot \hat{b} cos θ = a ^ ⋅ b ^
b ⃗ T = k a ^ \vec{b}_{T} = k \hat{a} b T = k a ^
k = c o s θ ∣ b ⃗ ∣ k = cos{\theta} |\vec{b}| k = c o s θ ∣ b ∣
另一个特别重要的应用,是判断两个向量之间是否同向,或者是否接近。
从余弦函数cos θ \cos{\theta} cos θ 的图像可以发现,当两个向量之间的夹角小于90°时,向量的点乘得到的是一个正数,当夹角大于90°时得到的是一个负数。
因此我们可以通过两个向量之间的点乘是否大于零去判断两个向量是否同向(夹角是不是锐角) 。
同时可以通过判断点乘结果是否足够接近于1(单位向量情况下),来判断两个向量是否足够接近 。在光照模型中这点非常重要。
2.2.2、向量的点乘满足的数学性质
a ⃗ ⋅ b ⃗ = b ⃗ ⋅ a ⃗ \vec{a} \cdot \vec{b} = \vec{b} \cdot \vec{a} a ⋅ b = b ⋅ a
a ⃗ ⋅ ( b ⃗ + c ⃗ ) = a ⃗ ⋅ b ⃗ + a ⃗ ⋅ c ⃗ \vec{a} \cdot (\vec{b} + \vec{c}) = \vec{a} \cdot \vec{b} + \vec{a} \cdot \vec{c} a ⋅ ( b + c ) = a ⋅ b + a ⋅ c
( k a ⃗ ) b ⃗ = a ⃗ ( k b ⃗ ) = k ( a ⃗ b ⃗ ) (k\vec{a})\vec{b} = \vec{a}(k\vec{b}) = k(\vec{a}\vec{b}) ( k a ) b = a ( k b ) = k ( a b )
1 2 const aDotb = Cartesian3 .dot (a, b);
2.3、向量的叉乘
向量的叉乘会输入两个向量进行运算,最终得到一个与之前两个向量都垂直的向量 。
如果 a ⃗ × b ⃗ = c ⃗ \vec{a} \times \vec{b} = \vec{c} a × b = c ,那么 c ⃗ \vec{c} c 垂直于 a ⃗ \vec{a} a 并且垂直于 b ⃗ \vec{b} b 。
叉乘的方向由右手定则(右手系的情况下)判断,因此向量的叉乘不满足交换律:a ⃗ × b ⃗ = − b ⃗ × a ⃗ \vec{a} \times \vec{b} = -\vec{b} \times \vec{a} a × b = − b × a
叉乘的模计算公式为:∣ a ⃗ × b ⃗ ∣ = ∣ b ⃗ ∣ ∣ a ⃗ ∣ sin θ |\vec{a} \times \vec{b}| = |\vec{b}| |\vec{a}| \sin{\theta} ∣ a × b ∣ = ∣ b ∣ ∣ a ∣ sin θ ,可以发现公式的右侧部分 ∣ b ⃗ ∣ ∣ a ⃗ ∣ sin θ |\vec{b}| |\vec{a}| \sin{\theta} ∣ b ∣ ∣ a ∣ sin θ 刚好是向量 a ⃗ \vec{a} a , b ⃗ \vec{b} b 组成的平行四边形的面积公式。因此叉乘的模刚好等于向量 a ⃗ \vec{a} a , b ⃗ \vec{b} b 组成三角形面积的两倍 。
1 2 const aCrossb = Cartesian3 .cross (a, b, new Cartesian3 ());
2.3.1、向量的叉乘在图形学上的作用
计算三角形面积(三角形三个顶点计算出两个向量,这两个向量叉乘取模,模的一半就是三角形的面积)
1 2 3 4 5 6 7 8 9 function triangleArea (a: Cartesian3,b: Cartesian3,c: Cartesian3 ): number{ const ab = Cartesian3 .subtract (b, a, new Cartesian3 ()); const ac = Cartesian3 .subtract (c, a, new Cartesian3 ()); const cross = Cartesian3 .cross (ab, ac, new Cartesian3 ()); return Cartesian3 .magnitude (cross) / 2 ; }
判断左边还是右边
假设在XY平面中有两个向量 a ⃗ \vec{a} a , b ⃗ \vec{b} b ,并且有 a ⃗ × b ⃗ = c ⃗ \vec{a} \times \vec{b} = \vec{c} a × b = c ,c ⃗ \vec{c} c 一定垂直于XY平面,也就是沿着Z轴正向,或者与Z轴方向相反。我们就可以通过判断 c ⃗ \vec{c} c 的Z分量是否大于零,来判断 a ⃗ \vec{a} a , b ⃗ \vec{b} b 的位置关系。在右手系下,如果 c ⃗ \vec{c} c 的Z分量大于零,则 a ⃗ \vec{a} a 在 b ⃗ \vec{b} b 的右侧。
判断里面还是外面
原理与判断左右类似,通过判断点p是否在所有边的同侧,来判断点p是否在三角形里面。
上图中,p在 c a ⃗ \vec{ca} c a 、 a b ⃗ \vec{ab} a b 、 b c ⃗ \vec{bc} b c 的左侧,因此p在三角形abc内侧