three.js 实现同步3D窗口视角和3D辅助方位视角

155 阅读1分钟

1.同步3D窗口视角(同步旋转和缩放视角)

在主的场景中,新增一个新的渲染器视口和相机(左侧窗口),克隆赋值主相机坐标和四元数旋转; image.png

            // 左侧小窗口渲染器设置
            renderer.setClearColor(0xeeeeee, 1);

            renderer.clearDepth(); // 清除缓存;

            renderer.setScissorTest(true);

            renderer.setScissor(20, 20, insetWidth, insetHeight);

            renderer.setViewport(20, 20, insetWidth, insetHeight);

            // 同步相机四元数(控制旋转)
            camera3.position.copy(camera.position);
            camera3.quaternion.copy(camera.quaternion);

            renderer.render(scene, camera3);

2.3D辅助方位视角(同步旋转视角,视角不跟随缩放)

在主的场景中,新增一个新的渲染器、相机(右侧窗口)、场景和控制器,克隆赋值主相机坐标和四元数旋转,调整两个相机的旋转角度和方向。

        // 主场景
        // renderer
        threeD = document.getElementById('r3d');
        renderer = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true,

        });

        renderer.setSize(threeD.offsetWidth, threeD.offsetHeight);
        threeD.appendChild(renderer.domElement);

        // scene
        scene = new THREE.Scene();
        // camera
        camera = new THREE.PerspectiveCamera(75, threeD.offsetWidth / threeD.offsetHeight, 0.1, 100000);
        camera.position.y = 400;
        camera.up.set(Math.PI / 2, 0, 0);
        
        
        
        // 右侧窗口场景
        threeD2 = document.getElementById('map');
        renderer2 = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true,

        });
        renderer2.setSize(threeD2.offsetWidth, threeD2.offsetHeight);
        // renderer.setViewport(20, 200, window.innerWidth / 2, window.innerHeight / 2);
        threeD2.appendChild(renderer2.domElement);

        //矩形范围宽高都是canvas画布的二分之一  左侧偏移20 顶部偏移200
        //矩形范围宽高都是canvas画布的四分之一  左侧偏移20 顶部偏移200

        // scene
        scene2 = new THREE.Scene();

        // camera
        camera2 = new THREE.PerspectiveCamera(75, threeD2.offsetWidth / threeD2.offsetHeight, 0.1, 100000);
        camera2.position.z = 400;
        camera2.up.set(0, 0, Math.PI / 2)

        // controls
        controls2 = new AMI.TrackballControl(camera2, threeD2);

        controls2.noPan = true;
        controls2.noRotate = true;
        controls2.noZoom = true;

image.png

全部代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <title>orientation</title>
    <link rel="stylesheet" type="text/css" href="demo.css">
    <script type="text/javascript" src="https://use.edgefonts.net/source-code-pro.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.120.0/build/three.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ami.js/0.0.22/ami.min.js"></script>
</head>

<style>
    #map {
        position: absolute;
        width: 350px;
        height: 200px;
        background: rgb(171, 167, 175);
        bottom: 20px;
        right: 20px;
        z-index: 10;
    }
</style>

<body>
    <div id="my-lut-container">
        <div>Transfer function<div id="my-tf" class="my-tf"></div>
        </div>
    </div>
    <div id="r3d"></div>
    <div id="map"></div>
</body>

