#Quaternion orientation woes.

8 messages · Page 1 of 1 (latest)

swift mortar
#

Let's say I have an object made of three (or as many is necessary to solve this) points in space.

  • think of it like a collection of drones - each with a position, each outputting a point of light, but no connection between them. They may vary in distance from each other at any one time, but what I want to do is determine their overall rotation as a unit.

As far as I understand it, I can form two vectors say from A to B and A to C - normalize those vectors, making them unit vectors - and then take the cross product. THREE.Vector3.cross().

That should give me a unit vector AD pointing in the direction perpendicular to AB and AC.

If I designate a unit vector UP as (0, 0, 1) (z being up) - I should be able to get a quaternion rotation by THREE.Quaternion.fromUnitVectors() - which should give me a quaternion representing the rotation from UP to AD.

Please check my logic there.

Now if all of the above is correct, I should have a quaternion rotation - but with no guarantee that we haven't added some sort of spin to UP on the way to AD?

I understand I am likely misunderstanding something fundamental here, but I can't quite grok where my confusion lies, nor how to correct for that spin.

tawdry cove
#

To lock the 3 points into an unambiguous orientation, you would need both the cross vector and a vector in the plane of the three points or an x/y axis to map to a vector in that plane (like how you mapped the z-axis to the AD vector.

You may also know this, but keep in mind that cross products are not commutative. That is, the order in which the cross product happens matters. If you don't heed this rule, not only could your set of points be "spun" around your UP vector but also flipped the wrong way.

I hope that helps.

swift mortar
#

Maybe my confusion lies in how to do what you describe correctly.

I have three vectors represented by axis arrows right now....
one is the cross product (call it AD)
the other two are the local (0, 1, 0) call that UP and (1, 0, 0) RIGHT,.

I can see they look largely correct - but simply turning them into quaternion rotations and multiplying seems to only give me the correct result -most- of the time.

tawdry cove
#

I've never used quaternions in three.js, so I'm not sure how to get the API to do what you want to be honest.
If you have a conceptual or mathematical question about quaternions, that's something I'm pretty familiar with.
If you can characterize the conditions that cause a failure for this to work according to your expectations, that would probably help.
But the AD vector (normalized cross product of in-plane vectors) will only describe the rotation of the plane the 3 objects make, not the rotation of the objects within that plane.
If the relative distances between those objects is changing, too, then we are dealing with more than simple rotation.
That, too, can be expressed with quaternions, but that would be beyond my ability to help you with, as that would involve scaling and possibly skewing, which are beyond my experience.

#

If the edges of the triangle these three points make remain at least proportionally equivalent when their distances change, then that's not to hard, but if the edges can change length in different proportion to one another, then that's a bit of a different problem you have on your hands.

swift mortar
#

Interesting.
I didn't consider the effect the changes in the edge proportions would have on the rotation matrix overall..... but of course that would make a difference.

The edges in question remain -mostly- proportional - but do have slight variations frame to frame.

For the most part however - it seems with some futzing around, the following seems to work......

swift mortar
#

function rotQuaternionCalculation() {
uVecPlane = marker9.sub(marker0);
uVecPlane.normalize();
let vec2 = new THREE.Vector3().copy(marker13);
vec2.sub(marker0);

normal = new THREE.Vector3().crossVectors(uVecPlane, vec2);
normal.normalize();

tangent = new THREE.Vector3().crossVectors(uVecPlane, normal );
tangent.normalize();

binormal = new THREE.Vector3().crossVectors(tangent, normal);
binormal.normalize();

let rotMatrix = new THREE.Matrix3().set(
tangent.x, tangent.y, tangent.z,
-binormal.x, -binormal.y, -binormal.z,
normal.x, normal.y, normal.z);
// overwrite previous - not sure which is correct.
rotMatrix = new THREE.Matrix3().set(
tangent.x, -binormal.x, normal.x,
tangent.y, -binormal.y, normal.y,
tangent.z, -binormal.z, normal.z);

let tMat4 = new THREE.Matrix4().setFromMatrix3(rotMatrix);
let tQuat = new THREE.Quaternion().setFromRotationMatrix(tMat4);
tQuat.normalize();
return tQuat;
}
var uVecPlane;
var binormal, normal, tangent;

#

I feel like my error is somewhere in how I'm plugging the unit vectors into "let rotMatrix ="

the latter of the two seems to yield the more accurate results - but not as close as I'd like.

Oddly, using the above of the two -also- gives me semi-accurate results - I would have thought it would be wildly off.