Just lately I am engaged on handtracking ARs. To align 3D fashions to arms, I needed to match coordinates of 3D mannequin objects to a coordinate of a hand to make results like 3D fashions on a hand and so on.
It’s a bit difficult to align them, so let me clarify methods to do it right here.
For example we now have a goal coordinate XYZ (e.g. hand) and a coordinate xyz (e.g. 3D mannequin) to align. We already know the vectors of XYZ and xyz. X/Y/Z are orthogonal one another and normalized (the size is 1) and x/y/z are additionally. The purpose is to align the xyz vectors to XYZ.
Aligning the origin positions are usually not defined on this article as a result of we will do it simply by setting the XYZ origin place to xyz origin place.
Within the following steps, I align z/Z and x/X. Nonetheless, the order of operation doesn’t matter. Chances are you’ll align y/Y first and z/Z subsequent.
First, let’s align the z axis.
Calculate the cross vector
z × Z and θ with the dot product and Arccosine which is used to rotate the coordinate across the cross vector. To attain the rotation, we will use a quaternion. Calculating quaternion by ourselves is a bit difficult and often 3D CG engine has built-in operate to calculate it from the axis to rotate round and the angle. When you actually need to implement by your self, it’s possible you’ll refer this article.
That is an instance pseudocode. Your programming language / 3D CG engine (e.g. Three.js / Unity / Unreal Engine) ought to have cross / dot / normalize / acos / fromAxisAngle.
Vec3 z = ... // Your z Vec3 Z = ... // Your Z Vec3 axisZ = normalize(cross(z, Z)); // Normalized cross vector. float angleZ = acos(dot(z, Z)); // The angle between z and Z --> theta within the picture. Quaternion qz = fromAxisAngle(axisZ, angleZ); // Later we are going to make different quaternions so let's title it qz.
Now we have got the quaternion
qz to align z to Z axis.
By making use of the quaternion
qz to your coordinate, it’s best to have x’/y’/z’ like the next picture.
Aligning x/X axes is mainly the identical course of as we did for z/Z. Nonetheless, please don’t forget apply the quaternion
qz to the x vector. Let’s title the rotated x vector as
Pseudocode ought to be like this.
applyQuaternion is a operate to use a quaternion to a vector. Your programming language / 3D engine ought to have an equal.
Vec3 rotatedX = applyQuaternion(x, qz); // x' Vec3 X = ... // Your X Vec3 axisX = normalize(cross(rotatedX, X)); float angleX = acos(dot(rotatedX, X)); // The angle between x' and X --> phi within the picture Quaternion qx = fromAxisAngle(axisX, angleX);
We have got the following quaternion
Now we now have
qx. By combining the quaternions, we can have the ultimate quaternion we will notice our coordinate alignment.
multiplyQuaternions is a operate to mix two quaternions into one. Your programming language / 3D engine ought to have an equal. Please watch out that the order of
qx is vital.
Quaternion q = mltiplyQuaternions(qz, qx);
By making use of the quaternion
q to x/y/z respectively, you will get vectors similar to X/Y/Z.
I confirmed pseudo code within the above. I additionally offer you guys an instance in Three.js.
// Your coordinates. // x/y/z are vectors that will likely be aligned FROM. const x = new Vector3(...); const y = new Vector3(...); const z = new Vector3(...); // <-- You don't want this really. // X/Y/Z are vectors that will likely be aligned TO. const X = new Vector3(...); const Y = new Vector3(...); const Z = new Vector3(...); // <-- You don't want this really. const axisZ = z.clone().cross(Z).normalize(); const angleZ = Math.acos(z.dot(Z)); const qz = new Quaternion().setFromAxisAngle(axisZ, angleZ); const rotatedX = x.clone().applyQuaternion(qz); const axisX = rotatedX.clone().cross(X).normalize(); const angleX = Math.acos(rotatedX.dot(X)); const qx = new Quaternion().setFromAxisAngle(axisX, angleX); // Remaining quaternion const q = new Quaternion().multiplyQuaternions(qz, qx); // You need to use q like this. yourModel.rotation.setFromQuaternion(q)