Threes.js入門篇之9 - 全景圖

allenjiao發表於2018-03-14

全景圖是一個當下非常流行的展示方式,在 VR | AR領域有廣泛應用。

       在三維內的 全景圖 通常是根據 滑鼠事件調整攝像機位置(在包圍球內旋轉),其基本思路一致,包圍球可以通過 球面、立方體來實現,在幾何上面貼上全景圖紋理,一個典型的全景紋理圖可能是下面這幾種:

    

       或者也有可能是多副圖的形式,組成一個Cube(根據實際的方式會有所不同)。

       概念就不解釋了,我們先來看下 多魚眼全景的展示效果(webgl_panorama_dualfisheye.html):

        

       參考程式碼:

[html] view plain copy
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3.     <head>  
  4.         <title>three.js webgl - dual fisheye panorama</title>  
  5.         <meta charset="utf-8">  
  6.         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">  
  7.         <style>  
  8.             body {  
  9.                 background-color: #000000;  
  10.                 margin: 0px;  
  11.                 overflow: hidden;  
  12.             }  
  13.   
  14.             #info {  
  15.                 position: absolute;  
  16.                 top: 0px; width: 100%;  
  17.                 color: #000000;  
  18.                 padding: 5px;  
  19.                 font-family:Monospace;  
  20.                 font-size:13px;  
  21.                 font-weight: bold;  
  22.                 text-align:center;  
  23.             }  
  24.   
  25.             a {  
  26.                 color: #0000ff;  
  27.             }  
  28.         </style>  
  29.     </head>  
  30.     <body>  
  31.   
  32.         <div id="container"></div>  
  33.         <div id="info">  
  34.             <a href="http://threejs.org" target="_blank">three.js webgl</a> - dualfisheye panorama.  
  35.         </div>  
  36.   
  37.         <script src="../build/three.js"></script>  
  38.   
  39.         <script>  
  40.   
  41.             var camera, scene, renderer;  
  42.   
  43.             var isUserInteracting = false,  
  44.             onMouseDownMouseX = 0onMouseDownMouseY = 0,  
  45.             lon = 0onMouseDownLon = 0,  
  46.             lat = 0onMouseDownLat = 0,  
  47.             phi = 0theta = 0,  
  48.             distance = 500;  
  49.   
  50.             init();  
  51.             animate();  
  52.   
  53.             function init() {  
  54.   
  55.                 var container, mesh;  
  56.   
  57.                 container = document.getElementById( 'container' );  
  58.   
  59.                 camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 2000 );  
  60.   
  61.                 scene = new THREE.Scene();  
  62.   
  63.                 var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 ).toNonIndexed();  
  64.                 geometry.scale( - 1, 1, 1 );  
  65.   
  66.                 // Remap UVs  
  67.   
  68.                 var normals = geometry.attributes.normal.array;  
  69.                 var uvs = geometry.attributes.uv.array;  
  70.   
  71.                 for ( var i = 0l = normals.length / 3; i < l; i ++ ) {  
  72.   
  73.                     var x = normals[ i * 3 + 0 ];  
  74.                     var y = normals[ i * 3 + 1 ];  
  75.                     var z = normals[ i * 3 + 2 ];  
  76.   
  77.                     if ( i < l / 2 ) {  
  78.   
  79.                         var correction = ( x == 0 && z == 0 ) ? 1 : ( Math.acos( y ) / Math.sqrt( x * x + z * z ) ) * ( 2 / Math.PI );  
  80.                         uvs[ i * 2 + 0 ] = x * ( 404 / 1920 ) * correction + ( 447 / 1920 );  
  81.                         uvs[ i * 2 + 1 ] = z * ( 404 / 1080 ) * correction + ( 582 / 1080 );  
  82.   
  83.                     } else {  
  84.   
  85.                         var correction = ( x == 0 && z == 0 ) ? 1 : ( Math.acos( - y ) / Math.sqrt( x * x + z * z ) ) * ( 2 / Math.PI );  
  86.                         uvs[ i * 2 + 0 ] = - x * ( 404 / 1920 ) * correction + ( 1460 / 1920 );  
  87.                         uvs[ i * 2 + 1 ] = z * ( 404 / 1080 ) * correction + ( 582 / 1080 );  
  88.   
  89.                     }  
  90.   
  91.                 }  
  92.   
  93.                 geometry.rotateZ( - Math.PI / 2 );  
  94.   
  95.                 //  
  96.   
  97.                 var texture = new THREE.TextureLoader().load( 'textures/ricoh_theta_s.jpg' );  
  98.                 texture.format = THREE.RGBFormat;  
  99.   
  100.                 var material   = new THREE.MeshBasicMaterial( { map: texture } );  
  101.   
  102.                 mesh = new THREE.Mesh( geometry, material );  
  103.                 scene.add( mesh );  
  104.   
  105.                 renderer = new THREE.WebGLRenderer();  
  106.                 renderer.setPixelRatio( window.devicePixelRatio );  
  107.                 renderer.setSize( window.innerWidth, window.innerHeight );  
  108.                 container.appendChild( renderer.domElement );  
  109.   
  110.                 document.addEventListener( 'mousedown', onDocumentMouseDown, false );  
  111.                 document.addEventListener( 'mousemove', onDocumentMouseMove, false );  
  112.                 document.addEventListener( 'mouseup', onDocumentMouseUp, false );  
  113.                 document.addEventListener( 'wheel', onDocumentMouseWheel, false );  
  114.   
  115.                 //  
  116.   
  117.                 window.addEventListener( 'resize', onWindowResize, false );  
  118.   
  119.             }  
  120.   
  121.             function onWindowResize() {  
  122.   
  123.                 camera.aspect = window.innerWidth / window.innerHeight;  
  124.                 camera.updateProjectionMatrix();  
  125.   
  126.                 renderer.setSize( window.innerWidth, window.innerHeight );  
  127.   
  128.             }  
  129.   
  130.             function onDocumentMouseDown( event ) {  
  131.   
  132.                 event.preventDefault();  
  133.   
  134.                 isUserInteracting = true;  
  135.   
  136.                 onPointerDownPointerX = event.clientX;  
  137.                 onPointerDownPointerY = event.clientY;  
  138.   
  139.                 onPointerDownLon = lon;  
  140.                 onPointerDownLat = lat;  
  141.   
  142.             }  
  143.   
  144.             function onDocumentMouseMove( event ) {  
  145.   
  146.                 if ( isUserInteracting === true ) {  
  147.   
  148.                     lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;  
  149.                     lat = ( onPointerDownPointerY - event.clientY ) * 0.1 + onPointerDownLat;  
  150.   
  151.                 }  
  152.   
  153.             }  
  154.   
  155.             function onDocumentMouseUp( event ) {  
  156.   
  157.                 isUserInteracting = false;  
  158.   
  159.             }  
  160.   
  161.             function onDocumentMouseWheel( event ) {  
  162.   
  163.                 distance += event.deltaY * 0.05;  
  164.   
  165.             }  
  166.   
  167.             function animate() {  
  168.   
  169.                 requestAnimationFrame( animate );  
  170.                 update();  
  171.   
  172.             }  
  173.   
  174.             function update() {  
  175.   
  176.                 if ( isUserInteracting === false ) {  
  177.   
  178.                     lon += 0.1;  
  179.   
  180.                 }  
  181.   
  182.                 lat = Math.max( - 85, Math.min( 85, lat ) );  
  183.                 phi = THREE.Math.degToRad( 90 - lat );  
  184.                 theta = THREE.Math.degToRad( lon - 180 );  
  185.   
  186.                 camera.position.x = distance * Math.sin( phi ) * Math.cos( theta );  
  187.                 camera.position.y = distance * Math.cos( phi );  
  188.                 camera.position.z = distance * Math.sin( phi ) * Math.sin( theta );  
  189.   
  190.                 camera.lookAt( scene.position );  
  191.   
  192.                 renderer.render( scene, camera );  
  193.   
  194.             }  
  195.   
  196.         </script>  
  197.     </body>  
  198. </html>  

相關文章