几何变换(旋转、缩放、平移)

  创建场景中的三维模型往往需要设置显示大小、位置、角度,three.js提供了一系列网格模型对象的几何变换方法,从WebGL的角度看,旋转、缩放、平移对应的都是模型变换矩阵, 有兴趣可以学习webgl教程中的《WebGL旋转变换》等课程。

  网格模型对象的旋转、缩放、平移等方法或属性可以查找three.js文档的Object3D对象,该对象是网格模型对象、点模型对象、线条模型对象的基类。

几何变换3D对象Object3D方法属性.translateX ( distance ).translateY ( distance ).translateZ ( distance )平移.rotateX ( rad ).rotateY ( rad ).rotateZ ( rad ).rotateOnAxis ( axis, angle )旋转对象类型Vector3scale缩放对象类型Vector3Float.x.y.z属性set(x,y,z)方法.position位置对象类型Euler.x.y.z属性set方法rotation角度.translateOnAxis ( axis, distance )属性值属性值弧度Float绕x轴旋转x轴坐标属性.x属性值Floatx方向缩放倍数.y.z方法set(x,y,z)rad 弧度Floataxis平移方向Vector3

立方体网格模型代码

    /**
     * 创建网格模型
     */
    var box=new THREE.BoxGeometry(100,100,100);//创建一个立方体几何对象
    var material=new THREE.MeshLambertMaterial({color:0x0000ff});//材质对象
    var mesh=new THREE.Mesh(box,material);//网格模型对象
    scene.add(mesh);//网格模型添加到场景中

缩放

立方体网格模型x轴方向放大2倍,如果连续执行两次该语句,相等于比原来方法4倍


    mesh.scale.x = 2.0;//x轴方向放大2倍
    

立方体网格模型整体缩小0.5倍,相当于xyz三个方向分别缩小0.5倍


    mesh.scale.set(0.5,0.5,0.5);//缩小为原来0.5倍
    

  网格模型Mesh的属性scale返回值是一个Vector3对象,查看three.js官方文档你可以知道Vector3对象具有属性x、y、z对于上面的代码而言xyz表示坐标值,xyz数据类型是float,Vector3对象还具有方法set(),set方法有三个表示xyz坐标的参数。

平移

立方体网格模型沿着x轴正方向平移100,可以多次执行该语句,每次执行都是相对上一次的位置进行平移变换


     mesh.translateX(100);//沿着x轴正方向平移距离100
    

网格模型沿着向量(0,1,0)表示的方向平移100


    var axis = new THREE.Vector3(0,1,0);//向量axis
    mesh.translateOnAxis(axis,100);//沿着axis轴表示方向平移100

  translateOnAxis(axis, distance)方法相比.translateX、.translateY、.translateZ更通用,可以实现立方体沿着任何方向旋平移,参数axis表示平移方向,使用对象Vector3表示

旋转

立方体网格模型绕立方体的x轴旋转π/4,可以多次执行该语句,每次执行都是相对上一次的角度进行旋转变化


    mesh.rotateX(Math.PI/4);//绕x轴旋转π/4
    

网格模型绕(0,1,0)向量表示的轴旋转π/8


    var axis = new THREE.Vector3(0,1,0);//向量axis
    mesh.rotateOnAxis(axis,Math.PI/8);//绕axis轴旋转π/8

  rotateOnAxis(axis, angle)方法相比.rotateX、.rotateY、.rotateZ更通用,可以实现立方体绕任何轴旋转,参数axis表示旋转轴,使用对象Vector3表示

位置属性position

立方体网格模型位置坐标(80,2,10)


        mesh.position.y = 80;//设置网格模型几何中心y坐标
    

立方体网格模型几何中心y轴坐标值80


    mesh.position.set(80,2,10);//设置网格模型几何中心三维坐标

  position属性和平移方法translateX()一样都是设置距离,方法translateX()设置的相对上次位置进行平移,两次执行该方法,距离会叠加,position属性设置的距离是相对坐标系原点位置, 两次执行position属性立方体的会只会更新重新定位,两次的距离参数不是叠加关系,而是替换关系。

角度属性rotation

立方体网格模型位置坐标(80,2,10)


     mesh.position.y = 80;//设置网格模型几何中心y坐标
    

