How to transform a body as if it was attached to another body

Post Reply
Teyn
Posts: 6
Joined: Wed Jan 07, 2015 10:13 am

How to transform a body as if it was attached to another body

Post by Teyn »

Hello,

I am trying to do an augmented reality board game where the player holds a marker in front of him, and a board with a sphere and obstacles gets rendered on top of it. I update the position of virtual board with body.setWorldTransform and I noticed that as player rotates and moves the board in real life, the virtual sphere often falls under the board(because the sphere is small and just a subtle movement of the board can cause the sphere to fall through the CollisionBody of the board). So I thought about moving and rotating the sphere along with the board so that it always stays on top of the board. But I can not get it to work properly.

Basically,
https://giphy.com/gifs/error-bullet-xT0 ... fullscreen - Here is my situation

as you can see on the image, I've got two rigidBodies: 1.) The green one(The board) has a btCompoundShape that consists of the board and the green sphere 2.) The white rigidBody has its own btSphereShape.

And as I apply transformation to the board, I want the white sphere to move with the board. I added that green sphere just to show what I want, the green sphere sits perfectly on the board and moves along with it.

Applying the same transformation to the white sphere as well obviously doesnt bring the desired result. I would very much appreciate if someone could explain how to move the white sphere as if it was attached(via btCompoundShape) to the board just as the green sphere is.

Thanks to everybody.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: How to transform a body as if it was attached to another body

Post by Erwin Coumans »

You should use a constraint to move the board, instead of directly setting its position (and/or velocity). BodyA of the constraint is the board, bodyB is some fixed object. Then you configure the constraint transforms to sync to some transform.

This is how it is done in the Bullet VR examples using pybullet. In addition, you may want to run at 240Hz (instead of 60 Hz).

https://github.com/bulletphysics/bullet ... tracker.py
Teyn
Posts: 6
Joined: Wed Jan 07, 2015 10:13 am

Re: How to transform a body as if it was attached to another body

Post by Teyn »

I'm sorry but I still don't understand how would this help me. So the sphere would not be part of the constraint? what is making it move along with the board then? - https://www.youtube.com/watch?v=6AKgH4On65A - this is exactly what I want. It may seem as if there was not much movement of the board exepct for the rotation, but there is.The movement(there is always slight movement of the board because of how the augmented reality coordinates are calculated and insufficent resolution of image, so even though it appears as if the guy was just holding the marker in front of him the board pretty much always moves atleas around 5 units back and forth)(and there is no scaling within augmented reality so if he moves it further away, it goes hundreds of units back).

And the ball in the video stays on top of the board without any glitches.

I'm now using btStaticPlaneShape and this prevents the ball from falling undearneath the board but it still may sometimes pass through obstacles.

EDIT: I also found this topic: https://pybullet.org/Bullet/phpBB3/view ... f=&t=11055 . It describes one of the problems that I have, basically when the board is rotated up too quickly, the ball shoots up to the sky and when it is rotated down too quickly, tha ball stays in the air and then slowly falls down because of gravitation. How could I keep the ball on the board?
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: How to transform a body as if it was attached to another body

Post by Erwin Coumans »

what is making it move along with the board then?
Gravity pulls the ball against the board, and friction makes the ball move the board. This works just fine in Bullet, and using pybullet and its VR physics server makes it really easy to create this exact scenario in your video. It is important that you use a constraint to allow the physics engine to move the board to target the user controlled frame.

