How to use Bullet to control a smooth camera...

Post Reply
Zeal
Posts: 47
Joined: Thu Oct 18, 2007 6:49 am

How to use Bullet to control a smooth camera...

Post by Zeal »

I would like to use bullet to control a smooth 'mouse look' camera, like those typically found in videogames. In otherwords, a camera that can move with the WASD keys, and rotate/look with the mouse. I am kinda hoping bullet can handle this motion for me, since it already works on a fixed time step, so I know the results will be smooth across varrying framerates.

Can anyone please give me some tips as to how to create such a camera? It seems like all you would need to do is create a simple sphere rigid body, and inject forces to move it (and set the dampening really high so it doesnt slide forever?). Not sure how to do the rotation though... I dont want the user to pitch more than -90 to +90 degrees (yaw can go a full 360 degrees). How can I clamp these angles?

Thanks for any advice
Zeal
Posts: 47
Joined: Thu Oct 18, 2007 6:49 am

Re: How to use Bullet to control a smooth camera...

Post by Zeal »

Am I the only person who has tried to use bullet to help make a smooth camera? If youve every tried to make a camera that stays smooth even during varying frame rates you know what a pain in the butt it can be.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How to use Bullet to control a smooth camera...

Post by Flix »

I've implemented a simple semi-physic camera in my own Ogre - Bullet wrapper and it's working well. So I can give you some hint (in case you're using Ogre as well: I guess I've already seen you're nick in the Ogre forums, so I think this can be the case).

My approach was to create a "split" motion state for a spherical camera (it's a rigid body with very very very little mass, zero friction and restitution).
"split" means that the camera position is handled by Bullet, but the orientation is left to Ogre (so the physic sphere can be angular "locked" or not: nothing changes).

The main difficulty at this point is moving the camera by setting its velocity each time (well, actually modifying it at each key pressure, so that for example you can leave 20% the old velocity and add 80% of the new velocity: this looks smoother and better: you can use the camera Quaternion -zAxis to detect the forward direction, as far as I remember). Then you have to implement damping when you release a motion button, so that after a very short amount of time it stops.

As I told, it works well, and doesn't bounce a lot (like I thought before trying it) and does not affect other bodies too (its mass is too little).
It's not a full-physic solution but for my purposes it is enough.

Hope it helps.
Zeal
Posts: 47
Joined: Thu Oct 18, 2007 6:49 am

Re: How to use Bullet to control a smooth camera...

Post by Zeal »

"split" means that the camera position is handled by Bullet, but the orientation is left to Ogre (so the physic sphere can be angular "locked" or not: nothing changes).
Hmm I want Bullet to handle the movement AND rotation. Thats the whole point - let Bullet handle rotation & movement at a fixed time step, so you get smooth, framerate independent movement as you move the mouse / look around.

I would still be curious to see your code though. Does anyone else have a solution that handles movement AND rotation?
sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Re: How to use Bullet to control a smooth camera...

Post by sipickles »

Flix wrote:As I told, it .... does not affect other bodies too (its mass is too little).
Using a collision filter might be better than tiny mass? See http://bulletphysics.com/Bullet/BulletP ... c223854848
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How to use Bullet to control a smooth camera...

Post by Flix »

sipickles wrote:
Using a collision filter might be better than tiny mass?
No, when i wrote that my (semi)physic camera does not affect other bodies I meant that the "impact" between the camera and other bodies does not "move" other bodies because its mass is too low (it's a good thing).

One of the main problems I'm experiencing so far with this approach is that I'm afraid that when I set the velocity of a dynamic rigid body (the camera) with setLinearVelocity(...) calls, it is not updated by Bullet until next real (not interpolation) time step. This makes the camera velocity dependent on the CPU speed, because high CPU speed means more interpolation steps (*). I'm not sure that this explanation is correct, but maybe I should try to process the input at the same frequency as the Bullet engine to see if this can improve something...

P.S. When I said:
it's a rigid body with very very very little mass, zero friction and restitution
I forgot to mention that the camera gravity must be set to zero too.

(*) - Well, I'm thinking that this makes the camera velocity dependent on the CPU speed, because at each (rendering) step I set the linear velocity based on getLinearVelocity(...) (basically I add velocity), and getLinearVelocity(...) can return the value I added last rendering step, without Bullet taking it into consideration if it made an interpolation step (I'm sure nobody will understand what I'm saying, but no matter...)
sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Re: How to use Bullet to control a smooth camera...

Post by sipickles »

Flix wrote:I'm thinking that this makes the camera velocity dependent on the CPU speed, because at each (rendering) step I set the linear velocity based on getLinearVelocity(...) (basically I add velocity), and getLinearVelocity(...) can return the value I added last rendering step, without Bullet taking it into consideration if it made an interpolation step (I'm sure nobody will understand what I'm saying, but no matter...)
I read ya I think! :)

You are setting the linear velocity directly, in a loop independent of bullets simulation steps.

My question is, why go to all the trouble of adding a camera using bullet, then control the velocity directly? Surely the bullet way to do this is by applying forces? In this approach, the movement of the camera is coupled to bullet updates, not CPU speed
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How to use Bullet to control a smooth camera...

Post by Flix »

sipickles wrote:
You are setting the linear velocity directly, in a loop independent of bullets simulation steps.
Yes, that's why I'm thinking of processing the input at the same Bullet frequency.
Anyway for completeness: I calculate the "velocity delta" based on the "rendering" timeSinceLastFrame (this is what people usually do when programming without a physic engine, since timeSinceLastFrame is bigger on slower PC). But my tests show that using my faster PC (FPS 250), the camera movement is 4 times slower than on my old slower PC(FPS 60). Since the Bullet time step was FPS 60, I'm starting to think that this is caused by interpolation steps (but I might be wrong).

sipickles wrote:
Surely the bullet way to do this is by applying forces
Well, I think that setting the velocity directly is an option for dynamic rigid bodies (I remember that that was possible in ODE too); kinematic rigid bodies need to set their transform directly.
I don't know if switching to adding forces can improve the situation, but probably my camera needs more constraint and precise control (for example: at every step I keep only about 20% of the old velocity and set 80% of the new one; this is very good to limit camera bounciness due to its very low mass).
Probably the way to go here is to process the input at the same frequency as Bullet. I wander if somebody has some experience in this approach.

Thank you for your contribution.
sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Re: How to use Bullet to control a smooth camera...

Post by sipickles »

Fair enough if you wanna do it that way. Just sounds to me like you are reprogramming a system already provided by bullet. For example:
Flix wrote:at every step I keep only about 20% of the old velocity and set 80% of the new one; this is very good to limit camera bounciness due to its very low mass).
Why not just use the linear and angular damping already provided by bullet? :)
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How to use Bullet to control a smooth camera...

