一、挖空原理说明
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 οnlοad="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>