I am trying to make draggable objects, as seen in this example: https://www.script-tutorials.com/demos/467/index.html
The objects which should be draggable are in the array objectMoverLines.
I have added a plane to my scene with the following code:
plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(500, 500, 8, 8), new THREE.MeshBasicMaterial({color: 0x248f24, alphaTest: 0}));
plane.visible = false;
scene.add(plane);
The problem occurs under the onDocumentMouseDown function. For some reason, if the planes visibility is set to false (plane.visible = false), then at a certain point, intersectsobjmovers will not be populated. If the plane's visibility is set to true, however, it will work fine (but obviously, that causes a huge plane to be in the way of everything):
function onDocumentMouseDown(event) {
// Object position movers
var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
vector.unproject(camera);
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersectsobjmovers = raycaster.intersectObjects(objectMoverLines);
if (intersectsobjmovers.length > 0) {
console.log('clicking an object mover');
// Disable the controls
controls.enabled = false;
// Set the selection - first intersected object
objmoverselection = intersectsobjmovers[0].object;
// Calculate the offset
var intersectsobjmovers = raycaster.intersectObject(plane);
// At this point, intersectsobjmovers does not include any items, even though
// it should (but it does work when plane.visible is set to true...)
offset.copy(intersectsobjmovers[0].point).sub(plane.position);
} else {
controls.enabled = true;
}
}
Also, this is what I currently have under the onDocumentMouseMove function:
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
// Get 3D vector from 3D mouse position using 'unproject' function
var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
vector.unproject(camera);
// Set the raycaster position
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
if (objmoverselection) {
// Check the position where the plane is intersected
var intersectsobjmovers = raycaster.intersectObject(plane);
// Reposition the object based on the intersection point with the plane
objmoverselection.position.copy(intersectsobjmovers[0].point.sub(offset));
} else {
// Update position of the plane if need
var intersectsobjmovers = raycaster.intersectObjects(objectMoverLines);
if (intersectsobjmovers.length > 0) {
// var lookAtVector = new THREE.Vector3(0,0, -1);
// lookAtVector.applyQuaternion(camera.quaternion);
plane.position.copy(intersectsobjmovers[0].object.position);
plane.lookAt(camera.position);
}
}
requestAnimationFrame( render );
}
try this:
plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(500, 500, 8, 8),
new THREE.MeshBasicMaterial( {
color: 0x248f24, alphaTest: 0, visible: false
}));
scene.add(plane);
Related
I'm a total newbie with Threejs.
I've got this dice prototype working as intended. The user can grab it and throw it. What I want to do now is determine which side of the dice is touching the ground. The prototype is using Three.js with Cannon.js for the physics.
I tried attaching invisible cubes to each side and confirm which invisible cube is intersecting with the ground but I could not get that to work.
I've also got collision detection working but as far as I can figure, there is no way to determine which side of the cube is facing the ground.
Could you please show me a method I could use to determine which side of the cube is facing/touching the ground?
Any help would be appreciated.
Code
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>Beginning my Three.js Journey</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="container"></div>
<div id="msgbox"></div>
<script type="module">
import * as CANNON from './cannon-es.js'
import * as THREE from 'https://unpkg.com/three#0.122.0/build/three.module.js'
import Stats from 'https://unpkg.com/three#0.122.0/examples/jsm/libs/stats.module.js'
// three.js variables
const msgBox = document.getElementById('msgbox')
let camera, scene, renderer, stats
let movementPlane
let clickMarker
let raycaster
let cubeMesh
let dice
let floor
// cannon.js variables
let world
let jointBody
let jointConstraint
let cubeBody
let isDragging = false
// To be synced
const meshes = []
const bodies = []
var diceSize = 1
initThree()
initCannon()
animate()
function initThree() {
// Camera
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.5, 1000)
camera.position.set(0, 2, 10)
// Scene
scene = new THREE.Scene()
scene.fog = new THREE.Fog(0x000000, 500, 1000)
// Renderer
renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setClearColor(scene.fog.color)
renderer.outputEncoding = THREE.sRGBEncoding
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
document.body.appendChild(renderer.domElement)
// Stats.js
stats = new Stats()
document.body.appendChild(stats.dom)
// Lights
const ambientLight = new THREE.AmbientLight(0x666666)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
const distance = 20
directionalLight.position.set(-distance, distance, distance)
directionalLight.castShadow = true
directionalLight.shadow.mapSize.width = 2048
directionalLight.shadow.mapSize.height = 2048
directionalLight.shadow.camera.left = -distance
directionalLight.shadow.camera.right = distance
directionalLight.shadow.camera.top = distance
directionalLight.shadow.camera.bottom = -distance
directionalLight.shadow.camera.far = 3 * distance
directionalLight.shadow.camera.near = distance
scene.add(directionalLight)
// Raycaster for mouse interaction
raycaster = new THREE.Raycaster()
// Floor
const floorGeometry = new THREE.PlaneBufferGeometry(100, 100, 1, 1)
floorGeometry.rotateX(-Math.PI / 2)
const floorMaterial = new THREE.MeshLambertMaterial({ color: 0x777777 })
floor = new THREE.Mesh(floorGeometry, floorMaterial)
floor.receiveShadow = true
scene.add(floor)
// Click marker to be shown on interaction
const markerGeometry = new THREE.SphereBufferGeometry(0.2, 8, 8)
const markerMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 })
clickMarker = new THREE.Mesh(markerGeometry, markerMaterial)
clickMarker.visible = false // Hide it..
scene.add(clickMarker)
// Dice faces
let texture = new THREE.TextureLoader().load( 'https://picsum.photos/id/237/200/200' );
let textureOne = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29527' );
let textureTwo = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29533' );
let textureThree = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29539' );
let textureFour = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29545' );
let textureFive = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29551' );
let textureSix = new THREE.TextureLoader().load( 'https://openclipart.org/image/800px/29557' );
let diceGeometry = new THREE.BoxGeometry(diceSize,diceSize,diceSize);
let material2 = new THREE.MeshStandardMaterial( {color: 0xff0051, wireframe: false} )
var diceMaterial = [
new THREE.MeshPhongMaterial({
// wireframe: true,
map: textureFour //left
}),
new THREE.MeshPhongMaterial({
map: textureThree //right
}),
new THREE.MeshPhongMaterial({
map: textureTwo // top
}),
new THREE.MeshPhongMaterial({
map: textureFive // bottom
}),
new THREE.MeshPhongMaterial({
map: textureOne // front
}),
new THREE.MeshPhongMaterial({
map: textureSix //back
})
];
dice = new THREE.Mesh( diceGeometry, diceMaterial );
dice.castShadow = true;
meshes.push(dice)
scene.add( dice );
// Movement plane when dragging
const planeGeometry = new THREE.PlaneBufferGeometry(100, 100)
movementPlane = new THREE.Mesh(planeGeometry, floorMaterial)
movementPlane.visible = false // Hide it..
scene.add(movementPlane)
window.addEventListener('resize', onWindowResize)
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
function initCannon() {
// Setup world
world = new CANNON.World()
world.gravity.set(0, -10, 0)
// Floor
const floorShape = new CANNON.Plane()
const floorBody = new CANNON.Body({ mass: 0 })
floorBody.addShape(floorShape)
floorBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
world.addBody(floorBody)
// Cube body
const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5))
cubeBody = new CANNON.Body({ mass: 5 })
cubeBody.addShape(cubeShape)
cubeBody.position.set(0, 5, 0)
bodies.push(cubeBody)
world.addBody(cubeBody)
// Joint body, to later constraint the cube
const jointShape = new CANNON.Sphere(0.1)
jointBody = new CANNON.Body({ mass: 0 })
jointBody.addShape(jointShape)
jointBody.collisionFilterGroup = 0
jointBody.collisionFilterMask = 0
world.addBody(jointBody)
// TEST =========
// When a body collides with another body, they both dispatch the "collide" event.
cubeBody.addEventListener('collide', (event) => {
// console.log(event.target)
console.log(dice)
})
// ==============
}
function msg(msg) {
msgBox.innerHTML = msg
}
window.addEventListener('pointerdown', (event) => {
// Cast a ray from where the mouse is pointing and
// see if we hit something
const hitPoint = getHitPoint(event.clientX, event.clientY, dice, camera)
// Return if the cube wasn't hit
if (!hitPoint) {
return
}
// Move marker mesh on contact point
showClickMarker()
moveClickMarker(hitPoint)
// Move the movement plane on the z-plane of the hit
moveMovementPlane(hitPoint, camera)
// Create the constraint between the cube body and the joint body
addJointConstraint(hitPoint, cubeBody)
// Set the flag to trigger pointermove on next frame so the
// movementPlane has had time to move
requestAnimationFrame(() => {
isDragging = true
})
})
// Returns an hit point if there's a hit with the mesh,
// otherwise returns undefined
function getHitPoint(clientX, clientY, mesh, camera) {
// Get 3D point form the client x y
const mouse = new THREE.Vector2()
mouse.x = (clientX / window.innerWidth) * 2 - 1
mouse.y = -((clientY / window.innerHeight) * 2 - 1)
// Get the picking ray from the point
raycaster.setFromCamera(mouse, camera)
// Find out if there's a hit
const hits = raycaster.intersectObject(mesh)
// Return the closest hit or undefined
return hits.length > 0 ? hits[0].point : undefined
}
window.addEventListener('pointermove', (event) => {
if (!isDragging) {
return
}
// Project the mouse onto the movement plane
const hitPoint = getHitPoint(event.clientX, event.clientY, movementPlane, camera)
if (hitPoint) {
// Move marker mesh on the contact point
moveClickMarker(hitPoint)
// Move the cannon constraint on the contact point
moveJoint(hitPoint)
}
})
document.addEventListener('pointerup', () => {
isDragging = false
// Hide the marker mesh
hideClickMarker()
// Remove the mouse constraint from the world
removeJointConstraint()
})
function showClickMarker() {
clickMarker.visible = true
}
function moveClickMarker(position) {
clickMarker.position.copy(position)
}
function hideClickMarker() {
clickMarker.visible = false
}
// This function moves the virtual movement plane for the mouseJoint to move in
function moveMovementPlane(point, camera) {
// Center at mouse position
movementPlane.position.copy(point)
// Make it face toward the camera
movementPlane.quaternion.copy(camera.quaternion)
}
// Add a constraint between the cube and the jointBody
// in the initeraction position
function addJointConstraint(position, constrainedBody) {
// Vector that goes from the body to the clicked point
const vector = new CANNON.Vec3().copy(position).vsub(constrainedBody.position)
// Apply anti-quaternion to vector to tranform it into the local body coordinate system
const antiRotation = constrainedBody.quaternion.inverse()
const pivot = antiRotation.vmult(vector) // pivot is not in local body coordinates
// Move the cannon click marker body to the click position
jointBody.position.copy(position)
// Create a new constraint
// The pivot for the jointBody is zero
jointConstraint = new CANNON.PointToPointConstraint(constrainedBody, pivot, jointBody, new CANNON.Vec3(0, 0, 0))
// Add the constraint to world
world.addConstraint(jointConstraint)
}
// This functions moves the joint body to a new postion in space
// and updates the constraint
function moveJoint(position) {
jointBody.position.copy(position)
jointConstraint.update()
}
// Remove constraint from world
function removeJointConstraint() {
world.removeConstraint(jointConstraint)
jointConstraint = undefined
}
function animate() {
requestAnimationFrame(animate)
// Step the physics world
world.fixedStep()
// Sync the three.js meshes with the bodies
for (let i = 0; i !== meshes.length; i++) {
meshes[i].position.copy(bodies[i].position)
meshes[i].quaternion.copy(bodies[i].quaternion)
}
// Render three.js
renderer.render(scene, camera)
stats.update()
}
</script>
</body>
</html>
I made a new THREE.PlaneBufferGeometry(100, 100, 100, 100); and have been able to update position of vertices to change the mesh's shape like following:
I achieved this by following this discussion: Threejs drag points
What am I looking for?
I want to be able to extrude a face (grab 4 vertices), so I achieve something like this:
I want to keep it all part of the same mesh, to keep it clean, because I will be exporting it as a single mesh with the ColladaExporter.
Edit
In order to achieve this, I would need to clone vertex and extrude them upwards. This means, adding 4 new vertex and connecting them together.
I tried this:
var geo = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
geo.rotateX(-Math.PI * 0.5);
geo.translate(0,0.5,0);
//And the merge them together
var newplane = BufferGeometryUtils.mergeBufferGeometries([plane, geo]);
newplane = BufferGeometryUtils.mergeVertices(newplane,1);
And I got this:
I was hoping all vertices merged with the plane, leaving a flat plane. I did this for testing purposes, but it only merged one corner.
I started building a "cube" with multiple and placing them in the right spot, to then apply again BufferGeometryUtils.mergeVertices, but the vertices don't seem to merge correctly:
Edit 2 / Progress
I managed to create a PlaneBufferGeometry and extrude it by manually modifying the vertexes and normals, as told in: https://threejs.org/docs/#api/en/core/BufferGeometry
Extruded plane has all vertices connected, so whenever I drag one vertex it drags a whole piece, the problem now is that I need to connect these new vertices to the original grid to avoid this:
Goal is to merge all vertices, now I need to find a way to merge the base plane with the new extruded piece.
Edit 3 / Done
I made it, I will post answer when I have some time. I spent all day long on these today, and already very tired.
Not sure if that's what you need, but here's the modified example from the answer you referred to (please notice the difference in mouseMove implementation). I've extended that for two points only, but I believe you should get the idea:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(1.25, 7, 7);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.PlaneBufferGeometry(10, 10, 10, 10);
geometry.rotateX(-Math.PI * 0.5);
var plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
wireframe: true,
color: "red"
}));
scene.add(plane);
var points = new THREE.Points(geometry, new THREE.PointsMaterial({
size: 0.25,
color: "yellow"
}));
scene.add(points);
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 0.25;
var mouse = new THREE.Vector2();
var intersects = null;
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var currentIndex = null;
var planePoint = new THREE.Vector3();
var dragging = false;
window.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mousemove", mouseMove, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseDown(event) {
setRaycaster(event);
getIndex();
dragging = true;
}
function mouseMove(event) {
if (dragging && currentIndex !== null) {
setRaycaster(event);
raycaster.ray.intersectPlane(plane, planePoint);
var indicesToMoveUp = [currentIndex-1, currentIndex];
var delta_x = geometry.attributes.position.getX(currentIndex) - planePoint.x;
geometry.attributes.position.setXYZ(currentIndex, planePoint.x, planePoint.y, planePoint.z);
geometry.attributes.position.needsUpdate = true;
var old_x_neighbour = geometry.attributes.position.getX(currentIndex - 1);
geometry.attributes.position.setY(currentIndex-1, planePoint.y);
geometry.attributes.position.setZ(currentIndex-1, planePoint.z);
geometry.attributes.position.setX(currentIndex-1, old_x_neighbour - delta_x);
geometry.attributes.position.needsUpdate = true;
}
}
function mouseUp(event) {
dragging = false;
currentIndex = null;
}
function getIndex() {
intersects = raycaster.intersectObject(points);
if (intersects.length === 0) {
currentIndex = null;
return;
}
currentIndex = intersects[0].index;
setPlane(intersects[0].point);
}
function setPlane(point) {
planeNormal.subVectors(camera.position, point).normalize();
plane.setFromNormalAndCoplanarPoint(planeNormal, point);
}
function setRaycaster(event) {
getMouse(event);
raycaster.setFromCamera(mouse, camera);
}
function getMouse(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
I'm having an issue with the mousemove function in a three.js scene. The goal is for the text to change color when the mouse is over the object. I've followed many examples from the web and the raycaster doesn't register the object. I tried adding update() in the function animate() like in the link above, but the console indicates an error, "update is not defined." I can't put the mousemove function after the init function because it doesn't recognize the object variable.
var mouse = { x: 0, y: 0 }, INTERSECTED;
var projector = new THREE.Projector();
var scene, camera,renderer;
function init(font){...
//loaded the font, camera, etc.
var option="object";
var geometry_option= new THREE.TextGeometry( option{font:font, size:200,height:20, curveSegments:2});
var material_option = new THREE.MeshBasicMaterial( { color: 0x0000000, side: THREE.BackSide } );
var option1= new THREE.Mesh(geometry_option, material_option); //added the position and added it to the scene.
//added other functions under function init such as mousedown,mousemove, etc.
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
function update()
{
// 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_option= ray.intersectObjects([option1] );
if ( intersects_option.length > 0 )
{
if ( intersects_option[ 0 ].object != INTERSECTED )
{
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects_option[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
INTERSECTED.material.color.setHex( 0xffff00 );
}
}
else
{
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
}
}
} // close init function
I have a .obj file on the web page using Three js.
My aim is, when I drag the mouse left/right, the OBJ model should rotate which I am able to do so USING THREE.TrackballControls().
Next thing is, I want to touch on the specific points on that OBJ model and if the mouse is down on those points something would happen(like a counter increase which will be shown on the web page).
I have seen DOMevents for three js but it looks like it allows us to click on the whole object not on specific points on the objects.
How can I achieve that?
You have to create a raycaster. (r69)
mouse_vector = new THREE.Vector3(),
mouse = { x: 0, y: 0, z: 1 };
var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
var dir = new THREE.Vector3();
function onMouseDown( event_info )
{
event_info.preventDefault();
mouse.x = ( event_info.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event_info.clientY / window.innerHeight ) * 2 + 1;
mouse_vector.set( mouse.x, mouse.y, mouse.z );
mouse_vector.unproject(camera);
var direction = mouse_vector.sub( camera.position ).normalize();
ray = new THREE.Raycaster( camera.position, direction );
ray.set( camera.position, direction );
intersects = ray.intersectObjects(scene.children, true);
if( intersects.length )
{
intersects.forEach(function(clicked)
{
// Your stuff like
if (clicked.object.typ == 'yourObject')
{
//Event on click..
}
});
}
}
I set a canvas renderer which contain two meshs (cubes). What i need to do is to catch the click event on each cube to call the convenient method for it.
So far, i could catch the click event on all the renderer, means when i click on cube1 and cube2, the click belong the same 'cause it's bound to the renderer :)
My question is, how to bind the click event on each cube?
My relevant code is the following:
//dom
var containerPopUp=document.getElementById('popup');
//renderer
var rendererPopUp = new THREE.CanvasRenderer();
rendererPopUp.setSize(420,200);
containerPopUp.appendChild(rendererPopUp.domElement);
//Scene
var scenePopUp = new THREE.Scene();
//Camera
var cameraPopUp = new THREE.PerspectiveCamera(50,60/60,1,1000);
cameraPopUp.position.z = 220;
cameraPopUp.position.y = 20;
//
scenePopUp.add(cameraPopUp);
//Add texture for the cube
//Use image as texture
var img2D = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial
map:THREE.ImageUtils.loadTexture('img/2d.png')
});
img2D.map.needsUpdate = true; //ADDED
//Add Cube
var cubeFor2D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img2D);
cubeFor2D.position.x =- 60;
cubeFor2D.position.y = 20;
scenePopUp.add(cubeFor2D);
//
var img3D = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial
map:THREE.ImageUtils.loadTexture('img/3d.png')
});
img3D.map.needsUpdate = true;
var cubeFor3D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img3D);
cubeFor3D.position.x = 60;
cubeFor3D.position.y=20;
scenePopUp.add(cubeFor3D);
//
rendererPopUp.render(scenePopUp,cameraPopUp);
//
animate();
rendererPopUp.domElement.addEventListener('click',testCall,false);//Here the click event is bound on the whole renderer, means what ever object in the renderer is clicked, the testCall method is called.
As you can see, cubeFor2D and cubeFor3D are contained in the renderer. I need to bind the click event on each mesh. I tried this with the threex.domevent.js:
var meshes = {};
meshes['mesh1'] = cubeFor2D;
meshes['mesh1'].on('mouseover', function(event){
//response to click...
console.log('you have clicked on cube 2D');
});
But it doesn't work, in the console, i got this error:
TypeError: meshes.mesh1.on is not a function
Of course, i included the API source code file:
<script src="threex.domevent.js"></script>
You can generate a callback like this. First define your callback function for each object:
mesh.callback = function() { console.log( this.name ); }
Then follow the standard picking pattern:
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onDocumentMouseDown( event ) {
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects );
if ( intersects.length > 0 ) {
intersects[0].object.callback();
}
}
EDIT: updated to three.js r.70
Create a click handler
window.addEventListener('click', onDocumentMouseDown, false);
Define the function onDocumentMouseDown, note that raycaster the difference in above answer is the index position of the object clicked!
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onDocumentMouseDown( event ) {
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
console.log(scene.children);
var intersects = raycaster.intersectObjects( scene.children );
console.log(intersects[1]);
if ( intersects.length > 0 ) {
intersects[1].object.callback();
}}
Define the Mesh object
var mesh_menu_title = new THREE.Mesh(geometry_menu, materials_menu);
mesh_menu_title.name = 'select_lang';
mesh_menu_title.callback = function() { select_language();}
scene.add(mesh_menu_title);
define the callback function
function select_language(){
var selectedObject = scene.getObjectByName("select_lang");
scene.remove( selectedObject );
var selectedObject = scene.getObjectByName("start");
scene.remove( selectedObject );
var selectedObject = scene.getObjectByName("menu");
scene.remove( selectedObject );
}
So this code above will handle specific object clicked inside my canvas, then callback a function, the "mesh.callback" and it will remove some scene childs from the canvas.
It doesn't work if you use intersects[0].object.callback(); because at the index 0 the stored object are the vertices.