Hi, this is a difficult problem to report - my project to animate a human skeleton now runs to 8 classes and thousands of lines of code so I cannot reproduce a playground example.
[ Please note I am not using any kind of external rigging, mesh deformations, skins - when I use the term bone I mean something that looks like a real bone in your body - there is a risk of confusion here. I am performing non-deforming transforms on meshes that resemble human bones - all relationships and joints are handled by my code - nothing to do with more usual animation and rigging examples ]
Basically the problem is that I have never been able to get the recommended method for updating vertex or mesh positions after transformations to work in order that I can immediately use their new (updated) world co-ordinates to calculate other transformations - before the render. It seems I have to wait for a render in order that I can read updated vertex positions in world space.
I have read the recommended fixes along the lines of
var matrix = mesh.getWorldMatrix(true);
var local_position = new BABYLON.Vector3(0,1,0);
var global_position = BABYLON.Vector3.TransformCoordinates(local_position, matrix);
but I have never been able to get this to work in my code, tried to use it in various situations over the months, as part of a new sub-project I now encounter the same familiar problem again.
I have started a new version of my code which has the pelvis as the root or start of the chain of parent-child relationships which describe the structure of the bones of the skeleton, the root used to be a bone in the foot.
The structure simplified is…
root => joint => bone => joint => bone => joint => bone => joint => bone
The joints are rotational with varying degrees of freedom.
The root is just a special bone because it is the head of the chain - it has no parent.
The bones are all meshes, the joints are either small spheres (debug mode) or TransformNodes (non-debug mode) - performance reasons when I do not need to see the joint positions.
Now that I have changed the linkage so that the root bone is the pelvis and not the foot the consequence is that an instruction to get the skeleton to “squat” means that instead of moving down the skeleton now raises his legs and hangs suspended - this was expected, the penalty I have to pay for more flexibility is that I have to implement a new class called “gravity”.
The job of gravity is to say - “ohh the legs have folded at various joints and because the pelvis is now the root the legs will simply have raised up leaving the skeleton hovering above the ground - I better calculate how much to move the entire skeleton down so his feet are still on the ground.”
The basic idea in the code is…
- rotate thigh bone in pelvis joint one increment
- rotate lower leg about knee one increment
- rotate foot so its still horizontal
- scan absolute position of vertices in foot to find lowest - once found measure distance to floor.
- move entire skeleton up or down to by the amount calculated in 4 so that the lowest part of the foot is now on the ground.
- Repeat go back to 1 - next incremental movement in the animation.
Always the problem I find is that the reported absolute positions of vertices in step 4 is not up to date with the changes in the rotation of bones in steps 1 2 3 infact the positions reported correspond to the previous pass through all the steps.
This “lag” would be expected if I were not calling mesh.getWorldMatrix(true) because the render has not yet updated the world matrix for each mesh in the chains of bones, however I am calling getWorldMatrix(true).
I have actually written a temporary function in the class responsible for bones and joints that calls it on absolutely every one of my meshes before and after the leg bones have been rotated. Its deliberate absolute overkill but it just does not seem to help - it seems that whenever I transform meshes in the same piece of code that I then try to calculate geometric consequences of those transformations that the transformations have not yet been applied to the world matrix to enable me to obtain the new world co-ordinates. I have been in this position previously in other areas of my code.
I just wanted to check if there is anything obvious that I should know about?
Characteristics that might be peculiar to my example and not others…
Almost all movements are pure rotations - indeed the only translations involved are ones implemented in the class gravity that are intended to push the skeleton back onto the ground so he does a squat and not a leg raise. Prior to the implementation of gravity there were no translations involved at all only rotations of bones about joints, the joint usually having been in turn rotated about another joint and so on. Is there something about long chains of parent child meshes in which each child is rotated in the local space of its parent and that parent in turn is rotated in the local space of its parent and so on.
Long chains - there are hundreds of bones in my model - are there any hard limits set up in the mesh.getWorldMatrix(true) which do not act due to timeouts or lengths of child parent chains?
Babylon can cope with my chains of bones - I can animate the skeleton in real time with no evidence of it having problems - the updating must be working correctly in the render it just seems that I cannot provoke the same update inbetween render frames so that I can perform rotations, measure new relationships and then make adjustments in the form of secondary transformations in this case to move the skeleton so that its lowest points are back on the ground.
Always the pattern is that after a render everything tallies up but I cannot seem to provoke the same state of resolution in my code that the render achieves.
Eventually I intend the gravity class will become more sophisticated and automatically identify the lowest 3 non adjacent points on the entire skeleton and automatically reposition so that these form a stable base on the ground so I do need the general solution.
Thanks for any advice on what could be wrong - I know previous reports of bugs in this area have either been fixed or not verified but to me it looks as if there is still something here that is amiss.