Top

使用Three.js挖空安装门来解决重叠闪烁的问题

    一、挖空原理说明

subtract 用墙面减去与门重叠的部分,产生一个新的对象,导入材质安装门即可

//参与减去几何体 
//平行于x轴门
var meshH4Door = new ThreeBSP( meshHDoor );  
//平行x轴横墙面
var meshWall4 = new ThreeBSP( meshH4 );

//平行x轴横墙面meshWall4对象 减去与meshH4Door门重叠部分  
var subtract_bsp = meshWall4.subtract( meshH4Door );
var result = subtract_bsp.toMesh( new THREE.MeshLambertMaterial({ 
	shading: THREE.SmoothShading,
	map: THREE.ImageUtils.loadTexture('./img/floor-1.jpg'),
	color: 0xff0000}) );
result.geometry.computeVertexNormals();
//添加至场景中
scene.add( result );   

效果图

源代码如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>threejs中挖空解决闪烁bug</title>
        <style>
            #canvas-frame {
                width: 100%;
                height: 450px;
            }
        </style>
    </head>
    <body onload="threeStart()">
        <div id="canvas-frame" ></div>
    </body>
    <script type="text/javascript" src="./lib/three.js" ></script>
    <!-- 运算挖门 解决闪烁bug -->
    <script type="text/javascript" src="lib/ThreeCSG.js"></script>
    <script type="text/javascript">
            var renderer, //渲染器
                width = document.getElementById('canvas-frame').clientWidth, //画布宽
                height = document.getElementById('canvas-frame').clientHeight; //画布高
            //照相机配置
            var fov = 45,//拍摄距离  视野角值越大,场景中的物体越小
                near = 1,//最小范围
                far = 1000;//最大范围
            //DOM对象
            var canvas = null;
            //初始化DOM对象   
            function initDOM(){
                canvas = document.getElementById("canvas-frame");
            }
            //初始化渲染器
            function initThree(){
                renderer = new THREE.WebGLRenderer({
                     antialias : true
                     //canvas: document.getElementById('canvas-frame')
                });
                renderer.setSize(width, height);
                renderer.setClearColor(0xFFFFFF, 1.0);
                document.getElementById('canvas-frame').appendChild(renderer.domElement);
                    renderer.setClearColor(0xFFFFFF, 1.0);
            }
            //初始化场景
            var scene;
            function initScene(){
                scene = new THREE.Scene();
            }
            var camera;
            function initCamera() {  //透视相机
                camera = new THREE.PerspectiveCamera(fov,  width/height , near, far);
                camera.position.x = 150;
                camera.position.y = 150;
                camera.position.z =450;
                camera.up.x = 0;
                camera.up.y = 1; //相机朝向--相机上方为y轴
                camera.up.z = 0;
                camera.lookAt({  //相机的中心点
                    x : 0,
                    y : 0,
                    z : 0
                });
            }
            function initLight(){
                // light--这里使用环境光
                //var light = new THREE.DirectionalLight(0xffffff); /*方向性光源*/
                //light.position.set(600, 1000, 800);
                var light = new THREE.AmbientLight(0xffffff); //模拟漫反射光源
                light.position.set(600, 1000, 800); //使用Ambient Light时可以忽略方向和角度,只考虑光源的位置
                scene.add(light);
            }
            function initObject(){  //初始化对象
                //初始化地板
                initFloor();
                initWall();
            }
            function initGrid(){ //辅助网格
                var helper = new THREE.GridHelper( 1000, 50 );
                helper.setColors( 0x0000ff, 0x808080 );
                scene.add( helper );
            }
            function initFloor(){
            	
            	 //导入材质
                var texture = THREE.ImageUtils.loadTexture('img/floor-1.jpg', {}, function() {
                    renderer.render(scene, camera);
                });
                /**
                 * 关于material材料注意点说明 
                 * MeshBasicMaterial:对光照无感,给几何体一种简单的颜色或显示线框。
                 * MeshLambertMaterial:这种材质对光照有反应,用于创建暗淡的不发光的物体。
                 * MeshPhongMaterial:这种材质对光照也有反应,用于创建金属类明亮的物体。
                 */
                var material = new THREE.MeshLambertMaterial({
                    map: texture
                });
                
                //创建一个立方体
                var geometry = new THREE.BoxGeometry(400, 20, 400);
                 for ( var i = 0; i < geometry.faces.length; i += 2 ) {
                    var hex = Math.random() * 0xffffff;
                    geometry.faces[ i ].color.setHex( hex );
                    geometry.faces[ i + 1 ].color.setHex( hex );
                }
                //var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors} );
                //将material材料添加到几何体geometry
                var mesh = new THREE.Mesh(geometry, material);
                mesh.position = new THREE.Vector3(0,0,0);
                scene.add(mesh);
            }
            //墙面
            function initWall(){
            	
            	 //导入墙面材质(后面墙面共用)
                var texture = THREE.ImageUtils.loadTexture('img/floor-1.jpg', {}, function() {
                    renderer.render(scene, camera);
                });
                /**
                 * 关于material材料注意点说明 
                 * MeshBasicMaterial:对光照无感,给几何体一种简单的颜色或显示线框。
                 * MeshLambertMaterial:这种材质对光照有反应,用于创建暗淡的不发光的物体。
                 * MeshPhongMaterial:这种材质对光照也有反应,用于创建金属类明亮的物体。
                 */
                var material = new THREE.MeshLambertMaterial({
                    map: texture
                });
                
                /*--------平行z轴横墙面3、x轴为墙面的厚度、 z轴为墙面长度、y轴为墙面高度--------------------*/
            	//平行z轴横墙面1   x轴为墙面厚度
            	var geometryH1 = new THREE.BoxGeometry(10, 65, 360);
            	/*var materialH1 = new THREE.MeshBasicMaterial( { color:0xFF0000 } );*/
            	//将material材料添加到几何体geometry
	            var meshH1 = new THREE.Mesh(geometryH1, material);
	            meshH1.position.x = 180;
	            meshH1.position.y = 45;
	            //scene.add(meshH1);
	            var meshWall1 = new ThreeBSP( meshH1 );
	            
	            var geometryHDoor1 = new THREE.BoxGeometry(10, 56, 35);
            	var materialHDoor1 = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor1 = new THREE.Mesh(geometryHDoor1, materialHDoor1);
	            meshHDoor1.position.x = 180;
	            meshHDoor1.position.y = 45;
	            meshHDoor1.position.z = 0;
	            //scene.add(meshHDoor2);
	            var meshHDoor1 = new ThreeBSP( meshHDoor1 );
	            //墙面减去重叠的门
	            subtractMesh(meshHDoor1, meshWall1);
	            
	            //为墙面1安装门
	            var geometryHDoor1 = new THREE.BoxGeometry(10, 56, 35);
	            //加载材质
	            var textureDoor1 = THREE.ImageUtils.loadTexture('img/door.png', {}, function() {
	                renderer.render(scene, camera);
	            });
	            var materialDoor1 = new THREE.MeshBasicMaterial({
	                map: textureDoor1
	            });
            	//var materialHDoor2 = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor1 = new THREE.Mesh(geometryHDoor1, materialDoor1);
	            meshHDoor1.position.x = 180;
	            meshHDoor1.position.y = 45;
	            meshHDoor1.position.z = 0;
	            scene.add(meshHDoor1);
	            
	            //平行z轴横墙面2 x轴为墙面厚度
            	var geometryH2 = new THREE.BoxGeometry(10, 65, 360);
            	var materialH2 = new THREE.MeshBasicMaterial( { color:0xFF00FF } );
            	//将material材料添加到几何体geometry
	            var meshH2 = new THREE.Mesh(geometryH2, materialH2);
	            meshH2.position.x = -180;
	            meshH2.position.y = 45;
	            var meshWall2 = new ThreeBSP( meshH2 );
	            //scene.add(meshH2);
	            
	            var geometryHDoor2 = new THREE.BoxGeometry(10, 56, 35);
            	var materialHDoor2 = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor2 = new THREE.Mesh(geometryHDoor2, materialHDoor2);
	            meshHDoor2.position.x = -180;
	            meshHDoor2.position.y = 45;
	            meshHDoor2.position.z = 0;
	            var meshHDoor2 = new ThreeBSP( meshHDoor2 );
	            //scene.add(meshHDoor2);
	            //墙面减去重叠的门
	            subtractMesh(meshHDoor2, meshWall2);
	            
	            
	            //为墙面2安装门
	            var geometryHDoor2 = new THREE.BoxGeometry(10, 56, 35);
	            //加载材质
	            var textureDoor2 = THREE.ImageUtils.loadTexture('img/door.png', {}, function() {
	                renderer.render(scene, camera);
	            });
	            var materialDoor2 = new THREE.MeshBasicMaterial({
	                map: textureDoor2
	            });
            	//var materialHDoor2 = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor2 = new THREE.Mesh(geometryHDoor2, materialDoor2);
	            meshHDoor2.position.x = -180;
	            meshHDoor2.position.y = 45;
	            meshHDoor2.position.z = 0;
	            scene.add(meshHDoor2);
	        /*--------平行z轴横墙面3、x轴为墙面的厚度、 z轴为墙面长度、y轴为墙面高度--------------------*/
	            
	            
	       /*--------平行x轴横墙面3、x轴为墙面长度、 z轴为墙面厚度、y轴为墙面高度--------------------*/
	       //平行x轴横墙面3   z轴为墙面厚度
            	var geometryH3 = new THREE.BoxGeometry(365, 65, 10);
            	var materialH3 = new THREE.MeshBasicMaterial( { color:0x808080 } );
            	//将material材料添加到几何体geometry
	        var meshH3 = new THREE.Mesh(geometryH3, material);
	            meshH3.position.x = 0;
	            meshH3.position.y = 45;
	            meshH3.position.z = -180;
	            var meshWall3 = new ThreeBSP( meshH3 );
	            //scene.add(meshH3);
	            
	            //平行x轴横重叠门3 z轴为墙面厚度
            	var geometryHDoor = new THREE.BoxGeometry(35, 50, 10);
            	var materialHDoor = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor = new THREE.Mesh(geometryHDoor, materialHDoor);
	            meshHDoor.position.x = 0;
	            meshHDoor.position.y = 45;
	            meshHDoor.position.z = -180;
	            var meshHDoor3 = new ThreeBSP( meshHDoor );
	            //scene.add(meshHDoor);
	            //墙面减去重叠的门
	            subtractMesh(meshHDoor3, meshWall3);
	            
	            //平行x轴横墙面3安装门
                var geometryDoor3 = new THREE.BoxGeometry(35, 50, 10);
                //加载材质
	            var textureDoor3 = THREE.ImageUtils.loadTexture('img/door.png', {}, function() {
	                renderer.render(scene, camera);
	            });
	            var materialDoor3 = new THREE.MeshBasicMaterial({
	                map: textureDoor3
	            });
                door3 = new THREE.Mesh( geometryDoor3,materialDoor3);
                door3.position.x = 0;
	            door3.position.y = 45;
	            door3.position.z = -180;
                scene.add(door3);
                 /*--------平行x轴横墙面3、 z轴为墙面厚度、y轴为墙面高度--------------------*/
	            
	            /*--------平行x轴横墙面4、 z轴为墙面厚度、y轴为墙面高度--------------------*/
	            //平行x轴横墙面4 z轴为墙面厚度
            	var geometryH4 = new THREE.BoxGeometry(365, 65, 10);
            	var materialH4 = new THREE.MeshBasicMaterial( { color:0x00AABB,  wireframe: true} );
            	//将material材料添加到几何体geometry
	            var meshH4 = new THREE.Mesh(geometryH4, materialH4);
	            meshH4.position.x = 0;
	            meshH4.position.y = 45;
	            meshH4.position.z = 180;
	            //平行x轴横墙面4  挖出一道门
				var meshWall4 = new ThreeBSP( meshH4 );
	            //scene.add(meshH4);
	            
	            //平行x轴横重叠门4 z轴为墙面厚度
            	var geometryHDoor = new THREE.BoxGeometry(35, 50, 10);
            	var materialHDoor = new THREE.MeshBasicMaterial( { color:0x00BBAA} );
            	//将material材料添加到几何体geometry
	            var meshHDoor = new THREE.Mesh(geometryHDoor, materialHDoor);
	            meshHDoor.position.x = 0;
	            meshHDoor.position.y = 45;
	            meshHDoor.position.z = 180;
	            //scene.add(meshHDoor);
	            //重叠门
	            var meshHDoor4 = new ThreeBSP( meshHDoor );
	            //墙面减去重叠的门
	            subtractMesh(meshHDoor4, meshWall4);
	            
				//平行x轴横墙面4安装门
                var geometryDoor4 = new THREE.BoxGeometry(35, 50, 10);
                //加载材质
	            var textureDoor4 = THREE.ImageUtils.loadTexture('img/door.png', {}, function() {
	                renderer.render(scene, camera);
	            });
	            var materialDoor4 = new THREE.MeshBasicMaterial({
	                map: textureDoor4
	            });
                door4 = new THREE.Mesh( geometryDoor4,materialDoor4);
                door4.position.x = 0;
	            door4.position.y = 45;
	            door4.position.z = 180;
                scene.add(door4);
                /*--------平行x轴横墙面3、x轴为墙面长度、 z轴为墙面厚度、y轴为墙面高度-------------------*/
                
            }
            
            //运算减去
            /*
             * meshDoor 门面
             * meshWall 墙面  
             */
            function subtractMesh(meshDoor,meshWall){
            	//平行x轴横墙面4减去与meshHDoor门重叠部分
				var subtract_bsp = meshWall.subtract( meshDoor );
				var result = subtract_bsp.toMesh( new THREE.MeshLambertMaterial({
					shading: THREE.SmoothShading, 
					map: THREE.ImageUtils.loadTexture('./img/floor-1.jpg') 
				}));
				result.geometry.computeVertexNormals();
				scene.add( result );
            }
            //初始化页面加载
            function threeStart(){
                //初始化DOM对象
                initDOM();
                //初始化渲染器
                initThree();
                //初始化场景
                initScene();
                //初始透视化相机
                initCamera();
                //初始化光源
                initLight();
                //模型对象
                initObject();
                //初始化网格辅助线
                initGrid();
                //渲染
                //renderer.render(scene, camera);
                //实时动画
                animation();
                //监听鼠标滚动事件
                canvas.addEventListener('mousewheel', mousewheel, false);
            }
            function animation(){
                //相机围绕y轴旋转,并且保持场景中的物体一直再相机的视野中
                //实时渲染成像
                var timer = Date.now()*0.0001;
                camera.position.x = Math.cos(timer)*400;
                camera.position.z = Math.sin(timer)*400;
                camera.lookAt(scene.position);
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
	        //鼠标滑轮-鼠标上下滑轮实现放大缩小效果
	        function mousewheel(e) {
	            e.preventDefault();
	            //e.stopPropagation();
	            if (e.wheelDelta) {  //判断浏览器IE,谷歌滑轮事件
	                if (e.wheelDelta > 0) { //当滑轮向上滚动时
	                    fov -= (near < fov ? 1 : 0);
	                }
	                if (e.wheelDelta < 0) { //当滑轮向下滚动时
	                    fov += (fov < far ? 1 : 0);
	                }
	            } else if (e.detail) {  //Firefox滑轮事件
	                if (e.detail > 0) { //当滑轮向上滚动时
	                    fov -= 1;
	                }
	                if (e.detail < 0) { //当滑轮向下滚动时
	                    fov += 1;
	                }
	            }
	            //改变fov值,并更新场景的渲染
	            camera.fov = fov;
	            camera.updateProjectionMatrix();
	            renderer.render(scene, camera);
	            //updateinfo();
	        }
    </script>
</html>
posted @ 2017-01-12 15:53  Avenstar  阅读(3321)  评论(0编辑  收藏  举报