『壹』 如何實現Three.js中的模型世界軸旋轉和自旋轉
ThingJS 使用角度控制物體旋轉。
通常使用如下屬性和介面控制物體旋轉:
在世界坐標系下,使用angles屬性來設置或訪問旋轉信息。
obj.angles = [0,45,0] //設置世界坐標系Y軸向旋轉45角度在父物體坐標系下,使用 localAngles 屬性來設置或訪問旋轉信息。
obj.localAngles = [0,45,0] //設置父物體坐標系Y軸向旋轉45角度在自身坐標系下,使用如下介面方法:
//使用rotate,可輸入角度和軸向。設置沿給定軸向轉一定角度,傳入的旋轉軸是自身坐標系下的軸方向 obj.rotate( 45, [0,1,0]) //沿自身x軸向旋轉,等同於 obj.rotate( 30, [1,0,0]) obj.rotateX(30) //沿自身y軸向旋轉,等同於 obj.rotate( 90, [0,1,0]) obj.rotateY(90)我們還可以使用lookAt介面方法,使得物體的觀察方向一直對准一個位置或物體
//讓物體面向[0,1,0],該坐標是在世界坐標下obj.lookAt( [0,1,0]) //讓物體一直面向攝影機obj.lookAt( app.camera ) //讓物體一直面向一個物體obj.lookAt( obj ) //讓物體一直面向一個物體,同時物體沿自身Y軸向再旋轉90度obj.lookAt( obj, [0,90,0] ) //取消lookAt功能obj.lookAt( null )查看示例網頁鏈接
正常情況下,子物體會隨著父物體旋轉而一起旋轉,如果想控制子物體不隨父物體旋轉,可通過設置子物體的inheritAngles屬性為 false 而實現。
『貳』 Three.js 實現VR看房
准備工作:
1、three.js https://threejs.org/build/three.js
2、搭建項目環境 我使用的live-server
3、720°全景圖
目錄結構
mian.js
; (function () {
// 在THREEjs中,渲染一個3d世界的必要因素是場景(scene)、相機(camera)、渲染器(renderer)。渲染出一個3d世界後,可以往裡面增加各種各樣的物體、光源等,形成一個3d世界。
// 創建場景
const scene = new THREE.Scene()
// 創建透視攝像銷卜機
// new THREE.PrespectiveCamera('視角', '指投影窗口長寬比例', '表示重距離攝像機多遠的位置開始渲染', '表示距離攝像機多遠的位置截止渲染');
// 正交攝像機是一個矩形可視區域,物體只有在這個區域內才是可見的物體無論距離攝像機是遠或事近,物體都會被渲染成一個大小。一般應用場景是2.5d游戲如跳一跳、機械模型
// 透視攝像機是最常用的攝像機類型,模擬人眼的視覺,近大遠小(透視)。Fov表示的是視角,Fov越大,表示眼睛睜猜斗鉛得越大,離得越遠,看得更多。如果是需要模擬現實,基本都是用這個相機
const camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 1000)
// 創建ThreeJs渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
// 設置渲染器場景的大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 渲染器添加到頁面
document.body.appendChild(renderer.domElement)
// 上面的確是把3d世界畫出來了,只是沒有什麼東西。在three.js中,我們需要增加光源和mesh
// mesh即是網格。在計算機里,3D世界是由點組成的,無數的面拼接成各種形狀的物體。這種模型叫做網格模型。一條線是兩個點組成,一個面是3個點組成,一個物體由多個3點組成的面組成
// 而網格(mesh)又是由幾何體(geometry)和材質(material)構成的
// 我們所能想像到的幾何體,框架都自帶了,我們只需要調用對應的幾何體構造函數即可創建。幾何體的創建方法都是new,如BoxBuffer:const geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
// 創建的時候,一般定義了渲染一個 3D 物體所需要的基本數據:Face 面、Vertex 頂點等信穗好息。THREE.xxxGeometry指的是框架自帶的幾何體,不同幾何體所需要的參數有所不同,大概是width、height、radius、depth、segment、detail、angle等屬性
// 更多geometry相關api
// BufferGeometry和Geometry有什麼不同?就實現的效果來說它們都是一樣,但是BufferGeometry的多了一些頂點屬性,且性能較好。對於開發者來說,Geometry對象屬性少體驗更好。THREE解析幾何體對象的時候,如果是Geometry,則會把對象轉換成ufferGeometry對象,再進行下一步渲染
// 創建幾何模型
// THREE.BoxGeometry('x軸長', 'y軸長', 'z軸長')
const geometry = new THREE.SphereGeometry(50, 256, 256);
// 創建貼圖 720°圖片,需要硬體支持 這里的圖是借用網路上面的
const texture = new THREE.TextureLoader().load('https://qhyxpicoss.kujiale.com/r/2019/07/01/_3000x4000.jpg?x-oss-process=image/resize,m_fill,w_1600,h_920/format,webp')
//創建材質
const material = new THREE.MeshBasicMaterial({ map: texture })
// 渲染球體的雙面
material.side = THREE.DoubleSide;
// 創建網格對象
const mesh = new THREE.Mesh(geometry, material)
// 網格對象填加到場景
scene.add(mesh)
// 攝像機放球體中心
camera.position.set(-0.3, 0, 0)
// 控制器(如果報錯去github自己拷貝一個OrbitControls.js https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js )
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => {
renderer.render(scene, camera);
});
controls.minDistance = 1;
controls.maxDistance = 2000;
controls.enablePan = false;
// 調整max
controls.minDistance = 1 // controls.maxDistance = 200;
controls.maxDistance = 2
function animate () {
requestAnimationFrame(animate)
renderer.render(scene, camera)
}
animate()
window.onresize = function () {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
})()
『叄』 three.js 怎樣綁定陀螺儀
three.js 綁定陀螺儀實現例子如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<script>
<div id="CanvasBody">
<input id="onDevice" type="button" value="開啟陀螺儀">
</div>
<!-- 滑鼠控制 (OrbitControls.js) -->
<script>
THREE.OrbitControls=function(object,domElement){return}event.preventDefault();event.stopPropagation();handleMouseWheel(event);scope.dispatchEvent(startEvent);scope.dispatchEvent(endEvent)}function onKeyDown(event){if(scope.enabled===false||scope.enableKeys===false||scope.enablePan===false){return}handleKeyDown(event)}function onTouchStart(event){if(scope.enabled===false){return}switch(event.touches.length){case 1:if(scope.enableRotate===false){return}handleTouchStartRotate(event);state=STATE.TOUCH_ROTATE;break;case 2:if(scope.enableZoom===false){return}handleTouchStartDolly(event);state=STATE.TOUCH_DOLLY;break;case 3:if(scope.enablePan===false)
</script>
<!-- 控制陀螺儀 (DeviceOrientationControls.js) -->
<!-- 代碼 -->
<script>
"use strict";
(function (CanvasBody, _window) {
var Scene = void 0,
Camera = void 0,
Renderer = void 0,
FpsStats = void 0,
AnimateFrame = void 0,
Controls = void 0,
Devices = void 0;
var onDevice = document.getElementById("onDevice");
var isDeviceing = 0;
/* 初始化函數 */
function initScene() {
Scene = new THREE.Scene();
}
// 初始化照相機
function initCamera() {
Camera = new THREE.PerspectiveCamera(60, CanvasBody.clientWidth / CanvasBody.clientHeight, 1, 3000);
Camera.position.set(1, 0, 0);
Camera.lookAt({ x: 200, y: 0, z: 0 });
}
// 初始化渲染器
function initRenderer() {
Renderer = new THREE.WebGLRenderer();
Renderer.setSize(CanvasBody.clientWidth, CanvasBody.clientHeight);
Renderer.setClearColor(0x000000, 1);
CanvasBody.appendChild(Renderer.domElement);
}
// 初始化監視器
function initFpsStats() {
FpsStats = new Stats();
CanvasBody.appendChild(FpsStats.domElement);
FpsStats.domElement.style.cssText = "position: absolute;top: 0;left: 0;";
}
// 初始化控制器
function initControls() {
Controls = new THREE.OrbitControls(Camera);
}
// 初始化陀螺儀
function initDevices() {
Devices = new THREE.DeviceOrientationControls(Camera);
}
/* 窗口改變事件 */
function windowChange() {
initCamera();
Renderer.setSize(CanvasBody.clientWidth, CanvasBody.clientHeight);
initDevices();
initControls();
}
/* 控制陀螺儀 */
function controlDevice(event) {
if (isDeviceing === 0) {
isDeviceing = 1;
onDevice.value = "關閉陀螺儀";
} else {
isDeviceing = 0;
onDevice.value = "開啟陀螺儀";
}
}
/* 動畫 */
function animate(time) {
FpsStats.begin();
Renderer.clear();
isDeviceing === 0 ? Controls.update() : Devices.update();
Renderer.render(Scene, Camera);
FpsStats.end();
AnimateFrame = requestAnimationFrame(animate);
}
/* 初始化 */
function init() {
// 初始化
initScene();
initCamera();
initRenderer();
initFpsStats();
initControls();
initDevices();
// 初始化綁定陀螺儀
Devices.connect();
_window.addEventListener("resize", windowChange, false);
onDevice.addEventListener("click", controlDevice, false);
AnimateFrame = requestAnimationFrame(animate);
}
init();
/* 場景內物體 */
(function () {
var r = Math.sqrt(5000 * 1827 / 4 / Math.PI);
var texture = THREE.ImageUtils.loadTexture("http://cdn.attach.w3cfuns.com/notes/pics/201606/14/141100b7m85b4k8kb3337z.jpg", {}, function () {
var geometry = new THREE.SphereGeometry(r, 100, 100);
var material = new THREE.MeshLambertMaterial({
map: texture,
side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(geometry, material);
Scene.add(mesh);
mesh.position.set(0, 0, 0);
var al = new THREE.AmbientLight(0xffffff);
Scene.add(al);
});
})();
})(document.getElementById("CanvasBody"), window);
</script>
</body>
</html>