I’m trying to convert a THREE.Object3D quaternion to and insert normal vector and rotation for use in a DXF drawing.
Below is partially working code. The insert vector seems to be calculated correctly but the rotation around that vector only works if the object insert vector is near (x: 0, y: 1, z: 0) plane. I don't seem to be able to find a way to account for the vector.
import { MathUtils, Object3D, Quaternion, Vector3 } from "three";
export function getRotationOnPlaneFromQuaternion(quaternion: Quaternion) {
const object = new Object3D();
object.quaternion.copy(quaternion);
const insertNormal = object.up.clone().applyQuaternion(object.getWorldQuaternion(new Quaternion()));
const initialForward = new Vector3(0, 0, 1);
// 2. Compute the current forward vector
const currentForward = initialForward.clone().applyQuaternion(object.quaternion);
// 3. Project the vectors onto the plane perpendicular to the up-axis
const initialProjected = initialForward.clone().projectOnPlane(insertNormal);
const currentProjected = currentForward.clone().projectOnPlane(insertNormal);
// 4. Compute the angle between the projected vectors
let rotation = MathUtils.radToDeg(currentProjected.angleTo(initialProjected));
// 5. Determine the direction of the rotation
const crossProduct = new Vector3().crossVectors(initialProjected, currentProjected);
if (crossProduct.y < 0) {
rotation = 360 - rotation;
}
console.log(quaternion, insertNormal, rotation);
return { rotation, insertNormal };
}
getRotationOnPlaneFromQuaternion(new Quaternion(0.0016539615100301002, 0.6118680073155581, 0.0021380584578606005, 0.7909552672187234)); // Works 75.44951016783165
getRotationOnPlaneFromQuaternion(new Quaternion(0.06902894353202288, 0.5853380727748623, 0.09461360593069452, 0.8022858661897604)); // 71.75956142781651 - Expected around ~89
getRotationOnPlaneFromQuaternion(new Quaternion(0.13752154621828078, 0.5945058704625087, 0.17854775191073505, 0.7718622251405822)); // 73.6215463749499 - Expected around ~90
I found a similar question here DXF files - How does the normal vector and position relative to this provide full understanding of block position but it didn't help me solve the problem.
You are using the y-component of the cross product (
crossProduct.y
) to determine the direction of the rotation. However, this may not be reliable in all cases, as it depends on the orientation of your objects. Instead, you can use the dot product between the normal vector and the cross product to determine the sign of the rotation.Here is the updated code: