添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
完美的长颈鹿  ·  ISO感光度设定·  4 月前    · 
豁达的马克杯  ·  analyticsvidhya-blog-z ...·  7 月前    · 
玩足球的手套  ·  页面重载开启·  9 月前    · 

Three.js本地矩阵 .materix 和世界矩阵 .matrixWorld

在学习本地矩阵 .materix 之前你应该先对WebGL的旋转、平移、缩放等变换矩阵有一定的认知,在了解世界矩阵 .matrixWorld 之前你应该现对象Three.js中层级模型的概念有一定的了解,Threejs如何通过 Group 来创建一个父子关系层级模型。

一个对象的本地矩阵 .materix 包含了该对象的旋转、平移和缩放变换,本地矩阵是平移矩阵、缩放矩阵和旋转矩阵的乘积。

一个对象的世界矩阵 .matrixWorld 是该对象本地矩阵及其所有所有祖宗对象本地矩阵的乘积,或者每一个对象的世界矩阵是对象本地矩阵和父对象的世界矩阵的乘积。

下面用一章流程图来表达Three.js本地矩阵 .materix 是什么,本地矩阵 .materix 和世界矩阵 .matrixWorld 又有什么关系。

Object3D

Object3D 是网格Mesh、点Points、线Line等模型对象的基类,组对象 Group 也是 Object3D 对象的基类。

Object3D 封装本地矩阵 .matrix 、位置 .position 、缩放 .scale 、角度 .rotation 等属性,封装了旋转相关方法 .rotateX() .rotateZ() ,平移相关方法 .translateX() .translateZ()

四元数属性 .quaternion 和角度属性 .rotation

两个属性表达的含义是一样的,都是旋转相关的信息,都会被转化为旋转矩阵。

方法改变属性

对于Three.js一些对象的属性可以直接设置属性值,也可以通过方法改变属性值。

执行旋转方法 .rotateZ() 查看,查看角度属性 .rotation 属性值欧拉对象z属性的变化

// 一个网格模型对象,基类是Object3D
var mesh = new THREE.Mesh()
// 绕z轴旋转
mesh.rotateZ(Math.PI)
console.log('查看角度属性值的变化',mesh.rotation);
console.log('查看四元数属性变化',mesh.quaternion);

执行平移方法.translateX()查看,查看位置.position属性值x分量变化

// 一个网格模型对象,基类是Object3D
var mesh = new THREE.Mesh()
// 沿着x轴平移100
mesh.translateX(100)
console.log('查看位置属性的变化',mesh.position);

更新本地矩阵属性.updateMatrix()

执行Object3D.updateMatrix()方法可以提取位置.position、缩放.scale和四元数.quaternion的属性值转化为变换矩阵设置本地矩阵属性.matrix

// Object3D.js源码
updateMatrix: function () {
  // 把位置、四元数、缩放属性转化为平移、旋转、缩放矩阵,三个矩阵的乘积是本地矩阵
  this.matrix.compose( this.position, this.quaternion, this.scale );
  this.matrixWorldNeedsUpdate = true;
// Matrix4.js源码
// 通过属性值设置变换矩阵
compose: function ( position, quaternion, scale ) {
  // 四元数矩阵转化为旋转矩阵,然后改变本地矩阵
  this.makeRotationFromQuaternion( quaternion );
  // 缩放属性转化为缩放矩阵,然后改变本地矩阵
  this.scale( scale );
  // 位置属性转化为平移矩阵,然后改变本地矩阵
  this.setPosition( position );
  return this;
// 一个网格模型对象,基类是Object3D
var mesh = new THREE.Mesh()
// 缩放网格模型
mesh.scale.set(900,900,900)
// 位置、角度、缩放属性值更新到矩阵属性matrix
mesh.updateMatrix();
console.log('查看本地矩阵属性matrix',mesh.matrix.elements);

更新世界矩阵属性.updateMatrixWorld()

调用.updateMatrixWorld()方法首先会更新对象的本地矩阵属性,然后更新对象的世界矩阵属性。

.updateMatrixWorld()方法封装了递归算法,会遍历对象的所有子对象,对象本身和

// Object3D.js源码
updateMatrixWorld: function ( force ) {
  // 更新对象的本地矩阵属性
  if ( this.matrixAutoUpdate ) this.updateMatrix();
  if ( this.parent === null ) {
    // 如果一个对象没有父对象,也就是树结构对象的根节点对象,世界矩阵就等于本地矩阵
    this.matrixWorld.copy( this.matrix );
  } else {
    // 更新对象的世界矩阵,父对象的世界矩阵和对象本地矩阵的乘积
    this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
 // 通过递归算法遍历一个对象的所有子对象,执行与根对象一样的操作更新本地和世界矩阵属性
  var children = this.children;
  for ( var i = 0, l = children.length; i < l; i ++ ) {
    children[ i ].updateMatrixWorld( force );

WebGL渲染器

场景对象的.autoUpdate属性默认值是true,执行.render()方法的时候scene.updateMatrixWorld()默认执行,也就是说执行 Threejs执行渲染器渲染方法的时候,场景对象所有子孙对象的世界矩阵属性和本地矩阵属性才会更新。

// WebGLRenderer.js源码
this.render=function(){
  // WebGL渲染器中执行场景对象的updateMatrixWorld()方法,更新场景和场景所有子孙对象的本地矩阵
  if (scene.autoUpdate === true) scene.updateMatrixWorld();

世界坐标和本地坐标

位置属性.position表示本地坐标,也就是说该对象相对父对象的偏移位置。通过Object3D.getWorldPosition()方法可以返回一个模型的世界坐标,是模型对象相对坐标原点的位置坐标,也就是该对象位置属性.position及其所有祖宗对象的.position相加。

var worldPosition = new THREE.Vector3();
mesh.getWorldPosition(worldPosition)
console.log('世界坐标',worldPosition);
console.log('本地坐标',mesh.position);
// Object3D.js源码
getWorldPosition: function ( target ) {
  if ( target === undefined ) {
    console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
    target = new Vector3();
  this.updateMatrixWorld( true );
  通过矩阵对象setFromMatrixPosition方法从世界矩阵中提取平移矩阵分量,然后转化为position属性
  return target.setFromMatrixPosition( this.matrixWorld );