Accessing group child for rollover in three.js - javascript

So I have a raycaster in three.js that allows me to detect when my group is rolled over. It currently works so that when I mouse over any child of the group, the entire group's material changes.
Here's my question : how can I detect which specific child was rolled over and highlight only that specific child ?
Here's the code :
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(tiles_group.children, true);
if ( intersects.length > 0 ) {
intersectedObject = intersects[0].object;
intersectedObject.material.emissive.setHex( 0xffffff );
intersected = true;
} else {
intersected = false;}
This should be easy but after hours of searching and trying I can't seem to find the proper logic/syntax. Thanks in advance to anyone reading/replying to this post !

SHORT ANSWER : create one material per object instead of one material for all of them
EXPLANATION : As WestLangley pointed out, I just needed to create a separate material for each child object instead of having them all share the same material, ie putting the material creation INSIDE the loop used to generate the objects so that every object gets its own material. This way, material is changed individually for each object.

Related

Remove object from three js scene by selecting it

My three js scene contains many OBJ models, some of which are preloaded with the scene, some of which are added to the scene via button click.
A user of my application may add an object but then decide to remove it. I am trying to figure out how to this but need guidance.
Ideally I would do this my holding shift and clicking the object to delete, or by adding the object to a group with shift + select and then deleting with a keyboard press (similar to the grouping here: https://threejs.org/examples/?q=drag#misc_controls_drag).
I would imagine the first way is easier to implement as I had a lot of trouble trying to group the OBJ models this way previously (I think due to their associated MTL files preventing their material being of type Lambert).
Thank you for your support!
If you are able to identify the object by raycasting from the 'Shift-Click' event then you should be able to go up to the object's parent and remove it. The next animate frame will not draw it.
const intersects = raycaster.intersectObjects( objects, true );
if (intersects.length > 0) {
const doomed = intersects[0].object;
doomed.parent.remove(doomed);
}

Three.js raycasting object selection with animation

Raycasting selection is working fine for my project on static meshes, however for animated meshes the ray selection doesn't seem to see the movement of the mesh and only responds to the mesh's non-animated (original) position.
My selection code is as follows:
element.addEventListener( 'mouseup', function ( event )
{
var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
vector = vector.unproject(camera);
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(pickable_objects, true);
if (intersects.length > 0)
{
//I change the object's material colour so that I can see the selection
}
}
Where pickable_objects is an array of three.js mesh objects that are selectable, these do not carry animation information as far as I am aware, so the result I'm complaining about may not be surprising to some.
I haven't included the colour changing code or the JSON mesh reader code here as I don't believe it's pertinent.
So with static meshes the ray casting is very accurate, but for animated meshes I have to click in the very centre of the object or find its original non-animated position to make the selection work.
If you take a look at the source code in the github repo, particularly Raycaster.js, you'll see that the actual implementation is in the geometry object. For instance Mesh.js implements the raycast by iterating over its triangles and checking whether the ray intersects any of them but SkinnedMesh.js does not override this method.
Finally, a quick search in the issues page showed that this is actually a known limitation - https://github.com/mrdoob/three.js/issues/6440.
You seem to be left with 2 options - bump the issue in github and ask for an ETA or implement this yourself (and send a pull request afterwards hopefully).

Babylon.js Mesh Picking & Ignoring Some Meshes

I am currently working on a small project using the new Babylon.js framework. One of the issues I have run into is that I basically have two meshes. One of the meshes is supposed to be the background, and the other is supposed to follow the cursor to mark where on the other mesh you are targeting. The problem is that when I move the targeting mesh to the position of the cursor, it blocks the background mesh when I use scene.pick, resulting in the other mesh having its position set on its self.
Is there any way to ignore the targeting mesh when using scene.pick so that I only pick the background mesh or is there some other method I could use? If not, what would be the steps to implement this sort of feature to essentially raycast only through certain meshes?
If you need code samples or any other forms of description, let me know. Thanks!
Ok, it's easy.
So, we have two meshes. One is called "ground", the second "cursor". If you want to pick only on the ground you have two solutions :
First:
var ground = new BABYLON.Mesh("ground",scene);
ground.isPickable = true ;
var cursor = new BABYLON.Mesh("cursor", scene);
cursor.isPickable = false;
...
var p = scene.pick(event.clientX, event.clientY); // it return only "isPickable" meshes
...
Second:
var ground = new BABYLON.Mesh("ground",scene);
var cursor = new BABYLON.Mesh("cursor", scene);
...
var p = scene.pick(event.clientX, event.clientY, function(mesh) {
return mesh.name == "ground"; // so only ground will be pickable
});
...
regards.

Determine if a mesh is visible on the viewport according to current camera

I have been developing an app with three.js but I have encountered this problem and I cannot seem to find any solution to it.
I want to determine which meshes are visible right now according to where the camera is currently aiming, so i can refresh my objects (data is coming from a service) or not depending on if they are being shown on the viewport.
I'm using THREE.js in CANVAS mode (I have found a solution using WebGL that says if objects are rendered or not, but i need CANVAS for this project).
I have been trying to find if three.js sets somehow a property to indicate whether the object is visible or not (currently on the screen, not on the entire 3D world), but I can't find it. Meshes have a visible: property but it's always on true even if the camera is not aiming to that object.
This is the code you're after:
var frustum = new THREE.Frustum();
var cameraViewProjectionMatrix = new THREE.Matrix4();
// every time the camera or objects change position (or every frame)
camera.updateMatrixWorld(); // make sure the camera matrix is updated
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
cameraViewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromMatrix( cameraViewProjectionMatrix );
// frustum is now ready to check all the objects you need
console.log( frustum.intersectsObject( object ) );

Making a rotation around a point

I'm using THREE API in order to realize some animations in my app. Now i have a real problem : i'd like making spherical rotation around a specific point. The "rotate" method included in mesh objects allow me to make them, but the center of the rotation is (by default i guess) the center of the mesh.
Then, i only rotate my objects around themself...
I have already found some examples, but they don't solve my problem. I tried to create objects 3D parents like groups, and tried to make the rotation around this groups after having translated them, but this still does not work...
Can you please give me a hand about that ?
I'm so sorry, i found my problem... Making a jsfiddle made me realize i forgot to instanciate my parent as " a new Object 3D() ", that was why i didn't see any objects in my scene when i used animation on my parent... i give you a short part of my code anyway dedicated to interested people finding any help :
// mesh
mesh = new THREE.Mesh( geometry, material );
parent = new THREE.Object3D();
parent.add(mesh);
// if i want my rotation point situated at (300;0;0)
parent.position.set(300,0,0);
mesh.position.set(-300, 0, 0);
scene.add(parent);
http://jsfiddle.net/KqTg8/6/
Thank you

Categories