Sitting on a chair

1

Dear Jedi Council, I stand before you a humble potato with no real grasp of maths, and -1 Häagen-Dazs 500ml for my troubles.

The Mission
My mission was simple, walk my avatar over to a chair and sit down. I hypothesised all of the ways to achieve my goal. Problem one was that my chair could be any direction, so I created an invisible mesh( prob should have expanded the bounding box for this one but you live and learn) around the chair and on intersection of the player mesh, I rotated the chair towards the player. It only cost me a day.

My potato brain thinks in 360 degrees so initially, I was just thinking I need the angle between the front of the chair and the player position. Eventually, I managed to figure out creating a matrix, and using look to

          let lookMatrix = Matrix.LookAtLH(
            this.chair.mesh.position,
            this.engine.avatar.mesh.position,
            Vector3.Up()
          ).invert();

          let rotationQuaternion = Quaternion.FromRotationMatrix(lookMatrix);

But now I know that If I dot product the vectors and then divide by the square root added together then I end up with an angle if I do a arcsign …still don’t get it.

Right-handed vs Left
I think I’m inverting because of the whole left and right thing and blender being in the Right-hand mode and me not going that and building everything without setting the right-hand mode for GLTF things first, doh!

The Story Continues
Anyway, so far, walk over to the chair, chair rotates (it’s not perfect for sure but hey ho), cool!

Build an animation of a little dude sitting on the chair, cool, I thought this probably isn’t going to work because the animation will move the x,z position of the player and the origin will be all messed up, this is 100% what happens.

2

My question is, what is the right way to think about this getting an avatar to sit on a chair from standing, it’s not as easy as getting them into a sitting position because there is a small jump and x,z move involved to get them into position on the chair. I thought this might be solved by creating a spline in blender and having the player follow it with easing to replicate the jump into the right position.

I’m parenting the player to the chair so when the chair spins back to its starting position we’re pretty good.

I guess what I’m really lost with is the correct flow from blender to Babylon, how do I do in each one.

Also just a massive thank you to this incredible team, and an amazing engine, the fantastic youtube content, I promise I’ve tried to solve this one myself as best I can but I think I’m, missing some of those high school fundamentals to get this right solo.

Final thoughts
It feels like the choreography between the player, the animation for sitting, the movement onto the chair is something that is done in blender and not in engine and I am just the consumer of these things.

Did I miss a trick with animation groups, was the correct approach do something with combined animation groups…

Again thank you super humbly, and sorry I couldn’t figure it out on my own.

2 Likes

Adding @PatrickRyan our amazing artist to the thread :slight_smile:

1 Like

No problem at all, we’re very happy to help! Patrick will be of great help here :smiley:

LOL

This might be the single best first post sentence EVER!!! LOL HAHAHA Amazing.

@potato_noob - Welcome to the Babylon Family! We are sincerely glad to have you hear learning Babylon.js!

P.S. - You’re not the only humble potato with no real grasp of maths. We should start a club!

8 Likes

I’ve spent the last week living off your pirate youtube content @PirateJC, all potatoes welcome but you might be a grade above the “can’t do maths club” :rofl:

1 Like

My approach to math:

Like A Boss Ship GIF

5 Likes

The intersection of meshes is a damn fine way to lose a ship!

1 Like

@potato_noob I’m happy to help out here as you have an interesting problem right at the intersection of code and art and the solve can lean one way or the other depending on what you determine is important.

In thinking about the problem, I thought of how I’ve seen other games handle characters getting into a seated position on chairs. The main question I would want to ask is “how important is the time taken to animate the character sitting down?” Is this an action that is supposed to take time and is a balancing mechanism for your design? Or is it just a simple interaction that the user needs to get through as quickly as possible? There is also the question of how free is the user to enter a chair from any position? Can they try to sit down when the back of the chair is facing them or is it better to limit the player’s ability to sit down by having them move in front of the chair first? Sometimes I find that in trying to solve a technical problem, a design solution presents itself and is a better solution than the technical solve because it makes the experience better.

