I'm trying to check if an object (this.target) is looking at a specific position (newPosition). What I have right now is the following:
new THREE.Matrix4().lookAt( newPosition, this.target.position, this.target.up ) == this.target.matrix
But for some reason, this won't work. How are you meant to check if an Object3D is looking at a specific position?
That won't work because the matrix for your target is not in the same place, and can be scaled differently and all sorts of stuff.
A better technique is to raycast from your eye object, and see if it hits the target object.
http://threejs.org/examples/#webgl_geometry_terrain_raycast
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
// See if the ray from the camera into the world hits one of our meshes
var intersects = raycaster.intersectObject( mesh );
Related
I want to rotate all objects in a scene around the origin 0,0,0 along the x axis. However, setting obj.rotation.x += 0.1; doesn't rotate along the origin, but along the the center of the object instead. How can I achieve the desired rotation of the object around the origin? I feel that there should be an easy way, but could not find any in the official docs or online.
Instead of adding the objects to the scene, add them to a THREE.Group() object:
var group = new THREE.Group();
scene.add(group);
...
var mesh1 = new THREE.Mesh(...);
group.add(mesh1);
var mesh2 = new THREE.Mesh(...);
group.add(mesh2);
//and so on with meshes
and then in the render loop:
group.rotation.x += 0.1;
Threejs.r84
You can use THREE.Object3D()
Add all your meshes to an object with myObject.add(myMesh)
And then use myObject.rotateX(angle)
where the angle is in radians, myObject is an Object3D object and myMesh is the mesh to be added.
This will rotate the object around x-axis in local space.
More can be found in the documentation: Object3D
For each mesh (THREE.Object3D) Three.js provide a very handy properties - boundingSphere and boundingSphere that have intersectsSphere and isIntersectionBox methods.
With all this I thought I can use it for simple collision detection but when I try it appears that collision happens all the time because (I tried boundingSphere) boundingSphere.center is always in (0, 0, 0); So If I want to check collisions between 2 meshes I should for each object - clone boundingSphere object and then get it world coordinates and only then to use intersectsSphere.
something like this:
var bs = component.object.geometry.boundingSphere.clone();
bs.center.setFromMatrixPosition(component.object.matrixWorld);
...
if (_bs.intersectsSphere(bs)){
is this how it suppose to be used or am I missing something and there are more convenient way of doing collisions detection based on boundingBox/boundingSphere?
If you want to do collision detection with bounding boxes you need the boxes in the world coordinate system. The bounding volumes in the intersectsSphere and isIntersectionBox properties of the mesh are in the local coordinate system of the object.
You can do like you did: clone the volumes and move them to the correct position in the world coordinate system, that is a good solution.
Otherwise you can also set a new box from your meshes and do collision using those boxes. Let's say you have a THREE.Mesh called mesh then you can do:
sphere = new THREE.Sphere.setFromPoints( mesh.vertices );
box = new THREE.Box3.setFromObject( mesh );
A little tip. During development it can be nice to see the bounding boxes in your scene, for this you can use the THREE.BoundingBoxHelper:
var helper = new THREE.BoundingBoxHelper( mesh );
scene.add( helper );
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).
I have a problem updating a vertex of a line in three.js
So, I want to have a line in my scene, that its start is always at the (0,0,0) and its end is always in a specific position of the users screen (in x,y coordinates).
What I do to achieve that (and I almost succeed) is to have an invisible plane looking always to the camera and also have its position always a little bit in front of the camera. The reason I do that is because I want the line to seem like "going towards" the user's screen. So I "send" a raycaster from the desired screen position (in x,y) and I check in which point of the plane it intersect and that's my 3D point in three.js scene. Then I update one of the 2 vertices of the line.
The problem
What I do works fine, the line end is where I want to be, but something in updating the camera and the vertex is not synchronized and causes some noticeable glitches. When I move the camera, the line do not update itself quickly and smoothly, and as a result I see the line in other position before I see it in the calculated and desireable one.
Please take a look at this jsfiddle I created to emulate the problem.
What can I do to avoid these glitches?
Thanks
code i use in render function :
var cameToCenterScaled = camera.position.clone();
cameToCenterScaled.setLength(cameToCenterScaled.length()*0.9);
plane.position.set(cameToCenterScaled.x, cameToCenterScaled.y, cameToCenterScaled.z);
plane.lookAt(camera.position);
// define in pixels where in screen we want the line to end
var notePos = findNotePoint(120,30);
linemesh.geometry.vertices[ 1 ].set(notePos.x, notePos.y, notePos.z) ;
linemesh.geometry.verticesNeedUpdate = true;
when you raycast you set the raycaster from camera, you have to make sure the camera matrices are updated
simply add
camera.updateMatrixWorld();
before you call
raycaster.setFromCamera( new THREE.Vector2( x_, y_ ) , camera );
and the line will behave as you described
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 ) );