The issues in that other thread (https://pybullet.org/Bullet/phpBB3/view ... f=&t=11055) should be resolved by using a small timestep, and making the constraint between the board and the user controller (such as a VR controller) a little bit soft.

I'll create some pybullet example to re-create the effect in that video soon (https://www.youtube.com/watch?v=6AKgH4On65A), using HTC Vive or Oculus Rift controllers to move the board. If that example works well, would that resolve your issue?

There should be no need to hack the system with custom gravity etc, but if you really want, you can also modify the gravity vector and keep the board static. That is another solution to the problem of using a too large time step, and too fast linear/angular velocity, relative to the size of the sphere. As long as you use a very small timestep, there should be no tunneling.
Teyn
Posts: 6
Joined: Wed Jan 07, 2015 10:13 am

Re: How to transform a body as if it was attached to another body

Post by Teyn »

Well your example would definitely be appreciated. However currently I'm under a very bad deadline and so I naturally look for all sorts of solutions. I still do not quite understand what you are suggesting and there is no time to even test it further. (really very bad deadline) .

But I actually fixed the problem. So the solution I found is:

I let the physics run on their own, and whenever I update the transformation of the board(really the transformation of the marker changes)(30 times a second)(because the camera runs only on 30FPS) I get the relative position and rotation of the sphere to the board

Code: Select all

              sphere.getWorldTransform(sphereMat);
		    	Matrix4 tmp = new Matrix4().set(board.getCenterOfMassTransform());
			    tmp .inv();
			    tmp .mul(sphereMat);
			    tmp .getTranslation(tempVector);
			    tmp.getRotation(tempQuat);
			    
then I change the actuall transformation of the board (So I get the new coordinates from the camera image and apply them)

Code: Select all

              ARLibrary.getGlTransformMatrix(marker, Matrix);         
                       board.setWorldTransform(Matrix);
                       
And then I reset the transformation of the sphere, translate it to [0, 0, 0] (this is the origin the board is rotated around, no matter what is the rotation or translation)(Or maybe it isn't :D I dont think it is, because the board seems to be rotating rather around borad.getCentreOfMassPosition, but the solution works perfectly...). I then apply the board's rotation to the sphere and translate(relativly to the new rotation) the sphere back by the old
relativePosition of sphere to the board taken earlier. Then I apply the old relativeRotation of the sphere to the board(so basically restoring the rotation the sphere had before I transfered the board) and lastly I add the translation of the board to the sphere.

Code: Select all

                       sphereMat.setToTranslation(0, 0, 0);       // rotating the ball around 
				 boardMat.getRotation(tempQuat2);      // now getting the new rotation of the board
				 sphereMat.rotate(tempQuat2);               // applying it
				 sphereMat.translate(tmp);                     // going back by the old relative positon of the sphere to the board                                     so really we are rotating around the same point as the board, (moving to that point, rotating, and the translating back(relatively to the rotation)) 
				 
				    
				    boardMat.getTranslation(tmp);       //so far we only applied the board's rotation, no we apply the translation aswell( .trn moves the ball independently from the rotation of the ball)
				    sphereMat.trn(tmp); 
				    
				    sphereMat.rotate(tempQuat);        // now we apply the old rotation the sphere had before we moved the board(so basically restoring the balls rotation
				    sphere.setWorldTransform(sphereMat);
So to conclude: The way to keep the ball on the board is to rotate it around the same point as the board is rotated and translate it along with the board. This actually behaves as if the sphere was part of the board's shape(part of the board's body).

Just a little problem I am getting here is that : let's say the board is rotated by 45 degrees down(around the Z axis for example), (the ball is sliding down on it due to gravity) and then I rotate the board quickly by 90 degrees up, (the ball should now slide down but to a different direction) and it does, but the forces that were pulling the ball down are now the forces that are pulling it up(well it behaves like it (the forces are still the same direction but the board has rotated so they kinda now pull it up a bit)(really imagine the situation, this would happen in real life aswell)), and so it takes like 1 second till it starts sliding down. (for an AR game like this, this is quite a lot of time) . But that's just how physics work so not much to fix here, but I'd like to atleast reduce that time, this will howevery probably not be such a huge problem.

I mean my current problem could be fixed by applying a huge gravity , but then limiting the velocity right before calling the world.step , so that the ball is not moving fast as hell . but it is not ideal because again if the rotation of the board was too quick, world.step modifies the velocity to be huge again and moves it by that much..
Post Reply