Threejs实现全景图功能

可以利用Threejs中的立方体或者球体实现全景图功能,把立方体或球体当成天空盒子,将无缝衔接的图片贴上,看起来就像在一个场景中,相机一般放置在中央,只要离边缘足够远就看不出是立方体或球体,但如果超出边界就能看到他们。Threejs也有官方的全景图实例:

https://threejs.org/examples/?q=pano#webgl_panorama_cube

https://threejs.org/examples/?q=pano#css3d_panorama

下面的实现代码在以上实例webgl_panorama_cube的基础上修改,去掉了OrbitControls对视角的控制,改用鼠标拖动事件控制天空盒的旋转,鼠标滚轮控制相机的FOV。

1、立方体实现

立方体6个面要贴上6个方向的图片,这6个图片如下所示

Threejs实现全景图功能_第1张图片

图片加载的顺序是正X(px.jpg),负X(nx.jpg),正Y(py.jpg),负Y(ny.jpg),正Z(pz.jpg)和负Z(nz.jpg),将他们分别赋给6个材质的贴图,然后作为立方体skyBox的材质,因为相机在skyBox的内部,而内部的面不会显示,所以要将X轴或者Z轴的放大倍数变为负数,这样才能看到内部,scale.z=-1时相当于将Z轴正向的面移到Z轴负方向上。

var materials = [];
var texturepx = new THREE.TextureLoader().load( 'cubetexture/px.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: texturepx} ) );
var texturenx = new THREE.TextureLoader().load( 'cubetexture/nx.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: texturenx} ) );	
var texturepy = new THREE.TextureLoader().load( 'cubetexture/py.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: texturepy} ) );
var textureny = new THREE.TextureLoader().load( 'cubetexture/ny.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: textureny} ) );
var texturepz = new THREE.TextureLoader().load( 'cubetexture/pz.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: texturepz} ) );
var texturenz = new THREE.TextureLoader().load( 'cubetexture/nz.jpg' );
materials.push( new THREE.MeshBasicMaterial( { map: texturenz} ) );

var skyBox = new THREE.Mesh( new THREE.BoxBufferGeometry( 100, 100, 100 ), materials );
skyBox.geometry.scale( 1, 1, - 1 );

在鼠标按下的mousemove事件中旋转skyBox(也可以旋转相机视角),旋转速度可以自己调节

var bMouseDown = false;
var x = -1;
var y =-1;
container.onmousedown=function(event){
	x=event.clientX;
	y=event.clientY;
	bMouseDown = true;
}
container.onmouseup=function(event){
    bMouseDown = false;
}
container.onmousemove=function(event){
	if(bMouseDown){
		skyBox.rotation.y += -0.005*(event.clientX-x);
		skyBox.rotation.x += -0.005*(event.clientY-y);
		if(skyBox.rotation.x>Math.PI/2)
		{
			skyBox.rotation.x = Math.PI/2
		}
		if(skyBox.rotation.x<-Math.PI/2)
		{
			skyBox.rotation.x = -Math.PI/2
		}
		x=event.clientX;
		y=event.clientY;
	}
}

在mousewheel事件中改变camera的FOV值

container.onmousewheel=function(event){
    if(event.wheelDelta!=0){
	    camera.fov+=event.wheelDelta>0?1:-1;
	    if(camera.fov>150)
	    {
		    camera.fov=150;
	    }
	    else if(camera.fov < 30)
	    {
		    camera.fov = 30;
	    }
	    camera.updateProjectionMatrix();
	}
}

如果要禁掉右键菜单可以在body标签加上οncοntextmenu="return false"

完整代码如下



	
		three.js cube panorama
		
		
	
	
		

运行结果

2、球体实现

下面这张图片将6个面合成到一张图片中,这样的图片也可以由球体来实现

Threejs实现全景图功能_第2张图片

当然也要球体的UV设置正确才能正常展示,Threejs中的SphereBufferGeometry/SphereGeometry可以直接使用,球体是用多面体来近似,面数越多越接近真实球体,性能也会随着面数增多而下降,SphereBufferGeometry的第二和第三个参数分别表示水平方向和垂直方向的段数,第一个参数是球体的半径,只要不超过相机的远截面值即可。

var material = new THREE.MeshBasicMaterial();
var texture = new THREE.TextureLoader().load( 'pano.jpg' );
material.map = texture;

var skyBox= new THREE.Mesh(new THREE.SphereBufferGeometry(100, 100, 100),material);
skyBox.geometry.scale( 1, 1, -1 );

其他的与立方体的实现差不多,完整代码如下



	
		three.js sphere panorama
		
		
	
	
		

 

你可能感兴趣的:(Threejs)