1. 程式人生 > >three.js全景視訊

three.js全景視訊

小生最近學習three.js,將three.js官網提供的網站例項翻譯翻譯,共同學習。接下來翻譯一下 webgl_video_panorama_equirectangular.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - equirectangular video panorama</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				background-color: #000000;
				margin: 0px;
				overflow: hidden;
			}

			#info {
				position: absolute;
				top: 0px; width: 100%;
				color: #ffffff;
				padding: 5px;
				font-family:Monospace;
				font-size:13px;
				font-weight: bold;
				text-align:center;
			}

			a {
				color: #ffffff;
			}
		</style>
	</head>
	<body>

		<div id="container"></div>

		<script src="../build/three.js"></script>

		<script>
		    //原理:通過three.js建立一個球模型,將視訊貼到球模型上,通過矩陣變換將視訊貼到模型內部,觀察點不動,通過滑鼠拖動,改變相機的位置來實現全景視訊的觀看。
		    //當然需要將模型新增到場景中,通過渲染器不斷的渲染 
			var camera, scene, renderer;
			var texture_placeholder,//多餘程式碼
			isUserInteracting = false,//滑鼠按下的標誌,開始滑鼠沒有按下為false
			onMouseDownMouseX = 0, onMouseDownMouseY = 0,
			lon = 0,//記錄水平方向的偏角,即水平角
            onMouseDownLon = 0,//多餘程式碼
			lat = 0,//記錄豎直方向的偏角,即仰俯角
            onMouseDownLat = 0,//多餘程式碼
			phi = 0,//在three.js中 phi代表與xoy平面的夾角,即仰俯角
            theta = 0, //theta代表與xoy平面的夾角, 即水平角
			distance = 500,//觀察點到相機的距離,即球半徑
			onPointerDownPointerX = 0,//記錄滑鼠按下瞬間的螢幕x值
			onPointerDownPointerY = 0,//記錄滑鼠按下瞬間的螢幕x值
			onPointerDownLon = 0,//記錄上一次滑鼠水平移動的角度.
			onPointerDownLat = 0;//記錄上一次滑鼠豎直移動的角度.

			init();
			animate();

			function init() {

				var container, mesh;

				container = document.getElementById( 'container' );

				camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1100);//透視投影,即遠景相機,模仿人眼
				camera.target = new THREE.Vector3( 0, 0, 0 );//初始化相機觀察點

				scene = new THREE.Scene();//初始化場景

				var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );//建立半徑為500,水平垂直分割面分別為60,40的緩衝球面
				geometry.scale(  -1, 1, 1 );//進行縮放,進行矩陣變換,將視訊貼在球內表面

				var video = document.createElement( 'video' );
				video.width = 640;
				video.height = 360;
				video.loop = true;//視訊是否迴圈
				video.muted = true;//是否關閉音訊
				video.src = "textures/pano.webm";
				video.setAttribute( 'webkit-playsinline', 'webkit-playsinline' );
				video.play();

				var texture = new THREE.VideoTexture( video );//視訊紋理
				texture.minFilter = THREE.LinearFilter;//紋理在縮小時的過濾方式,預設THREE.LinearMipMapNearestFilter選擇最臨近的mip層,並執行線性過濾
				texture.format = THREE.RGBFormat;//畫素資料的顏色格式, 預設為THREE.RGBAFormat,還有以下可選引數
			    //THREE.AlphaFormat = 1019;	//GL_ALPHA 	Alpha 值
			    //THREE.RGBFormat = 1020;		//Red, Green, Blue 三原色值
			    //THREE.RGBAFormat = 1021;	//Red, Green, Blue 和 Alpha 值
			    //THREE.LuminanceFormat = 1022;	//灰度值
			    //THREE.LuminanceAlphaFormat = 1023;	//灰度值和 Alpha 值

				var material = new THREE.MeshBasicMaterial({ map: texture });//基礎網孔材料

				mesh = new THREE.Mesh( geometry, material );

				scene.add( mesh );

				renderer = new THREE.WebGLRenderer();//webGL渲染器
				renderer.setPixelRatio(window.devicePixelRatio);//返回當前裝置的畫素比
				renderer.setSize( window.innerWidth, window.innerHeight );
				container.appendChild( renderer.domElement );

				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
				document.addEventListener( 'wheel', onDocumentMouseWheel, false );

				//

				window.addEventListener( 'resize', onWindowResize, false );

			}

			function onWindowResize() {
                //自適應
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

			}
            //滑鼠按下
			function onDocumentMouseDown( event ) {

				event.preventDefault();//阻止預設行為

				isUserInteracting = true;

				onPointerDownPointerX = event.clientX;
				onPointerDownPointerY = event.clientY;

				onPointerDownLon = lon;
				onPointerDownLat = lat;
                
			}

			function onDocumentMouseMove( event ) {
				if ( isUserInteracting === true ) {
                    //按下並移動,計算移動的角度
					lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
					lat = (  onPointerDownPointerY -event.clientY ) * 0.1 + onPointerDownLat;
				}

			}
            //滑鼠擡起
			function onDocumentMouseUp( event ) {

				isUserInteracting = false;

			}
            //滑鼠滾輪操作,改變相機位置
			function onDocumentMouseWheel( event ) {

				distance += event.deltaY * 0.05;

			}

			function animate() {

				requestAnimationFrame( animate );
				update();

			}

			function update() {
                //將角度轉化為弧度
				lat = Math.max( - 85, Math.min( 85, lat ) );
				phi = THREE.Math.degToRad( 90 - lat );
				theta = THREE.Math.degToRad( lon );
                //球面座標計算公式,相當於相機在球面移動,觀察點不動
				camera.position.x = distance * Math.sin( phi ) * Math.cos( theta );
				camera.position.y = distance * Math.cos( phi );
				camera.position.z = distance * Math.sin( phi ) * Math.sin( theta );

				camera.lookAt( camera.target );

				/*
				// distortion
				camera.position.copy( camera.target ).negate();
				*/
                //渲染
				renderer.render( scene, camera );

			}