Threes.js入门篇之9 - 全景图
全景图是一个当下非常流行的展示方式,在 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 UVs
- var 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>
Threes.js入门篇之9 - 全景图相关推荐
- Threes.js入门篇之6 - 场景漫游
THREE.js 支持两种形式的漫游,第一人称漫游(First Person) 和 飞行(Fly),可以分别参考 example 下的 "misc_fps.html" 和 &quo ...
- Threes.js入门篇之2 - Hello World
与OpenGL一样,Three.js 符合右手坐标系,X轴向右,Y轴向上,Z轴朝外: Three.js 的绘制流程可以描述为: 1. 生成 渲染器 - THREE.WebGLRenderer,并绑定C ...
- Threes.js入门篇之7 - 场景光照
Three.js 主要支持四种光源模式,分别是 环境光.点光源.平行光 和 聚光灯.另外有半球光源.面光源等,本节暂不涉及. 一. 环境光 Ambient Light:所有对象的整体光照模型,控制整 ...
- Threes.js入门篇之3 - 场景与相机
• Three.js 的场景 THREE.Scene 执行场景树管理,场景的创建只需要一句话: var scene = new THREE.Scene(); 场景常用操作包含: 1.scene.add ...
- Threes.js入门篇之5 - 场景操纵器Trackball
Three.js 提供了很多操纵器,example下也给了一些操纵器(也叫控制器)的例子,引用 js 可以参考 examples/js/controls/TrackballControls.js . ...
- Threes.js入门篇之4 - World View Projection
在三维世界,一个模型要想最终呈现到一个照片上,需要经过三次矩阵变换,这三个矩阵分别是: 模型矩阵(World) - 视图矩阵(View)- 投影矩阵(Projection) 一. 模型矩阵 将 局部坐 ...
- Threes.js入门篇之8 - 材质与纹理
材质是指几何对应的 颜色信息,想让一个对象最终呈现出你所希望的样子,其中最重要的一个因素就是材质. 来看一下例子 "canvas_material.html" [html] vie ...
- js入门篇--制作简单闪烁图片
js入门篇–制作闪烁图片 刚刚学习,大神勿喷,还请多多指点... <body "soccerOnload()" topmargin="0"> //o ...
- (转)web前端开发分享-css,js入门篇
关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...
最新文章
- Qtum量子链AUR开发工具包即日上线
- kotlin中学习笔记——null
- 计算机基础:离散数学和完备性
- 剑指offer---用两个栈实现队列
- BugkuCTF-Reverse题signin
- 商业分析在敏捷中的角色
- 我感到惭愧不已的飞鸽传书
- 容器编排技术 -- kubernetes 通过环境变量向容器暴露 Pod 信息
- Java使用String对象的split()方法分割字符串的小坑
- LSTM训练过程与参数解读
- 20190925 On Java8 第二十二章 枚举
- 【Emacs】Emacs for windows基本配置文件【转载】
- HDU 1465 不容易系列之一 (错排)
- 一款基于SpringCloudAlibaba从0到1手敲的商城项目mtg-shop
- 昆冶金计算机高考录取分数线,昆明冶金高等专科学校2020年录取分数线(附2018-2020年分数线)...
- 使用n2n实现内网访问
- srm32定时器的ETR功能
- 行为式验证码小侃,滑块验证码详解
- 微博数据爬虫——V影响力榜top100用户(一)
- 计算机考研复试之英语口语面试