RotationFromAxis / RotationQuaternionFromAxis to arbitrarily align a face to a plane

OK, fixed!

My solution is convoluted but it allows me to freely rotate an object until a Vector3 is aligned to another Vector3:

  • bake world matrix into absolute position and rotation of each child node (this is different to bakeTransformIntoVertices, and is a custom function I saw here), edit: or just remove parent of child node
  • remove parent reference temporarily from each child node (they are now freely floating in space in the same position)
  • clone the transform node and make it look at one of the absolute positions of the former child nodes
  • re-add the child nodes to the original parent node
  • copy the rotation from the cloned transform node to the original transform node

In the sketch this basically just means click on a mesh → mesh centers in the viewport

And it could also be done with “lookAt” instead of creating a clone - but this way there is future possibility to interpolate or modify the rotation start and end point.


    // BAKE TRANSFORM

    function bakeWorldMatrix( mesh ) {

        if (mesh.parent) mesh.parent.computeWorldMatrix(true)
        mesh.computeWorldMatrix(true)
        let rotation = BABYLON.Quaternion.Identity()
        let position = BABYLON.Vector3.Zero()

        mesh.getWorldMatrix().decompose(BABYLON.Vector3.Zero(), rotation, position)
        if (mesh.rotationQuaternion) {
            mesh.rotationQuaternion.copyFrom(rotation)
        } else {
            rotation.toEulerAnglesToRef(mesh.rotation)
        }

        // REMOVE PARENT

        if (mesh.parent) mesh.parent = undefined

        mesh.position.x = position.x
        mesh.position.y = position.y
        mesh.position.z = position.z

        return mesh 
    }

    // ============ ATTEMPT ============

    function alignPolygonMeshToFloor( mesh ) {

        const centerPoint = new BABYLON.Vector3(0,0,0)
        const groundPoint = ground.getAbsolutePosition().clone()
        const cameraPoint = camera.position.clone()

        // BAKE TRANSFORMS INTO CHILDREN (AND REMOVE PARENT)

        polygonMeshes.map( polyMesh => bakeWorldMatrix(polyMesh) )
        // OR polygonMeshes.map( polyMesh => polyMesh.setParent(null) )


        // NODE LOOKS AT MESH ABSOLUTE POSITION

        mainTransformNode.lookAt( mesh.getAbsolutePosition() )

        // CLONE NODE TO GET A NEW ROTATION (AND DELETE)

        let clone = mainTransformNode.clone("clonedTransformNode")
        clone.lookAt( cameraPoint )
        bakeWorldMatrix( clone )
        const rotationQuaternion = clone.rotationQuaternion ? clone.rotationQuaternion.clone() : null
        const rotation = clone.rotation ? clone.rotation.clone() : null
        clone.dispose()

        // ADD CHILDREN BACK TO NODE + SET NODE ROTATION TO CLONES

        polygonMeshes.map( polyMesh => polyMesh.setParent( mainTransformNode ) )
        if (rotationQuaternion) mainTransformNode.rotationQuaternion = rotationQuaternion
        if (rotation) mainTransformNode.rotation = rotation

    }

Hope this is useful for others!

3 Likes