Check if positions are behind object

Hi,

I have a 3D character along with several predefined positions on the floor. Is there a way to check if a position is behind the 3D character and not in front or sideways?

I’ve included a rough sketch of what I’m trying to achieve (sorry for the poor drawing). Essentially I would like to return all of the positions of the red circles within the red lines and exclude all other circles outside of these two lines.

Is this possible? If so, is there any suggestion on how I can achieve this? I’m sorry but I don’t actually know which functions to use from Three JS for something like this or if it is possible.

Thank you!

1 Like

Hi!
Just an option. Let’s have the object (O) and the target (T)

  1. Get direction vector of the object in global space, dirO.
  2. Get the normalized vector of (T.position - O.position) in global space, dirT.
  3. Find the dot-product of these vectors let d = dirO.dot(dirT);, if d less than 0 or some negative value (val), then the target locates in the object’s back hemisphere. And the lesser val, the more narrow sector at back you define.

Hi,

Thank you very much for the detailed steps! By “getting direction vector of object”, do you mean something like this?

var matrix = new THREE.Matrix4();
matrix.extractRotation( mesh.matrix );

var direction = new THREE.Vector3( 0, 0, 1 );
matrix.multiplyVector3( direction );

There is that method: three.js docs

Hello,

I haven’t tested it myself but maybe you can use frustums

Frustums are used to determine what is inside the camera’s field of view. They help speed up the rendering process - objects which lie outside a camera’s frustum can safely be excluded from rendering.

There is a method containsPoint

What I need is to detect whether the target positions are behind an object and not the camera. Does frustums also work with objects? If so, how would I read the frustum of an object?

@prisoner849 I tried something like this:

var o_position		= mesh.position;	
var t_position 		= new THREE.Vector3(-13.37393856048584, 1.4, -15.271000862121582);															
var dirO 			= mesh.getWorldDirection(t_position);
var dirT			= t_position.sub(o_position).normalize();
var d 				= dirO.dot(dirT);

And I get 0.99999999 but when I change the values of t_position to position values of a location in front of the 3D object, I also get 0.999999. Shouldn’t positions in front of the 3D object be greater than 1?

It is used with the camera but you can use it too. It is just some form. Instead of being a box it is defined by planes.

let f = new THREE.Frustum(p0,p1,p2,p3,p4,p5);

p0 to p5 are planes that limit the frustum. Your character is a plane, the floor is a plane, there is a plane at the 2 lines perpendicular to the floor, another plane parallel to the floor that defines the height of the frustum and another plane far behind the character which defines how far your floor goes back.

If you understand how you define these planes, you will be able to set the Frustum and then use the containsPoint Method.

@abstract Thank you for the detailed explanation. I tried the containsPoint() method with the camera’s frustum like this and it seemed to detect what’s in front:

frustum.setFromMatrix(new THREE().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));							
console.log(frustum.containsPoint(target))

But how can I add a backwards looking projectionMatrix and matrixWorldInverse to a 3D object, so that the frustum looks backwards and checks for containsPoint ?

maybe you can apply a rotation

Thanks! Can you please tell me how do I rotate frustum in the opposite direction of where the mesh is facing?

If you don’t understand Frustum, maybe you can use Box3.

You just have to provide 2 points. Based on the position of your character and the floor it shouldn’t be difficult to calculate these two points.

“Behind” and “in front” are relative notions, you have to define what they mean for you. You need a reference. If it is, for instance, relative to the z position of your mesh then everything with a greater z is behind but you can also say everything with a greater z is in front. It’s up to you. If behind is between your character and the position of the camera then do the calculations accordingly: all z positions between z character and z camera are behind. Same for your two lines, if they are parallel, and just have a different x, you may just compare the x of your objects with the x of your lines. If the disposition is like the drawing, just using the coordinates shouldn’t be too difficult.

I’m just giving you ideas, you have to adapt them to your case and your scene.

Here is an attempt with dot-product:

2 Likes

@ prisoner849 very nice

Since it is an angle objects close to the subject are not detected so it depends on what OP is looking for

@abstract I did understand Frustum and managed to get your method to work by:

  1. Creating an invisible camera
  2. Adding it to the same position as the 3D character
  3. Check if positions are within the invisible camera’s frustum

But what I don’t know is how do I set the invisible camera to always face the opposite direction of where the 3D character is facing.

I tried this method, which works like a reverse lookAt but it only works if I have a previous set of lookAt coordinates.

var vector			= new THREE.Vector3();
var origin_vector	= new THREE.Vector3(origin.x, origin.y, origin.z);
var target_vector	= new THREE.Vector3(target.x, target.y, target.z);

vector.subVectors(origin_vector, target_vector).add(origin_vector);
hidden_camera.lookAt(vector);

Can you please tell me how can I have the invisible camera to always look in the opposite direction of where the 3D character is facing?

you can place the camera at the character and then rotate it the opposite rotation you apply to your character. When your character turns right or left you to apply a rotation? apply the opposite one to the invisible camera. Normally you can set the target direction of your camera so set the camera at the character position and the target behind. It should work

Ok sorry, I was busy, I didn’t read your message well. Since you did everything, the only thing you have now is to define the normal to your character and take the opposite vector.

this example manages to get a normal to each face of the sphere and draw an arrow. You may use the same idea. if you get the surronding box of your character, just use one of the sides

Hello, I’m also interested in this function and I was wondering, does the camera not contain the frustum property directly? Is it not possible to get the current state from the camera object instead of computing it with "frustum.setFromMatrix(new THREE().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)) " ?

It seems the boundingBox doesn’t care about the orientation of your mesh. So all in all, I would set everything and apply the opposite rotations to the invisible camera I apply to the character. Otherwise, you need to look for a vertex in your character and use it as a reference.

You may also have a look at this example: three.js examples

@abstract Thank you very much for the detailed explanation and steps. I was able to get your solution working and it’s great! :slight_smile: