【Three.js】八、three.js几何体的组合与合并

【Three.js】八、three.js几何体的组合与合并

一、几何体的组合

THREE.Group()可用来创建一个组,每一组中可包含多个对象,可对这些对象进行整体的调整,也可以单独调整组中的某个对象。使用add方法即可向组中添加对象。

示例:

import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initTrackballControls, initThree, initStats} from "../../util/util";

function init(){
    let stats = initStats();
    let {camera, scene, renderer} = initThree();

    let spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(0, 30, 50);
    spotLight.castShadow = true;
    spotLight.shadow.mapSize.set(2048, 2048);
    scene.add(spotLight);

    let axes = new THREE.AxesHelper(20);
    scene.add(axes);

    let planeGeometry = new THREE.PlaneBufferGeometry(60, 40, 1,1);
    let planeMaterial = new THREE.MeshLambertMaterial({
        color: 0xffffff
    });
    let plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.rotation.x = -0.5*Math.PI;
    plane.receiveShadow = true;
    scene.add(plane);

    let cubeGeometry = new THREE.BoxBufferGeometry(5,5,5,5,5,5);
    let cubeMaterial = new THREE.MeshStandardMaterial({
        color: 0x00ffff
    });
    let cube1 = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube1.position.set(-6, 5, 0);
    let cube2 = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube2.position.set(6, 5, 5);

    let group = new THREE.Group();
    group.add(cube1, cube2);
    scene.add(group);

    let gui = new dat.GUI();
    let cube1GUI = gui.addFolder('cube1');
    let cube2GUI = gui.addFolder('cube2');
    let groupGUI = gui.addFolder('group');
    let cube1Controls = {
        positionX: cube1.position.x,
        positionY: cube1.position.y,
        positionZ: cube1.position.z,
        scale: 1
    };
    let cube2Controls = {
        positionX: cube2.position.x,
        positionY: cube2.position.y,
        positionZ: cube2.position.z,
        scale: 1
    };
    let groupControls = {
        positionX: group.position.x,
        positionY: group.position.y,
        positionZ: group.position.z,
        scale: 1
    };
    cube1GUI.add(cube1Controls, 'positionX', -10, -6);
    cube1GUI.add(cube1Controls, 'positionY', 5, 10);
    cube1GUI.add(cube1Controls, 'positionZ', 0, 10);
    cube1GUI.add(cube1Controls, 'scale', 0, 3);
    cube2GUI.add(cube2Controls, 'positionX', 6, 10);
    cube2GUI.add(cube2Controls, 'positionY', 5, 10);
    cube2GUI.add(cube2Controls, 'positionZ', 5, 10);
    cube2GUI.add(cube2Controls, 'scale', 0, 3);
    groupGUI.add(groupControls, 'positionX', -10, 10);
    groupGUI.add(groupControls, 'positionY', 0, 10);
    groupGUI.add(groupControls, 'positionZ', -10, 10);
    groupGUI.add(groupControls, 'scale', 0, 3);
    let trackballControls = initTrackballControls(camera, renderer);
    function render(){
        stats.update();
        trackballControls.update();
        cube1.position.set(cube1Controls.positionX, cube1Controls.positionY, cube1Controls.positionZ);
        cube1.scale.set(cube1Controls.scale, cube1Controls.scale, cube1Controls.scale);
        cube2.position.set(cube2Controls.positionX, cube2Controls.positionY, cube2Controls.positionZ);
        cube2.scale.set(cube2Controls.scale, cube2Controls.scale, cube2Controls.scale);
        group.position.set(groupControls.positionX, groupControls.positionY, groupControls.positionZ);
        group.scale.set(groupControls.scale, groupControls.scale, groupControls.scale);
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }
    render();
}
init();

在这里插入图片描述
  上例创建了两个立方体,并加入了一个Group中,使用右侧控制器可对这两个立方体进行位置及缩放的变化;其中group选项下可对整体进行调整,cube1/cube2分别对应一个立方体。

二、几何体的合并

通过THREE.Geometry.merge()方法可实现几何体之间的合并,一旦合并无法单独控制被合并的几何体。当页面存在大量几何体,使用合并可提高页面性能。

  如下,场景中显示500个立方体,观察fps好想还可以,通过右侧控制器将cubeNumber调至10000个点击redraw,你会发现fps迅速降低至低于30fps,如果勾选merge,你会发现fps就正常了。

import '../../stylus/index.styl'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import {initTrackballControls, initStats, initThree} from "../../util/util";

function init () {
    let stats = initStats();
    let {scene, camera, renderer} = initThree();
    camera.position.set(-100, 100, 80);
    let cubeMaterial = new THREE.MeshNormalMaterial({
        transparent: true,
        opacity: 0.8
    });
    let addCube = () => {
        let cubeGeometry =  new THREE.BoxGeometry(4,4,4,4);
        let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = - 100 + Math.round(Math.random() * 200);
        cube.position.y =  Math.round(Math.random() * 10);
        cube.position.z = - 100 + Math.round(Math.random() * 200);
        return cube;
    };

    for (let i = 0; i < 500; i++) {
        scene.add(addCube());
    }

    let gui = new dat.GUI();
    let guiControls = {
        cubeNumber: 500,
        merge: false,
        redraw: function () {
            let removeArr = [];
            scene.children.forEach(item => {
                item instanceof THREE.Mesh && removeArr.push(item);
            });
            removeArr.forEach(item => scene.remove(item));
            if ( this.merge ) {
                let geometry = new THREE.Geometry();
                for (let i = 0; i < this.cubeNumber; i++) {
                    let cubeMesh = addCube();
                    cubeMesh.updateMatrix();
                    geometry.merge(cubeMesh.geometry, cubeMesh.matrix);
                }
                scene.add(new THREE.Mesh(geometry, cubeMaterial));
            } else {
                for (let i = 0; i < this.cubeNumber; i++) {
                    scene.add(addCube());
                }
            }
            addCube();
        }
    };
    gui.add(guiControls, 'cubeNumber');
    gui.add(guiControls, 'merge');
    gui.add(guiControls, 'redraw');
    let trackballControls = initTrackballControls(camera, renderer);
    function render() {
        stats.update();
        trackballControls.update();
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }
    render();
}

init();
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值