文章目录

  • Three 中的矩阵关系
    • THREE 中的矩阵
    • 三维投影矩阵(u_matrix)计算公式
      • 相机投影矩阵(ProjectMatrix)
      • 物体位置矩阵(ObjectWorldMatrix)
  • Box3
  • Vector3
    • Vector3 的方法
      • setFromMatrixScale( m: Matrix4 ): this
      • applyMatrix4( m: Matrix4 ): this
  • Matrix3
    • Matrix3 的属性
    • Matrix3的方法
      • set() : Matrix3
      • identity():Matrix3
      • clone():this
      • copy(m:Matrix3):this
      • extractBasis( xAxis: Vector3, yAxis: Vector3, zAxis: Vector3 ): Matrix3
      • setFromMatrix4( m: Matrix4 ): Matrix3
      • multiplyScalar( s: number ): Matrix3
      • determinant(): number
      • getInverse( matrix: Matrix3, throwOnDegenerate?: boolean ): Matrix3
      • transpose(): Matrix3
      • getNormalMatrix( matrix4: Matrix4 ): Matrix3
      • transposeIntoArray( r: number[] ): Matrix3
      • setUvTransform( tx: number, ty: number, sx: number, sy: number, rotation: number, cx: number, cy: number ): Matrix3
      • equals( matrix: Matrix3 ): boolean
      • fromArray( array: number[], offset?: number ): Matrix3
      • toArray( array?: number[], offset?: number ): number[]
      • multiply( m: Matrix3 ): Matrix3
      • premultiply( m: Matrix3 ): Matrix3
      • multiplyMatrices( a: Matrix3, b: Matrix3 ): Matrix3
      • multiplyVector3( vector: Vector3 ): any
  • 分离轴定理(Separating Axis Theorem)

Three 中的矩阵关系

REF: https://juejin.im/post/6844903510769664014


  我们将相机的位置方向, 相机的类型, 物体的位置和形变能转换为 矩阵, 将这些矩阵进行一系列计算后, 最终得到三维投影矩阵: u_matrix

  基于它, 任意给定三维坐标[x, y, z], 我们都能算出相机视平面上的位置:

  [x, y] = u_matrix * [x, y, z, 1]

THREE 中的矩阵

  THREE定义了场景(Scene)和相机(Camera), Scene用来添加管理三维物体, Camera用来控制相机的位置, 角度等。

  THREE中定义了下述三个矩阵:

  • 相机投影类型:投影矩阵(ProjectMatrix
  • 相机的位置和方向: 视图矩阵 (CameraMatrixWorldInverseViewMatrix)
  • 物体的位置和形变: 物体位置矩阵(ObjectWorldMatrix)

三维投影矩阵(u_matrix)计算公式

  三维投影矩阵计算公式如下:

const uMatrix = ProjectMatrix * CameraMatrixWorldInverse * ObjectMatrixWorld

相机投影矩阵(ProjectMatrix)

  在THREE中,通过用不同的相机类实例化,得到不同类型的相机,例如定义一个透视投影相机:

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  • 获得 ProjectionMatrix

    camera.projectionMatrix
    

### 相机视图矩阵(CameraMatrixWorldInverse)

  有的三维引擎或教程,会把视图矩阵称为ViewMatrix(例如webglfundamentals)

  视图矩阵的含义是,固定其他因素,我们改变了相机的位置和角度后,它眼中的世界也会发生变化,这种变化就是视图矩阵。

  前面提到,相机在三维空间中的位置camera.matrixWorld,而它的视图矩阵是相机位置矩阵的逆矩阵CameraMatrixWorldInverse,它也符合了我们的生活经验:

  • 固定相机,人向左移动
  • 固定人,向右移动相机

  这两种情况在相机眼中是一样的。

  在THREE中,我们一般通过设置camera的position和up,调用lookAt来改变相机的视图矩阵

camera.position.set(x, y, z);
camera.up.set(x, y, z);
camera.lookAt(x, y, z);
  • 获得 CameraMatrixInverse

    camera.matrixWorldInverse
    

  我们知道,最终的投影是在GLSL顶点着色器中计算的。

  在一次绘制中,ProjectionMatrixCameraMatrixWorldInverse一般不会发生变化,而ObjectMatrixWorld每个物体都可能不同, 所以为了减少顶点着色器中的计算量,有些三维引擎会在javascript程序中提前计算出ProjectionMatrix * CameraMatrixWorldInverse的值传递给顶点着色器,这个矩阵一般称为ViewProjectionMatrix

物体位置矩阵(ObjectWorldMatrix)

  ObjectWorldMatrix 描述了物体在三维场景中的位置。

  • 获得 ObjectWorldMatrix

    object.matrixWorld
    

  前面提到,THREE中的物体是有层级关系的,所以THREE中物体的matrixWorld是通过local matrixobject.matrix)与父亲的matrixWorld递归相乘得到的, 其中的原理可以查阅webglfundamentals中的这篇教程

