-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for Skinned Mesh #9
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great find & thanks for filing! Does this affect all FBX files/skinned meshes? The skinned-mesh
example doesn't seem to work well for me; the last bone seems to just twitch -- some comments inline that I suspect could be the culprit. The current examples also act strangely (the bones begin to fold in on each other), which are only regular mesh/geometry -- what direction do the bones point for SkinnedMesh/Skeleton? It's been a while since I've dug into this code so I'm a bit rusty, but interested in learning more
examples/skinned-mesh.html
Outdated
const chain = new IK.IKChain(); | ||
var currentBone = boneGroup | ||
for (let i = 0; i < 4; i++) { | ||
currentBone = currentBone.children[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currentBone
doesn't appear to change over the loop, setting multiple joints to the same bone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, if you print out the joint array at the end, each joint as a bone with a unique UUID. I've noticed this kind of bug with console.logging before, I think it's a real issue :0
examples/skinned-mesh.html
Outdated
|
||
update() { | ||
if(this.target){ | ||
this.target.position.z = 1+Math.sin(0.01*Date.now()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
performance.now()
is probably more appropriate here
Hey, thanks for checking out the fix. So I looked into it again and yes the other examples seem to act strangely, with the constraint of 90. However when you increase the constraint to 360, the examples are identical to the original. Ideally this constraint should be 180 degrees.. is there a reason why in the constraint code you use THREE.IK/src/IKBallConstraint.js Line 38 in d502845
|
I also just pushed a commit that makes the |
For a ball joint, 90 degrees of rotation is 45 degrees from the normal in any direction |
Hm, but I think the angle you are calculating is the full angle between the direction and parent direction, not the angle from the normal |
In the images you just posted it looks to me like there is 45 degrees between parent/child directions, which would correspond to a 90 degree constraint parameter in the current implementation -- although I think it would make more sense to have this correspond to a 45 degree constraint parameter |
In the images, the blue lines indicate forward/+Z -- along the plane of a child bone, the angles are > 90 degrees. This patch also changes the axis of the child bone (#1) to -Z. Is the issue your facing from FBX loader using a different forward axis for the bones? If this were a hinge constraint, it looks like it'd be around 45 degrees in those examples -- a ball/socket constraint (AFAIK) however is total range of motion, similar to field of view (e.g. a VR headset with 120 degrees of horizontal FOV is 60 degrees to the left and 60 degrees to the right). Our shoulders, for example, have a range of movement of around 180 degrees, able to be rotated around a hemisphere. |
So it seems like the constraint angle calculation is messed up by the z flipping, because after flipping the parent bone, it's flipped direction is used to see if a constraint should be applied to its child. I can think of some ways to fix this, but want to check with you first if there is an obvious solution :) |
@jsantell , So I went ahead and just flipped the z axis permanently to be consistent with the skinned mesh. All examples seem to be restored. Let me know if changing the schema to -Z is okay. I think it should be fine for now since there are no other examples that have +Z skinning. In the future maybe this could be parameterized. |
i try this for some time without this patch from this PR using a skinnedMesh gltf model the source is here https://glitch.com/edit/#!/uncovered-produce would be realy cool some one could look at this |
hi @arpu, I checked it out. There are a few things I noticed - I added that here: now it seems like the IK is working when you move the target around. However the mesh does not look like its binded correctly. Have you used this model before? |
wau thx a lot now this all makes much more sense for me, thx a lot for the hint for now for me it looks like the bone IK scaling is wrong |
add this line~ https://glitch.com/edit/#!/quiver-tune still not sure what's going on with the mesh bindings, my guess is that the skeleton bind matrices were not imported correctly.. |
awesome! the strange is i cannot see the IKHelper Bones anymore |
I'm not sure I follow, but is the issue the FBX model uses -Z as it's forward direction? Trying a handful of skeletons, there were no consistent patterns I've seen (others noted in #1), and it doesn't appear to be specific to SkinnedMesh (correct me if I'm wrong!) If that's the case, then maybe a better solution could be a utility to convert the axes of the bones to a consistent direction. Thoughts? |
@jsantell , The model I am testing with right now is exported from HoudiniFx, but as you mentioned, it's not a consistent pattern with other softwares. I'm not sure if a utility to convert the axes of the bones would work, because if you flip the bones you would also need to flip the skinned weight coefficients, right? I feel like a less messy option would be to just add a parameter to the IK constructor. |
sorry for the noise in this thread, will open a new Issue |
Weights are mapping from vertices to bones, so those shouldn't change I think. Changing coordinate systems/orientations is a surprisingly difficult task AFAIK in the general sense, although some are easier than others (e.g. -Z -> +Z). While not a coordinate system, the same idea applies; could the IK system get away with not having an opinion about this, and use whatever is provided? (I haven't looked at the code in a bit, but have learned a lot of things over the last few months 😄 )
I think this would still require a coordinate mapping conversion, no? |
Note: this is a good resource on coordinate system remapping although unsure if it's applicable for rotations, and the closest thing I've ever seen for a generalizable formula. Looking at more rigs and the code, an idea: what if the joints use their children's position to determine what the forward is by storing the joint's initial rotation? Maya has +X, this FBX here has -Z, openGL/three use +Z, etc., I don't think a solution that requires any specific direction (even +Z) will work without some sort of coordinate system casting, which should already be handled at the model level.
That might work for the generalized case? There are a lot of implicit assumptions about forward in the codebase which would have to be changed. What do you think? @arpu @sneha-belkhale |
@jsantell
What I meant by this was a parameter to notify that the bones were modeled in a -Z forward coordinate system. If so, we could just apply the fixes that I've made in this PR. However, this obviously would not generalize to any coordinate system so probably not a good solution. I think the approach you have described sounds reasonable, should keep things consistent. I just did a test where I go through the bone hierarchy and align the parent quaternion so that it's forward is pointing towards the child position. In the screenshot you can see that the blue lines of the bones are facing the next bone, so it seems to be implemented correctly. However there is clearly still a binding issue. I think because the bind matrices given with the model are no longer accurate. Oh and this image is after I tried |
Hey, so spent some time debugging the issue above and turns out there was a bug in my conversion code. I fixed it and seems like the binding matrices have updated correctly! I'll push the conversion utility soon, currently only works on a single chain skeleton, but should be good enough to start a review. |
Hey, just for an update on this, the utility has worked for the example, my project, and issue #10, which are from HoudiniFX and Blender. Probably should test a model from Maya as well.. I just don't have one. So for this pull request, we no longer need to change any of the existing code. Instead, the utility and the example of how to use it should do. @jsantell , let me know what you think. |
Glad to see the Z flip is working well! Until landing some generalized way of handling the orientations in the core, having this utility available to fix -Z models will be valuable. Thank you! I added the dependencies to be managed by npm and updated three.js to latest r102 and made the appropriate changes #11 (and committed for gh-pages); could you squash and rebase your commits then with only the new example/assets? |
… axis conversion utility to convert models to +Z Forward coordinate system
@jsantell awesome, the PR now has one commit with the asset, example, and utility. |
Thanks @sneha-belkhale! Looking great, let's get this merged in -- thanks for your patience, this solution looks great for folks wanting to use this with practical, real models! |
Hey @jsantell ,
Firstly, thanks for making this repo ~~
Secondly, I looked into integrating the three.ik system with the three.js skinned meshes / skeletons. Things looked really disastrous on the first try, the vertex points were completely out of place causing the bones to look dislocated.
It was pretty clear that there was a discrepancy between the direction of the
IK.Joints
and the direction of the three.js bones. It may not have been apparent to you if you were testing using the helpers, because the helpers are designed relative to the direction between theIK.Joints
anyways.I've added a fix to the src files in this PR that addresses this fix by using the correct direction when applying the transformation to the three.js bone -- along with a small example for testing.
Let me know what you think.
If it looks alright, I can make a better example and we can add it to the page.