【three.js学习笔记】05 场景中的对象 添加对象/移除对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/towrabbit/article/details/80295192

This player dreamed of sunlight and trees. Of fire and water. It dreamed it created. And it dreamed it destroyed.
–End Poem《minecraft》

这是游戏《我的世界》终末之诗里的一句话,其实差不多可以表达了对于这个世界的认识,如果放在一个three.js创建的三维世界中,场景(scene)就是整个世界,包括了这个世界的所有东西,光(Lights),一个立方体(cube),一个平面(plane),或者是一个模型(XXX),他们都是这个世界里面的对象,他们有着自己的属性(如材质颜色)和方法(如跳跃移动等),而相机(camera)就是观察这个世界的眼睛,他决定了我们以什么角度 什么位置来观察这个我们所创造出来的世界。

创建场景

在第一章的地方就讲过怎么样创建一个最基本的场景,这里不重复了
html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/three.js/92/three.min.js"></script>
    <script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
    <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
    <title>场景</title>
    <style>
        body{
            margin:0;padding:0;
            overflow:hidden;
        }
    </style>
</head>
<body>
    <div id="WebGL-output"></div>
</body>

js:

        var scene,camera,renderer,axes;
        function init(){
            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
            camera.position.set(-30,30,30);
            camera.lookAt(scene.position);

            renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(new THREE.Color(0Xeeeeee));
            renderer.shadowMapEnabled;
            renderer.setSize(window.innerWidth,window.innerHeight);
            document.getElementById("WebGL-output").appendChild(renderer.domElement);


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

            planeGeometry = new THREE.PlaneGeometry(60,30);
            var planeMaterial = new THREE.MeshPhongMaterial({color:0xeeeeee});
            var plane = new THREE.Mesh(planeGeometry,planeMaterial);
            plane.position.set(15,0,0);
            plane.rotation.x = -0.5*Math.PI;
            scene.add(plane);

            var stats = new Stats();
            document.body.appendChild(stats.dom);

            var controls = new THREE.TrackballControls(camera,renderer.domElement);
            controls.maxDistance = 400.0;
            controls.minDistance = 20.0;

            var spotlight = new THREE.SpotLight(0xffffff);
            var spotlightHelper = new THREE.SpotLightHelper(spotlight);
            spotlight.position.set(-50,100,2);
            spotlight.castShadow = true;
            spotlight.shadow.mapSize.width = 2000;  // default512
            spotlight.shadow.mapSize.height = 2000; // default512
            scene.add(spotlight);
            scene.add(spotlightHelper);


            function animate(){
                requestAnimationFrame(animate);
                renderer.render(scene,camera);
                controls.update();
                stats.update();
            }

            function onResize(){
                camera.aspect = window.innerWidth/window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            }

            window.addEventListener('resize', onResize, false);
            animate();
            onResize();
        }
        init();

上面的代码运行之后可以看到一个有点像是金属材质的平面

创造

向这个场景中加入对象的方法,把这个方法放在gui组件里面:
外部全作用域:

        var guiControl = new function(){
            this.addCube = function(){
                var cubeSize = Math.ceil(Math.random()*3);//大小1-3之间 1,2,3
                var cubeGeometry = new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize);
                var cubeMaterial = new THREE.MeshLambertMaterial({color:Math.random()*0xffffff});
                var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

                cube.castShadow = true;
                cube.name = "方块—" + scene.children.length;
                console.log(planeGeometry.parameters.width);
                cube.position.x = -16 + Math.round((Math.random() * planeGeometry.parameters.width));
                cube.position.y = 2 + Math.round(Math.random() * 20);
                cube.position.z = - 15 + Math.round((Math.random()*planeGeometry.parameters.height));
                console.log("添加方块:"+cube.name);
                scene.add(cube);
            }
        }

这里面有一个生成一个随机颜色方块的方法并放在了一个对象当中
在init方法中添加,初始化dat gui对象:

    var gui = new dat.GUI();
    gui.add(guiControl, 'addCube');

然后运行,在右上角的gui面板中按addcube,就会在平面上随机产生一个新的立方体
生成很多个立方体:
在init函数中添加代码

function addmanycube(number){
    for (var i = 0 ; i < number; i++){
         guiControl.addCube();
    }
}

addmanycube(50);

运行:
生成很多立方体

运行一下我们发现可以生成很多的立方体,并且点击右上角控制板上面的按钮会发现场景中会增加一个新的立方体;

毁灭

既然谈到了创造,就不得不说毁灭,这是与创造相对应的
在gui控制组件对象中添加函数:

    var guiControl = new function(){
    ...
    this.removeCube = function(){
             var allChildren = scene.children;
             var lastObject = allChildren[allChildren.length-1];
             if(lastObject instanceof THREE.Mesh){
                 scene.remove(lastObject);
                 this.numberOfObjects = scene.children.length;
        }
    }

    ...

}

然后将这个函数添加进gui控制组件中:

    init(){
    ...
    gui.add(guiControl, 'removeCube');
    ...

}

这个时候:点击左上角的removeCube就会让方块消失一个:这里的对象组类似于堆栈,先添加的方块是最后移除的,后添加的方块最先移除

获取某个对象

方法:.getObjectById();
通过唯一的id标示来获取对象;
之前已经生成过50个方块,我们试试从其中获取一个方块 并且让他的速度更快一些:

            function animate(){
                requestAnimationFrame(animate);
                renderer.render(scene,camera);
                scene.traverse(function (obj) {
                    if(obj instanceof THREE.Mesh && obj != plane){
                        //obj.rotation.x += guiControl.rotateSpeed;
                        obj.rotation.y += (guiControl.rotateSpeed);
                    }
                });
                var obj = scene.getObjectById(20);//获取这个方块
                obj.rotation.y += 0.4;//让这个方块每帧比其他方块快0.4
                controls.update();
                stats.update();
            }

然后你就会发现我就是我,是不一样的烟火,在所有速度都一样块的方块中,有一个方块有点不太一样,它转的比别人更快了。

添加雾化效果

这是一个内置的函数,可以添加雾化效果,在远处的物体会被一层定义了颜色的雾覆盖,这样会让画面更有深度的感觉:
在gui控制器中添加雾化效果函数

var guiControl = new function(){
    ...
    this.fog = function(){
        scene.fog = new THREE.Fog( 0xffffff, 0.01, 100)//雾气颜色,近处的距离, 远处的距离
    }
}

//在init函数中将这个方法添加控制按钮
function init(){
...
    gui.add(guiControl, 'fog');
...
}

运行,点击右上角的控制面板fog按钮,场景就能产生雾化效果了
three.js雾化效果

覆盖材质

覆盖材质是一个场景属性,可以让这个场景中所有对象的材质变成一样:

scene.overrideMaterial = new THREE.MeshPhongMaterial({color:0xffffff});
这会让整个场景中所有的对象的材质变得一样:
three.js场景材质替换
包括其中的辅助线的材质都变掉了,这个属性并不是很常用。

猜你喜欢

转载自blog.csdn.net/towrabbit/article/details/80295192