Some years ago now I made a generalized implementation of real-time Inverse Kinematics (IK) using the Jacobian method with two optional solvers: Transpose and Damped Least Square.
I finally got around to making a public example project here:
The solver works for arbitrary long joint chains, support constraints, and are implemented to work with imported armatures “out of the box”. Please ask if you guys have any questions or trouble using it! (also general improvements would be welcome )
And thanks for the tips! Porting it sounds smart I’ve had my trepidations for doing paralell computing on IK, but maybe I’ll get around to that as well
I just did an implementation where most of the mathematical calculations was done with WASM using SIMD, but after testing on my computer and phone it became clear the performance was exactly the same. So for now I’ve refrained from merging it into the Main branch of the project since it is a slightly more complicated (and certainly more mystical) setup.
There might be some performance benefit for monstrously long joint chains, so if anyone is interested in that, you could check it out I suppose.. or maybe there’s an even smarter implementation I haven’t tried yet.
Yes, when you test “pure” WASM with a small number of nodes, you won’t notice much difference. But in a real scenario, for example with around 30 bones, the situation changes: if the matrices are stored directly in WASM memory and then read by PlayCanvas via mat4.data and passed to the GPU without any intermediate processing in JavaScript, you get the maximum performance benefit by minimizing unnecessary copying and JS overhead.
const len = 16;
const pointer = YourWasmModule.alloc(4 * len); // for example, or get pointer by your IK solver
const matrix = new Float32Array(YourWasmModule.FLOAT32.buffer, pointer, len);
// patch node
someNode._worldTransform.data = matrix;
// ...
// resolve for example
YourWasmModule.solve(pointer...);
Hmm… I did test with 18 joints and the Damped Least Square solver (which should be most computationally heavy and therefore benefit the most) and still almost no performance improvement with my current WASM setup. I’m very new to WASM though, so probably as you show there are better ways of doing it. Still, I think in most normal real-time use cases you usually wanna limit yourself to 3-4 joints per arm, in which current setup is good I think.
Sooo.. think I will save the rest of this adventure for another time!
Not gonna stop anyone from making a fork and super-compute this thing though