立方体网格模型几何中心y轴坐标值80


    mesh.position.set(80,2,10);//设置网格模型几何中心三维坐标

  rotation属性和旋转方法rotateX()差异类似position属性和平移方法translateX()的差异,一个是相对坐标系设置角度、位置,一个是相对当前的三维模型的状态设置角度、位置参数。 旋转与平移参考的都是坐标系,不过参考的坐标系稍有不同,平移参考的是世界坐标系或者说三维场景对象Scene的坐标系,和相机对象一样,在整个三维场景中的位置, 三维模型的旋转参考的是模型坐标系,也就是对三维模型本身建立的坐标系。

坐标系

1.场景中的立方体、圆柱等三维模型的位置属性、平移方法参照Scene对象的世界坐标系

2.场景中立方体、圆柱等的三维模型的角度属性、旋转方法参照模型自身的模型坐标系

three.js世界坐标系—模型坐标系

一个几何体-多个网格模型

  下面的程序是通过一个几何体创建了多个网格模型,网格模型可以共享几何体对象和材质对象都,几何体对象本质上是一组顶点相关数据,每创建一个网格模型, 相当于多次利用显存中的同一组定点相关数据渲染出多个三维模型的效果,几何体顶点虽然是同一组数据,但是可以在GPU着色器中对这组数据进行矩阵变换,来呈现出不同的效果。

    /**
     * 创建网格模型1、网格模型2
     */
    var box=new THREE.BoxGeometry(50,50,50);//创建一个立方体几何对象
    var material=new THREE.MeshLambertMaterial({color:0x0000ff});//材质对象
    var mesh1=new THREE.Mesh(box,material);//网格模型对象1
    var mesh2=new THREE.Mesh(box,material);//网格模型对象2
    mesh1.translateX(-50);//沿着x轴负方向平移距离50
    mesh2.translateX(50);//沿着x轴正方向平移距离50
    scene.add(mesh1);//网格模型1添加到场景中
    scene.add(mesh2);//网格模型2添加到场景中
        

  代码中的网格模型mesh1、网格模型mesh2都是通过同一个几何体对象Geometry创建,默认情况下,几何体对象的顶点位置决定了网格模型在场景中的显示位置, 两个网格模型执行方法translateX()进行平移变换错开显示。网格模型的平移变换方法translateX()会通过three.js引擎转化为WebGL中CPU顶点着色器的矩阵变换程序。

几何体和网格模型几何变换比较

  更改上面的程序,插入下面一段代码,放大其中一个网格模型,可以看到另外外一个网格模型的显示大小并不受影响。


    mesh2.scale.y = 2.0;//y轴方向放大2倍
        

  网格模型对象可以进行缩放平移旋转变换,几何体对象也拥有相关的几何变换方法和属性,几何体进行几何变换,本质上更改的是显存中的顶点相关数据, 网格模型进行几何变换,不会更改显存中的顶点数据,顶点数据的变换是在GPU渲染管线的顶点着色器处理单元中借助程序逐顶点执行矩阵乘法运算。

  几何体对象执行方法scale(),尺寸缩小为原来的0.5倍,刷新浏览器你会看到两个网格模型代表的立方体都缩小了,对比上面的程序可以看出更改几何体的参数,与之相关的网格模型都会变化。 这很好理解,网格模型的几何变换更改的是要与顶点数据进行乘法运算的模型矩阵,几何体对象进行变换更累刷新的是显存上的顶点相关数据,每次渲染出一个网格模型, 都会从网格模型构造函数指定的顶点对象获取顶点数据。


    var box=new THREE.BoxGeometry(50,50,50);//创建一个立方体几何对象
    box.scale(0.5,0.5,0.5);//几何体缩小为原来0.5倍
        

  几何体对象可以进行上面程序中的缩放变换,自然也有平移、缩放变换的相关方法,具体使用方法可以参考three.js文档的Geometry对象,立方体、球体等几何体的构造函数返回的结果都是Geometry对象, 这些构造函数返回的对象都会继承Geometry对象的属性和方法。

几何变换几何体对象Geometry方法旋转.rotateX ( rad ).rotateY ( rad ).rotateZ ( rad )平移.translate ( x, y, z )缩放.scale ( x, y, z )方法返回几何体对象GeometryradFloat弧度xyzFloat坐标