Post by Flix »

sipickles wrote:
Why not just use the linear and angular damping already provided by bullet?
I already do it when I leave the input buttons, so that the camera stops in a very short time; but, when I move, the direction of the (80%) new velocitity can be of course different than the direction of the (20%) old velocity: I can't use high damping while I am moving, and I think that in this situation the bounciness is better limited by this approach rather than just accumulating forces.

Hope it makes sense.
sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Re: How to use Bullet to control a smooth camera...

Post by sipickles »

Zeal wrote:Not sure how to do the rotation though... I dont want the user to pitch more than -90 to +90 degrees (yaw can go a full 360 degrees). How can I clamp these angles?
This is something I am also interested in but have not yet resolved. Contrainsts perhaps?
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How to use Bullet to control a smooth camera...

Post by Flix »

Zeal wrote:
Not sure how to do the rotation though... I dont want the user to pitch more than -90 to +90 degrees (yaw can go a full 360 degrees). How can I clamp these angles?
sipickles added:
This is something I am also interested in but have not yet resolved. Contrainsts perhaps?
Well, I did not have this problem because, as I told before, my semi-physic camera has the angular part not physically controlled by Bullet, so I can simply assign the camera quaternion each step like this:
void GlutDemoApplicationEx::camera_rotate(btScalar x,btScalar y) {
const btScalar factor = 0.1;
m_azi -= x*factor;//yaw
m_ele -= y*factor;//pitch

if (m_ele<-90.0) m_ele=-90.0;
else if (m_ele>90.0) m_ele=90.0;

camera_orientation = btQuaternion(btRadians(m_azi),btRadians(m_ele),0)); // ctr with setEuler(...)
But I think that probably you can retrieve the Euler angles from the physic camera quaternion (camera->getWorldTransform().getEulerYPR(...)), and if the pitch is too negative (or too positive) add a torque/angular impulse/angular velocity (according to your favourite physic strategy) in the opposite direction...
Well, to tell the truth, I agree with sipickles that contrainsts would be the best way to solve it (maybe the generic 6dof with roll blocked and pitch limited).

Hope this helps.
Post Reply