What about animations that move bones ?
And all this is now a problem because of the UNITY/GLTF/BABYLON skinning. Like what you applied the fix for.
So if i go back to .babylon scene files i dont have to worry about this at all because we move the mesh in non-gltf version and not the bones… But in gltf version the parent meshes we move are really bones… so we are moving the bones and need to call refreshBoundingInfo and every position move so the little bounding rects come along with us… And that does matter mater if i move 1 unit or 100 units… if the mesh is in camera view or not… In gltf… if you want that little WHITE BOUND rect that shows in the inspector to FOLLOW the character at all times… You GOTTA call refreshBoundingInfo … So i t can follow the bones we just moved (Since the parent meshes are now bones)
Wow… I think i got it… Its kinda a bummer … But i think i understand WHY its doing it. But that might not work as the DEFAULT usage of the Babylon Toolkit… VS using Native Babylon Scene Files…
Yo @bghgary … I decided to try push off the bounding info update to my Character Controller component… Take a Look:
/**
* Babylon character controller class
* @class CharacterController
*/
export class CharacterController extends BABYLON.ScriptComponent {
private skins:BABYLON.AbstractMesh[] = null;
private lastPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();
private lastRotation:BABYLON.Quaternion = BABYLON.Quaternion.Identity();
public constructor(transform: BABYLON.TransformNode, scene: BABYLON.Scene, properties: any = {}) {
super(transform, scene, properties);
// ..
// Validate Skin Bounding Box Info
// ..
let skinned:boolean = false;
const metadata:any = this.getMetadata();
if (metadata != null && metadata.skin === true) {
skinned = true;
}
this.skins = this.transform.getChildMeshes(false, (node) => {
const data:any = BABYLON.SceneManager.FindSceneMetadata(node as BABYLON.TransformNode);
return ((data != null && data.skin === true) || (skinned === true && node.name.indexOf("_primitive") >= 0));
});
if (skinned === true && this.transform instanceof BABYLON.AbstractMesh) {
if (this.skins == null) this.skins = [];
this.skins.unshift(this.transform as BABYLON.AbstractMesh);
}
}
protected start(): void {
// Start render loop function
}
protected update(): void {
// Update render loop function
}
protected after(): void {
if (this.skins != null && this.skins.length > 0) {
if (this.transform.position.x !== this.lastPosition.x || this.transform.position.y !== this.lastPosition.y || this.transform.position.z !== this.lastPosition.z) {
// ..
// Refresh Skin Bounding Box Info
// ..
this.skins.forEach((skin:BABYLON.AbstractMesh) => {
skin.refreshBoundingInfo(true);
});
this.lastPosition.x = this.transform.position.x;
this.lastPosition.y = this.transform.position.y;
this.lastPosition.z = this.transform.position.z;
}
}
}
protected destroy(): void {
this.skins = null;
}
}
That seems to be working… The Character Controller
1… On construction, get all the SKIN type meshes (and primitives if the the top level mesh was a skin with submeshes that the GLTF split apart into separate nodes for each primitive)
2… On after… it check that the root transform position has changed, if so it updates ALL skin bounding box info.
UPDATE:
Seems to be working BUT DOES ADD QUITE A BIT of overhead in performance… But my question is… Should i be checking for ROTATION as well and update the bounding box info when the rotation changes as well ???
Same issue with animation moving bones. This is an issue with GPU skinning in general. Unity AFAIK computes skinning on the CPU.
Yes, which is why it’s not done by default. If this is being done per frame, it’s effectively doing CPU skinning.
I would think so if you are talking changing the rotation of a node linked to a bone.
Yo @bghgary … I need your advise yet again.
What would you do about the GLTF Skinning.
A… Just dont do refreshBoundingInfo (Which leaves the bounding box at its original pos even those the character itself ha moved…via the parent meshes which are bones) and make the user update his own bounding box when moving… Note: I hate this option
B… Create some kind of strategic refreshBoundingInfo like i am doing now… I have my character controller check the last position of the ROOT game object if the difference is more than 0.1 I refresh the bounding info for EACH AND EVERY mesh or child mesh that comprises the character. Note: This adds a bit of a performance hit. But checking the difference in position and only calling when greater than a certain threshold (0.1) is betting than just calling refreshBoundingInfo on every frame no matter what.
C… Go back to using native babylon scene files. Which does skinning a bit different. That way is better when it comes to moving a skinned mesh around in the world. But you loose all the GLTF stuff… like the binary data that is ready to go strait to the GPU. Blend shapes, etc…
Im torn… I wanna do GLTF but i so worried about performance … especially when using more than one skinned character in your scene. But using the native babylon scene files, I never had to worry about the performance of moving my character around. But you get the overhead of EVERYTHING being strait JSON… Mesh Data, Animation Data, Weights, Joints… Etc… All the stuff that in GLTF gets encoded to the binary stream of the GLTF.
This is depressing (after all the work i put in to try and make a Babylon Game Dev IDE)
What Would Gary Do ???
Hello!
Also interested to hear Gary’s advice on glTF skinning.
I’ve read your work for a few years, and it is great. Thank you.
Also M, I wonder… did you get all Remy rigging and bone animations working after import?
Worth checking and confirming all. I ran into a tough IK complexity worth sharing, if so.
Also interested in GPU/CPU in frame based animation and glTF skinning!
About performance - we keep 60fps by continual optimization on many low-poly. So it is possible.
Within limited understanding. Seems like Remy is high-poly?
Is your performance concern at load-time or run-time, both, or other?
Cool thread.
Yo @aFalcon … I did get the rigging and bone animations working pretty good. I even got multi-target animation (I got a fish animation that was PARTLY transform animation and partly skeletal animation… But GLTF allowed me to easily create Animation Channels that had different targets when you play the single animation BOTH the transform and the bones get animated… That was one of things i really like about encoding into gltf… BlendShapes and BlendShape animation was pretty easy in GLTF as well)
A far a IK… Well i use a AnimationState system i made before and left a small little CALLBACK hook AFTER i had updated all the bone._matrix with WEIGHTED animations blending (including layers)… In the callback is here i intended the BoneIKController to do its work… Right after the animation state set all the bone matrix BUT before anything else… The perfect spot to do Bone IK Stuff.
Run time performance concerns about having to update the skin bounding box info every frame to keep in sync with the actual character… Plus if the bounding boxes are NOT in camera view… it wont render that peice of geometry the bounding box is for.
Basically … If you want that little BOUNDING rect that show in the inspector to be in sync with character (And you do want that)… Then you gotta do some kind of mesh.refreshBoundingInfo… But do it strategically …
Yes Remy is HIGH-POLY … but more like the characters you will get when downloading from Mixamo or some other character building software… He is not that bad though on performance if i DID NOT have to refreshBoundingInfo on every frame
Awesome, did-not-know this about EASY BlendShapes glTF! Thank you @MackeyK24 !
Have you seen @Pryme8 's FISH. It is very realistic. He used a sin wave on the body transform.
If you haven’t seen, it’s worth a look… BUT… oh you have skeletal??? Interesting!
Compare Fish - new thread!
ha! Oops. falcon did low-poly fish physics for some bad~bugs…
-
Animation Channels. Like! I hear you.
-
Bone Matrix - I know nothing of this. Interesting!
-
Callback Hook - sounds like an improvement since deep-dive there…
Cool. Thanks for sharing.
I wonder if you and Gary find a surprise alternative to refresh Bounding Info on every frame.
How to keep the skin on those bones!?!
I’m not there yet, maybe next year!
Yo @bghgary … Some food for thought…
If you at least put that option in to NOT break my skin sub meshes into separate primitives.
I could at least optimize my characters like Remy to have 1 skin with sub meshes for each material.
that way i only have to update 1 bounding box per character… the main skin mesh
Think about it … Please
We can definitely add an option for this, but it might be a bit before I can add it. Feel free to open an issue on GitHub to add this feature.
I want to figure out a way to fix your issue. I’m preparing for a conference next week, so it might be some time before I have something.