Box3

REF: https://www.mrguo.link/article?id=12


  在线案例点击three.js Box3。

  Box3 在3D空间中表示一个包围盒。其主要用于表示物体在世界坐标中的边界框。它方便我们判断物体和物体、物体和平面、物体和点的关系等等。

  构造器参数Box3( min : Vector3, max : Vector3 ),其参数为两个三维向量,第一个向量为Box3在3D空间中各个维度的最小值,第二个参数为Box3在3D空间中各个维度的最大值,代码如下。

var box = new THREE.Box3(new THREE.Vector3(-2,-2,-2), new THREE.Vector3(2,2,2));
js

  这个box就表示3D空间中中心点在(0,0,0),长宽高为4的包围盒。

Vector3

REF: https://www.mrguo.link/article?id=14


Vector3 的方法

setFromMatrixScale( m: Matrix4 ): this

  从变换矩阵(transformation matrix)m中, 设置该向量为其中与缩放相关的元素。

var vec1 = new THREE.Vector3();
var matrix = new THREE.Matrix4().makeScale(1,2,3);
vec1.setFromMatrixScale(matrix);//返回Vector3 {x: 1, y: 2, z: 3}

applyMatrix4( m: Matrix4 ): this

  将该向量乘以四阶矩阵m(第四个维度隐式地为1

var vec1 = new THREE.Vector3(1,0,0);
var matrix = new THREE.Matrix4().makeRotationZ(-Math.PI/6);
vec1.applyMatrix4(matrix);//返回值和上面相同

Matrix3

  three.js文档中以行为主的顺序显示矩阵。 但是,如果您正在阅读源代码,您必须对这里列出的任何矩阵进行转置transpose,以理解计算。例如:

var matrix3 = new THREE.Matrix3().set( 1,2,3,4,5,6,7,8,9);
//而其内部elements则展示为: matrix3.elements = [1,4,7,2,5,8,3,6,9];

Matrix3 的属性

  elements:Array :矩阵列优先column-major列表。

  isMatrix3:Boolean:用于判定此对象或者此类的派生对象是否是三维矩阵。默认值为 true

Matrix3的方法

set() : Matrix3

  三维矩阵不能在构造函数中直接设置参数值,需要通过set()方法设置,set()方法参数采用行优先row-major, 而它们在内部是用列优先column-major顺序存储在数组当中。

identity():Matrix3

  将此矩阵重置为3x3单位矩阵。

var matrix = new THREE.Matrix3();
matrix.identity();//返回elements: (9) [1, 0, 0, 0, 1, 0, 0, 0, 1]

clone():this

  创建一个新的矩阵,元素 elements 与该矩阵相同。

copy(m:Matrix3):this

  将矩阵m的元素复制到当前矩阵中。

extractBasis( xAxis: Vector3, yAxis: Vector3, zAxis: Vector3 ): Matrix3

  将此矩阵的基提取到提供的三个轴向量中。

var matrix = new THREE.Matrix3();
matrix.set( 1,2,3,4,5,6,7,8,9);
var a = new THREE.Vector3();
var b = new THREE.Vector3();
var c = new THREE.Vector3();
matrix.extractBasis(a, b, c);
console.log(a,b,c);
//返回Vector3 {x: 1, y: 4, z: 7} Vector3 {x: 2, y: 5, z: 8} Vector3 {x: 3, y: 6, z: 9}

setFromMatrix4( m: Matrix4 ): Matrix3

  将当前矩阵设置为4X4矩阵,m左上3X3

var matrix = new THREE.Matrix3();
var matrix4 = new THREE.Matrix4().makeScale(2,2,2);
matrix.setFromMatrix4(matrix4)//elements: (9) [2, 0, 0, 0, 2, 0, 0, 0, 2]

multiplyScalar( s: number ): Matrix3

  当前矩阵所有的元素乘以该缩放值s

var matrix = new THREE.Matrix3();
matrix.set( 1,2,3,4,5,6,7,8,9);
matrix.multiplyScalar(2)//elements: (9) [2, 8, 14, 4, 10, 16, 6, 12, 18]

determinant(): number

  计算并返回矩阵的行列式determinant 。

var matrix = new THREE.Matrix3();
matrix.set( 1,2,3,4,5,6,7,8,9);
matrix.determinant()//返回0

getInverse( matrix: Matrix3, throwOnDegenerate?: boolean ): Matrix3

  求传入矩阵m的逆矩阵,使用解析法将该矩阵设置为传递矩阵m的逆矩阵。

  行列式为零的矩阵不能求逆。如果尝试这样做,该方法将返回一个零矩阵。

var matrix1 = new THREE.Matrix3();
var matrix2 = new THREE.Matrix3();
matrix1.set(1,2,3,4,5,6,7,8,9); matrix2.set(1,1,0,0,1,1,0,0,1);
new THREE.Matrix3().getInverse(matrix1)//因为行列式的值为0,所以返回零矩阵elements: (9) [0, 0, 0, 0, 0, 0, 0, 0, 0]
new THREE.Matrix3().getInverse(matrix2)//因为行列式的值不为0,所以返回elements: (9) [1, 0, 0, -1, 1, 0, 1, -1, 1]

  求逆矩阵的方法有很多,可以通过伴随矩阵求逆矩阵,也可以行做差来构造逆矩阵。

transpose(): Matrix3

  将该矩阵转置。

var matrix = new THREE.Matrix3();
matrix.set(1,1,0,0,1,1,0,0,1);//返回elements: (9) [1, 0, 0, 1, 1, 0, 0, 1, 1]; matrix.transpose();
console.log(matrix);//返回elements: (9) [1, 1, 0, 0, 1, 1, 0, 0, 1];

getNormalMatrix( matrix4: Matrix4 ): Matrix3

  将这个矩阵设置为给定矩阵的正规矩阵normal matrix(左上角的3x3)。

  正规矩阵是矩阵m的逆矩阵inverse的转置transpose

this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();

  上面是three.js的源码,从源码可以看出这是setFromMatrix4,getInverse和transpose的组合用法。

var matrix = new THREE.Matrix3();
var matrix4 = new THREE.Matrix4().makeScale(2,2,2);
matrix.getNormalMatrix(matrix4);//返回elements: (9) [0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5]

transposeIntoArray( r: number[] ): Matrix3

  将当前矩阵的转置Transposes存入给定的数组array : Array但不改变当前矩阵, 并返回当前矩阵。

var matrix = new THREE.Matrix3();
matrix.set(1,1,0,0,1,1,0,0,1);
var array = [];
matrix.transposeIntoArray(array);
console.log(array);//返回[1, 1, 0, 0, 1, 1, 0, 0, 1]

setUvTransform( tx: number, ty: number, sx: number, sy: number, rotation: number, cx: number, cy: number ): Matrix3

tx - x偏移量

ty - y偏移量

sx - x方向的重复比例

sy - y方向的重复比例

rotation- 旋转(弧度)

cx- 旋转中心x

cy- 旋转中心y

  使用偏移,重复,旋转和中心点位置设置UV变换矩阵。

var matrix = new THREE.Matrix3();
matrix.setUvTransform(0,0,0,0,0,0.5,0.5);
console.log(matrix);//返回elements: (9) [0, -0, 0, 0, 0, 0, 0.5, 0.5, 1]

equals( matrix: Matrix3 ): boolean

  如果矩阵m与当前矩阵所有对应元素相同则返回true

fromArray( array: number[], offset?: number ): Matrix3

  使用基于列优先格式column-major的数组来设置该矩阵。

var matrix = new THREE.Matrix3();
matrix.fromArray([1,4,7,2,5,8,3,6,9]);//因为是基于列优先原则,所以设置的数组和elements属性相同,不需转置。

toArray( array?: number[], offset?: number ): number[]

  使用列优先column-major格式将此矩阵的元素写入数组中。这是fromArray的逆运算。

var matrix = new THREE.Matrix3();
matrix.set(1,2,3,4,5,6,7,8,9);
matrix.toArray(array);
console.log(array);//返回[1, 4, 7, 2, 5, 8, 3, 6, 9]

multiply( m: Matrix3 ): Matrix3

  将当前矩阵乘以矩阵m

var matrix1 = new THREE.Matrix3();
var matrix2 = new THREE.Matrix3();
matrix1.set(1,2,3,4,5,6,7,8,9);
matrix2.setFromMatrix4(new THREE.Matrix4().makeScale(0.5, 0.5, 0.5));//通过4维矩阵,得到三维矩阵
matrix1.multiply(matrix2);//返回elements: (9) [0.5, 2, 3.5, 1, 2.5, 4, 1.5, 3, 4.5]

premultiply( m: Matrix3 ): Matrix3

  将矩阵m乘以当前矩阵。和上面相比这是左乘和右乘的问题。

multiplyMatrices( a: Matrix3, b: Matrix3 ): Matrix3

  设置当前矩阵为矩阵a x 矩阵b。和上面的方法差不多

multiplyVector3( vector: Vector3 ): any

  和Vector3.applyMatrix3一样

var matrix1 = new THREE.Matrix3();
matrix1.set(1,2,3,4,5,6,7,8,9);
var vector3 = new THREE.Vector3(1,2,3);
matrix1.multiplyVector3(vector3);//返回Vector3 {x: 14, y: 32, z: 50}

分离轴定理(Separating Axis Theorem)

原文:https://aotu.io/notes/2017/02/16/2d-collision-detection/

  概念:通过判断任意两个 凸多边形 在任意角度下的投影是否均存在重叠,来判断是否发生碰撞。若在某一角度光源下,两物体的投影存在间隙,则为不碰撞,否则为发生碰撞。

图例:

  在程序中,遍历所有角度是不现实的。那如何确定 投影轴 呢?其实只需对多边形的每一条边都判断一遍即可。且在判断过程中,若提前发现间隙,则不用进行剩下的判断了。

  每个投影轴其实就是对应边的法向量:

圆形与多边形之间的碰撞检测

  由于圆形可近似地看成一个有无数条边的正多边形,而我们不可能按照这些边一一进行投影与测试。我们只需将圆形投射到一条投影轴上即可,这条轴就是圆心与多边形顶点中最近的一点的连线,如图所示:

  因此,该投影轴和多边形自身的投影轴就组成了一组待检测的投影轴了。另外,圆的投影可以先投影圆心那一点,然后再在两边加上半径即可。

  而对于圆形与圆形之间的碰撞检测依然是最初的两圆心距离是否小于两半径之和。

threeJS 中数学相关内容相关推荐

  1. Android studio根据文本提取出的关键词在sqlite数据库中查找相关内容

    Android studio根据文本提取出的关键词在sqlite数据库中查找相关内容 一.介绍 二.Android studio连接.操作和查看sqlite数据库 三.在数据库中查找相关内容 四.运行 ...

  2. c语言中如何读取文件的内容,急急急!!!如何读取文件中的相关内容

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 c语言下午就要交了,急死人了!!! 在读取文件时,我需要输入一个名字,然后显示名字相关内容,如: Orlando Magic 姓名 球队 出场数 时间 得 ...

  3. 关于thread中mutex相关内容的理解

    在C++11中,引入了thread线程库,而为了应对线程的同步,又引入了互斥量mutex,而又因为mutex的各种问题,后续又引申出了使得mutex更安全的机制. 下面就以我的个人理解,介绍一下. 值 ...

  4. 在win7操作系统中的文件中搜索相关内容

    win7 >Windows 资源管理器->组织->文件夹和搜索选项->搜索->搜索内容->选中 :始终搜索文件名和内容(此过程可能需要几分钟)(C)->确定, ...

  5. 如何从字符串中提取相关内容

    实例1 sql语句相关 {/*** \s 表示一个\t.一个\n等* \s Matches a whitespace character (QChar::isSpace()).* \s* 多个* \s ...

  6. 开发中最全网络相关内容

    iOS中网络相关内容 声明:部分图片来源于网络,有些内容也来自各个平台老师讲解的视频,部分内容来自<计算机网络>这本书中,除去参考其他博客链接外,其他部分不作出参考链接来源展示,如有相关原 ...

  7. 【Linux】41. grep结合awk -F 获取文件中的关键内容

    ip addr |grep inet |awk -F ' ' '{print $2}' 上面这句话就是:找出ip addr命令输出的内容中包含inet的所有行,并把这些行中用空格' '分隔的内容输出, ...

  8. python对文件的操作都有什么_python中文件操作的相关内容总结(附示例)

    本篇文章给大家带来的内容是关于python中文件操作的相关内容总结(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 1. 文件操作介绍 说到操作文件我们肯定会想到流,文件的操 ...

  9. 量化风控定价中的相关指标性内容还有哪些?

    无论是授信跟定价,其中最重要的一点就是给客户打分,做风险分层.对公业务如此,个人信贷亦然,在量化风控上都有一些方法通用.还记得我们在较早前文章中介绍的量化风险的内容吗?请看:瞅瞅银行的LGD模型是怎么 ...

最新文章

  1. 前腾讯员工不堪房价压力回老家进国企!终于过上了清闲的日子,他又担心这个问题?...
  2. What should we do when meet a crash in android?
  3. [BZOJ4259]残缺的字符串
  4. 华为荣耀20s云服务_华为荣耀20和20s的区别
  5. Python Selenium打开谷歌浏览器
  6. LINUX中用C获得当前执行应用的所在路径
  7. 计算机计算公式代码,简单的计算器代码
  8. mfp服务器控制中心,固网1008MFP驱动
  9. gg修改器修改数值没有用怎么办_gg修改器如何使用?gg修改器使用方法
  10. 图片从RGB转换成Lab
  11. mipi的dsi全称_MIPI DSI协议介绍
  12. html5取消backspace后退功能,js屏蔽退格键(backspace或者叫后退键与F5)
  13. 【VOLTE】【SRVCC】 SRVCC TO 3GPP
  14. 大鱼吃小鱼java源代码_大鱼吃小鱼 JAVA游戏源码
  15. 【C语言】第五章 - 操作符
  16. 几个java小问题代码(大神不喜勿喷)
  17. selenium使用谷歌浏览器
  18. vue中下载文件使用file-saver,文件错误excel无法打开
  19. chiplogic-网表提取-(2)二极管三极管电阻器件插入
  20. 11月03日解题报告

热门文章

  1. 发布一个嘿嘿嘿的技术方案 —— 商用群发p2p网络
  2. 某40岁程序员找工作,因技术老旧被拒绝,竟泪洒当场!
  3. 调研字节码插桩技术,用于系统监控设计和实现
  4. 如何培养一个搞垮团队的Leader?
  5. 【Java并发编程】面试必备之线程池
  6. 360展示广告智能化演进
  7. 我是Redis,MySQL大哥被我害惨了!
  8. 云原生时代消息中间件的演进路线
  9. 图解TensorFlow--大数据平台技术栈16
  10. 程序员,你就是三明治!