Recently, more and more you can stumble upon a circular panorama on the Internet. Take for example the same
cheese house . This spectacular little thing may soon become commonplace for sites of restaurants, hotels, hotels, etc. However, what to do if there are problems with flash on the computer? This is a real situation that has arisen in my work due to the tight security policy of the IT department.
In this small article I will tell you about the difficulties that I encountered on the way of creating an interactive panorama on WebGL + THREE.js.
Define the requirements for the panorama:
- We use WebGL, since Canvas panoramas are just awful, and new IE is supported ;
- View panoramas by dragging the mouse button;
- Active elements designed to pay attention and communicate information;
- Ability to view multiple panoramas on one page.
To understand how to implement this, I propose to present the following: “We are in the center of a sphere, on the inner surface of which a panorama texture is applied. We are a camera that can turn and look up or down. There are elements on the inner surface of the sphere ("at" the surface, as it turned out), and when we hover over them, a window appears with information. "
Sphere
There are at least two options for the implementation of the panorama: cubic and spherical. I chose spherical, since the placement of visually identical active elements implies an equidistant distance from the center. For the prototype, take an existing
sample of the panorama from the site of the library developer. He completely suits us with one exception. This is a sphere with a texture turned inside out. It is hard to imagine how it might look.
')
mesh.scale.x = -1;
Unfortunately, this one detail puts a complete cross over the possibility of adding elements. The bottom line is that to get at least some information about an object in space using a pointer, you have to “shoot” the ray (Raycaster) from the pointer point in the direction of the vector, only in this case the ray will not hit the wall of the sphere, because the camera ( start) is not inside. This is done because the texture is stretched only from the outside, but now it is possible to fix this simply by adding the
side property to the object of the sphere's matter:
mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/2294472375_24a3b8ef46_o.jpg' ) side: THREE.BackSide } ) );
By the way, this is a typical object creation in the world of THREE.js. As a rule, the geometry of the object is created, the material (texture), and then added to the scene.
Items
Now we need to think about what those active elements will be of themselves. Ideally, they should be flat sprites, always displayed facing the camera. Yes Yes exactly :)

But here we are in for a surprise. In THREE.js, there are two “classes” for rendering:
WebGLRenderer and
CanvasRenderer . And two types of simple objects:
Particle (particle) and
Sprite . WebGL works with Sprite, and Canvas with Particle. In this case, we need WebGL, and the Sprite object does not have volume in space. That is, it is
impossible to get on it with the mouse.
Well, let's take and simulate these same sprites using a 3D object with a plane geometry (PlaneGeometry):
var itemGeometry = new THREE.PlaneGeometry(35, 35), pointMapHovered = THREE.ImageUtils.loadTexture( "img/information-hover.PNG" ), pointMap = THREE.ImageUtils.loadTexture( "img/information-unhover.PNG" ); point = new THREE.Mesh( itemGeometry, new THREE.MeshBasicMaterial({ map: pointMap, transparent:true
I want to draw your attention to why this is the case: the geometry of the point and the texture are cached, and the material will be created anew each time. The fact is that when you hover the mouse over a point, we will replace the texture with a brighter one, for example, but if MeshBasicMaterial is cached and is common to everyone, everyone will light up. As for mouse hovering, everything is simple - take it
from here .
The last important part that caused difficulties is the recalculation of the coordinates of the panorama area on the page to the coordinates of the WebGL space for precise selection of points. Visually, the elements are visible, but their coordinates on the page do not coincide with the coordinates of the 3D space. There is an
answer to StackOverFlow.
Data
Since it is supposed to be able to view many panoramas on one page, it is better to put all the data in JSON. Like that:
{ "points": [ { "coords": { "x": 302.0282521739266, "y": -32.30522607035554, "z": 389.86440214968525 }, "header": "", "body": "." }, ], "texture": "panorama.jpg", "name": " " }
To view different panoramas, we will replace the texture of the sphere, delete points and build new ones according to the coordinates.
What happened
I invite you to see
DemoI apologize in advance for the materials used. Description of the bakery plant # 7, as well as its name was invented from the head, any coincidences are random and have no connection with reality.
link