Obtaining a Plane object from a PlaneGeometry in three.js - three.js

Just trying some some intersection experiments with three.js. Wanted to see if I could figure out when a cube intersected a PlaneGeometry. I can get the bbox of the Cube easily enough with
var bbox = new THREE.Box3().setFromObject(mesh);
where the mesh is the cube's mesh. I also have a PlaneBufferGeometry object. It looks like I might get the intersection info from the intersectsBox() method in the Plane object (or vice versa with the intersectsPlane() method in Box3. But I can't see easily how to get the Plane object from the PlaneBufferGeometry (or PlaneGeometry). I can create the Plane from three coplanar points or a point on the plane and the normal, but I don't see offhand how to get those from a given PlaneGeometry. If/when I constructed the PlaneBufferGeometry I could do it from the inputs to that, but how to obtain the Plane from an arbitrary PlaneGeometry object? Still looking but suggestions are welcome.

Related

How to find the coordinates of the viewfield corners of my Three.js camera?

My Three.js app has a static perspective camera looking on (0,0,0). How can I find the x/y coordinates in the y=0 plane of the corners of the camera's viewfield? The app covers the entire web browser, so this would correspond to the corners of the web browser. I want to render 3D models between those corners.
I want to render 3D models between those corners.
Just having the mentioned corner points is not sufficient to determine whether the user can see an object or not. The camera also has a near/far plane and also a perspective which you should take into account.
I suggest you use a different workflow and create an instance of THREE.Frustum based on the camera's projection screen matrix. The code looks like so:
const frustum = new THREE.Frustum();
const projScreenMatrix = new THREE.Matrix4();
projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromProjectionMatrix( _projScreenMatrix );
You can then use methods like Frustum.intersectsObject() or Frustum.intersectsSprite() to determine whether 3D objects are in the view frustum or not.
This is actually the way WebGLRenderer performs view frustum culling.

Raycasting to intersect objects that have been displaced by vertex shader

Let's say I have a vertical list of meshes created from PlaneBufferGeometry with ShaderMaterial. The meshes are distributed vertically and evenly spaced.
The list will have two states:
Displaying the meshes as they are
Displaying meshes with each object's vertices transformed by the vertex shader to the same arbitrary value, let's say z = -50. This gives a zoomed out effect and the user can scroll through this list (in the code we do this by moving the camera y position)
In my app I'm trying to make my mouseover events work for the second state but it's tricky since the GPU transforms the vertices so the updated vertices are not reflected in the attributes on the JS side.
*Note I've looked into GPU picking and do not want to use it because I believe there should be a simpler way to do this without render targets
Attempted Solution
My current approach is to manually change the boundingBox of each plane when we are in the second state like so:
var box = new THREE.Box3().setFromObject(plane);
box.min.z = -50;
box.max.z = -50;
plane.geometry.boundingBox = box;
And then to change the boundingSphere's center to have the same z position of -50 after computing it.
I did this approach because I looked into the Raycaster and Mesh code for THREE.js and it seems like they check both boundingSphere and boundingBox for object intersections. So I thought if I modified both of them to reflect the transforms done by the GPU, the raycaster would work fine but it doesn't seem to be working for me.
The relevant raycaster code is here:
// mouse being vec2 of normalized coordinates and camera being a perspective camera
raycaster.setFromCamera( mouse, camera );
const intersects = raycaster.intersectObjects( planes );
Possible Theories
The only thing I can think of that's wrong about this approach is maybe I'm not projecting the mouse coords right? Since all the objects now lie on the plane z = -50 would I need to project those mouse coordinates to that plane?
Inspired by the link posted by #prisoner849 I found a working solution to just create additional transparent planes equal to the number of planes in the scene. In these planes, I set the z position to -50 and just intersect with these when in state #2.
A bit hacky, but works for now.

three.js - clamp line to 'top' of mesh

I am building a 3d terrain in three.js. I do this by creating a PlaneGeometry, and setting the z values of the PlaneGeometry vertices to elevation data. I then load NAIP (National Agriculture Imagery Program) Imagery into a MeshPhongMaterial. The mesh is created from the PlaneGeometry and MeshPhongMaterial. This all works great.
Where I am stuck is trying to plot a trail on top of this mesh. I do this by creating a Geometry, whose vertices are of type Vector3. I cant figure out how to set the z values of these Vector3 vertices so that this Geometry lies on top of the mesh. In the attached images, I have just hard-coded 2 for the z value - and you can see that some places the trail (white line)is above the terrain, and in others it disappears below it.
I tried using the z-value from the intersecting point of where the trail intersects the PlaneGeometry - that didnt work.
Any easy ways to do just clamp the trail to the mesh?
You can raycast down onto you mesh from each point in your path to get the point on the surface, then move the path point slightly above that point.

Obtaining normal of the mesh face using raycaster intersectObjects - Three.js

I tried to obtain the normal of the mesh face using these:
ray = new THREE.Raycaster(x, y);
var intersection = ray.intersectObjects(objectsOptical, true);
var vector = intersection[0].face.normal;
Added intersection[0].point and intersection[0].face.normal (multiplied by constant) as one vertex and intersection[0].point as second vertex of a (gray) line. And I got this (red lines are rays and gray should be normals - but they are not):
Illustrative image
Please help me to obtain NORMALS of the mesh FACE.
Thank you.
The normals that you have plotted with red lines look like they might be correct taking into effect perspective projection.
The raycast test hits a single triangular face from your mesh. The normal you are referring to is the normal for the face object the ray hit, ie. from the original mesh.
In the source code for THREE.Raycaster the intersection calculations can be seen returning the face directly.
Elsewhere it is suggested that Ray.intersectObjects() requires face centroids. However I'm not sure about this since the source code doesn't refer to centroids.
Perhaps the normals in the original geometry weren't correct. Try this function first:
geometry.computeFaceNormals();

Three.js: cause an Object3D to travel parallel to my camera's X axis

Say I have a simple triangle as the only element/child in an Object3D class. I have a PerspectiveCamera looking at it, and I would like to have the Object3D travel down the camera's positive X axis, say, when I press a key.
How can I manipulate things so that the Object3D travels parallel along the camera's X axis? In looking at the inner workings of the PerspectiveCamera, I see members for things like matrixWorld and matrixWorldInverse but am not sure what they represent or how best to use them here.
Can I use the camera's matrixWorldInverse matrix to get the Object3D into camera coordinates, then move the object along the camera's x-axis (which I'm not sure how to find, as I don't see an entry for it in PerspectiveCamera, though I may not be seeing it) then multiply the Object3D by the 'matrixWorld' matrix again to move it back to world coordinates?
Have you tried making your object a child of your camera? Then any movement of the camera would affect your object. And if you place the camera lets say on the y-z plane of your object, then any movement of the object on its x-axis will also appear to be on the x-axis of the camera.

Resources