Set plane orientation

I have an issue with setting a plane orientation to the face normal direction in local space.

I am using a raycaster to get an intersection point and the intersection face normals, using I am adding a plane in the mesh that is found based on the intersection point and I set the plane orientation based on the face normal in local space, here is the example please click on the model and you will see a small plane that is oriented based on the face direction, here is the code I use and it works fine. Start

// Set the position of the plane at the intersection point in local coordinates of the intersected object.
const localIntersection = intersectionPoint.clone().sub(this.deepestChild.position);
this.helperPlane.position.copy(localIntersection);

// Orient the plane to match the normal of the intersected face.
this.helperPlane.lookAt(new THREE.Vector3().addVectors(intersectionPoint, faceNormal.clone()));
  
// Adjust the plane's position and rotation to be in the local space of the deepest child
this.helperPlane.applyMatrix4(this.deepestChild.matrixWorld.clone().invert());

When trying to do this when adding the plane in a bone I can’t figure out how to set the plane orientation in the bone local space, I have figured out how to set the local position but not the orientation, below is the code and example Start

 // Calculate the local position of the intersection within the deepest bone's space
const worldToLocal = new THREE.Matrix4().copy(this.deepestChild.matrixWorld).invert();
const localIntersection = intersectionPoint.clone().applyMatrix4(worldToLocal);

// Set the position of the plane at the calculated local intersection point
this.helperPlane.position.copy(localIntersection);

// Orient the plane to match the normal of the intersected face
this.helperPlane.lookAt(new THREE.Vector3().addVectors(intersectionPoint, faceNormal.clone()));

I am learning matrices and vertices and 3D math in general so I apologize if the terminology I used is wrong I tried my best to explain it.

I have spent all day on this with no luck, I literally don’t understand the math for the bone case :frowning:

Thank you!

There are 3 methods you should familiarize yourself with…

object.attach( object )
object.worldToLocal( point )
object.localToWorld( point )

.attach works differently than .add. It tries to keep the visual representation of the object the same, while changing its parent.
So in your case with having the correct result on the skin, and then wanting to put that result in the bone space… You may be able to just bone.attach( helperPlane ) after you set up the helperplane in the scene first like you are doing.

worldToLocal takes a point in world space, and converts it to local space of an object. This takes into account any parent/child hierarchy in between, and trying to do this manually with matrices is a pain.

localToWorld takes a point in local object space, and converts it to world space. This takes into account any parent/child hierarchy in between, and trying to do this manually with matrices is a pain.

So… it’s Good to learn about matrices and transforms etc. but once you’ve internalized it, you can often avoid having to deal directly with matrices, by just using those 3 functions I mentioned above.

1 Like

Thank you for the answer and it did help I modified the mesh version from the matrices approach to a simple one using the methods that you suggested it works and makes more sense and easier to understand the code than using matrices.

When I add the plane in a Mesh works great but when adding the plane in a Bone the position works as expected but not the orientation based on the face normals, I literally don’t understand what is going on I am exhausted trying to understand this :)…

// Convert the intersection point to the local space of the deepestChild
const localIntersection = new THREE.Vector3();
this.deepestChild.worldToLocal(localIntersection.copy(intersectionPoint));

// Set the position of the plane at the calculated local intersection point
this.helperPlane.position.copy(localIntersection);

// Calculate the target in local space to orient the plane
const localTarget = localIntersection.clone().add(faceNormal);
  
// Orient the plane to match the local face normal
this.helperPlane.lookAt(localTarget);

//Set the helper plane up in world space....
this.helperPlane.position.copy( intersectionPoint );
this.helperPlane.lookAt(new THREE.Vector3().addVectors(intersectionPoint, faceNormal.clone()));

//Now attach it to the bone(?) this automatically converts the helperPlanes matrix/transform into the bone space...

//I'm assuming you've found the relevant bone through other means?
bone.attach( this.helperPlane );


//Now helperPlane will be a child of the bone and rotate/move with it etc.
1 Like

Well this was easy :slight_smile:

I feel like it is impossible to learn all this stuff but I refuse to give up!

For others that might need this, there are just three lines of code…

this.helperPlane.position.copy(intersectionPosition);
plane.lookAt(new THREE.Vector3().addVectors(intersectionPosition, faceNormal.clone()));
intersectionChild.attach(plane);

Thank you!

1 Like

The attach method is amazing, it saves you from making some crazy math calculations that are prone to errors, I am starting to love threejs :slight_smile:

Thank you again!

2 Likes

yesss… i went far too long without knowing about those methods… and they are a total game changer.

1 Like