Get exact Intersection-Point of a Ray and a Sprite - three.js

I want to get the exact intersection point of a ray and a sprite. But when I do this:
var ray = new THREE.Raycaster( camera.position, vector.sub(camera.position ).normalize());
var sprite = new THREE.Sprite(spriteMaterial);
var intersect = ray.intersectObject(sprite);
then intersect.point is just the position of the sprite, instead of the exact point that I need.
I need this so I can check if the part of the texture that has been clicked is visible or not. (Alpha value)
Is there a way to get the exact intersection, or is there a better way to achieve my goal?

This is not currently supported. See Raycaster.js if you want to try to hack your own solution. Sprites can be rotated (turned on their side), so the solution is not trivial.
A reasonable work-around is to create a Mesh from a PlaneGeometry and set
mesh.quaternion = camera.quaternion.
three.js r.64

Related

threejs - raycasting in AR with controller after repositioning

I'm rather new to threejs, so what I'm doing might not be the most efficient way.
I have an object in AR on a mobile device and I want to know if I intersect with it when touching on the screen.
I use the following code to generate the raycast, and it works initally.
const tempMatrix = new THREE.Matrix4();
tempMatrix.identity().extractRotation(this.controller.matrixWorld);
this.raycaster.ray.origin.setFromMatrixPosition(this.controller.matrixWorld);
this.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);
However, I have the ability to reposition the object (i.e. reset the position so the object is in front, relative to the current camera direction and position) by moving and rotating the whole scene.
After the repositioning, the raycasting is completely offset and is not casting rays anywhere near where I touch the screen.
Repositioning is done like this (while it works, if there's a better way, let me know!) :
public handleReposition(): void {
const xRotation = Math.abs(this.camera.rotation.x) > Math.PI / 2 ? -Math.PI : 0;
const yRotation = this.camera.rotation.y;
this.scene.rotation.set(xRotation, yRotation, xRotation);
this.scene.position.set(this.camera.position.x, this.camera.position.y, this.camera.position.z);
}
How can I achieve to raycast to the correct new location?
Thanks!
Assuming this.scene is actually the main threejs Scene, it's usually a bad idea to change its rotation or position, since it will affect everything inside the scene, including the controller. I'd suggest moving your object instead, or add your object(s) to a Group and move that.

Change facing direction of CSS3DObject

I have a 3D scene with a bunch of CSS object that I want to rotate so that they are all pointing towards a point in the space.
My CSS objects are simple rectangles that are a lot wider than they are high:
var element = document.createElement('div');
element.innerHTML = "test";
element.style.width = "75px";
element.style.height = "10px";
var object = new THREE.CSS3DObject(element);
object.position.x = x;
object.position.y = y;
object.position.z = z;
Per default, the created objects are defined as if they are "facing" the z-axis. This means that if I use the lookAt() function, the objects will rotate so that the "test" text face the point.
My problem is that I would rather rotate so that the "right edge" of the div is pointing towards the desired point. I've tried fiddling with the up-vector, but I feel like that wont work because I still want the up-vector to point up. I also tried rotating the object Math.PI/2 along the y axis first, but lookAt() seems to ignore any prior set rotation.
It seems like I need to redefine the objects local z-vector instead, so that it runs along with the global x-vector. That way the objects "looking at"-direction would be to the right in the scene, and then lookAt() would orient it properly.
Sorry for probably mangling terminology, newbie 3D programmer here.
Object.lookAt( point ) will orient the object so that the object's internal positive z-axis points in the direction of the desired point.
If you want the object's internal positive x-axis to point in the direction of the desired point, you can use this pattern:
object.lookAt( point );
object.rotateY( - Math.PI / 2 );
three.js r.84

ThreeJS cant move camera

Im trying to move camera by changing its world matrix. But it doesen't seem to work. No matter what the camera wont move.
camera.matrixAutoUpdate = false
camera.matrixWorld = portal_view(camera,port1_quad,port2_quad)
i have tried using the matrixupdate = true but still nothing. What am i douing wrong ?
function portal_view(camera, src_portal, dst_portal) {
var inverse_view_to_source = new THREE.Matrix4().getInverse(camera.matrix).multiply(src_portal.matrix);
var new_mat = dst_portal.matrix.clone().multiply(inverse_view_to_source);
new_mat.makeRotationY(3.14);
return new_mat;
}
matrixWorld of an object is computed from its position, quaternion and scale. You cant directly change the 'matrixWorld' of an object. In other words, if you change the matrixWorld, the change wont be reflected on position of the object. You have to change the position of the camera.
What you can do is, extract the translation and rotation from the matrix and change the camera position and quaternion according to it.

Scaling of mesh world-relative

In Object3D contains a mesh
Object3D has an arbitrary scaling
Mesh has an arbitrary rotation. So my mesh is scaled relative to world coordinates.
But when I detach my mesh in the scene (for example, with the aid of THREE.SceneUtils.detach (mesh, obj3d, scene) I get an incorrect result, the mesh is scaled only locally.
I tried to change the geometry of the mesh, but still get an incorrect result:
http://jsfiddle.net/Ni55aN/VsWb9/3426/
var euler = new THREE.Euler(-mesh.rotation.x,-mesh.rotation.y,-mesh.rotation.z);
mesh.geometry.applyMatrix(new THREE.Matrix4().makeRotationFromEuler(mesh.rotation));
mesh.geometry.applyMatrix(new THREE.Matrix4().makeScale(
obj.scale.x,
obj.scale.y,
obj.scale.z
));
mesh.geometry.applyMatrix(new THREE.Matrix4().makeRotationFromEuler(euler));
mesh.geometry.verticesNeedUpdate=true;
I realized what was my mistake.
It was necessary to apply getInverse of my first matrix instead .makeRotationFromEuler with negative values
var firstMatrix=new THREE.Matrix4().makeRotationFromEuler(mesh.rotation);
var inverseMatrix=new THREE.Matrix4().getInverse(firstMatrix);
mesh.geometry.applyMatrix(firstMatrix);
mesh.geometry.applyMatrix(new THREE.Matrix4().makeScale(
obj.scale.x,
obj.scale.y,
obj.scale.z
));
mesh.geometry.applyMatrix(inverseMatrix);
mesh.geometry.verticesNeedUpdate=true;

THREE.raycaster : Possible to use it for enemy Ai?

I've just started learning THREE and have been messing about with the three.js example of controllable MD2 characters to try and fashion it into a 3rd person shooter kind of game. I've been trying to write a simple algorithm for the enemy characters and I'm pretty sure that ray-casting would be ideal.The whole idea is that the enemies should stop rotating once they're facing the player. But Here's the problem that's giving me sleepless nights! :
Let's say, the enemy object is the origin for the ray caster ray. No matter what direction I set for the direction of that ray ( even, for example (1,0,0) - the positive x-axis), the ray's direction is always pointing towards the center of the scene!!!
Please help! haven't been able to find any Example online for this kind of use for the ray caster (apart from collision detection which I really don't need at the moment).
If all you want is for enemies to stop rotating when they are looking at the player, I would consider just checking the direction between them, as it's a lot faster than casting a ray to see if it intersects:
// Assuming `enemy` is a THREE.Mesh
var targetDir = enemy.position.clone().sub(player.position).normalize();
var currentDir = (new THREE.Vector3()).applyMatrix4(enemy.matrixWorld).sub(enemy.position).normalize();
var amountToRotate = currentDir.sub(targetDir);
var offset = amountToRotate.length();
Then rotate each axis no more than the value for that axis in amountToRotate if offset is greater than some threshold.
That said, here is how you use a Raycaster, given the variables above:
var raycaster = new THREE.Raycaster(enemy.position, targetDir);
var intersections = raycaster.intersectObject(player);
Note that if you are running any of the above code in an animation loop, it will create a lot of garbage collection churn because you are constantly creating a bunch of new objects and then immediately throwing them away. A better pattern, which is used a lot in the library itself, is to initialize objects once, copy values to them if you need to, and then use those copies for computation. For example, you could create a function to do your raycasting for you like this:
var isEnemyLookingAtPlayer = (function() {
var raycaster = new THREE.Raycaster();
var pos = new THREE.Vector3();
return function(enemy) {
raycaster.ray.origin.copy(enemy.position);
raycaster.ray.direction.copy(pos.copy(enemy.position).sub(player.position).normalize());
return !!raycaster.intersectObject(player).length;
};
})();

Resources