【ThreeJs原理解析】第4期 | 向量

前言

在Three.js中,向量(Vector)是一个非常重要的概念,广泛应用于各种场景,几乎所有的几何、变换、物理、动画等操作都离不开向量的运算。理解向量的概念和使用方法对于掌握Three.js是非常重要的。

向量应用场景示例:

  1. 几何体的位置和方向

    • 位置 :几何体(如MeshSprite等)的位置通常使用Vector3来表示。例如,mesh.position就是一个Vector3对象,表示几何体在三维空间中的位置。
    • 方向 :几何体的旋转和朝向也可以使用向量来表示。例如,mesh.rotation使用欧拉角(Euler angles)来表示旋转,但也可以通过Quaternion来表示,而Quaternion的计算通常涉及到向量。
  2. 相机

    • 位置 :相机的位置(camera.position)是一个Vector3对象,表示相机在三维空间中的位置。
    • 目标点 :相机的目标点(camera.lookAt)也是一个Vector3对象,表示相机所指向的位置。
  3. 光线

    • 光源位置 :光源(如PointLightSpotLight)的位置通常使用Vector3来表示。
    • 光线方向:在光线追踪或阴影计算中,光线的方向通常使用向量来表示。
  4. 变换矩阵

    • 平移 :平移矩阵的计算涉及到向量。例如,Matrix4.makeTranslation(vector)方法会根据一个Vector3向量生成一个平移矩阵。
    • 旋转 :旋转矩阵的计算也涉及到向量。例如,Matrix4.makeRotationAxis(axis, angle)方法会根据一个旋转轴向量生成一个旋转矩阵。
  5. 碰撞检测

    • 在碰撞检测中,物体的位置、速度、方向等通常使用向量来表示。例如,Raycaster类用于检测射线与物体的交点,其计算涉及到向量的运算。
  6. 物理引擎

    • 在结合物理引擎(如Cannon.jsOimo.js)时,物体的速度、加速度、力等通常使用向量来表示。
  7. 数学运算

    • Three.js提供了丰富的向量运算方法,如加法、减法、点积、叉积、归一化等。这些运算在各种计算中都非常常见,例如计算法线、投影、反射等。
  8. 材质和着色器

    • 在自定义着色器中,向量用于表示顶点位置、法线、UV坐标等。例如,在顶点着色器中,gl_Position是一个四维向量,表示顶点在裁剪空间中的位置。

数学原理

向量本身就是数学概念,three只是按照向量计算逻辑用js实现了一遍,在读源码之前理解数学逻辑对我们充分理解源码至关重要

1. 什么是向量(vector)

从点A(x1,y1,z1) 到 点B(x2,y2,z2)构成的有向线段:

俩个核心点:

  • 长度(模):点A到点B的距离
  • 方向 :点A到点B的方向

2. 单位向量

长度(模)为1的向量

3. 向量长度(模)

4. 向量运算

1. 加法

向量加法满足平行四边形法则和三角形法则 即: a + b =(X1+X2,Y1+Y2)

2. 减法

向量加法满足三角形法则

即: a - b =(X1-X2,Y1-Y2)

3. 点乘

4. 叉乘(向量积)

5. 点乘和叉乘应用场景(核心点⭐️)

一般在webgl计算三维空间坐标中

  • 叉乘的几何意义是计算平面的法线,因为叉乘能计算出一根同时垂 直于原向量的新向量,而叉乘的数量积的几何意义可以用来计算三角面的面积;
  • 点乘的几何意义是计算夹角。例如计算光源入射折射对物体表面的影响,

源码解析

源码地址:Threejs-Vector3

1. constructor

ps: threejs中的向量(vector)默认是以原点为起始点,构造函数内部的xyz是终点坐标

js 复制代码
constructor( x = 0, y = 0, z = 0 ) {
    Vector3.prototype.isVector3 = true;
    
    this.x = x;
    this.y = y;
    this.z = z;
}

2. 向量基本运算

以下源码实现逻辑均可参照上述的数学原理,唯一的不同只是用js实现了一下

js 复制代码
// 向量长度(模)
length() {
    return Math.sqrt( this.x * this.x 
                    + this.y * this.y 
                    + this.z * this.z );
}

// 向量加法
add( v ) {
    this.x += v.x;
    this.y += v.y;
    this.z += v.z;

    return this;
}

// 向量减法
sub( v ) {
    this.x -= v.x;
    this.y -= v.y;
    this.z -= v.z;

    return this;
}

// 向量点乘
dot( v ) {
    return this.x * v.x + this.y * v.y + this.z * v.z;
}

// 向量叉乘
cross( v ) {
    return this.crossVectors( this, v );
}

crossVectors( a, b ) {
    const ax = a.x, ay = a.y, az = a.z;
    const bx = b.x, by = b.y, bz = b.z;

    this.x = ay * bz - az * by;
    this.y = az * bx - ax * bz;
    this.z = ax * by - ay * bx;

    return this;
}

3. 其他常用api详解

ps: set***, get***, copy***, clone*** 等简单api自行查看,不多赘述

1. distanceTo

俩点间距离公式,秒了🥲

js 复制代码
distanceTo( v ) {
    return Math.sqrt( this.distanceToSquared( v ) );
}

distanceToSquared( v ) {
    const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
    return dx * dx + dy * dy + dz * dz;
}

2. normailze

向量归一化:不改变向量方向且将向量的模变为1,实现逻辑就是将x,y,z按比例扩大或缩小。

js 复制代码
normalize() {
    return this.divideScalar( this.length() || 1 );
}
divideScalar( scalar ) {
    return this.multiplyScalar( 1 / scalar );
}
multiplyScalar( scalar ) {
    this.x *= scalar;
    this.y *= scalar;
    this.z *= scalar;

    return this;
}

原理也很简单,分两步:

  1. 计算向量的模
  2. 将该向量的x,y,z坐标除以这个向量的模

3. angleTo

计算当前向量与另一个向量之间的夹角(弧度)

js 复制代码
angleTo( v ) {

    const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );

    if ( denominator === 0 ) return Math.PI / 2;

    const theta = this.dot( v ) / denominator;

    // clamp, to handle numerical problems

    return Math.acos( clamp( theta, - 1, 1 ) );

}

原理: 根据向量点乘运算公式,即可求出角度

相关推荐
m0_548514779 分钟前
前端打印功能(vue +springboot)
前端·vue.js·spring boot
执键行天涯16 分钟前
element-plus中的resetFields()方法
前端·javascript·vue.js
Days205021 分钟前
uniapp小程序增加加载功能
开发语言·前端·javascript
喵喵酱仔__22 分钟前
vue 给div增加title属性
前端·javascript·vue.js
dazhong201232 分钟前
HTML前端开发-- Iconfont 矢量图库使用简介
前端·html·svg·矢量图·iconfont
m0_748248771 小时前
前端vue使用onlyoffice控件实现word在线编辑、预览(仅列出前端部分需要做的工作,不包含后端部分)
前端·vue.js·word
莫惊春1 小时前
HTML5 第五章
前端·html·html5
Json____1 小时前
前端node环境安装:nvm安装详细教程(安装nvm、node、npm、cnpm、yarn及环境变量配置)
前端·windows·npm·node.js·node·nvm·cnpm
阿福的工作室1 小时前
4. React 性能优化技巧:如何让你的应用更快
前端·react.js·前端框架
CL_IN1 小时前
金蝶云星空与华为云AX无缝数据集成技术详解
服务器·前端·华为云