Threes.js入门篇之9

来源:互联网 发布:淘宝新势力周报名入口 编辑:程序博客网 时间:2024/06/10 20:15

       全景图是一个当下非常流行的展示方式,在 VR | AR领域有广泛应用。

       在三维内的 全景图 通常是根据 鼠标事件调整摄像机位置(在包围球内旋转),其基本思路一致,包围球可以通过 球面、立方体来实现,在几何上面贴上全景图纹理,一个典型的全景纹理图可能是下面这几种:

    

       或者也有可能是多副图的形式,组成一个Cube(根据实际的方式会有所不同)。

       概念就不解释了,我们先来看下 多鱼眼全景的展示效果(webgl_panorama_dualfisheye.html):

        

       参考代码:

<!DOCTYPE html><html lang="en"><head><title>three.js webgl - dual fisheye 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: #000000;padding: 5px;font-family:Monospace;font-size:13px;font-weight: bold;text-align:center;}a {color: #0000ff;}</style></head><body><div id="container"></div><div id="info"><a href="http://threejs.org" target="_blank">three.js webgl</a> - dualfisheye panorama.</div><script src="../build/three.js"></script><script>var camera, scene, renderer;var isUserInteracting = false,onMouseDownMouseX = 0, onMouseDownMouseY = 0,lon = 0, onMouseDownLon = 0,lat = 0, onMouseDownLat = 0,phi = 0, theta = 0,distance = 500;init();animate();function init() {var container, mesh;container = document.getElementById( 'container' );camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 2000 );scene = new THREE.Scene();var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 ).toNonIndexed();geometry.scale( - 1, 1, 1 );// Remap UVsvar normals = geometry.attributes.normal.array;var uvs = geometry.attributes.uv.array;for ( var i = 0, l = normals.length / 3; i < l; i ++ ) {var x = normals[ i * 3 + 0 ];var y = normals[ i * 3 + 1 ];var z = normals[ i * 3 + 2 ];if ( i < l / 2 ) {var correction = ( x == 0 && z == 0 ) ? 1 : ( Math.acos( y ) / Math.sqrt( x * x + z * z ) ) * ( 2 / Math.PI );uvs[ i * 2 + 0 ] = x * ( 404 / 1920 ) * correction + ( 447 / 1920 );uvs[ i * 2 + 1 ] = z * ( 404 / 1080 ) * correction + ( 582 / 1080 );} else {var correction = ( x == 0 && z == 0 ) ? 1 : ( Math.acos( - y ) / Math.sqrt( x * x + z * z ) ) * ( 2 / Math.PI );uvs[ i * 2 + 0 ] = - x * ( 404 / 1920 ) * correction + ( 1460 / 1920 );uvs[ i * 2 + 1 ] = z * ( 404 / 1080 ) * correction + ( 582 / 1080 );}}geometry.rotateZ( - Math.PI / 2 );//var texture = new THREE.TextureLoader().load( 'textures/ricoh_theta_s.jpg' );texture.format = THREE.RGBFormat;var material   = new THREE.MeshBasicMaterial( { map: texture } );mesh = new THREE.Mesh( geometry, material );scene.add( mesh );renderer = new THREE.WebGLRenderer();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() {if ( isUserInteracting === false ) {lon += 0.1;}lat = Math.max( - 85, Math.min( 85, lat ) );phi = THREE.Math.degToRad( 90 - lat );theta = THREE.Math.degToRad( lon - 180 );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( scene.position );renderer.render( scene, camera );}</script></body></html>

2 0