三维相关数学知识

528 阅读6分钟

1.向量和矩阵:Three.js 使用向量和矩阵来表示和变换 3D 对象的位置、旋转和缩放。你需要了解向量和矩阵的基本概念、运算和变换。

向量是有方向和大小的量,可以表示为一组有序的数字。在二维空间中,一个向量通常表示为(x, y),其中x和y分别表示向量在x轴和y轴上的分量。在三维空间中,一个向量通常表示为(x, y, z),其中x、y和z分别表示向量在x轴、y轴和z轴上的分量。向量可以进行加法、减法、标量乘法和向量乘法等运算。

        var vector1 = new THREE.Vector3(1, 2, 3);
        var vector2 = new THREE.Vector3(4, 5, 6);
        var result1 = vector1.add(vector2); // 向量相加 (5, 7, 9)
        var result2 = vector1.sub(vector2); // 向量相减 (1, 2, 3)


        var vector = new THREE.Vector3(1, 2, 3);
        var scalar = 2;
        var result1 = vector.multiplyScalar(scalar); // 向量乘以标量 (2,4,6)
        var result2 = vector.divideScalar(scalar); // 向量除以标量   (0.5, 1, 1.5)


        // 点乘
        const a = new THREE.Vector3(1, 2, 3)
        const b = new THREE.Vector3(2, 3, 4)
        // 点乘结果
        const dotValue = a.dot(b)   // 2+6+12
        
        

image.png

image.png

 const a = new THREE.Vector3(-6, 8, 0) 
 const b = new THREE.Vector3(5, 12, 0) 
 const dotValue = a.dot(b) // 66

     
         🌰: 
1:点乘为0,垂直两个单位向量的点乘,得到的是两个向量夹角的cos值,通过它可以知道两个向量的相似性
         <!-- (5,5,0) (0,0,5) -->
         
         cosθ = (A·B) / (|A| * |B|)
         
2: 比如光线方向点乘三角面的法线(垂直于该三角面的向量),点积越大,说明夹角越小,光线更接近于直射三角面,所以更明亮,就可以设置更明亮的颜色
        // 假设有三个顶点的坐标 
        var vertex1 = new THREE.Vector3(x1, y1, z1); 
        var vertex2 = new THREE.Vector3(x2, y2, z2); 
        var vertex3 = new THREE.Vector3(x3, y3, z3); 
        // 计算两个边向量 
        var edge1 = new THREE.Vector3().subVectors(vertex2, vertex1); 
        var edge2 = new THREE.Vector3().subVectors(vertex3, vertex1); 
        // 计算法线向量 
        var normal = new THREE.Vector3().crossVectors(edge1, edge2).normalize();
        
        var lightDirection = new THREE.Vector3(1, 1, 1).normalize(); // 光线方向向量
3: ab点积大于零,所以b物体在人的前方,ac点积小于零,c物体在人的后方
        // 假设有人的位置向量a、物体b的位置向量b、物体c的位置向量c 
        var a = new THREE.Vector3(ax, ay, az); // 人的位置向量 
        var b = new THREE.Vector3(bx, by, bz); // 物体b的位置向量 
        var c = new THREE.Vector3(cx, cy, cz); // 物体c的位置向量 
        // 计算ab和ac的点积 
        var dotAB = a.dot(b); 
        var dotAC = a.dot(c); 
        // 判断物体在人的前方还是后方 
        if (dotAB > 0) { 
        console.log("物体b在人的前方");
        } else if (dotAC < 0) { 
        console.log("物体c在人的后方"); 
        } else { console.log("物体b和物体c与人的位置关系无法确定"); }
叉乘:::
       1. 将向量 `vector1` 的 x、y、z 分量分别表示为 `x1``y1``z1`       2.  将向量 `vector2` 的 x、y、z 分量分别表示为 `x2``y2``z2`       3.  计算叉积的每个分量:
        - x 分量:`crossProduct.x = y1 * z2 - z1 * y2`
        - y 分量:`crossProduct.y = z1 * x2 - x1 * z2`
        - z 分量:`crossProduct.z = x1 * y2 - y1 * x2`
       
       4.  最终得到的 `crossProduct` 即为向量 `vector1` 和 `vector2` 的叉积结果。在给定的示例中,计算得到的结果为 `( -3, 6, -3 )`。
       
       如下3-4-3面积计算
2. 坐标系:Three.js 使用右手坐标系来表示 3D 空间。你需要了解如何在三维空间中定义坐标轴和坐标变换(平移、旋转和缩放)
3. 几何学:你需要了解基本的几何形状,如点、线、面、多边形等,以及它们的属性和计算方法。
1. 点(Point):点是几何学中最基本的元素,它没有长度、宽度或高度,只有一个位置。点通常用坐标表示,如 (x, y) 或 (x, y, z)。

