Three.js: raycaster do not intersect when THREE.Points has only 1 vertex or has vertexs arranged in line

Created on 1 Dec 2015  ยท  18Comments  ยท  Source: mrdoob/three.js

I made this question on stackoverflow, but it seems to be about three.js itself:

I spent several hours to understand this problem. For some inexplicable reason (for me) raycaster.intersectObject( pointCloud ); do not intersect my 'pointCloud' Object when it has just one vertex (the respective position array attribute with three elements). If the Object has two or more vertexs only then raycaster.intersectObject works.

My geometry is a THREE.BufferGeometry() and I'm using a custom ShaderMaterial. My object is a THREE.Points.

this.pointCloud = new THREE.Points( geometry, material0 );
Any ideas?

โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“ New edition of my question โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“โ†“

Ok, I think the problem here is that when I have a THREE.Point, with a Buffer Geometry with just one vertex (something really specific and odd, but in my case possible) the calculation for a boundingBox min and max, is :

boundingBox: 
  max: 
     THREE.Vector3  x: 50  y: 50  z: -50
  min: 
    THREE.Vector3  x: 50  y: 50  z: -50

And the problem is not just with one vertex, with a set of vertexs arranged in the same line (less odd), the min and max of the boundingBox of the geometry draws a line. I mean, for example, same X pos, Y pos, but different Z pos,

boundingBox: 
  max: 
    THREE.Vector3 x: -100 y: 0 z: 133
  min: 
    THREE.Vector3 x: -100 y: 0 z: -33

So, I think here is why in these both cases raycast intersection do not work.

More details:

In this last case for example, following the thread of the raycast.intersection:

//in my file.js
intersections = raycaster.intersectObject( pc.pointCloud , true);  
//line 7734 three.js
intersectObject( object, this, intersects, recursive ); 
//line 7678 three.js 
object.raycast( raycaster, intersects ); 
//line 16542 three.js
if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) {... 
//line 6152 three.js
intersectBox: function ( box, optionalTarget ) {...

Here, inside this intersectBox function :

//line 6188 three.js 
if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;

...the evaluation is true, so returns null and the intersections can't be achieved. I assume the problem is that it evaluates the x and y positions of the boundedBox that are the same, and that's why ( tmin > tymax) or (tymin > tmax) gives true.
But if I change the position of my particles, to share x and z, and have y as the different one, is the same result, is not intersecting.

Maybe with this new information someone is able to help me to set a good fix for this.

...edit this three.js function?, or do a trick in my geometry to give a valid boundedBox?....

Thanks!

Three.js 72

Bug

Most helpful comment

It does not make sense to me that a bounding sphere of radius zero works, but a bounding box of size zero does not.

All 18 comments

Your bounding box has no volume. Try this and report back:

pointCloud.geometry.boundingBox = null;

Yes, That is!

Now the intersection is working always, and is even better than before.

Once again...! I've learned a lot thanks to your goodwill.
Thank you so much @WestLangley !.

OK, well, something needs to be fixed. Raycaster should work when the bounding box has no volume.

@Javingka Could you put together a jsfiddle?

Sure @mrdoob here is the jsfiddle

In the line 90 you can find the call to each of these functions

  //geometry.computeBoundingSphere(); // it works
  geometry.computeBoundingBox(); // does not work
  //geometry.boundingBox = null; // it works

Thanks.

Thanks for the jsfiddle!

Because vertices have no size, the bounding box ends up being:

mix: -100, 0, 0
max: 100, 0, 0

The solution is probably to replace the boundingBox check with a boundingSphere check.

This should solve the points in a line case, but I'm not sure we can do much about the single point case. Unless we always expand the sphere/box by 1 unit?

Updated the jsfiddle using dev: http://jsfiddle.net/egL97deu/12/

Can't the "grater than" also have equals ?
tmin >= tymax
Etc.

It does not make sense to me that a bounding sphere of radius zero works, but a bounding box of size zero does not.

Oh, I didn't try with just one vertex. The jsfiddle uses 3 vertices.

here is with one point.
there is a function to pass positions as arrays with values between -1 to 1.

I guess raycaster.params.Points.threshold should be considered when computing the bounding sphere. The code is not really designed for that, however.

Yeah... ๐Ÿ˜•

A simple fix would be a check if the radius > 0, so single Points with one vertex would work:
https://github.com/mrdoob/three.js/blob/dev/src/objects/Points.js#L50

if ( raycaster.ray.intersectsSphere( sphere ) === false && sphere.radius > 0)

What would the sphere.radius be for a geometry with a single vertex?

I think the best solution is to add the precision to the bounding sphere radius prior to doing the ray interstection test. Something like:

sphere.copy( geometry.boundingSphere );
sphere.applyMatrix4( matrixWorld );
sphere.radius += threshold;

I remember that in Octree they use material.size for sphere.radius.

West Langley's suggested fix of adding the threshold to the sphere radius seems to work.
I tried adding it to r81 - the result was that raycast correctly intersects objects that are either single points (only point in a geo) or that are in a geo in which all points are coincident on the same position (e.g. due to an invalid layout configuration).

Was this page helpful?
0 / 5 - 0 ratings