three Vector3 三维向量(上)

232 阅读13分钟

Vector3 是一个用于表示三维空间中向量的类,常用于计算机图形学、物理模拟和游戏开发等领域。它通常包含三个分量:xyz。以下是一些基本操作和用法:

Vector3 有三个属性六十九个方法

Vector3( x : Float, y : Float, z : Float ) x - 向量的x值,默认为0。 y - 向量的y值,默认为0。 z - 向量的z值,默认为0。 创建一个新的Vector3。

属性

  • isVector3 : Boolean 查看是否是三维向量
  • x : Float x 座标
  • y : Float y 座标
  • z : Float z 座标

方法

  • add ( v : Vector3 ) : this 将传入的向量v和这个向量相加。
  • addScalar ( s : Float ) : this 将传入的标量s和这个向量的x值、y值以及z值相加。
  • addScaledVector ( v : Vector3, s : Float ) : this 将所传入的v与s相乘所得的乘积和这个向量相加。
    // 创建一个 Vector3 对象
    const vectorA = new THREE.Vector3(1, 2, 3);
    // 创建另一个 Vector3 对象
    const vectorB = new THREE.Vector3(4, 5, 6);
    // 缩放因子
    const scale = 2;
    // 使用 addScaledVector 方法
    vectorA.addScaledVector(vectorB, scale);
    console.log(vectorA); // 输出: Vector3(9, 12, 15)
  • addVectors ( a : Vector3, b : Vector3 ) : this 将该向量设置为a + b。
  • applyAxisAngle ( axis : Vector3, angle : Float ) : this applyAxisAngle 是 THREE.Vector3 类的一个方法,用于将当前向量围绕指定的轴进行旋转。这个方法使用了旋转轴和旋转角度(以弧度为单位)。
    const vector = new THREE.Vector3(1, 0, 0); // 原始向量在 x 轴
    // 定义旋转轴(这里是 y 轴)
    const axis = new THREE.Vector3(0, 1, 0); // y 轴
    axis.normalize(); // 确保轴是单位向量
    // 定义旋转角度(例如,90度,转换为弧度)
    const angle = Math.PI / 2; // 90 degrees in radians
    // 应用轴角旋转
    vector.applyAxisAngle(axis, angle);
    // 因为 2.220446049250313e-16 的绝对值非常小,接近于零,通常在数值计算中,这个值可以被视作 0。
    console.log(vector); // 输出旋转后的向量 { "x": 2.220446049250313e-16, "y": 0, "z": -1 }
  • applyEuler ( euler : Euler ) : this 在 Three.js 中,Vector3.applyEuler() 方法用于将给定的 Euler 旋转应用到一个 Vector3 向量上。它改变向量的方向,而不会改变其长度。这在三维空间中非常有用,尤其是当你需要对一个向量进行旋转时。是围绕 原点 (0, 0, 0) 进行旋转的
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(1, 0, 0);
    // 创建一个 Euler 对象(旋转角度),单位为弧度
    const euler = new THREE.Euler(Math.PI / 2, 0, 0);
    // 将 Euler 旋转应用到向量
    vector.applyEuler(euler);
    // 输出旋转后的向量
    console.log(vector);
  • applyMatrix3 ( m : Matrix3 ) : this Vector3.applyMatrix3() 是 Three.js 中 Vector3 类的一个方法,它将一个 Matrix3(3x3 矩阵)应用到当前的 Vector3 向量上。这种操作可以用来执行向量的各种线性变换,如缩放、旋转、剪切等。 1729425659369.png
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(1, 2, 3);
    // 创建一个 3x3 矩阵
    const matrix = new THREE.Matrix3();
    // 为矩阵设置缩放和旋转的值
    matrix.set(
        2, 0, 0,  // x 方向缩放 2 倍
        0, 0, 1,  // y 轴变换(90 度旋转)
        0, -1, 0  // z 轴变换
    );
    // 将矩阵应用到向量上
    vector.applyMatrix3(matrix);
    console.log(vector);  // 输出变换后的向量 { "x": 2, "y": 3, "z": -2 }
  • applyMatrix4 ( m : Matrix4 ) : this Vector3.applyMatrix4() 是 Three.js 中 Vector3 类的一个方法,它将一个 4x4 矩阵 Matrix4 作用于当前的 Vector3 向量。这个方法允许你对向量进行各种线性变换(如缩放、旋转、平移等),并且可以进行齐次坐标的操作(即将 3D 空间中的向量扩展到 4D 空间,以支持平移等仿射变换)。 1729470264804.png

