Search code examples
javascriptthree.jspolyhedra

Three.js polygon/polyhedron name or title


Here is a sample code of my page. I want to get name of object, when user clicks it. And it works well with cube or sphere, but fails with polygon. You may watch console logs to see clicks responds. What should I do to get polygon name on click?

<html> 
<head> 
	<title>Моё 3</title> 
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<style>
		body { margin: 0; }
		canvas { width: 100%; height: 100% }
	</style> 
</head> 
<body>
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
	<script src="http://stemkoski.github.io/Three.js/js/Three.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Detector.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Stats.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/OrbitControls.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.KeyboardState.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.FullScreen.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.WindowResize.js"></script>
<script>
/*
	Three.js "tutorials by example"
	Author: Lee Stemkoski
	Date: July 2013 (three.js v59dev)
*/

// MAIN
var polyhedronShape, polyhedronPts = [], cube, mesh;
// standard global variables
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();

// custom global variables
var targetList = [];
var projector, mouse = { x: 0, y: 0 };

init();
animate();

// FUNCTIONS 		
function init() 
{
	// SCENE
	scene = new THREE.Scene();
	// CAMERA
	var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
	var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
	scene.add(camera);
	camera.position.set(0,150,400);
	camera.lookAt(scene.position);	
	// RENDERER
	if ( Detector.webgl )
		renderer = new THREE.WebGLRenderer( {antialias:true} );
	else
		renderer = new THREE.CanvasRenderer(); 
	renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
	container = document.getElementById( 'ThreeJS' );
	container.appendChild( renderer.domElement );
	// EVENTS
	THREEx.WindowResize(renderer, camera);
	THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
	// CONTROLS
	controls = new THREE.OrbitControls( camera, renderer.domElement );
	// STATS
	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.bottom = '0px';
	stats.domElement.style.zIndex = 100;
	container.appendChild( stats.domElement );
	// LIGHT
	var light = new THREE.PointLight(0xffffff);
	light.position.set(0,250,0);
	scene.add(light);
	// FLOOR
	var floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
	floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; 
	floorTexture.repeat.set( 10, 10 );
	var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
	var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
	var floor = new THREE.Mesh(floorGeometry, floorMaterial);
	floor.position.y = -0.5;
	floor.rotation.x = Math.PI / 2;
	scene.add(floor);
	// SKYBOX/FOG
	var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
	var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
	var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
	scene.add(skyBox);
	
	////////////
	// CUSTOM //
	////////////

	
	//////////////////////////////////////////////////////////////////////

	// this material causes a mesh to use colors assigned to faces
	var faceColorMaterial = new THREE.MeshBasicMaterial( 
	{ color: 0xffffff, vertexColors: THREE.FaceColors } );
	
	var sphereGeometry = new THREE.SphereGeometry( 80, 32, 16 );
	for ( var i = 0; i < sphereGeometry.faces.length; i++ ) 
	{
		face = sphereGeometry.faces[ i ];	
		face.color.setRGB( 0, 0, 0.8 * Math.random() + 0.2 );		
	}
	var sphere = new THREE.Mesh( sphereGeometry, faceColorMaterial );
	sphere.name = "Sphere";
	sphere.title = "Magic sphere";
	sphere.position.set(0, 50, 0);
	scene.add(sphere);
	
	targetList.push(sphere);







	
	// Create an array of materials to be used in a cube, one for each side
	var cubeMaterialArray = [];
	// order to add materials: x+,x-,y+,y-,z+,z-
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff3333 } ) );
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff8800 } ) );
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xffff33 } ) );
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x33ff33 } ) );
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x3333ff } ) );
	cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x8833ff } ) );
	var cubeMaterials = new THREE.MeshFaceMaterial( cubeMaterialArray );
	// Cube parameters: width (x), height (y), depth (z), 
	//        (optional) segments along x, segments along y, segments along z
	var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
	// using THREE.MeshFaceMaterial() in the constructor below
	//   causes the mesh to use the materials stored in the geometry
	cube = new THREE.Mesh( cubeGeometry, cubeMaterials );
	cube.name = "Cube";
	cube.title = "Cube to do";
	cube.position.set(-100, 50, -50);
	scene.add( cube );		
	targetList.push(cube);


	
	
	
	
	// polyhedron

				polyhedronPts.push( new THREE.Vector2 ( -100, 600 ) );
				polyhedronPts.push( new THREE.Vector2 ( 300, 600 ) );
				polyhedronPts.push( new THREE.Vector2 ( 600, -100 ) );
				
				polyhedronShape = new THREE.Shape( polyhedronPts );

				var extrudeSettings = {amount: 20}; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5
				
				var geometry = new THREE.ExtrudeGeometry( polyhedronShape, extrudeSettings );

				polyhedron = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshBasicMaterial( { color: 0x00cc00 } ), new THREE.MeshBasicMaterial( { color: 0xff3333, wireframe: true, transparent: true } ) ] );
				//geometry.computeVertexNormals();
				polyhedron.name  = "Polyhedron";
				polyhedron.title = "Polyhedron is nice";
				polyhedron.position.set( 0, -333, 0 );
				//polyhedron.rotation.set( 0, 0, 100 );
				//polyhedron.scale.set( 1, 1, 1 );
				scene.add(polyhedron);
				targetList.push(polyhedron);
	
	
	
	
	
	//////////////////////////////////////////////////////////////////////
	
	// initialize object to perform world/screen calculations
	projector = new THREE.Projector();
	
	// when the mouse moves, call the given function
	document.addEventListener( 'mousedown', onDocumentMouseDown, false );
	
}

function onDocumentMouseDown( event ) 
{
	// the following line would stop any other event handler from firing
	// (such as the mouse's TrackballControls)
	// event.preventDefault();
	
	//console.log("Click.");
	
	// update the mouse variable
	mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
	mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
	
	// find intersections

	// create a Ray with origin at the mouse position
	//   and direction into the scene (camera direction)
	var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
	projector.unprojectVector( vector, camera );
	var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );

	// create an array containing all objects in the scene with which the ray intersects
	var intersects = ray.intersectObjects( targetList, true );
	
	// if there is one (or more) intersections
	if ( intersects.length > 0 )
	{
		console.log(intersects[0]);
		//console.log("Hit @ " + toString( intersects[0].point ) );
		console.log("Hit @ " + intersects[0].object.name);
		// change the color of the closest face.
		intersects[ 0 ].face.color.setRGB( 0.8 * Math.random() + 0.2, 0, 0 ); 
		intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
	}

}

function toString(v) { return "[ " + v.x + ", " + v.y + ", " + v.z + " ]"; }

function animate() 
{
    requestAnimationFrame( animate );
	render();		
	update();
}

function update()
{
	if ( keyboard.pressed("z") ) 
	{ 
		// do something
	}
	
	controls.update();
	stats.update();
}

function render() 
{
	renderer.render( scene, camera );
}

</script>

</body>
</html>


Solution

  • The call to THREE.SceneUtils.createMultiMaterialObject() (to create your polyhedron) returns a THREE.Object3D where the call to THREE.Mesh() (to create your sphere and cube) returns a THREE.Mesh. So they are different entities but you treat them the same. If instead you call:

        polyhedron = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x00cc00 } ) );
    

    then you can get the name of your polyhedron, since now polyhedron is of type THREE.Mesh()

    Otherwise you would have to parse the children of the polyhedron (since it is a THREE.Object3D())