Raycasting sphere to create a hyperlink

raycasting

#1

Hi,

I would like to create hyperlinks on the spheres, ,planets". Links will be referring to a div, made in index.html, to create a push-up content (just like when you click on hamburger icon in this site: http://serwer1814906.home.pl/LEM-01/lem_desktop.html). So every sphere will open another div.

I have created basic code, using raycaster, to make sphere earth as a hyperlink to a three.js homepage - but it doesn’t work. Can you help me with writing proper code for that?

Code comes here (it’s pretty long, I have made 6-spheres here):

// --- cleaning console --- //
console.clear();

// --- threeJS --- //
var renderer, scene, camera, distance, raycaster, projector, labelRenderer;

var container = document.getElementById('container');

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var distance = 400;


var clock = new THREE.Clock();
var textureLoader = new THREE.TextureLoader();

var earth, saturn, mars, jowish, mercury, jupiter, line;


init();
animate();



// -- basic initialization -- //
function init() {
	

	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.2, 25000);
	camera.position.set(100, 100, 2000);
	scene.add(camera);

	light = new THREE.PointLight(0xffffff, 1, 1000);
	light.position.set(150, 50, 100);
	light_two = new THREE.PointLight(0xffffff, 1, 1000);
	light_two.position.set(-100, 50, 500);
	light_three = new THREE.PointLight(0xffffff, 1, 1000);
	light_three.position.set(250, 800, 450);
	
	scene.add(light, light_two, light_three);

	createPlanet();

				

	var size = 10000, step = 70;

	var geometry = new THREE.Geometry();
	var material = new THREE.LineBasicMaterial({
		color: 0x404040,
		linewidth: 1
	});

	for ( var i = - size; i <= size; i += step){
		geometry.vertices.push(new THREE.Vector3( - size, - 0.04, i));
		geometry.vertices.push(new THREE.Vector3( size, - 0.04, i));

		geometry.vertices.push(new THREE.Vector3( i, - 0.04, - size));
		geometry.vertices.push(new THREE.Vector3( i, - 0.04, size));
	}

	var line = new THREE.Line( geometry, material, THREE.LinePieces);
	line.rotation.x = Math.PI / 2;
	scene.add(line);



	var curve = new THREE.SplineCurve( [
		new THREE.Vector2( -1000, -100 ),
		new THREE.Vector2( -500, -250 ),
		new THREE.Vector2( 10, -200 ),
		new THREE.Vector2( 50, -500 ),
		new THREE.Vector2( 1200, 0 )
	] );

	var points = curve.getPoints( 500 );
	var geometry = new THREE.BufferGeometry().setFromPoints( points );

	var material = new THREE.LineBasicMaterial( { 
		color : 0xffffff,
		linewidth: 2
	} );

				// Create the final object to add to the scene
	var splineObject = new THREE.Line( geometry, material );
	scene.add(splineObject);

	var curve = new THREE.SplineCurve( [
		new THREE.Vector2( -1500, 800 ),
		new THREE.Vector2( -500, 300 ),
		new THREE.Vector2( 220, 450 ),
		new THREE.Vector2( 300, 300 ),
		new THREE.Vector2( 1100, 600 )
	] );

	var points = curve.getPoints( 500 );
	var geometry = new THREE.BufferGeometry().setFromPoints( points );

	var material = new THREE.LineBasicMaterial( { 
		color : 0xffffff,
		linewidth : 2 
	} );

				// Create the final object to add to the scene
	var splineObject = new THREE.Line( geometry, material );
	scene.add(splineObject);


	renderer = new THREE.WebGLRenderer({
		antialias: true
	});
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize(window.innerWidth, window.innerHeight);
	renderer.setClearColor(0x000, 1);
	container.appendChild(renderer.domElement);
	document.body.appendChild( renderer.domElement );


	labelRenderer = new THREE.CSS2DRenderer();
	labelRenderer.setSize( window.innerWidth, window.innerHeight );
	labelRenderer.domElement.style.position = 'absolute';
	labelRenderer.domElement.style.top = 0;
	document.body.appendChild( labelRenderer.domElement );


	renderer.render(scene, camera);

	document.addEventListener('mousemove', onMouseMove, false);
	window.addEventListener('resize', onWindowResize, false);
}