2. 线(Line):线由两个点构成,它们之间的直线路径称为线段。线段有长度,可以通过两点之间的距离来计算( new THREE.Vector3( 0, 1, 0 ).distanceTo(new THREE.Vector3( 1, 1, 0 )))

3. 面(面):面是由三个或更多个线段组成的闭合曲线。面可以是平面的,也可以是在三维空间中的曲面。面的属性包括面积、周长、法向量(指与平面垂直的非零向量)等。

4. 多边形(Polygon):多边形是由直线段组成的简单闭合图形。多边形的属性包括边数、内角和、外角和、面积等。常见的多边形有三角形、四边形、五边形等。
   1. 比如内角和计算(n边形的内角和是(n-2)×180°.)
   2. 1. 几何计算:通过计算多边形的内角和,可以得到多边形的形状信息。例如,对于一个正多边形,内角和可以用来验证其是否是一个正多边形,或者用来计算多边形的边长、半径等。
   3. 渲染效果:内角和可以用来控制多边形的渲染效果。例如,根据多边形的内角和来确定多边形的颜色、纹理等,从而实现不同的渲染效果


在几何学中,我们可以使用一些基本的计算方法来处理这些几何形状的属性和关系:

- 距离计算:计算两个点之间的距离,可以使用勾股定理或向量的长度来计算。( var distanceSquared = point1.distanceToSquared(point2); Math.sqrt(distanceSquared);)

- 面积计算:计算面的面积,可以使用不同的方法,如海伦公式(适用于三角形---直接通过三条边来计算面积)、矢量叉积(适用于任意多边形)等。
      - 	var p=(a+b+c)/2; var x=p*(p-a)*(p-b)*(p-c);  var y=Math.sqrt(x);
      -  
      var vector1 = new THREE.Vector3(1, 2, 0);
      var vector2 = new THREE.Vector3(3, 4, 0);
      var vector3 = new THREE.Vector3(5, 6, 0);
      var vector4 = new THREE.Vector3(7, 8, 0);
      var vector5 = new THREE.Vector3(9, 10, 0);

      var edge1 = new THREE.Vector3().subVectors(vector2, vector1);
      var edge2 = new THREE.Vector3().subVectors(vector3, vector1);
      var edge3 = new THREE.Vector3().subVectors(vector4, vector1);
      var edge4 = new THREE.Vector3().subVectors(vector5, vector1);

      var crossProduct1 = new THREE.Vector3().crossVectors(edge1, edge2);
      var crossProduct2 = new THREE.Vector3().crossVectors(edge2, edge3);
      var crossProduct3 = new THREE.Vector3().crossVectors(edge3, edge4);

      var area = 0.5 * (crossProduct1.length() + crossProduct2.length() + crossProduct3.length());

      console.log(area);
- 周长计算:计算线段或多边形的周长---如上例的edge1.lenght() ,可以将各个线段的长度相加。

- 角度计算:计算两个线段之间的夹角,可以使用向量的点积或反余弦函数来计算
   1- var vector1 = new THREE.Vector3(1, 2, 3);
      var vector2 = new THREE.Vector3(5, 6, 7);
      var dotProduct = vector1.dot(vector2);
      var angle = Math.acos(dotProduct / (vector1.length() * vector2.length()));
      var angleInDegrees = THREE.MathUtils.radToDeg(angle);
      console.log(angleInDegrees)


   2- var vector1 = new THREE.Vector3(2, 0, 0);
      var vector2 = new THREE.Vector3(2, 3.464, 0);  // 3.464 约等 Math.sqrt(3)*2
      var dotProduct = vector1.dot(vector2);
      var angle = Math.acos(dotProduct / (vector1.length() * vector2.length()));  //1.09
      
      度数 = 弧度 * (180 / Math.PI)  // 60度 
      <!-- var angleInDegrees = THREE.MathUtils.radToDeg(angle); -->
      <!-- console.log(angleInDegrees) -->

常见几何体:

image.png

  1. 三角函数:在 3D 图形编程中,三角函数非常重要。你需要了解三角函数的概念和常用的三角函数,如正弦、余弦和正切,以及它们在计算角度和旋转时的应用。

  2. 线性代数:线性代数是数学中与向量和矩阵相关的分支,它对于 3D 图形编程非常重要。你需要了解线性代数中的基本概念,如点积、叉积、矩阵乘法等。 developer.mozilla.org/zh-CN/docs/…

    1. 介绍矩阵:( 从 左至右 从 上至下 )