I am going to make the assumption from your image that you are limiting the player a bit since you imply that the character needs to be next to the chair to sit and can’t be on the other side of the desk, for example. I am also going to make an assumption from the art style of the character that you have some leeway for a more cartoonish style of motion rather than needing the ground you motion in the reality of human proportions. And I will make one more assumption based on the proportions of the character and scale of the chair that you will use some sort of jumping motion rather than climbing up onto the seat because the seat seems to be at the level of the character’s shoulder or chin (the perspective may be misleading me a bit on proportion, but the seat is definitely not around the knee level which would suggest realistic proportions.

So if there is a jumping motion for the character to sit, I would play that up with your solve. One way to help would be to require the character to be in front of the seat like in your first image. This way you can limit the possible collisions between meshes. I think if you use an exaggerated jump, think a Mario jump, to clear the arms of the chair then you can solve most of your problems. Then the only variables would be moving the character from a standing position to a seated position with a jump from any position within the 180-degree arc of the front of the chair.

For the animation cycle, if you animate the character doing a jump from a standing position high enough to clear the chair arms and then landing in a seated position at the height of the seat, this should be the only animation that you need. I would also add a null transform to the chair mesh at the floor level directly under where your character will sit. You should point the forward vector of this transform toward the front of the chair. This will give you the ending position and rotation of your character when seated.

To determine if the character is in front of the chair use a couple of BABYLON.Vector3 operations:

  • characterVecor = (character.position.subtract(chair.position)).normalize();
  • canSit = BABYLON.Vector3.Dot(characterVector, chairForward)

You will get chairForward from the forward vector of the null transform you put into the chair mesh. Then if canSit > 0 the character is in front of the chair. Now you just need to play three animations at the same time. Create an animation group that contains the jump animation and then you will create two animations to play with the jump animation in the same group. These two animations are:

  • A rotation animation on the mesh root starting at the character’s current forward rotation and ending at the chair’s forward rotation taken from the null transform.
  • A position animation on the mesh root starting from the character’s current world position and ending at the chair’s null transform world position.

When you play this group all three animations will play at once with the character jumping in the air while rotating and translating to land in the seat. Once there, you can discard that animation group and then parent the character mesh to the chair so that the chair can rotate and translate the character.

You can see why I mentioned that the animation of the character’s jump should land in the seated position at the height of the seat. This way you don’t need to worry about translating the game object other than in X and Y and the authored jump animation will take care of positioning on the chair so you won’t get any collision with the meshes.

If you happen to have chairs of different heights in the game, you may need to place the null transform exactly where the character will sit in each chair, and then you animate the jump to land seated at local (0, 0, 0) and then you will have your translation animation handle the final positioning. The reason I didn’t suggest this first is that the jump animation may look different from one chair to another if the Z height of the null transform changes. This will likely need some testing to get the timing right to make it look natural like the character is jumping into the chair. You can drastically change the look of the motion just with changing the easing modes of your rotate and translate motion, so be sure to test out the options.

I hope this helps you in some way, but please feel free to ping me with questions about this solution or if you have other limitations that you need to work around.

6 Likes

What flavor was it? If it was ‘nuts’ or ‘banana’ I can only recommend to change flavor :grin:
And then, don’t try @PatrickRyan’s trick in real life; It will cost you a new seater :laughing:
Welcome to the community and then for a first potato post, I’d say is a good one :smiley:
GL with your project and have a great day :sunglasses:

@PatrickRyan Thank you so much for taking the time to reply, and for giving me such a detailed explanation, It’s the perfect brain food for a Saturday!

Thank You
Your explanation helped me to understand a ton, and ratify the way I should be thinking about things, and indeed that animation should be separate from positional movements so the thing being animated isn’t moving away from its origin (unless it should and it’s a child of some parent and part of a bigger animation of things.)

I went back to the drawing board this morning, thinking that the code today was too rigid and needed a refactor to do what you’re suggesting, I did some miros:


Less important (Just wanted to show you I put some time into this :slight_smile: )


Much better visual representation of states between chair and player.

Sitting down2
Apologies for the image quality
[Known thing about this right now, I’m using slerp to get that chair to face the avatar and it takes a while to finish, even though it looks like it’s finished, so I think I need to shortcut that process after a certain point or the rotation looks off when the chair has finished rotation back. and that’s also because I don’t have enough control of the order of what’s happening yet, refactor happening today.][I’m not finishing of rotating the avatar before rotating the chair back and I’m not doing the jump animation properly.]

Some Questions…if it is ok…

If I was to move the player avatar in the engine, I’d do an approximation of the jumping movement from being in front of the chair to the seated position, while playing the jumping animation. I imagine the person building the assets, who has both the chair and the avatar, would be able to perfectly alight the movement and the jump. I’ve seen the effect of them doing this positional movement and baking it into the animation, which played out exactly as I thought it would, the player moved away from their origin and everything was madness!

Best placed person to figure out that arc and the timing

My potato brain suggests the artist would be able to create some sort of spline(might not be the right word, vectors that create a line or in this case an arc, a path3D in BJS) in Blender to show that movement arc? Potentially dump the duration of the movement out into the GLTF meta, and then I move the player based on the spline and the duration and add some easing.

I think it was this page in the documentation that got me thinking along these lines.

Essentially, I could approximate, but I feel like the person with the chair and avatar and animation would have a scientific gold-plated answer.

Refactor ahead
I’m going to refactor today so I can do the things you’ve mentioned, I don’t fully understand how transforms work so I’m going to do some more reading and YouTubing.

My movement system was originally based on weights, I set up a system where a state maps to animation, every update call I check the state and if the weight of that animation doesn’t fully = 1 then I will interpolate a bit more, and for all other animations, I will do the reverse and drop them down to 0.

It works but it can only handle one thing at a time, and what I need to do with this chair is disengage the avatar control, turn the avatar, and then play the jump& sit animation once, while also moving the avatar to the position of the TransformNode we created at the beginning (Thank you!).

So my plan is to essentially to completely stop that animation weighting system where ever it is and pause all animations where they are. Then kick in whatever I build today to let me do turn (which will need the walk animation playing and potentially a body turn animation), then animate and move the avatar to the chair in lock-step, then with the avatar state set properly they will prob go into some sort of idle animation and I can hand back control from this kind of choreographed system to the control + weighting system.

Combining animation
I was thinking that it would be hard work to create idle animations for both sitting and standing and that I might be able to combine sitting, and idle or sitting and using a phone for example, do you have a ball-park answer on where to read about something like this? I saw the videos on skeletons and influence, and it feels like I’d want to weight both the sitting and idle or sitting and playing on phone animations at once, but maybe changing:
the lower part of the skeletons influence for playing on phone
the upper part of the skeletons influence for idle
So ultimately you end up with half of one and half of the other

Is my thinking madness or is this a legitimate approach?

Again, thank you to everyone for the epic welcome, hopefully, I’ve included enough detail, both for future folks who are walking the same path and because you’ve all given up time to help me and I want to keep you all updated on where I end up on this.

@PatrickRyan Thank you again for your insight and help, I’ll report back after this epic refactor.

4 Likes

Salted Caramel for the win! But at the time Nuts & Bannans would have been the semantically correct choice. It’s funny, once you’ve worked on something like this, you look at games and other folks’ work in a completely different light, always so much to learn from everyone’s different approach. I’ll leave the chair jumping to the folks on “floor is lava”.

Thank you for the kind welcome, and I hope to be up to snuff eventually to the point where I can give back to this epic community.

I thought I’d report back after a VERY long weekend.

A bunch of Typescript Mixins later, we’re a bit further along.

Sitting down3
No arc jump and the rotation to face the front of the chair still isn’t quite right.

Sitting down4
Another Angle

I wrote a whole animation system to time and combine actions and then found actions manager which was fun. So I’ve got this whole thing happening via actions manager, my code feels a bit clunky and I got stung by the .then on actions manager not being a changing thing but being used on subsequent calls. Initially, I thought it was DoThis->Then Do this->Then Do this.

Is it delightful…almost, if I could just nail the arc in the jump, but something tells me that arc will cost me action manager, not sure InterpolateValueAction will net me the Mario jump lol.

In writing this, I was just thinking, that we stopped doing the x&z movements in the animation, but there is nothing stopping us from doing the y movement…hmmmmmm ??? HMMMMMM?

6 Likes

Lovely. Personally I think it might look better if the animation finishes in shortly time.

Do you mind sharing what drawing board you are using?

Hola amigo! Miro is my choice of collaborative drawing board, but you’ve also got mural which is a strong competitor.

On the animation, you’re 100% on the money, I’m still working out the optimum way of scripting actions together, action manager seems to work for now, but I’ve no doubt I’ll need to build something else soon. Finding action manager was a massive win though!

He could ‘jump’ a little bit higher before dropping on the chair (a matter of physics, I suppose… but then, who am I to say that :wink: It’s always (a lot) easier to post a crap comment than to create, isn’t it :crazy_face:
I luv your design and approach already. Please don’t give up, stay careful with the icecream and stay tuned :smile:

2 Likes

Folks…I suck…I’m still struggling with something that seems super basic, and I 100% know it’s because my maths & foundations suck here.

I’ve spent the evening putting together a playground to try and solicit some help with where I’m going wrong.

I’m sure all of this is completely wrong on onBeforeRender isn’t the right place to do what I’m doing because that slerp will carry on for a while even though it doesn’t look like it on screen.

W&S = Move forward
A&D = move left and right
Q&E = Turn left and right

In some scenarios, this playground works, and in others, it doesn’t. stand on the left or right of the chair and make sure you’re looking at a funny angle.

The idea is to click on the chair once inside the interaction mesh and have the player turn away from the chair, so when I move them onto the chair, they look like they are sitting…otherwise they would be riding the chair like a cowgirl or boy yeeeeeehaw!

If you come at the chair from the side and you’re slightly rotated, it never seems to face away from the chair perfectly.

Sorry I haven’t managed to nail this one folk, any help with where my thinking is wrong or what I’m clearly not understanding would be a win. Maybe I misunderstood what forward does on a mesh.

Sorry to bump folks, @PatrickRyan if you have any free moments could you take a look at my playground and see what I’ve messed up, I’m watching more maths videos as I type this in the hope that I can get my foundations right. The thing I can get right it getting the character to face away from the chair when clicking on it.

All I can say is that I luv it when people come up with things as complex and claim to have no understanding of what they are doing. Such humble persons are always welcomed, even though I have no faen clue how to solve their (claimed as simple) issue :smile:

The only thing I can say with my approach to maths which is basically the same as for @PirateJC (except I would have probably chosen the wrong direction to escape from the sinking boat :face_with_hand_over_mouth:)… the only thing that strike me here, is that I believe that the self rotation of the character when entering the trigger zone should actually be changed with a priority animation to have the avatar face forward to the seat. I believe this will make it a lot easier to run the final ‘jump on seat’ animation from there.

1 Like

Ah ok so you’re thinking rather than try and get the character to face the chairs forward, which is what I was trying to do (potato brained), actually get the character to face the chair , and then 180 the direction. I’ll finish Freya Holmer’s vector basics and give it a spin.

PS @mawa Babylon makes most of this easy hahaha, doesn’t feel complex when you have the power of abstractions on your side.

2 Likes