function createPlanet() {


			var EARTH_RADIUS = 2;
			var SATURN_RADIUS = 2.5;
			var MARS_RADIUS = 2;
			var JOWISH_RADIUS = 2;
			var MERCURY_RADIUS = 2.5;
			var JUPITER_RADIUS = 3;


 			var earthGeometry = new THREE.SphereBufferGeometry( EARTH_RADIUS, 120, 120 );
			var earthMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 50,
					map: textureLoader.load( 'js/texture/planet2.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet2.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
			earth = new THREE.Mesh( earthGeometry, earthMaterial );
			earth.position.x = 320;
			earth.position.y = 500;
			earth.position.z = 200;
			earth.rotation.y = Math.random() * 2 * Math.PI;
			earth.scale.x = earth.scale.y = earth.scale.z = Math.random() * 50 + 10;
			earth.userData = { URL: "http://threejs.org"};
				
				scene.add( earth );


			var earthDiv = document.createElement( 'div' );
			earthDiv.className = 'label';
			earthDiv.textContent = '.Projekt-1';
			earthDiv.style.marginTop = '-1em';
			var earthLabel = new THREE.CSS2DObject( earthDiv );
			earthLabel.position.set( (EARTH_RADIUS + 2), 0, 0 );
			earth.add( earthLabel );


			var saturnGeometry = new THREE.SphereBufferGeometry( SATURN_RADIUS, 120, 120 );
			var saturnMaterial = new THREE.MeshPhongMaterial( {
					specular: 0xffffff,
					shininess: 5,
					map: textureLoader.load( 'js/texture/planet4.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet4.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					//normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
			saturn = new THREE.Mesh( saturnGeometry, saturnMaterial );
			saturn.position.x = 750;
			saturn.position.y = 450;
			saturn.position.z = 100;
			saturn.rotation.y = Math.random() * 2 * Math.PI;
			saturn.scale.x = saturn.scale.y = saturn.scale.z = Math.random() * 50 + 10;
				
				scene.add( saturn );


			var saturnDiv = document.createElement( 'div' );
			saturnDiv.className = 'label';
			saturnDiv.textContent = '.Projekt-2';
			saturnDiv.style.marginTop = '-1em';
			var saturnLabel = new THREE.CSS2DObject( saturnDiv );
			saturnLabel.position.set( 0, (SATURN_RADIUS + 0.5), 0 );
			saturn.add( saturnLabel );

			var marsGeometry = new THREE.SphereBufferGeometry( MARS_RADIUS, 120, 120 );
			var marsMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 50,
					map: textureLoader.load( 'js/texture/planet5.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet2.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					//normalScale: new THREE.Vector2( 0.95, 0.85 )
				} );
			mars = new THREE.Mesh( marsGeometry, marsMaterial );
			mars.position.x = -350;
			mars.position.y = 250;
			mars.position.z = 100;
			mars.rotation.y = Math.random() * 2 * Math.PI;
			mars.scale.x = mars.scale.y = mars.scale.z = Math.random() * 50 + 10;
				
			scene.add( mars );


			var marsDiv = document.createElement( 'div' );
			marsDiv.className = 'label';
			marsDiv.textContent = '.Projekt-3';
			marsDiv.style.marginTop = '-1em';
			var marsLabel = new THREE.CSS2DObject( marsDiv );
			marsLabel.position.set( 0, (MARS_RADIUS + 0.5), 0 );
			mars.add( marsLabel );

			var jowishGeometry = new THREE.SphereBufferGeometry( JOWISH_RADIUS, 120, 120 );
			var jowishMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 50,
					map: textureLoader.load( 'js/texture/planet7.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet2.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					//normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
			jowish = new THREE.Mesh( jowishGeometry, jowishMaterial );
			jowish.position.x = -600;
			jowish.position.y = -200;
			jowish.position.z = 100;
			jowish.rotation.y = Math.random() * 4 * Math.PI;
			jowish.scale.x = jowish.scale.y = jowish.scale.z = Math.random() * 50 + 10;
				
				scene.add( jowish );


			var jowishDiv = document.createElement( 'div' );
			jowishDiv.className = 'label';
			jowishDiv.textContent = '.Projekt-4';
			jowishDiv.style.marginTop = '-1em';
			var jowishLabel = new THREE.CSS2DObject( jowishDiv );
			jowishLabel.position.set( JOWISH_RADIUS, 2, 0 );
			jowish.add( jowishLabel );


			var mercuryGeometry = new THREE.SphereBufferGeometry( MERCURY_RADIUS, 120, 120 );
			var mercuryMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 50,
					map: textureLoader.load( 'js/texture/planet6.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet2.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
			mercury = new THREE.Mesh( mercuryGeometry, mercuryMaterial );
			mercury.position.x = 400;
			mercury.position.y = -500;
			mercury.position.z = 100;
			mercury.rotation.y = Math.random() * 2 * Math.PI;
			mercury.scale.x = mercury.scale.y = mercury.scale.z = Math.random() * 50 + 10;
				
				scene.add( mercury );


			var mercuryDiv = document.createElement( 'div' );
			mercuryDiv.className = 'label';
			mercuryDiv.textContent = '.Projekt-5';
			mercuryDiv.style.marginTop = '-1em';
			var mercuryLabel = new THREE.CSS2DObject( mercuryDiv );
			mercuryLabel.position.set( MERCURY_RADIUS, 2, 0 );
			mercury.add( mercuryLabel );

			var jupiterGeometry = new THREE.SphereBufferGeometry( JUPITER_RADIUS, 120, 120 );
			var jupiterMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 50,
					map: textureLoader.load( 'js/texture/planet8.jpg' ),
					specularMap: textureLoader.load( 'js/texture/planet2.jpg' ),
					normalMap: textureLoader.load( 'js/texture/planet2_NRM.png' ),
					normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
			jupiter = new THREE.Mesh( jupiterGeometry, jupiterMaterial );
			jupiter.position.x = 900;
			jupiter.position.y = -180;
			jupiter.position.z = 50;
			jupiter.rotation.y = Math.random() * 2 * Math.PI;
			jupiter.scale.x = jupiter.scale.y = jupiter.scale.z = Math.random() * 50 + 10;
			jupiter.userData = { URL: "http://stackoverflow.com"};
			scene.add( jupiter );


			var jupiterDiv = document.createElement( 'div' );
			jupiterDiv.className = 'label';
			jupiterDiv.textContent = '.Projekt-6';
			jupiterDiv.style.marginTop = '-1em';
			var jupiterLabel = new THREE.CSS2DObject( jupiterDiv );
			jupiterLabel.position.set( JUPITER_RADIUS, 2, 0 );
			jupiter.add( jupiterLabel );



}



// -- events -- //
function onMouseMove(event) {

	mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
	mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
	mouseX = event.clientX - window.innerWidth / 2;
	mouseY = event.clientY - window.innerHeight / 2;
	camera.position.x += (mouseX - camera.position.x) * 0.01;
	camera.position.y += (mouseY - camera.position.y) * 0.01;
	camera.lookAt(scene.position);

};

function onDocumentMouseDown(event) {
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);

    var intersects = raycaster.intersectObjects(earth);
    if (intersects.length > 0) {
    //get a link from the userData object
        window.open(intersects[0].object.userData.URL);
    }
};


function onWindowResize() {
	camera.aspect = window.innerWidth / window.innerHeight;
	renderer.setSize(window.innerWidth, window.innerHeight);
	labelRenderer.setSize( window.innerWidth, window.innerHeight );
	camera.updateProjectionMatrix();
};


// ---- //
function animate() {
	requestAnimationFrame(animate);
	var elapsed = clock.getElapsedTime();
	render();
};



// -- render all -- //
function render() {

	var timer = 0.00001 * Date.now();

	earth.rotation.z += Math.PI / 500;
	saturn.rotation.y += Math.PI / 500;
	mars.rotation.y += Math.PI / 500;
	jowish.rotation.z += Math.PI / 500;
	mercury.rotation.z += Math.PI / 500;
	jupiter.rotation.z += Math.PI / 700;

	

	renderer.render(scene, camera);
	labelRenderer.render( scene, camera );


};

#2

Have you tried changing the raycaster.intersectObjects to look through all the meshes, and not specifically earth?

e.g:

var intersects = raycaster.intersectObjects(scene.children, true);

Try and log the intersects variable to see what that contains.


#3

Yeah, that would be much better, to look for all meshes… I have changed it to scene.children, yet not working.
Should I group this spheres to one object? I’ve tried this, but I think I’m making some stupid mistake, so nothing works then.


#4
var intersects = raycaster.intersectObjects(scene.children, true);

Pay attention to the second parameter. Set it to true.