1729470301784.png

    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(1, 1, 1);
    // 创建一个 4x4 矩阵
    const matrix = new THREE.Matrix4();
    // 为矩阵设置旋转和平移值
    matrix.makeRotationX(Math.PI / 4);  // 绕 X 轴旋转 45 度
    matrix.setPosition(2, 3, 4);  // 设置平移
    // 将矩阵应用到向量上
    vector.applyMatrix4(matrix);
    console.log(vector);  // 输出变换后的向量 { "x": 3, "y": 3, "z": 5.414213562373095 }
  • applyNormalMatrix ( m : Matrix3 ) : this 是 THREE.Vector3 类的方法,用于将一个法向量应用于 3x3 矩阵 Matrix3。通常在 3D 图形渲染中,法向量用于计算光照、反射等效果。当几何体发生旋转、缩放、或非均匀变换时,法向量也需要做相应的调整才能正确地与光照等效果匹配。applyNormalMatrix 用来处理这种变换,确保法向量正确地响应几何体的变化。 1729471438300.png 1729471493482.png

1729471524914.png

1729471547619.png

    // 创建一个法线向量
    const normal = new THREE.Vector3(1, 0, 0);
    // 创建一个 3x3 矩阵(用于缩放)
    const matrix = new THREE.Matrix3();
    matrix.set(
        2, 0, 0,  // x 轴缩放 2 倍
        0, 1, 0,  // y 轴缩放保持不变
        0, 0, 3   // z 轴缩放 3 倍
    );
    // 计算逆矩阵并转置,作为法线矩阵
    const normalMatrix = new THREE.Matrix3().getNormalMatrix(new THREE.Matrix4().set(
        2, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 3, 0,
        0, 0, 0, 1
    ));
    // 将法线矩阵应用到法线向量上
    normal.applyMatrix3(normalMatrix);
    // 输出变换后的法线向量
    console.log('变换后的法线:', normal); //  { "x": 0.5, "y": 0, "z": 0 }
    // 如果需要归一化法线
    normal.normalize();
    console.log('归一化后的法线:', normal); // { "x": 1, "y": 0, "z": 0 }
  • applyQuaternion ( quaternion : Quaternion ) : this Vector3.applyQuaternion() 是 Three.js 中 Vector3 类的一个方法,用于将四元数 Quaternion 作用到当前的 Vector3 向量上。四元数常用于 3D 空间中的旋转变换,因为它们能够避免欧拉角旋转中的万向节锁问题,并且在处理连续旋转时更加稳定。
     **绕 X 轴旋转**:叫做“俯仰”(pitch),可以让物体前后“点头”。
    **绕 Y 轴旋转**:叫做“偏航”(yaw),可以让物体左右“摆头”。
    **绕 Z 轴旋转**:叫做“翻滚”(roll),可以让物体左右“侧倾”。
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(1, 0, 0);  // 初始向量指向 X 轴
    // 创建一个 Quaternion(绕 Z 轴旋转 90 度)
    const quaternion = new THREE.Quaternion();
    quaternion.setFromAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI / 2);  // Z 轴旋转 90 度
    // 将四元数应用到向量上
    vector.applyQuaternion(quaternion);
    console.log(vector);  // 输出旋转后的向量 { "x": 2.220446049250313e-16, "y": 1, "z": 0 }
  • angleTo ( v : Vector3 ) : Float 以弧度返回该向量与向量v之间的角度。以中心点0,0,0 计算
  • ceil () : this 将该向量x分量、 y分量以及z分量向上取整为最接近的整数。
  • clamp ( min : Vector3, max : Vector3 ) : this min - 在限制范围内,x值、y值和z的最小值。 max - 在限制范围内,x值、y值和z的最大值。 如果该向量的x值、y值或z值大于限制范围内最大x值、y值或z值,则该值将会被所对应的值取代。 如果该向量的x值、y值或z值小于限制范围内最小x值、y值或z值,则该值将会被所对应的值取代。
  • clampLength ( min : Float, max : Float ) : this min - 长度将被限制为的最小值 max - 长度将被限制为的最大值 如果向量长度大于最大值,则它将会被最大值所取代。 如果向量长度小于最小值,则它将会被最小值所取代。 1729405598247.png 1729405797671.png
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(3, 4, 0);  // 长度为 5
    // 限制向量的长度在 2 到 4 之间
    vector.clampLength(2, 4);
    console.log(vector.length(), vector);  // 输出的长度将为 4 { "x": 2.4000000000000004, "y": 3.2, "z": 0 }
  • clampScalar ( min : Float, max : Float ) : this min - 分量将被限制为的最小值 max - 分量将被限制为的最大值 如果该向量的x值、y值或z值大于最大值,则它们将被最大值所取代。 如果该向量的x值、y值或z值小于最小值,则它们将被最小值所取代。
  • clone () : Vector3 返回一个新的Vector3,其具有和当前这个向量相同的x、y和z。
  • copy ( v : Vector3 ) : this 将所传入Vector3的x、y和z属性复制给这一Vector3。
  • cross ( v : Vector3 ) : this 是 Three.js 中 Vector3 类的一个方法,用于计算当前向量与另一个向量 v 的叉积。叉积是一个向量运算,它的结果是一个新的向量,该向量垂直于这两个输入向量。
    // 创建两个 Vector3 对象
    const vectorA = new THREE.Vector3(1, 0, 0);  // 向量 A
    const vectorB = new THREE.Vector3(0, 1, 0);  // 向量 B
    // 计算叉积
    const crossProduct = vectorA.cross(vectorB);
    console.log(crossProduct);  // 输出: Vector3 { x: 0, y: 0, z: 1 }
    
    // 示例2
    // 创建两个向量 A 和 B
    const vectorA = new THREE.Vector3(2, 0, 0);  // 向量 A,长度为 2
    const vectorB = new THREE.Vector3(0, 1, 0);  // 向量 B,长度为 1,垂直于 A
    // 计算叉积 C = A × B
    const crossProduct = vectorA.cross(vectorB);
    console.log(crossProduct);  // 输出: Vector3 { x: 0, y: 0, z: 2 }
    console.log(crossProduct.length());  // 输出: 2
  • crossVectors ( a : Vector3, b : Vector3 ) : this 将该向量设置为传入的a与b的叉积(cross product)。
  • distanceTo ( v : Vector3 ) : Float 计算该向量到所传入的v间的距离。 1729406497658.png
    // 创建两个 Vector3 对象
    const vectorA = new THREE.Vector3(1, 2, 3);  // 向量 A
    const vectorB = new THREE.Vector3(4, 5, 6);  // 向量 B
    // 计算向量 A 到向量 B 的距离
    const distance = vectorA.distanceTo(vectorB);
    console.log(distance);  // 输出: 5.196152422706632
  • manhattanDistanceTo ( v : Vector3 ) : Float 在 Three.js 中,manhattanDistanceTo 方法用于计算当前向量与另一个向量之间的曼哈顿距离(也称为城市街区距离)。曼哈顿距离是计算两个点之间的距离时,不考虑对角线的方式,只沿着坐标轴进行移动。
    // 创建两个 Vector3 对象
    const vectorA = new THREE.Vector3(1, 2, 3);  // 向量 A
    const vectorB = new THREE.Vector3(4, 5, 6);  // 向量 B
    // 计算向量 A 到向量 B 的曼哈顿距离
    const manhattanDistance = vectorA.manhattanDistanceTo(vectorB);
    console.log(manhattanDistance);  // 输出: 9 计算方式 4-1 = x 5-2 = y 6-3 = z
  • distanceToSquared ( v : Vector3 ) : Float 在 Three.js 中,distanceToSquared 方法用于计算当前向量与另一个向量之间距离的平方。这种方法在需要比较距离而不需要实际计算距离时非常有用,因为它可以避免开方运算,提高性能。v表示B this 表示 A 1729406753226.png
  • divide ( v : Vector3 ) : this 在 Three.js 中,divide 方法用于将当前向量与另一个向量的每个分量相除。这个操作通常用于实现向量的分量逐一相除,而不是简单的缩放。该方法返回对当前向量的修改,并允许链式调用。
    // 创建两个 Vector3 对象
    const vectorA = new THREE.Vector3(6, 8, 10);  // 向量 A
    const vectorB = new THREE.Vector3(2, 4, 5);    // 向量 B
    // 将向量 A 除以向量 B
    vectorA.divide(vectorB);
    console.log(vectorA);  // 输出: Vector3 { x: 3, y: 2, z: 2 }
  • divideScalar ( s : Float ) : this 将该向量除以标量s。
  • dot ( v : Vector3 ) : Float 在 Three.js 中,dot 方法用于计算当前向量与另一个向量之间的点积(内积)。点积是两个向量的乘积,结果是一个标量值,表示这两个向量在相同方向上的投影的乘积。点积的结果与向量之间的角度有关。 1729406995905.png
  • equals ( v : Vector3 ) : Boolean 检查该向量和v的严格相等性。
  • floor () : this 向量的分量向下取整为最接近的整数值。
  • fromArray ( array : Array, offset : Integer ) : this array - 来源矩阵。 offset - (可选)在数组中的元素偏移量,默认值为0。 设置向量中的x值为array[ offset + 0 ],y值为array[ offset + 1 ], z值为array[ offset + 2 ]。
  • fromBufferAttribute ( attribute : BufferAttribute, index : Integer ) : this attribute - 来源的attribute。 index - 在attribute中的索引。 从attribute中设置向量的x值、y值和z值。
  • getComponent ( index : Integer ) : Float index - 0, 1 or 2. 如果index值为0返回x值。 如果index值为1返回y值。 如果index值为2返回z值。
  • length () : Float 计算从(0, 0, 0) 到 (x, y, z)的欧几里得长度 (Euclidean length,即直线长度)
  • manhattanLength () : Float 在 Three.js 中,manhattanLength 方法用于计算当前向量的曼哈顿长度(也称为城市街区距离或绝对距离)。曼哈顿长度是通过计算向量各个分量的绝对值之和来得出的,表示从一个点到另一个点沿着坐标轴的总移动距离。
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(3, -4, 5);
    // 计算曼哈顿长度
    const manhattanLength = vector.manhattanLength();
    console.log(manhattanLength);  // 输出: 12
  • lengthSq () : Float 计算从(0, 0, 0)到(x, y, z)的欧几里得长度 (Euclidean length,即直线长度)的平方。 如果你正在比较向量的长度,应当比较的是长度的平方,因为它的计算效率更高一些。 1729407321016.png
  • lerp ( v : Vector3, alpha : Float ) : this v - 朝着进行插值的Vector3。 alpha - 插值因数,其范围通常在[0, 1]闭区间。 在该向量与传入的向量v之间的线性插值,alpha是沿着线的长度的百分比 —— alpha = 0 时表示的是当前向量,alpha = 1 时表示的是所传入的向量v。
  • lerpVectors ( v1 : Vector3, v2 : Vector3, alpha : Float ) : thisv1 - 起始的Vector3。 v2 - 朝着进行插值的Vector3。 alpha - 插值因数,其范围通常在[0, 1]闭区间。 将此向量设置为在v1和v2之间进行线性插值的向量, 其中alpha为两个向量之间连线的长度的百分比 —— alpha = 0 时表示的是v1,alpha = 1 时表示的是v2。
  • max ( v : Vector3 ) : this 如果该向量的x值、y值或z值小于所传入v的x值、y值或z值, 则将该值替换为对应的最大值。
  • min ( v : Vector3 ) : this 如果该向量的x值、y值或z值大于所传入v的x值、y值或z值, 则将该值替换为对应的最小值。
  • multiply ( v : Vector3 ) : this 在 Three.js 中,multiply 方法用于将当前向量与另一个向量进行分量乘法运算。此操作会逐个分量相乘,并返回对当前向量的修改,允许链式调用。 1729407474213.png
  • multiplyScalar ( s : Float ) : this 将该向量与所传入的标量s进行相乘。
  • multiplyVectors ( a : Vector3, b : Vector3 ) : this 按照分量顺序,将该向量设置为和a * b相等。
  • negate () : this 向量取反,即: x = -x, y = -y , z = -z。
  • normalize () : this 将该向量转换为单位向量(unit vector), 也就是说,将该向量的方向设置为和原向量相同,但是其长度(length)为1。
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(3, 4, 0);  // 向量的坐标为 (3, 4, 0)
    // 归一化向量
    vector.normalize();
    console.log(vector);           // 输出: Vector3 { x: 0.6, y: 0.8, z: 0 }
    console.log(vector.length());  // 输出: 1

