Raycasting after dynamically changing Mesh in Three.js - javascript

I have a mesh cloned from another mesh. But after cloning, I translate and rotate it. And do a ray-casting a point to it but it is not working as expected. It is keep intersecting with the original position before translation and rotation. Sample code is as below
const raycaster = THREE.Raycaster()
const proposedModel = model.clone()
proposedModel.translateX(1)
proposedModel.translateY(1)
proposedModel.translateZ(1)
const q = new THREE.Quaternion(
-0.847,
-0.002,
-0.505,
0.168
)
proposedModel.applyQuaternion(q)
const point = new THREE.Vector3(1,1,1)
raycaster.set(point, new THREE.Vector3(1,1,1))
const intersects = raycaster.intersectObject(object) // It keep intersecting with original position
Glad if any help, Thanks!

Call updateMatrixWorld() from the mesh after transformation will solve the problem. Credit to #prisoner849
proposedModel.updateMatrixWorld()
The reason is
An object's matrix stores the object's transformation relative to the
object's parent; to get the object's transformation in world
coordinates, you must access the object's Object3D.matrixWorld.
When either the parent or the child object's transformation changes,
you can request that the child object's matrixWorld be updated by
calling updateMatrixWorld().
Check detail here https://threejs.org/docs/#manual/introduction/Matrix-transformations

Related

Three.js: how to force update matrix after cloning? (to use with CSG ThreeBSP)

I'm trying to clone and then scale a mesh, but scaling does not seem to be working immediately on the cloned object, for programming purposes using CSG ThreeBSP. I think I should call a function after the scaling to force the matrix or other internal variables to recalculate immediately and not to wait for the full update loop on render side.
My code looks something like this:
var someMesh2 = someMesh1.clone();
someMesh2.scale.set(2,2,2);
someProgrammingOperation(someMesh2);
//It turns out that internally, someMesh2 still has the same properties (matrix?) as someMesh1 :(
What am I missing? Suggestions are also welcomed :)
object.matrix is updated for you by the renderer whenever you call renderer.render().
If you need to update the object matrix manually, call
object.updateMatrix();
and it will update the matrix from the current values of object.position, object.quaternion, and object.scale.
(Note that object.rotation and object.quaternion remain synchronized. When you update one, the other updates automatically.)
three.js r.84
In the end, my problem was that the CSG ThreeBSP object needed to work based on the Geometry of the object, not in the Mesh itself. I applied the scaling on the Geometry and it worked as expected.
There is a caveat though, that one should be careful as with the meshes and geometries instances, therefore is needed to do some cloning in order to keep the original objects as they were, as in the following example:
var clonedMesh = original.mesh.clone()
var clonedGeometry = clonedMesh.geometry.clone()
clonedMesh.geometry = clonedGeometry
clonedMesh.geometry.scale(2,2,2)
var someBsp = new ThreeBSP( clonedMesh )
var newMesh = someBspBsp.toMesh()
someScene.add newMesh

Webgl three.js Dependency of several objects

