WebGl中的数学知识 | 小册免费学

1,070 阅读3分钟

基础知识

脱离工具,建立一套与各个图形系统无关联的、简单的基于向量和矩阵运算的数学体系,用它来描述所有的几何图形信息

HTML, Canvas, SVG 的坐标系都是 x 轴向右,y 轴向下

WebGL 是中心点为原点,z 轴向外

HTML、SVG 和 Canvas 利用transform 进行坐标转换

WebGL 本身不提供 tranform 的 API,但我们可以在 shader 里做矩阵运算来实现坐标转换

用向量来表示点和线段

向量 v 有两个含义:

  • 一是可以表示该坐标系下位于 (x, y) 处的一个点;
  • 二是可以表示从原点 (0,0) 到坐标 (x,y) 的一根线段

一个向量包含有长度和方向信息

v.length = function(){
  return Math.hypot(this.x, this.y)
};

v.dir = function() { 
  return Math.atan2(this.y, this.x);
}

点乘,也叫数量积。结果是一个向量在另一个向量方向上投影的长度,是一个标量。 叉乘,也叫向量积。结果是一个和已有两个向量都垂直的向量。

向量的点乘

假设,现在有两个 N 维向量 a 和 b,a = [a1, a2, ...an],b = [b1, b2, ...bn],那向量的点积代码如下:

a•b = a1*b1 + a2*b2 + ... + an*bn

数学意义:在 N 维线性空间中,a、b 向量点积的几何含义,是 a 向量乘以 b 向量在 a 向量上的投影分量

image-20210329192700023

当 a、b 两个向量平行时,它们的夹角就是 0°,那么 a·b=|a|*|b|

当 a、b 两个向量垂直时,它们的夹角就是 90°,那么 a·b=0

向量的叉乘

image-20210329193723022

向量叉乘运算的结果不是标量,而是一个向量;其次,两个向量的叉积与两个向量组成的坐标平面垂直

可以通过右手定则判断

image-20210329193629035

二维向量叉积的几何意义就是向量 a、b 组成的平行四边形的面积

image-20210329192839762

i、j、k 分别是 x、y、z 轴的单位向量

a X b = [y1 * z2 - y2 * z1, - (x1 * z2 - x2 * z1), x1 * y2 - x2 * y1]

归一化

简单来说 就是求单位向量

归一化就是让向量 v0除以它的长度(或者说是模)。归一化后的向量方向不变,长度为 1。

在向量乘法里,如果 a、b 都是长度为 1 的归一化向量,那么|a X b| 的结果就是 a、b 夹角的正弦值,而|a • b|的结果就是 a、b 夹角的余弦值。

练习题

已知线段[(x0, y0)、(x1, y1)],以及一个点 (x2, y2),怎么求点到线段的距离?一个平面上放置了一个扫描器,方向延 y 轴方向(该坐标系 y 轴向上),扫描器的视角是 60 度。假设它可以扫描到无限远的地方,那对于平面上给定的任意一个点 (x,y),我们该如何判断这个点是否处于扫描范围内呢?

image-20210329200210969

简单来说 我们可以通过对当前目标向量归一化后与y轴的一个单位向量来进行叉乘,从而得到对应的正弦函数以此来判断角度 确定是否在扫描范围内

我们把归一化的向量 a 叉乘扫描器中线上的 v(0,1),由于扫描器关于 y 轴对称,所以扫描器边缘与 y 轴的夹角是正负 30 度。那么在与单位向量求叉积的时候,就会出现 2 种情况:

1.点在扫描范围内,如向量 a,就一定满足: |a X v| <= ||a||v|sin(30°)| = |sin(30°)| = 0.5;

2.点不在扫描范围内,如向量 b,就一定满足:|b X v| > ||b||v|sin(30°)| = |sin(30°)| = 0.5。

因此,只要任意一点所在的向量与单位向量的叉积结果的绝对值不大于 0.5(即 sin30°),就说明这个点在扫描范围内。所以我们可以用如下代码来判断:

const isInRange = Math.abs(new Vec2(0, 1).cross(v0.normalize())) <= 0.5;
// v0.normalize()即将v0归一化

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情