使用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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM