一、挖空原理说明
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 { 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>