detect collision for child mesh for three.js - three.js

I have an Object3D (position 10, 0, 30) with a child mesh (local position 0, 0, 0) constructed with BoxGeometry (w: 20, h: 20, d: 20).
Now if a ray is casted with the origin (-10, 0, 0) and direction (1, 0, 0) and checked for intersection, it detected intersection (incorrectly as the object is not in the path).
Consider this code:
const THREE = require('three');
let obj = new THREE.Object3D();
let boxGeo = new THREE.BoxGeometry(20, 20, 20);
let mat = new THREE.MeshPhongMaterial();
let mesh = new THREE.Mesh(boxGeo, mat);
obj.add(mesh);
obj.position.set(10, 0, 30);
let raycaster = new THREE.Raycaster(new THREE.Vector3(-10, 0, 0), new THREE.Vector3(1, 0, 0));
let intersects = raycaster.intersectObject(obj, true);
The intersects array is of length 2 whereas, it should be on length 0.

In order for Raycaster to correctly determine child objects recursively, I had to call updateMatrixWorld() on the parent object before checking intersectionObject.

Related

Three js raycaster WITHOUT camera

I seem to find only examples to use the raycaster with the camera, but none that just have a raycaster from Point A to Point B.
I have a working raycaster, it retrieves my Helpers, Lines etc. but it seems it does not recognize my sphere.
My first thought was my points are off, so i decided to create a line from my pointA to my pointB with a direction like so:
var pointA = new Vector3( 50, 0, 0 );
var direction = new Vector3( 0, 1, 0 );
direction.normalize();
var distance = 100;
var pointB = new Vector3();
pointB.addVectors ( pointA, direction.multiplyScalar( distance ) );
var geometry = new Geometry();
geometry.vertices.push( pointA );
geometry.vertices.push( pointB );
var material = new LineBasicMaterial( { color : 0xff0000 } );
var line = new Line( geometry, material );
This will show a line from my point (50 0 0) to (50 100 0) right trough my sphere which is at point (50, 50, 0) so my pointA and direction values are correct.
Next i add a raycaster:
To avoid conflicts with any side effects i recreated my points here:
var raycaster = new Raycaster(new Vector3( 50, 0, 0 ), new Vector3( 0, 1, 0 ).normalize());
var intersects = raycaster.intersectObject(target);
console.log(intersects);
Seems pretty straight forward to me, i also tried to use raycaster.intersectObjects(scene.children) but it gives Lines, helpers etc. but not my sphere.
What am i doing wrong? I am surely missing something here.
IMG of the line and the sphere:
What you see is explained in the following github issue:
https://github.com/mrdoob/three.js/issues/11449
The problem is that the ray emitted from THREE.Raycaster does not directly hit a face but its vertex which results in no intersection.
There are several workarounds to solve this issue e.g. slightly shift the geometry or the ray. For your case:
var raycaster = new THREE.Raycaster( new THREE.Vector3( 50, 0, 0 ), new THREE.Vector3( 0, 1, 0.01 ).normalize() );
However, a better solution is to fix the engine and make the test more robust.
Demo: https://jsfiddle.net/kzwmoug2/3/
three.js R106

How do you connect a geometry to two moving vertices

I have created some box geometries in my threejs app and I have successfully drawn a cylinder from the center of one to the center of another using the code below:
function cylinderMesh(pointX, pointY, material) {
var direction = new THREE.Vector3().subVectors(pointY, pointX);
var orientation = new THREE.Matrix4();
orientation.lookAt(pointX, pointY, new THREE.Object3D().up);
orientation.multiply(new THREE.Matrix4(1, 0, 0, 0,
0, 0, 1, 0,
0, -1, 0, 0,
0, 0, 0, 1));
var edgeGeometry = new THREE.CylinderGeometry(2, 2, direction.length(), 8, 1);
var edge = new THREE.Mesh(edgeGeometry, material);
edge.applyMatrix(orientation);
edge.position.x = (pointY.x + pointX.x) / 2;
edge.position.y = (pointY.y + pointX.y) / 2;
edge.position.z = (pointY.z + pointX.z) / 2;
return edge;
}
scene.add(cylinderMesh(vertex1, vertex2, globalMaterial));
My question is: How to I keep the cylinder "connected" to the two vertices I provide if they move?
I don't want to use a THREE.Line because I can't control the width of the line and I have noticed weird issues with clipping if the camera gets too close.
Any ideas?