1729407683503.png 1729407715570.png

  • project ( camera : Camera ) : this 在 Three.js 中,project 方法的作用主要是将三维空间中的点转换为屏幕空间的二维坐标。这对于很多 3D 应用场景是非常重要的。
    // 将3d座标转换为2d座标
    // 假设有一个三维空间中的点
    const vector = new THREE.Vector3(10, 20, 30);
    // 使用相机投影该点到 2D 空间
    vector.project(camera);
    console.log('2D NDC 到屏幕坐标:', JSON.stringify(vector)); // 2D NDC 到屏幕坐标: {"x":-0.43440845761373525,"y":2.6064507456824115,"z":1.006867353402007}
    // 将归一化设备坐标 (NDC) 转换为屏幕坐标
    const screenX = (vector.x + 1) / 2 * window.innerWidth;
    const screenY = -(vector.y - 1) / 2 * window.innerHeight;
    console.log('2D 屏幕坐标:', screenX, screenY); // 2D 屏幕坐标: 414.0130090267458 -316.4707968994351
    
    // 将2d座标转换为3d座标
    // 创建一个平面,用于投射点击事件
    const planeGeometry = new THREE.PlaneGeometry(100, 100);
    const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide });
    const plane = new THREE.Mesh(planeGeometry, planeMaterial);
    // 旋转平面
    plane.rotation.x = Math.PI / 4; // 绕 X 轴旋转 45 度
    plane.rotation.y = Math.PI / 4; // 绕 Y 轴旋转 45 度
    scene.add(plane);
    // 创建 Raycaster 和一个 Vector2 来存储鼠标的 2D 屏幕坐标
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();
    // 处理鼠标点击事件
    function onMouseClick(event) {
        // 将鼠标屏幕坐标转换为归一化设备坐标 (NDC)
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
        // 使用相机和鼠标坐标来更新射线投射
        raycaster.setFromCamera(mouse, camera);
        // 计算射线与平面的交点
        const intersects = raycaster.intersectObject(plane);
        if (intersects.length > 0) {
            console.log('3D 坐标:', intersects[0].point); // { "x": 11.903928909641753, "y": 31.26228769964039, "z": 14.427589990099856 }
        }
    }
    // 监听鼠标点击事件
    window.addEventListener('click', onMouseClick, false);
  • projectOnPlane ( planeNormal : Vector3 ) : this 在 Three.js 中,projectOnPlane 方法用于将一个三维向量投影到由给定法线定义的平面上。这个方法通常用于处理物体与平面之间的交互,尤其在物理模拟、碰撞检测和动画等场景中非常有用。 1729473200254.png 1729473564901.png
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(3, 4, 5); // 原始向量
    // 定义一个法向量,表示平面
    const planeNormal = new THREE.Vector3(0, 1, 0); // Y 轴法向量,表示水平面
    // 投影向量到平面
    vector.projectOnPlane(planeNormal);
    console.log('Projected Vector:', vector.x, vector.y, vector.z);  // 输出投影后的向量 3,0,5
    
    // 示例 2
    // 创建一个 Vector3 对象
    const vector = new THREE.Vector3(3, 4, 5); // 原始向量
    // 定义一个法向量,表示平面(这里选择一个任意法向量)
    const planeNormal = new THREE.Vector3(1, 1, 0).normalize(); // 正规化,确保长度为1
    // 投影向量到平面
    vector.projectOnPlane(planeNormal);
    console.log('Projected Vector:', vector.x, vector.y, vector.z);  // 输出投影后的向量 Projected Vector: -0.49999999999999956 0.5000000000000004 5