Three.js: Method to get the Hessian normal form of Plane geometries

Created on 4 Feb 2018  路  5Comments  路  Source: mrdoob/three.js

Hello!
To get the Hessian representation of a Plane geometry, I go through these stages:
1) Sample a random point on the surface (around 10 lines of code)
2) Get the world normals of the mesh (around 4 lines of code)
3) Calculate the normal.x, normal.y, normal.z and the constant p for the Plane constructor (around 10 lines of code)

So it takes around 24 lines of code to get the Plane object from a Plane mesh. I believe it would be really useful to have a one-liner (Plane.fromPlaneGeometry() or something like that) since the Plane class can be really handy when estimating collisions etc.

Thanks!

Enhancement

Most helpful comment

world normal = face.normal.applyMatrix4(newTHREE.Matrix4().extractRotation(mesh.matrixWorld))

Avoid calling new or clone() in hot methods.

To get you started, here is a first-cut at a method to do what you want. It is sightly more complicated if the mesh has a parent object.

THREE.Plane.prototype.setFromPlaneMesh = function ( mesh ) {

    var normal = new THREE.Vector3();

    return function setFromPlaneMesh( mesh ) {

        // assumes mesh is a child of the scene

        normal.set( 0, 0, 1 ).applyQuaternion( mesh.quaternion );

        this.setFromNormalAndCoplanarPoint( normal, mesh.position );

    };

}();

All 5 comments

Can you share the code you've written so we have more for context?

Thanks for the quick response.

I was looking for an efficient way to handle particle (Sprite) collisions with various objects. In my scene I have planes, boxes and the combination of those (rotated or not) so I thought a nice way would be to draw an imaginative line (represented using Line3) from the position at [t-1] to the position at [t] of the related sprite and check for the intersection of this line with the Hessian representations of my objects (a Plane for each face).

Since the THREE.js provides the normals I thought if I sampled a point on the surface, I could use the Hessian formula to represent my objects and then check for the intersections using intersectLine of the Plane class.

To sample the point I use a non THREE.js related function that I've written, which returns a random point on one of the 6 faces of a box, given the width, height and the depth. For surfaces I give 0 for the depth. To calculate the normals:

1) Get geometry.faces
2) For each face:
2a) world normal = face.normal.applyMatrix4(newTHREE.Matrix4().extractRotation(mesh.matrixWorld))
3) Normal for the Plane constructor: normal.x = a / (aa + bb + cc)
normal.y = b / (a
a + bb + cc)
normal.z = c / (aa + bb + c*c)
where a = x of world normal, b = y of world normal, c = z of world normal calculated in (2a)
4) Constant for the Plane constructor: -1 * ((a * sp.x) + (b * sp.y) + (c * sp.z)) where sp is the sampled point.
5) Create a new Plane object using the normal (2a) and the constant (4).

This seem to work as I'm still testing to detect strange behaviours. I'm aware that the Hessian plane and the Plane mesh are not the same thing, however, since we can create Bounding Boxes from objects using a one-liner (Box3.setFromObject()), I believe it would be great to have the same kind of method for the Plane class. It's just an opinion :)

since we can create Bounding Boxes from objects using a one-liner (Box3.setFromObject()), I believe it would be great to have the same kind of method for the Plane class.

I am against this suggestion. Creating bounding volumes like bounding spheres and AABBs from meshes is a generic approach which produces valid results for all types of geometries. This fact is not true for planes. From my point of view, this problem is too specifc needs to be solved in user code.

world normal = face.normal.applyMatrix4(newTHREE.Matrix4().extractRotation(mesh.matrixWorld))

Avoid calling new or clone() in hot methods.

To get you started, here is a first-cut at a method to do what you want. It is sightly more complicated if the mesh has a parent object.

THREE.Plane.prototype.setFromPlaneMesh = function ( mesh ) {

    var normal = new THREE.Vector3();

    return function setFromPlaneMesh( mesh ) {

        // assumes mesh is a child of the scene

        normal.set( 0, 0, 1 ).applyQuaternion( mesh.quaternion );

        this.setFromNormalAndCoplanarPoint( normal, mesh.position );

    };

}();

Thank you! I've never realized this was an option :)

Was this page helpful?
0 / 5 - 0 ratings