Three.js - Set rotation of object from normalized directions of the X, Y and Z-Axis

From a model file object definition the placement a new object is given by a location (a point in space) and the normalized directions of the X-Axis, the Y-Axis and the Z-Axis.
How can i translate this to a THREE.Euler so i can rotate my object correctly in space.
So the axes are off type THREE.Vector3.
If the new object is aligned with the world the values would be:
xAxis = new THREE.Vector3( 1, 0, 0 );
yAxis = new THREE.Vector3( 0, 1, 0 );
zAxis = new THREE.Vector3( 0, 0, 1 );
But if for example the whole local UCS of the object is rotated 180 degrees ( or Math.PI ) around the zAxis they would look like this:
xAxis = new THREE.Vector3( -1, 0, 0 );
yAxis = new THREE.Vector3( 0, -1, 0 );
zAxis = new THREE.Vector3( 0, 0, 1 );
So I need to do something like this:
var object3D = new THREE.Object3D();
object3D.position = location;
var euler = new THREE.Euler();
euler.setFromNormalizedAxes( xAxis, yAxis, zAxis );
object3D.rotation = euler;
Or create a rotation matrix from those axes:
var rotationMatrix = new THREE.Matrix4();
rotationMatrix.setFromNormalizedAxes( xAxis, yAxis, zAxis );
object3D.rotation.setFromRotationMatrix( rotationMatrix, "XYZ" );
I am not so good yet with these rotation matrices and euler rotations...
In the example you gave, the answer would be
object.quaternion.setFromRotationMatrix(
new THREE.Matrix4( -1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 )
);
The columns of the upper 3x3 of the Matrix4 are the new x-, y-, and z-axes.
You could set object.rotation instead. It does not matter.
three.js r.66

Can geometry be partially hidden by manipulating the far plane of the camera?

I'm attempting to manipulate the camera far plane to hide a portion of a THREE.Line object. However, I must be doing something wrong.
I set the near- and far plane using:
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 2, 0);
Next, I create the geometry:
geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-1, 0, 0));
geometry.vertices.push(new THREE.Vector3(1, 0, 0));
geometry.vertices.push(new THREE.Vector3(1, 0, -2)); // outside far plane
geometry.vertices.push(new THREE.Vector3(0, 0, -3)); // outside far plane
geometry.vertices.push(new THREE.Vector3(-1, 0, -2)); // outside far plane
geometry.vertices.push(new THREE.Vector3(-1, 0, 0));
Finally, I create the line and add it to the scene:
lines = new THREE.Line(geometry, material);
lines.frustumCulled = true; // default?
scene.add(lines);
The entire object is shown in the frustum.
Please see fiddle at http://jsfiddle.net/g52w4/2/
The near and far plane parameters are distances (from the camera). They should be positive, with the far greater than the near.
Set your far plane to 5, for example.
fiddle: http://jsfiddle.net/gpT5K/
three.js r.65

Create ArrowHelper with correct rotation

How do I create an ArrowHelper in Three.js (r58) with correct rotation?
var point1 = new THREE.Vector3(0, 0, 0);
var point2 = new THREE.Vector3(10, 10, 10);
var direction = new THREE.Vector3().subVectors(point1, point2);
var arrow = new THREE.ArrowHelper(direction.normalize(), point1);
console.log(arrow.rotation);
I always end up with with Object {x: 0, y: 0, z: 0} for the arrow rotation. What am I doing wrong?
ArrowHelper uses quaternions to specify it's orientation.
If you do this:
var rotation = new THREE.Euler().setFromQuaternion( arrow.quaternion );
you will see an equivalent orientation expressed in Euler angles, although in r.59, arrow.rotation is now automatically updated, so you will no longer see zeros.
EDIT: answer updated to three.js r.59

Resources