I’m trying to animate a rigged model. I’m relatively new to Three.js so am probably doing many things wrong. I’ve spend a lot of time researching online articles/docs etc. to try to get to the point where I’m not asking questions that are too stupid. My understanding is that most ‘animation’ of rigged models is done by changing the rotation of the ‘joints’ in the rig and then the children of those joints follow along.
Here’s what I’m trying to do. I have a vector3 of where I want a joint to go, and I can also get the vector3 of where the joint is now. In my reading someone suggested using the quaternion.setFromUnitVectors function to get the target quaternion. Here is what my code looks like…
function jointRotationTest() {
let quaternion = new THREE.Quaternion();
let currentposition = new THREE.Vector3();
let nextposition = new THREE.Vector3();
rightArm.getWorldPosition(currentposition);
nextposition.set(
0.24200116519857698,
1.0073554795387236,
0.05901729057492433
);
quaternion.setFromUnitVectors(currentposition, nextposition);
rightArm.quaternion.slerp(quaternion, 0.05);
}
Conceptually the way I’m thinking about the setFromUnitVectors function is that I need to get the world position (not local position) for the joint in question, and then use the current position of that joint and the future position of where I want it to head to (another vector 3) to get the quaternion. In this case I’ve been manually rotating the rightShoulder and then getting the real world position of the rightHand joint as the ‘nextposition’ Vector3. Again I’m certain I’m thinking about this wrong as when I run the code above the right arm goes up instead of down which is the opposite direction of what I’m expecting.
Ultimately I’m not married to this method, what I’m really interested in doing is animating the rig using Vector3’s that I can get from some other code I’m working on. Any suggestions would be sincerely appreciated.
I’m not sure if I understand you 100%, but this doesn’t sound quite right to me.
The vectors you give to Quaternion.setFromUnitVectors are not world positions. They are not positions at all, they are directions.
So if your arm starts out pointing in the positive X axis, and you want to rotate it such that it points in positive Z axis, you would create the following quaternion:
quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 1));
So, if you know the final rotation of the arm (as in the direction it should be pointing in) relative to where it started, then you can use this approach. But I think that’s something you need to compute first.
In the joint case, assuming a hand that moves freely, and an arm that is fixed to a pivot and rotates to maintain contact, you would subtract the pivot position of the hand from the pivot position of the arm, and that’s the direction to rotate to.
If you have more than 2 joints then it becomes more complicated and you need an inverse kinematic solver.
I’m curious to hear more about your project - usually I think you would do these animations in something like Blender and export them via glTF, or use an IK solver library (here’s the first thing that came up for me on google: GitHub - jsantell/THREE.IK: inverse kinematics for three.js)
Hi @Omar_Shehata , thank you so much for taking the time to respond. Allow me to provide a few more details to see if it helps. I’m getting my Vector3 from a pose estimation algorithm that runs near real time on a video feed. This algorithm collects position information on a number of points on the body. So for example I can get the Vector3 for right wrist, right elbow, right shoulder and so on. What I am trying to do (unsuccessfully so far) is use this information to ‘animate’ a 3D model (gltf) such that the 3D model ‘mimics’ the movement that is taking place by the person in the video that is being analyzed by the pose estimation algorithm.
I’m sure there is a better approach to trying to do this than what I am currently doing but despite many hours of research I haven’t figured it out yet so I decided to pose here. Does this help?