I have a problem with the dependency of objects. I want to make one object dependent on two other objects. If I change the position of one parent object (for example the y-Position), the dependent object (the child object) should rotate und should also move.
Here is a link where I realized it on a picture. On the left side is the initial state, on the right side the changed condition. The Cylinder should be dependent on the two boxes. That means that the cylinder is the child object and the boxes should be both parent objects of this child object.
I tried it with using parent and child properties, but I could not make the child object dependent on two parent objects.
Can someone help me?
This is my current code, but the lookAt Function does not work correctly.
//cube 1
var cube=new THREE.BoxGeometry(4,4,4);
var material=new THREE.MeshBasicMaterial ({ color: 0xffffff });
mesh1=new THREE.Mesh(cube,material);
mesh1.position.set(-2,2,0);
scene.add(mesh1);
//cube 2
var cube2=new THREE.BoxGeometry(2,2,2);
var material=new THREE.MeshBasicMaterial ({ color:0x000000 });
mesh2=new THREE.Mesh(cube2,material);
mesh2.position.x=6;
mesh2.position.y=2;
//mesh2.position.y=-2;
scene.add(mesh2);
//cylinder
var cylinder=new THREE.CylinderGeometry(1,1,6,30);
var material=new THREE.MeshBasicMaterial({ color:0xff3399 });
mesh3=new THREE.Mesh(cylinder,material);
mesh1.add(mesh3);
mesh3.lookAt(mesh2.position);
You need to two levels of hierarchy, eg:
cube1.add(cylinder)
cylinder.add(cube2)
Yeah, 2pha is right actually. I think what he actually needs is something like this (note you'll need to scale the cylinder or move the squares unless they are exactly cylinder height apart):
cylinder.position.x=cube1.position.x
cylinder.position.y=cube1.position.y
cylinder.position.z=cube1.position.z
cylinder.lookAt(cube2.position)
You may be able to do what you're after with the lookAt function on the Object3D class.
eg.
Add your cylinder as a child of cube1 so moving cube1 will also move the cylinder.
cube1.add(cylinder)
then when cube1 (or / and cube2) is moved call the lookAt function on cylinder to look at the cube2's position.
cylinder.lookAt(cube2.position)

three.js "exploding" an object in predefined pieces

This is a sort of a follow up question of my last problem. I want to explode (technical drawing style) an imported .obj geometry which contains n .obj parts.
For example a table as object, each part is one .obj, four legs and a table top.
5 files. loading them is no problem. Now each objects position is 0,0,0 that means I need to get the world position of them, which I did with this function:
function absPos( myMesh ) {
myMesh.geometry.computeBoundingBox();
var boundingBox = myMesh.geometry.boundingBox;
var position = new THREE.Vector3();
position.subVectors( boundingBox.max, boundingBox.min );
position.multiplyScalar( 0.5 );
position.add( boundingBox.min );
position.applyMatrix4( myMesh.matrixWorld );
var abspos = {x:position.x,y:position.y,z:position.z};
return abspos;
}
now I did assume that setting the object´s position to their world positions would just happen to move them to another world position but keep their relation but that is not the case. So I cannot just use the objects world position and use it to translate the objects until I mess with the world position?
As the objects position is 0,0,0 they don´t have a relation to each other and I cannot just multiply the values to "explode" the geometry.
Is there any chance to achieve this without messing with the world positions?

2D screen position from 3D position using three.js

I have some 3D objects within a rotating parent object.
I'm adding a set of 2D "hotspots" which follow these object's screen position. I got this to successfully convert the child object's position to 2D:
// HOTSPOTS //
var v1,m1,p,hotspotX,hotspotY;
v1 = new THREE.Vector3();
m1 = new THREE.Matrix4();
m1 = childObject.matrixWorld;
v1.setFromMatrixPosition(m1);
p = projector.projectVector(v1, camera1);
hotspotX = (p.x + 1) / 2;
hotspotY = (-p.y + 1) / 2;
The problem is that rather than using the child object's origin as the hotspot location, I'd like to set it relative of it, i.e the hotspot's y might be childObject.y-10. I think this needs to happen prior to converting to matrix. Is there a way to do the same as matrixWorld, but from a vector instead of an object?
I could just create extra empty objects for each hotspot and set their positions exactly where I want them, however seeing as the childObjects are already there I'd rather use those if I can. All previous examples I've found use functions which are now deprecated. Hope this makes sense, I'm new to matrices.
Thanks!

Three.JS, changing the world position of a child 3D object

So basically I have a child object3D of a group Object3D, while the child object's [x,y,z] coordinates are shown relative to the object space of the parent object, I want to change the location of the child object within the 3D space. So first I get the child object's position relative to the world space.
var wrld_pos = childobject.matrixWorld.multiplyVector3(new THREE.Vector3);
This returns a three element vector of the child's position within the world space. Now I wish to set the position my self. So I create a three element vector.
var new_pos = THREE.Vector3();
new_pos.x = 1;
new_pos.y = 2;
new_pos.z = 3;
childobject.matrixWorld.setPosition(new_pos);
Provided the function definition for setPosition, it essentially it sets the last three elements of the object's world matrix to the values of the vector passed as an argument, thus changing the location of the object in world space. And to make sure that the matrix updates after these changes, I call the following functions.
childobject.matrixWorldNeedsUpdate = true;
childobject.updateMatrixWorld();
Now upon inspecting the new world matrix of the object I noticed that the setPosition function did nothing, nothing at all.
Why? If real code examples are needed, I will provide them. But the above should represent the application domain and syntax I used very accurately.
EDIT: Answer updated.
You want to change the world position of a child object.
Assuming the scene has no transform applied, one way to do what you want is to use the following pattern:
scene.attach( child ); // detach from parent and add to scene
child.position.set( x, y, z );
parent.attach( child ); // reattach to original parent
The Object3D.attach( child ) method adds the child object, while maintaining the child's world transform.
three.js r.132
This answer might help with the case. Remove child from parent, change normal position, then attach again.
If use attach for setting position in animation loop for moving objects you can get objects shaking.
For me best solution is:
let newPosition = new THREE.Vector3(1,2,3);
let parentPosition = new THREE.Vector3();
childobject.parent.getWorldPosition(parentPosition);
childobject.position.set(
newPosition.x-parentPosition.x,
newPosition.y-parentPosition.y,
newPosition.z-parentPosition.z
);
If you need position and rotation attach is the only way.

Categories