主要研究three.js在3D場景中基本使用:畫一個簡單的房子、房子上畫門和玻璃、房間內放一個床、定義鼠標事件可以移動場景、動畫的使用等。
1.Three.js畫的一個簡單的房子,模擬地板以及四堵牆
准備素材:
3.jpg模擬地板
4.jpg模擬牆
代碼:
<!DOCTYPE html> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/OBJLoader.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> var scene,camera,webGLRenderer,stats; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ paintFloor(); paintWalls(40, 2, 10, 0, 0, -20, 1/2,0);//后面牆 paintWalls(40, 2, 10, 0, 0, 20, 1/2, 0);//前面牆 paintWalls(42, 2, 10, -20, 0, 0, 1/2, 0, 1/2);//左面牆 paintWalls(42, 2, 10, 20, 0, 0, 1/2, 0, 1/2);//右面牆 } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){ var loader = new THREE.TextureLoader; loader.load('./img/4.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ){ mesh.rotation.z = Math.PI * rotationZ; } scene.add(mesh); }); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); if(stats){ stats.update(); } } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
結果:
2.增加鼠標事件和鍵盤事件控制攝像頭進而模擬在房間內行走
控制器的使用,主要的控制器如下:
- 軌跡球控制器的使用:(使用鼠標改變場景以及在界面實時顯示相機的位置)
可用的鼠標事件如下:
(1)引入相關JS:
<script type="text/javascript" src="../libs/TrackballControls.js"></script>
(2)創建控制器並綁定到相機上
//鼠標控制動畫相關組件
var trackballControls, clock;
function initTrackballControls(){
clock = new THREE.Clock();
trackballControls = new THREE.TrackballControls(camera);
trackballControls.rotateSpeed = 1.0;
trackballControls.zoomSpeed = 1.0;
trackballControls.panSpeed = 1.0;
// trackballControls.noZoom=false;
// trackballControls.noPan=false;
trackballControls.staticMoving = true;
// trackballControls.dynamicDampingFactor=0.3;
}
(3)攝像機的位置更新在render循環中完成
function render() {
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
//鼠標事件
var delta = clock.getDelta();
trackballControls.update(delta);
logCameraPosition();
if(stats){
stats.update();
}
}
function logCameraPosition(){
var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
$("#logInfo").html(logInfo);
}
如果禁用鼠標縮放可以將noZoom設為true。
代碼如下:
<!DOCTYPE html> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/OBJLoader.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <script type="text/javascript" src="../libs/TrackballControls.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var trackballControls, clock; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ paintFloor(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面牆 paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面牆 initTrackballControls(); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); //鼠標事件 var delta = clock.getDelta(); trackballControls.update(delta); logCameraPosition(); if(stats){ stats.update(); } } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initTrackballControls(){ clock = new THREE.Clock(); trackballControls = new THREE.TrackballControls(camera); trackballControls.rotateSpeed = 1.0; trackballControls.zoomSpeed = 1.0; trackballControls.panSpeed = 1.0; // trackballControls.noZoom=false; // trackballControls.noPan=false; trackballControls.staticMoving = true; // trackballControls.dynamicDampingFactor=0.3; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){ var loader = new THREE.TextureLoader; loader.load('./img/4.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ){ mesh.rotation.z = Math.PI * rotationZ; } scene.add(mesh); }); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
效果:
- 軌道控制器(支持鼠標和鍵盤事件)
其支持的事件如下:
(1)使用的類庫是:https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js
(2)初始化control即可
function initOrbitControls(){ controls = new THREE.OrbitControls(camera,webGLRenderer.domElement); controls.minDistance = 1; controls.maxDistance = 5000; }
代碼如下:
<!DOCTYPE html> <!--房子中間加個床,采用封裝過的API實現 (采用軌道控制器)--> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs2/three.js"></script> <script type="text/javascript" src="../libs2/OBJLoader.js"></script> <script type="text/javascript" src="../libs2/stats.js"></script> <script type="text/javascript" src="../libs2/WebGL.js"></script> <script type="text/javascript" src="../libs2/OrbitControls.js"></script> <script type="text/javascript" src="../libs2/onEvent.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var controls; //事件相關 var threeOnEvent; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.setPixelRatio(window.devicePixelRatio); webGLRenderer.setClearColor(0xEEEEEE, 1.0); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ initEvent(); paintFloor(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面牆 paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面牆 initOrbitControls(); paintBed(); } var paintBed = function(){ var textures = []; loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front loadBedTextures(textures, 3, "./img/bedplate.jpg");//back loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom loadBedTextures(textures, 5, "./img/mattess.jpg"); //top //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(10, 10, 5); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery, textures); mesh.position.set(0, 2.5, 0) mesh.rotation.x = Math.PI * 1/2; //綁定一些數據 mesh.tags = "bed"; mesh.userData.ID = 1; mesh.name = "myBed"; //增加事件(點擊事件) mesh.on('click',function(m) {//m代表mesh對象 alert('1'); }) // hover eventLisener(鼠標懸浮事件) mesh.on('hover',function(m) { // mouse enter the mesh alert(m.name + " " + m.tags + " " + mesh.userData.ID); },function(m) { // mouse leave out the mesh }); scene.add(mesh); } function loadBedTextures(textures, index, url){ textures[index] = new THREE.MeshBasicMaterial({ map : new THREE.TextureLoader().load(url) }); } function initEvent(){ threeOnEvent = new THREE.onEvent(scene,camera); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); //鼠標事件 logCameraPosition(); if(stats){ stats.update(); } //更新事件 threeOnEvent.update(); } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initOrbitControls(){ controls = new THREE.OrbitControls(camera,webGLRenderer.domElement); controls.minDistance = 1; controls.maxDistance = 5000; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){ var loader = new THREE.TextureLoader; loader.load('./img/4.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ){ mesh.rotation.z = Math.PI * rotationZ; } scene.add(mesh); }); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
3.場景中添加一個床 (六面體),並且自定義鼠標點擊事件懸浮在床上的時候彈出框
這個都采用的是git上封裝過的JS庫來實現的,參考git地址:https://github.com/mrdoob/three.js/
three.js的事件機制用到的是onEvent,參考:https://github.com/YoneChen/three-onEvent
也通過tags、userData、name進行數據的綁定。
代碼如下:
<!DOCTYPE html> <!--房子中間加個床,采用封裝過的API實現--> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs2/three.js"></script> <script type="text/javascript" src="../libs2/OBJLoader.js"></script> <script type="text/javascript" src="../libs2/stats.js"></script> <script type="text/javascript" src="../libs2/WebGL.js"></script> <script type="text/javascript" src="../libs2/TrackballControls.js"></script> <script type="text/javascript" src="../libs2/onEvent.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var trackballControls, clock; //事件相關 var threeOnEvent; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.setPixelRatio(window.devicePixelRatio); webGLRenderer.setClearColor(0xEEEEEE, 1.0); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ initEvent(); paintFloor(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面牆 paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面牆 initTrackballControls(); paintBed(); } var paintBed = function(){ var textures = []; loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front loadBedTextures(textures, 3, "./img/bedplate.jpg");//back loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom loadBedTextures(textures, 5, "./img/mattess.jpg"); //top //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(10, 10, 5); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery, textures); mesh.position.set(0, 2.5, 0) mesh.rotation.x = Math.PI * 1/2; //綁定一些數據 mesh.tags = "bed"; mesh.userData.ID = 1; mesh.name = "myBed"; //增加事件(點擊事件) mesh.on('click',function(m) {//m代表mesh對象 alert('1'); }) // hover eventLisener(鼠標懸浮事件) mesh.on('hover',function(m) { // mouse enter the mesh alert(m.name + " " + m.tags + " " + mesh.userData.ID); },function(m) { // mouse leave out the mesh }); scene.add(mesh); } function loadBedTextures(textures, index, url){ textures[index] = new THREE.MeshBasicMaterial({ map : new THREE.TextureLoader().load(url) }); } function initEvent(){ threeOnEvent = new THREE.onEvent(scene,camera); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); //鼠標事件 var delta = clock.getDelta(); trackballControls.update(delta); logCameraPosition(); if(stats){ stats.update(); } //更新事件 threeOnEvent.update(); } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initTrackballControls(){ clock = new THREE.Clock(); trackballControls = new THREE.TrackballControls(camera); trackballControls.rotateSpeed = 1.0; trackballControls.zoomSpeed = 1.0; trackballControls.panSpeed = 1.0; // trackballControls.noZoom=false; // trackballControls.noPan=false; trackballControls.staticMoving = true; // trackballControls.dynamicDampingFactor=0.3; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){ var loader = new THREE.TextureLoader; loader.load('./img/4.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ){ mesh.rotation.z = Math.PI * rotationZ; } scene.add(mesh); }); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
結果:
4. 在牆上挖一個玻璃
在牆上挖玻璃需要用到ThreeBSP.js,實際上就是求兩個物體的差集之后進行添加;如果需要挖一個門,需要做的操作是:先在牆上求牆和門的差集得到一個mesh對象添加到scene中,並將門也添加到scene即可實現。
代碼如下:
<!DOCTYPE html> <!--房子中間加個床,采用封裝過的API實現--> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs2/three.js"></script> <script type="text/javascript" src="../libs2/OBJLoader.js"></script> <script type="text/javascript" src="../libs2/stats.js"></script> <script type="text/javascript" src="../libs2/WebGL.js"></script> <script type="text/javascript" src="../libs2/TrackballControls.js"></script> <script type="text/javascript" src="../libs2/onEvent.js"></script> <script type="text/javascript" src="../libs2/ThreeBSP.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var trackballControls, clock; //事件相關 var threeOnEvent; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.setPixelRatio(window.devicePixelRatio); webGLRenderer.setClearColor(0xEEEEEE, 1.0); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ initEvent(); paintFloor(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面牆 //添加帶玻璃的牆 var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面牆 var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false); var resultMesh = createResultMesh(wallMesh, windowMesh, true); scene.add(resultMesh); initTrackballControls(); paintBed(); } function createResultMesh(srcMesh, destMesh, addDest){ var srcBSP = new ThreeBSP(srcMesh); var destBSP = new ThreeBSP(destMesh); var resultBSP = srcBSP.subtract(destBSP); var result = resultBSP.toMesh(srcMesh.material); result.geometry.computeFaceNormals(); result.geometry.computeVertexNormals(); if(addDest){ scene.add(destMesh); } return result; } var paintBed = function(){ var textures = []; loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front loadBedTextures(textures, 3, "./img/bedplate.jpg");//back loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom loadBedTextures(textures, 5, "./img/mattess.jpg"); //top //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(10, 10, 5); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery, textures); mesh.position.set(0, 2.5, 0) mesh.rotation.x = Math.PI * 1/2; //綁定一些數據 mesh.tags = "bed"; mesh.userData.ID = 1; mesh.name = "myBed"; //增加事件(點擊事件) mesh.on('click',function(m) {//m代表mesh對象 alert('1'); }) // hover eventLisener(鼠標懸浮事件) mesh.on('hover',function(m) { // mouse enter the mesh alert(m.name + " " + m.tags + " " + mesh.userData.ID); },function(m) { // mouse leave out the mesh }); scene.add(mesh); } function loadBedTextures(textures, index, url){ textures[index] = new THREE.MeshBasicMaterial({ map : new THREE.TextureLoader().load(url) }); } function initEvent(){ threeOnEvent = new THREE.onEvent(scene,camera); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); //鼠標事件 var delta = clock.getDelta(); trackballControls.update(delta); logCameraPosition(); if(stats){ stats.update(); } //更新事件 threeOnEvent.update(); } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initTrackballControls(){ clock = new THREE.Clock(); trackballControls = new THREE.TrackballControls(camera); trackballControls.rotateSpeed = 1.0; trackballControls.zoomSpeed = 1.0; trackballControls.panSpeed = 1.0; // trackballControls.noZoom=false; // trackballControls.noPan=false; trackballControls.staticMoving = true; // trackballControls.dynamicDampingFactor=0.3; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var loader = new THREE.TextureLoader; var texture = new THREE.TextureLoader().load('./img/4.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var material = new THREE.MeshBasicMaterial({ color : 0x58ACFA, transparent : true, opacity : 0.6 }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
結果:
5.Tween動畫實現旋轉床
tween.js是一款可生成平滑動畫效果的js動畫庫。你只需要告訴tween你想修改什么值,以及動畫結束時它的最終值是什么,動畫花費多少時間等信息,tween引擎就可以計算從開始動畫點到結束動畫點之間值,來產生平滑的動畫效果。 其詳細用法參考: https://www.cnblogs.com/jiangxiaobo/p/6207264.html
代碼:
<!DOCTYPE html> <!--房子中間加個床,采用封裝過的API實現,動態改變床的位置--> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs2/three.js"></script> <script type="text/javascript" src="../libs2/OBJLoader.js"></script> <script type="text/javascript" src="../libs2/stats.js"></script> <script type="text/javascript" src="../libs2/WebGL.js"></script> <script type="text/javascript" src="../libs2/TrackballControls.js"></script> <script type="text/javascript" src="../libs2/onEvent.js"></script> <script type="text/javascript" src="../libs2/ThreeBSP.js"></script> <script type="text/javascript" src="../libs2/tween.min.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var trackballControls, clock; //事件相關 var threeOnEvent; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.setPixelRatio(window.devicePixelRatio); webGLRenderer.setClearColor(0xEEEEEE, 1.0); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ initEvent(); paintFloor(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面牆 //添加帶玻璃的牆 var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面牆 var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false); var resultMesh = createResultMesh(wallMesh, windowMesh, true); scene.add(resultMesh); initTrackballControls(); paintBed(); } function createResultMesh(srcMesh, destMesh, addDest) { var srcBSP = new ThreeBSP(srcMesh); var destBSP = new ThreeBSP(destMesh); var resultBSP = srcBSP.subtract(destBSP); var result = resultBSP.toMesh(srcMesh.material); result.geometry.computeFaceNormals(); result.geometry.computeVertexNormals(); if(addDest){ scene.add(destMesh); } return result; } var paintBed = function(){ var textures = []; loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front loadBedTextures(textures, 3, "./img/bedplate.jpg");//back loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom loadBedTextures(textures, 5, "./img/mattess.jpg"); //top //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(10, 10, 5); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery, textures); mesh.position.set(0, 2.5, 0) mesh.rotation.x = Math.PI * 1/2; //綁定一些數據 mesh.tags = "bed"; mesh.userData.ID = 1; mesh.name = "myBed"; //增加事件(點擊事件) mesh.on('click',function(m) {//m代表mesh對象 alert('1'); }) // hover eventLisener(鼠標懸浮事件) mesh.on('hover',function(m) { // mouse enter the mesh alert(m.name + " " + m.tags + " " + mesh.userData.ID); },function(m) { // mouse leave out the mesh }); scene.add(mesh); startAnnotation(mesh); } function startAnnotation(mesh) { var indexNumber = { indexNumber : 0 }; var currentTween = new TWEEN.Tween(indexNumber).to({ indexNumber : 2 },5000); currentTween.easing(TWEEN.Easing.Sinusoidal.InOut); currentTween.repeat(60);//重復次數 currentTween.yoyo(true);//結束之后反方向反彈 currentTween.onUpdate(function(){ var indexNumber = this.indexNumber; //改變床的旋轉角度實現旋轉床 mesh.rotation.z = Math.PI * indexNumber; //也可以根據數字的范圍進行一些其他動畫(比如說實現閃爍效果等) if(indexNumber < 1){ } else { } }); currentTween.start(); } function loadBedTextures(textures, index, url){ textures[index] = new THREE.MeshBasicMaterial({ map : new THREE.TextureLoader().load(url) }); } function initEvent(){ threeOnEvent = new THREE.onEvent(scene,camera); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); //鼠標事件 var delta = clock.getDelta(); trackballControls.update(delta); logCameraPosition(); if(stats){ stats.update(); } //更新事件 threeOnEvent.update(); //動畫 TWEEN.update(); } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initTrackballControls(){ clock = new THREE.Clock(); trackballControls = new THREE.TrackballControls(camera); trackballControls.rotateSpeed = 1.0; trackballControls.zoomSpeed = 1.0; trackballControls.panSpeed = 1.0; // trackballControls.noZoom=false; // trackballControls.noPan=false; trackballControls.staticMoving = true; // trackballControls.dynamicDampingFactor=0.3; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var loader = new THREE.TextureLoader; var texture = new THREE.TextureLoader().load('./img/4.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var material = new THREE.MeshBasicMaterial({ color : 0x58ACFA, transparent : true, opacity : 0.6 }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
結果:
床會一直旋轉。。。
6. 增加一個玻璃天窗,完成最終的房子
旋轉床、鼠標和鍵盤對場景縮放。
<!DOCTYPE html> <!--房子中間加個床,采用封裝過的API實現,動態改變床的位置--> <html> <head> <title>myHouse</title> <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script> <script type="text/javascript" src="../libs2/three.js"></script> <script type="text/javascript" src="../libs2/OBJLoader.js"></script> <script type="text/javascript" src="../libs2/stats.js"></script> <script type="text/javascript" src="../libs2/WebGL.js"></script> <script type="text/javascript" src="../libs2/OrbitControls.js"></script> <script type="text/javascript" src="../libs2/onEvent.js"></script> <script type="text/javascript" src="../libs2/ThreeBSP.js"></script> <script type="text/javascript" src="../libs2/tween.min.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <div id="logInfo" style="position: absolute; top: 0px; left: 20%; width: 50%; padding: 5px;"></div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //基本組件 var scene, camera, webGLRenderer, stats; //鼠標控制動畫相關組件 var controls; //事件相關 var threeOnEvent; function init() { stats = initStats(); scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.x = 20; camera.position.y = 40; camera.position.z = 50; camera.lookAt(scene.position); scene.add(camera); // create a render and set the size webGLRenderer = new THREE.WebGLRenderer({ antialias : true, alpha:true }); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.setPixelRatio(window.devicePixelRatio); webGLRenderer.setClearColor(0xEEEEEE, 1.0); webGLRenderer.shadowMapEnabled = true; // add spotlight for the shadows var spotLight = new THREE.PointLight(0xffffff); spotLight.position.set(30, 40, 50); scene.add(spotLight); initObjects(); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); render(); } function initObjects(){ initEvent(); paintFloor(); paintCell(); //畫牆--一般y取高度的1/2 paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面牆 paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面牆 paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面牆 //添加帶玻璃的牆 var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面牆 var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false); var resultMesh = createResultMesh(wallMesh, windowMesh, true); scene.add(resultMesh); initOrbitControls(); paintBed(); } function createResultMesh(srcMesh, destMesh, addDest) { var srcBSP = new ThreeBSP(srcMesh); var destBSP = new ThreeBSP(destMesh); var resultBSP = srcBSP.subtract(destBSP); var result = resultBSP.toMesh(srcMesh.material); result.geometry.computeFaceNormals(); result.geometry.computeVertexNormals(); if(addDest){ scene.add(destMesh); } return result; } var paintBed = function(){ var textures = []; loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front loadBedTextures(textures, 3, "./img/bedplate.jpg");//back loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom loadBedTextures(textures, 5, "./img/mattess.jpg"); //top //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(10, 10, 5); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery, textures); mesh.position.set(0, 2.5, 0) mesh.rotation.x = Math.PI * 1/2; //綁定一些數據 mesh.tags = "bed"; mesh.userData.ID = 1; mesh.name = "myBed"; //增加事件(點擊事件) mesh.on('click',function(m) {//m代表mesh對象 alert('1'); }) // hover eventLisener(鼠標懸浮事件) mesh.on('hover',function(m) { // mouse enter the mesh alert(m.name + " " + m.tags + " " + mesh.userData.ID); },function(m) { // mouse leave out the mesh }); scene.add(mesh); startAnnotation(mesh); } function startAnnotation(mesh) { var indexNumber = { indexNumber : 0 }; var currentTween = new TWEEN.Tween(indexNumber).to({ indexNumber : 2 },5000); currentTween.easing(TWEEN.Easing.Sinusoidal.InOut); currentTween.repeat(60);//重復次數 currentTween.yoyo(true);//結束之后反方向反彈 currentTween.onUpdate(function(){ var indexNumber = this.indexNumber; //改變床的旋轉角度實現旋轉床 mesh.rotation.z = Math.PI * indexNumber; //也可以根據數字的范圍進行一些其他動畫(比如說實現閃爍效果等) if(indexNumber < 1){ } else { } }); currentTween.start(); } function loadBedTextures(textures, index, url){ textures[index] = new THREE.MeshBasicMaterial({ map : new THREE.TextureLoader().load(url) }); } function initEvent(){ threeOnEvent = new THREE.onEvent(scene,camera); } function render() { requestAnimationFrame(render); webGLRenderer.render(scene, camera); logCameraPosition(); if(stats){ stats.update(); } //更新事件 threeOnEvent.update(); //動畫 TWEEN.update(); } function logCameraPosition(){ var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z; $("#logInfo").html(logInfo); } function initOrbitControls(){ controls = new THREE.OrbitControls(camera,webGLRenderer.domElement); controls.minDistance = 1; controls.maxDistance = 5000; } var paintFloor = function (){ var loader = new THREE.TextureLoader; loader.load('./img/3.jpg', function (texture) { //x和y超過圖片像素之后重復繪制圖片 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1, 1); //設置材質是雙面材質 var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建普通的平面幾何體 var gemotery = new THREE.PlaneGeometry(40,40); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 0; mesh.rotation.x = Math.PI/2; scene.add(mesh); }); } var paintCell = function (){ //設置材質是雙面材質 var material = new THREE.MeshBasicMaterial({ color : 0x58ACFA, transparent : true, opacity : 0.6 }); //創建普通的平面幾何體 //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(40, 40, 1); //創建網格對象 var mesh = new THREE.Mesh(gemotery,material); mesh.position.y = 9; mesh.rotation.x = Math.PI/2; scene.add(mesh); } var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var loader = new THREE.TextureLoader; var texture = new THREE.TextureLoader().load('./img/4.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //設置地板重復繪制的密度是1 * 1 texture.repeat.set(1,1); var material = new THREE.MeshLambertMaterial({ map : texture, side : THREE.DoubleSide }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){ var material = new THREE.MeshBasicMaterial({ color : 0x58ACFA, transparent : true, opacity : 0.6 }); //創建長方體幾何體 var gemotery = new THREE.BoxGeometry(width, depth, height); //創建網格對象以及進行位置的設定 var mesh = new THREE.Mesh(gemotery,material); mesh.position.set(x,y,z) mesh.rotation.x = Math.PI * rotationX; mesh.rotation.y = Math.PI * rotationY; if(rotationZ) { mesh.rotation.z = Math.PI * rotationZ; } if(addMesh) { scene.add(mesh); } return mesh; } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } window.onload = init; </script> </body> </html>
結果:
git源碼地址: https://github.com/qiao-zhi/threejsDemo
總結:
一般物體的y取的是高度是1/2;
旋轉角度的單位是Math.PI (乘以對應的角度,1就是180度,0.5就是90度)