threejs 中模型旋转实现原理和更新流程

在项目上,我们会通过设置 Mesh 上的rotation 属性来实现模型旋转的控制,那其中threejs 是怎么实现的呢?

调用 mesh.rotation 属性实现旋转

通过 Object3D 源码可以知道, rotation 其实是代理了 Euler 实例,当我们设置object.rotation.x , 其实调用的是 euler.x 设置。些时在 Object3D 中注册了一个变更回调,在更新了x值后会执行回调,在回调中会更新 Object3D 上的四元数计算旋转值。

image.png

在回调中他没有立马去更新 模型的 matrixWorld。当下次渲染函数执行的时候才会触发更新,更新流程如下

  1. 当执行renderer.render 的时候,会调用scene.updateMatrixWorld 方法,通过updatematrixWorld 方法会调用 updateMatrix。 在updatematrixWorld 方法中会递归调用子节点的此方法。从而更新模型 的matrixWorld.
    updateMatrix() {
              // 实现与四元数的结合
        this.matrix.compose( this.position, this.quaternion, this.scale );

        this.matrixWorldNeedsUpdate = true;

    }

    updateMatrixWorld( force ) {

        if ( this.matrixAutoUpdate ) this.updateMatrix();

        if ( this.matrixWorldNeedsUpdate || force ) {

            if ( this.parent === null ) {

                this.matrixWorld.copy( this.matrix );

            } else {
                              // 更新 matrixWorld
                this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );

            }

            this.matrixWorldNeedsUpdate = false;

            force = true;

        }

        // update children

        const children = this.children;

        for ( let i = 0, l = children.length; i < l; i ++ ) {

            const child = children[ i ];

            if ( child.matrixWorldAutoUpdate === true || force === true ) {

                child.updateMatrixWorld( force );

            }

        }

    }

在真实渲染模型 的时候,会在renderer.renderObject 方法中计算模型 的modelViewMatrix,这个矩阵就是着色器用来计算模型旋转后位置 的矩阵。从而实现旋转

        function renderObject( object, scene, camera, geometry, material, group ) {

            object.onBeforeRender( _this, scene, camera, geometry, material, group );
                        // 计算 modelViewMatrix
            object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
            object.normalMatrix.getNormalMatrix( object.modelViewMatrix );

            material.onBeforeRender( _this, scene, camera, geometry, object, group );

            if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {

                material.side = BackSide;
                material.needsUpdate = true;
                _this.renderBufferDirect( camera, scene, geometry, material, object, group );

                material.side = FrontSide;
                material.needsUpdate = true;
                _this.renderBufferDirect( camera, scene, geometry, material, object, group );

                material.side = DoubleSide;

            } else {

                _this.renderBufferDirect( camera, scene, geometry, material, object, group );

            }

            object.onAfterRender( _this, scene, camera, geometry, material, group );

        }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Threejs 为什么? webGL太难用,太复杂! 但是现代浏览器都支持 WebGL 这样我们就不必使用 Fla...
    强某某阅读 6,139评论 1 21
  • ## >背景:创建出threejs3D场景后如何使用鼠标操作场景内模型元素?,如拖动,放大缩小,平移,点击触发交互...
    小豆包3D世界阅读 1,984评论 0 0
  • react vr中文网:www.vr-react.com react vr qq群:481244084 示例源码 ...
    liu_520阅读 3,712评论 4 6
  • 概念性的知识 threejs是一个让用户通过javascript入手进入搭建WebGL项目的类库; WebGL 使...
    squidbrother阅读 1,137评论 0 2
  • 一、Unity简介 1. Unity界面 Shift + Space : 放大界面 Scene界面按钮渲染模式2D...
    MYves阅读 8,392评论 0 22