<script>
    let controls;
    let threeD;
    let renderer;
    let camera;
    let scene;

    let controls2;
    let threeD2;
    let renderer2;
    let camera2;
    let scene2;

    let camera3;
    let scene4;
    let controls4;

    let insetWidth;
    let insetHeight;

    let objHelper = new THREE.Object3D();
    let cube;

    /**
     * Handle window resize event
     */
    function onWindowResize() {
        // update the camera
        // camera.aspect = threeD.offsetWidth / threeD.offsetHeight;
        // camera.updateProjectionMatrix();

        // notify the renderer of the size change
        renderer.setSize(threeD.offsetWidth, threeD.offsetHeight);

        insetWidth = window.innerHeight / 4; // square
        insetHeight = window.innerHeight / 4;

        camera3.aspect = insetWidth / insetHeight;
        camera3.updateProjectionMatrix();
    }


    /**
     * Init the scene
     */
    function init() {
        /**
       * Rendering loop
       */
        function animate() {


            // 主窗口渲染器设置;
            controls.update();
            renderer.setClearColor(0x000000, 0);
            renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
            renderer.render(scene, camera);



            // 左侧小窗口渲染器设置
            renderer.setClearColor(0xeeeeee, 1);

            renderer.clearDepth(); // 清除缓存;

            renderer.setScissorTest(true);

            renderer.setScissor(20, 20, insetWidth, insetHeight);

            renderer.setViewport(20, 20, insetWidth, insetHeight);

            // 同步相机四元数(控制旋转)
            camera3.position.copy(camera.position);
            camera3.quaternion.copy(camera.quaternion);

            renderer.render(scene, camera3);

            renderer.setScissorTest(false);
            // ,克隆赋值主相机坐标和四元数旋转,
            requestAnimationFrame(function () { 
                animate();
            });
        }

        // renderer
        threeD = document.getElementById('r3d');
        renderer = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true,

        });

        renderer.setSize(threeD.offsetWidth, threeD.offsetHeight);
        threeD.appendChild(renderer.domElement);

        // scene
        scene = new THREE.Scene();
        // camera
        camera = new THREE.PerspectiveCamera(75, threeD.offsetWidth / threeD.offsetHeight, 0.1, 100000);
        camera.position.y = 400;
        camera.up.set(Math.PI / 2, 0, 0);


        camera3 = new THREE.PerspectiveCamera(40, 1, 1, 1000);
        camera3.position.copy(camera.position);


        insetWidth = window.innerHeight / 3;
        insetHeight = window.innerHeight / 5;



        camera3.aspect = insetWidth / insetHeight;
        camera3.updateProjectionMatrix();

        // controls
        controls = new AMI.TrackballControl(camera, threeD);
        controls.rotateSpeed = 5.5;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 0.8;
        controls.staticMoving = true;
        controls.dynamicDampingFactor = 0.3;


        controls4 = new AMI.TrackballControl(camera3, threeD);
        controls4.noPan = true;
        controls4.noRotate = true;
        controls4.noZoom = true;

        window.addEventListener('resize', onWindowResize, false);

        animate();

        const geometry = new THREE.BoxGeometry(100, 100, 100);
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        cube = new THREE.Mesh(geometry, material);
        scene.add(cube);


        const geometry4 = new THREE.BoxGeometry(100, 100, 100);
        const material4 = new THREE.MeshBasicMaterial({ color: 0xffff00 });
        const mesh4 = new THREE.Mesh(geometry4, material4);
        scene4.add(mesh4);



        init2();
    }


    // 开启另一个场景(右侧辅助方位);
    function init2() {
        /**
       * Rendering loop
       */
        function animate2() {
            // render
            controls2.update();

            renderer2.render(scene2, camera2);


            // 模型四元数与相机同步;
            objHelper.quaternion
                .copy(camera.quaternion)
                .inverse();
            objHelper.updateMatrixWorld();


            requestAnimationFrame(function () {
                animate2();
            });
        }

        // renderer
        threeD2 = document.getElementById('map');
        renderer2 = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true,

        });
        renderer2.setSize(threeD2.offsetWidth, threeD2.offsetHeight);
        // renderer.setViewport(20, 200, window.innerWidth / 2, window.innerHeight / 2);
        threeD2.appendChild(renderer2.domElement);

        //矩形范围宽高都是canvas画布的二分之一  左侧偏移20 顶部偏移200
        //矩形范围宽高都是canvas画布的四分之一  左侧偏移20 顶部偏移200

        // scene
        scene2 = new THREE.Scene();

        // camera
        camera2 = new THREE.PerspectiveCamera(75, threeD2.offsetWidth / threeD2.offsetHeight, 0.1, 100000);
        camera2.position.z = 400;
        camera2.up.set(0, 0, Math.PI / 2)

        // controls
        controls2 = new AMI.TrackballControl(camera2, threeD2);

        controls2.noPan = true;
        controls2.noRotate = true;
        controls2.noZoom = true;

        animate2();


        const geometry = new THREE.BoxGeometry(100, 100, 100);
        const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cube2 = new THREE.Mesh(geometry, material);
        objHelper.add(cube2)
        scene2.add(objHelper);

    }
    init();

</script>
</html>