image.png

 2. 矩阵相加          

image.png

3.矩阵乘常数

image.png

4. 矩阵相乘

image.png

1*7+2*9=3*11==58

image.png

这里要注意 矩阵向乘 不满足交换律

image.png

5. 矩阵相除
A/B = A × (1/B) = A × B-1  可以理解为矩阵A乘逆矩阵B

逆矩阵? 我们可以先了解什么是 单位矩阵
    

image.png

  • 它是个"方形"矩阵(相同数目的行和列),

  • 在对角线是 1,在其他位置是 0

  • 符号是大写字母 I

    计算逆矩阵的公式:

image.png

举个栗子:

image.png

矩阵用途

  1. 平移(Translation):矩阵可以用于将对象从一个位置平移到另一个位置。通过在矩阵中设置平移向量,可以将对象沿x、y和z轴移动。 // 创建一个平移向量 var translation = new THREE.Vector3(1, 2, 3); // 创建一个单位矩阵 var matrix = new THREE.Matrix4(); // 使用平移向量进行平移操作 matrix.translate(translation); // 应用平移矩阵到立方体 cube.applyMatrix4(matrix);

  2. 缩放(Scaling):矩阵可以用于对对象进行缩放,使其变大或变小。通过在矩阵中设置缩放因子,可以在x、y和z轴上进行缩放。 // 创建一个缩放向量 var scale = new THREE.Vector3(2, 2, 2); // 创建一个单位矩阵 var matrix = new THREE.Matrix4(); // 使用缩放向量进行缩放操作 matrix.scale(scale); // 应用缩放矩阵到立方体 cube.applyMatrix4(matrix);

  3. 旋转(Rotation):矩阵可以用于对对象进行旋转。通过在矩阵中设置旋转角度和旋转轴,可以绕任意轴进行旋转。 // 创建一个旋转轴向量 var axis = new THREE.Vector3(0, 1, 0).normalize(); // 创建一个旋转角度(弧度) var angle = Math.PI / 4; // 创建一个单位矩阵 var matrix = new THREE.Matrix4(); // 使用旋转轴和角度进行旋转操作 matrix.makeRotationAxis(axis, angle); // 应用旋转矩阵到立方体 cube.applyMatrix4(matrix);

  4. 投影(Projection):矩阵可以用于将3D场景投影到2D屏幕上。通过设置透视投影矩阵或正交投影矩阵,可以控制视野的大小和形状。

    透视投影矩阵:

    透视投影矩阵是一种常用的矩阵,用于将三维场景投影到二维屏幕上,以创建逼真的透视效果

    正交投影矩阵

    在这种投影模式下,无论物体距离相机距离远或者近,在最终渲染的图片中物体的大小都保持不变

  5. 变换(Transformation):矩阵可以用于组合多个变换,实现复杂的对象变换效果。通过将多个变换矩阵相乘,可以实现平移、缩放和旋转的组合变换。

    // 创建一个单位矩阵 var matrix = new THREE.Matrix4();

    // 创建一个平移向量 var translation = new THREE.Vector3(2, 0, 0);

    // 创建一个缩放向量 var scale = new THREE.Vector3(2, 2, 2);

    // 创建一个旋转轴向量 var axis = new THREE.Vector3(0, 1, 0).normalize();

    // 创建一个旋转角度(弧度) var angle = Math.PI / 4;

    // 使用平移向量进行平移操作 matrix.makeTranslation(translation.x, translation.y, translation.z);

    // 使用缩放向量进行缩放操作 matrix.scale(scale);

    // 使用旋转轴和角度进行旋转操作 matrix.makeRotationAxis(axis, angle);

    // 应用变换矩阵到对象 object.applyMatrix4(matrix);

在上面的示例中,我们首先创建了一个单位矩阵 matrix,它是一个空的矩阵。 然后,我们创建了一个平移向量 translation,一个缩放向量 scale,一个旋转轴向量 axis,和一个旋转角度 angle。 接下来,我们使用 makeTranslation 方法将平移向量应用到矩阵中,这将在矩阵中设置平移操作。 然后,我们使用 scale 方法将缩放向量应用到矩阵中,这将在矩阵中设置缩放操作。 最后,我们使用 makeRotationAxis 方法将旋转轴向量和旋转角度应用到矩阵中,这将在矩阵中设置旋转操作。 通过将多个变换矩阵相乘,我们可以将这些变换组合起来,然后通过调用 applyMatrix4 方法将变换矩阵应用到对象上,以实现多个变换的组合效果。 请注意,变换的顺序很重要,因为矩阵相乘不满足交换律。因此,变换的顺序会影响最终的结果。