PeizhuoLi / neural-blend-shapes

An end-to-end library for automatic character rigging, skinning, and blend shapes generation, as well as a visualization tool [SIGGRAPH 2021]
Other
637 stars 92 forks source link

forward kinematics implementation #26

Closed iszihan closed 1 year ago

iszihan commented 1 year ago

Hello, I was trying to understand the forward kinematics implementation and was looking at https://www.alecjacobson.com/weblog/?p=3763 this blog post for clarification, and the implementation doesn't seem to match up for non-parent bones.

`for i, p in enumerate(self.parents): if i != 0: rots[:, i] = torch.matmul(rots[:, p], rots[:, i]) pos[:, i] = torch.matmul(rots[:, p], offsets[:, i].unsqueeze(-1)).squeeze(-1) + pos[:, p] rest_pos[:, i] = rest_pos[:, p] + offsets[:, i]

        res[:, i, :3, :3] = rots[:, i]
        res[:, i, :, 3] = torch.matmul(rots[:, i], -rest_pos[:, i].unsqueeze(-1)).squeeze(-1) + pos[:, i]

` Suppose I have two bones located at b1, b2 with m1 and m2 as the local transformation matrix and b1 is b2's parent bone, according to the implementation in this codebase, the global translation for bone 2 is m1 m2 (-b1-b2) + ( m1 * b2 + b1 ).

However, according to the formula in this blog post, it should be m1 m2 (-b2) + m1 * (b1+b2) + b1

I'm wondering if you know why is the difference in this implementation?

PeizhuoLi commented 1 year ago

Hi, I think our implementation is the same as the post. Note that in our implementation, the rest_pos is the position of the root of a joint. Namely rest_pos of bone 2 is b2, while offset is the relative position of a bone (e.g. offset of bone 2 is b2 - b1). pos indicates the position of the root of the corresponding bone after applying the rotations, so pos of bone 2 is m1(b2 - b1) + b1.

Putting everything together, the global translation for bone 2 according to our implementation is m1m2 (-b2) + m1(b2 - b1) + b1. It is the same as t₁ = - q₁q₀x₁ + q₀x₁-q₀x₀+x₀ described in the post.

iszihan commented 1 year ago

Thank you for the quick reply! I was following the demo.py to understand it. In this line (https://github.com/PeizhuoLi/neural-blend-shapes/blob/6d108309bf6892240e5c15b527bc4f5178afed9a/demo.py#L90), skeleton is passed in as the offsets, which seems to be the root of joints when I visualized it. Is it not the case?

PeizhuoLi commented 1 year ago

Hi, skeleton is the offsets of a bone to its parent bone. The only "exception" is the offset of the root joint - it is the offset to the origin, thus is the absolute position.

iszihan commented 1 year ago

Thank you that explains it!