Is it possible to have a object highlighted while using fly controls? Like this but the boxes highlighting when you click them. What I ultimately want it to do is to click on a object and then it go onto a website. But for the moment I have tried to just highlight a object when it its clicked using:
function onDocumentMouseDown( event ) {
event.preventDefault();
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );
var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( mesh );
if ( intersects.length > 0 ) {
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
/*
// Parse all the faces
for ( var i in intersects ) {
intersects[ i ].face.material[ 0 ].color.setHex( Math.random() * 0xffffff | 0x80000000 );
}
*/
But this does not seem to work when I'm using fly controls is it possible? If not could the object just be highlighted to show some text?
I just tested this with the fly controls, its working fine. Make sure to raycast against an array that contains your meshes or just scene.children in this case.
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
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 );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
}
container.addEventListener( 'mousedown', onDocumentMouseDown, false );
Three.js r.71
Consider checking out https://github.com/jeromeetienne/threex.domevents to easily add DOM Events like click or mouseover to your meshes.
Related
I am new to Three.js. I have loaded a collada (.dae) file having multiple objects.
Now I want to translate each object on its z axis while on mouse over and restore its position when mouse left that object.
I am using "Raycaster" for this purpose.
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
raycaster = new THREE.Raycaster(camera.position, vector.sub( camera.position ).normalize());
mouse = new THREE.Vector2();
and the function is
function onDocumentMouseMove ( 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);
var intersect = raycaster.intersectObjects( scene.children[2].children);
// console.log(intersect);
if ( intersect.length > 0 )
{
}
else
{
}
}
I have the object where my mouse is intersecting but I'm not sure how to translate the object and restore it on mouse out so it looks smooth.
Edited
You need to move your intersect check out of your onDocumentMouseMove and check on your loop. onDocumentMouseMove will be called only when your moves moves, but the check will be called every frame.
Your loop should look contain the following:
raycaster.setFromCamera( mouse, camera );
var intersect = raycaster.intersectObjects(scene.children);
if ( intersect.length > 0 ) {
intersect[0].object.translateZ(1);
} else {
// For all of your objects:
cube.position.z = 0;
}
Here's a CodePen.
I have created a 2*2*2 geometry cube via Three.js. Now I want to detect the click event when clicking the faces (24 faces in total).
Please check my current implementation at https://jsfiddle.net/agongdai/pdwg3myr/17/. When clicking on the faces, I want to console.log the current face index. But the index is not always accurate. For example, clicking on the top-left gray cell should show 0, but actually clicking the bottom part of it shows 2.
Please help me to check the mouse click event handler:
var raycaster = new THREE.Raycaster();
function onDocumentMouseDown( event ) {
var vector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
vector.unproject( camera );
raycaster.setFromCamera( vector, camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObject( cube );
if ( intersects.length > 0 ) {
var index = Math.floor( intersects[0].faceIndex / 2 );
console.log(index);
}
}
Could anybody please help?
Em, after googling a lot, I found this page and applied the approach. It's working properly https://jsfiddle.net/agongdai/pdwg3myr/19/:
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onDocumentMouseDown(event) {
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.intersectObject(cube);
if (intersects.length > 0) {
var index = Math.floor(intersects[0].faceIndex / 2);
console.log(index);
}
}
Update
To adjust to the left/top shift and scrolling, update it to https://jsfiddle.net/agongdai/pdwg3myr/24/:
function onDocumentMouseDown(event) {
const holder = renderer.domElement;
const rect = holder.getBoundingClientRect();
mouse.x = ((event.pageX - rect.left - window.scrollX) / holder.clientWidth) * 2 - 1;
mouse.y = -((event.pageY - rect.top - window.scrollY) / holder.clientHeight) * 2 + 1;
...
}
Below is the code that i am currently experimenting with, raycaster.intersectObjects returns 0 always what am i missing here? I have also tried raycaster.intersectObjects( objects );
geometry.vertices.push(vertex);
objects.push(geometry);
var particleTexture = THREE.ImageUtils.loadTexture('images/test.jpg');
var materials = new THREE.PointsMaterial({
map:particleTexture,
size: 150
});
document.addEventListener('click', onDocumentMouseClick, false);
function onDocumentMouseClick(event) {
event.preventDefault();
var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); // z = 0.5 important!
vector.unproject( camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( scene.children, true );
}
particles = new THREE.Points(geometry, materials);
scene.add(particles);
You can intersect from Array, scene.childern is Object.
Try to make another array reference to inersected object.
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function onDocumentMouseUp( event ) {
event.preventDefault();
if(event.which == 1) { /// LMB
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
raycaster.params.Points.threshold = 100000;
var intersects = raycaster.intersectObjects( intersects_obj, false );
console.log(intersects_m);
}
}
var mouse = new THREE.Vector2();
var intersects_obj = [];
canvas.addEventListener( 'mousemove', onDocumentMouseMove, false );
canvas.addEventListener( 'mouseup', onDocumentMouseUp, false );
//var paticles = .... your code;
intersects_obj.push(paticles);
I have a cube created using three js.(WebGL renderer)
I have applied texture on all six sides of cube.
I want to detect on which side the user has clicked on cube ?
look intersects[0].faceIndex
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var raycaster = new THREE.Raycaster();
Cube = new THREE.Mesh( geometry,
new THREE.MeshFaceMaterial( materials ) );
scene.add( Cube );
function onDocumentMouseDown( event ) {
var vector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
vector.unproject( camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObject( Cube );
if ( intersects.length > 0 ) {
var index = Math.floor( intersects[0].faceIndex / 2 );
switch (index) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
}
}
}
i am trying to pick objects in a scene where i use an orthographic camera.
my code fragment already works, but it is not precise.
i already found some answers on stackoverflow, but those are deprecated or won't work anymore at all.
here is my code onMouseDown
function onDocumentMouseUp( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
var pos = camera.position;
var ray = new THREE.Raycaster(pos, vector.unproject(camera).sub(camera.position).normalize());
var intersects = ray.intersectObjects(objects);
if (intersects.length > 0) {
console.log("touched:" + intersects[0]);
}
else {
console.log("not touched");
}
}
please see http://jsfiddle.net/ujzpe07t/1/
if you click some pixels away left/right/above/below the cube, it still tells me that the object was touched.
i am using three.js r69.
any hints would be very much appreciated.
thanks, cheers!
Here is the pattern to use when raycasting (picking) with either an orthographic camera or a perspective camera:
var raycaster = new THREE.Raycaster(); // create once
var mouse = new THREE.Vector2(); // create once
...
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, recursiveFlag );
three.js r.84