Open Earth View - Tutorial

From OpenStreetMap Wiki
Jump to navigation Jump to search

Navigation

Introduction

The goal is to show how we can easily create a navigation system around the earth easily in web and 3D context.

Environment

We'll rely massively on three.js library and its OrbitControls example

Sources

[oev-navigation]

Hack the system

We'll modify three.js OrbitControls source code just a little bit to get "panUp()" and "panLeft()" methods publicly available to override them from our main page.

Add this:

	this.panLeft = panLeft;
	this.PanUp = panUp;

And replace function calls by their public methods:

#                               panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
#                               panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
                               scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
                               scope.panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );

And now, back to the main html page and three.js 3D scene: Put earth on the scene:

				loader.load( 'https://github.com/mrdoob/three.js/raw/dev/examples/textures/planets/earth_atmos_4096.jpg', function ( texture ) {
				    geometry = new THREE.SphereGeometry( R, 32, 32 );
   					material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
					earth = new THREE.Mesh( geometry, material );
					earth.position.z = -R;
					earth.updateMatrix();
					scene.add( earth );
				} );

And make the earth itself move around itself:

				controls = new THREE.OrbitControls( camera, renderer.domElement );
				controls.mouseButtons = { LEFT: THREE.MOUSE.RIGHT, MIDDLE: THREE.MOUSE.MIDDLE, RIGHT: THREE.MOUSE.LEFT };
# (...)
				controls.panLeft = function ( distance ) {
					earth.rotation.y += (distance / R) * (Math.cos(controls.getAzimuthalAngle())) / ( Math.max (0.2, Math.cos(earth.rotation.x)));
					theta = -(distance / R) * (Math.sin(controls.getAzimuthalAngle()));
					earth.rotation.x = Math.max(Math.min(earth.rotation.x + theta, Math.PI / 2), -Math.PI / 2);
				};

				controls.panUp = function ( distance ) {
					earth.rotation.y += (distance / R) * (Math.sin(controls.getAzimuthalAngle())) / ( Math.max (0.2, Math.cos(earth.rotation.x)));
					theta = (distance / R) * (Math.cos(controls.getAzimuthalAngle()));
					earth.rotation.x = Math.max(Math.min(earth.rotation.x + theta, Math.PI / 2), -Math.PI / 2);
				};

Demo

Screenshot:

Screenshot OEV navigation threejs.png