摘 要: 全景图是近年出现的一种新的交互式的虚拟场景表示方式,可以用相应的浏览器实现虚拟场景的漫游,具有很好的真实感和沉浸感。详细介绍了一种基于HTML5的全景图浏览器的实现原理,并给出了关键的HTML5代码。最终取得了良好的展示效果。
关键词: 全景图;展示;HTML5
全景图(Panorama)即用相机360°拍摄一组照片,然后用专业软件拼接成一个全景图像,通过计算机技术实现全方位互动式观看的真实场景还原展示方式。Apple公司推出的QuickTime VR第一次向大众展示了全景图像技术的视觉魅力。该系统采用与传统基于图形的建模过程截然不同的思路,利用图像或连续的视频为原始数据,经过处理形成全景图像,然后通过合适的空间模型将多幅图像组织成虚拟全景空间。近年来,基于全景图像的虚拟现实技术也得到了迅速发展,被广泛用于数字博物馆、虚拟旅游、房地产展示等虚拟漫游应用领域[1]。
全景图的制作流程包括全景图像采集、图像拼接以及全景图展示浏览3个步骤。目前,拼接完成后的全景图展示浏览通常利用特殊的播放软件(如Java、Quicktime、Flash)来体验它所提供的虚拟环境,若要发布到Internet,则需要在浏览器中加入这些程序的Plug-in程序[1-2]。但是以Plug-in形式运行的这些程序,存在严重的安全隐患和性能不佳等缺点。
HTML5是最新的Web标准,具有很多令人激动的新特性,其中用于绘画的Canvas元素为网页绘图及图像处理带来了很大的便捷。HTML5于2008年公布了一个草案,目前尚处于不断完善阶段。虽然速度缓慢,但对于互联网Web开发标准来说是一个巨大的飞跃。HTML5并非仅仅用于表示Web内容,在此平台上,视频、音频、图像、动画以及与设备的交互都将被标准化,解决了HTML4在Web应用功能上的欠缺。HTML5拥有全新的、更合理的tag,多媒体对象不在其他对象和embedtag中,而是有独立的音/视频tag,使Web向富媒体趋势发展;HTML5中的Canvas可以脱离Flash和Silverlight、Java Applet插件提供富动画,直接在浏览器显示图形或动画;HTML5提供了API接口,可以实现浏览器内编辑、拖放以及各种图形用户界面的能力;HTML5将使用CSS来呈现内容。随着HTML5的愈加成熟,目前新版本的浏览器如 Chrome、Firefox、Safari、Internet Explorer以及 Opera都已经支持了HTML5的某些特性,甚至现在的智能终端上的浏览器如UC浏览器、OperaHD等也开始支持HTML5[3-4]。
1 全景图浏览程序的设计思路
本文将采用HTML5程序实现全景图的浏览,直接嵌入到网页中,通过Web方式供用户浏览。设计过程分为以下3个步骤:
(1)获取数码照片。在场景中央将数码相机放于三角架上,调节三角架上的两个水平仪,使相机转动360°时大致保持在同一水平面上,每旋转一定角度拍摄一张照片,共拍摄15~20张照片。如果使用鱼眼镜头拍照,则只需要5张。图1所示为在某会议室内获取的照片。
(2)拼接全景图。将步骤(1)获取的照片导入到专业全景图拼接工具PTGui中,生成一幅全景图,如图2所示,具体步骤参考帮助文档。再使用Pano2VR转换为6张立方体面片,图3所示分别是后、右、前、左、上、下方向的图片。
(3)全景图展示。利用文本编辑器工具编写相应的展示全景图的js程序,嵌入到网页中,效果截图见图4,程序的关键代码见下一节。
2 全景浏览器的HTML5实现
Three.js是著名的轻量级Javascript 3D引擎,基于HTML5开发,可用于创建各种三维场景,包括了摄影机、光影、风格、材质等各种对象。使开发者可以轻松地开发复杂的三维场景。AlteredQualia是Three.js的主要代码贡献者之一。本文将利用Three.js来实现对全景图的展示。
(1)引用Three.js。
<script src="./js/Three.js"></script>
(2)创建场景、摄像机、画布等基础元素,部分代码如下:
var container, mesh;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 75,
window.innerWidth / window.innerHeight, 1, 1100 );
scene = new THREE.Scene();
scene.add( camera );
texture_placeholder = document.createElement( 'canvas' );
texture_placeholder.width = 128;
texture_placeholder.height = 128;
var context = texture_placeholder.getContext( '2d' );
context.fillStyle = 'rgb( 200, 200, 200 )';
context.fillRect( 0, 0, texture_placeholder.width,
texture_placeholder.height );
(3)创建立方体网格模型、渲染器。并把全景图片加载到网格模型上,然后再把网格模型放到场景中。实现了渲染函数,当鼠标等事件触发后,就要调用这个函数来调整摄像机和渲染场景。
var materials = [
loadTexture( 'px.jpg' ), // right
loadTexture( 'nx.jpg' ), // left
loadTexture( 'py.jpg' ), // top
loadTexture( 'ny.jpg' ), // bottom
loadTexture( 'pz.jpg' ), // back
loadTexture( 'nz.jpg' ) // front
];
mesh = new THREE.Mesh(new THREE.CubeGeometry
(300, 300, 300, 7, 7, 7, materials),
new THREE.MeshFaceMaterial() );
mesh.scale.x = - 1;
scene.add(mesh);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild( renderer.domElement);
function loadTexture( path ) {
var texture = new THREE.Texture(texture_placeholder);
var material = new THREE.MeshBasicMaterial
( { map: texture, overdraw: true } );
var image = new Image();
image.onload = function () {
texture.needsUpdate = true;
material.map.image = this;
render();
};
image.src = path;
return material;
}
function render() {
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = ( 90 - lat ) * Math.PI / 180;
theta = lon * Math.PI / 180;
target.x = 500 * Math.sin( phi ) * Math.cos(theta);
target.y = 500 * Math.cos( phi );
target.z = 500 * Math.sin( phi ) * Math.sin(theta);
camera.lookAt( target );
renderer.render( scene, camera );
}
(4)添加鼠标操控事件。程序代码如下:
document.addEventListener( 'mousedown',
onDocumentMouseDown, false );
document.addEventListener( 'mousemove',
onDocumentMouseMove, false );
document.addEventListener( 'mouseup',
onDocumentMouseUp, false );
function onDocumentMouseDown( event ) {
event.preventDefault();
isUserInteracting = true;
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting ) {
lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownPointerY )
* 0.1 + onPointerDownLat;
render();
}
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
render();
}
本文介绍了HTML5和基于HTML5的Three.js 3D引擎,提出了基于HTML5进行全景图像展示的设计思路及具体实现。实践证明,该方法展示交互效果良好。HTML5作为下一代HTML标准,将会带来更多的惊喜。
参考文献
[1] 邓杏杏,朱大明,杨袁聪.基于全景图的虚拟现实系统研究与探讨[J].地矿测绘,2009,25(1):26-28.
[2] 宋利,周源华,周军.一种全景图浏览器的JAVA实现算法[J].计算机应用与软件,2003,20(12):1-2.
[3] SHWETANK D.Taking your Web apps offline:a tale of Web storage,application cache and Web SQL[EB/OL]. (2011-03-22).http://dev.opera.corn/article/view/takingyou-Web-apps-offline- Web-Storage-appache-Websql/.
[4] CHRIS M,BRUCE L.New structural elements in HTML5 [EB/OL].(2010-12-21)[2011-04-15].http://dev.opera.com/artic1es/view/new-structural-elements-in.html5/.