点和向量的数学基础

计算机图形学数学基础译自 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 function
template<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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值