I've finally ported my semi-physic camera implementation (the angular part is not physically simulated) from my Bullet-Ogre environment to plain Bullet-OpenGL and I've added an attachment with the source code here. Hope you like it.
The physic camera topic has already been discussed here: http://www.bulletphysics.com/Bullet/php ... f=9&t=3619.
I haven't included an .exe file yet, because I don't know if there are limits in the attachment's size or type (maybe I'll try in a follow-up).
INSTALLATION:
The code does not include any project file, so the fastest way to compile it is probably to temporary replace the BasicDemo files with the ones in the attachment (or to clone the project settings and replace the files). I compiled the code with the VC++ 2008 Express compiler and with current (at the time of writing) Bullet SVN version.
FEATURES:
-> ghost object frustum culling (explained here: http://www.bulletphysics.com/Bullet/php ... f=9&t=3896)
-> alternative navigation system (now camera is no more bound to a target point)
-> semi-physic camera moved by setLinearVelocity(...) methods (but by defining USE_THE_FORCE in "btCamera.cpp" we can use applyCentralForce(...) methods). I know, it's the simplest possible collision camera and not a full physic solution, but the code can be easily extended to improve it.
-> alternative colors as proposed by orange here: http://www.bulletphysics.com/Bullet/php ... f=9&t=3941
CONTROLS:
arrow keys + pgUp/pgDown -> camera movement
LMB + mouse move -> camera rotation
MMB -> picking
RMB -> shooting boxes
F1/F2 -> adjust camera velocity
LICENSE:
Free of course, you can use the code as you like it (maybe we can put it in a Bullet Demo, but I don't think that the quality is good enough...).
CODE SNIPPET:
In case somebody is too lazy to look through the code, here is the important stuff:
Code: Select all
void btDefaultCamera::bindBtCameraToInput(btScalar mousePositionRelativeToLastFrameX,btScalar mousePositionRelativeToLastFrameY,const btVector3& cameraRelativeTranslationVector,btMatrix3x3* semiPhysicCameraOrientation,btScalar* m_azi,btScalar* m_ele) {
bool cameraAngleModified = (mousePositionRelativeToLastFrameX!=0 || mousePositionRelativeToLastFrameY!=0);
if (cameraAngleModified) {
btMatrix3x3& q=*semiPhysicCameraOrientation; // From now on q is the Matrix that represents the camera orientation
btMatrix3x3 oldQ=q; // We clone q
btScalar& yaw = *m_azi; // From now on yaw is *m_azi ( global yaw, not a relative delta )
btScalar& pitch = *m_ele; // From now on pitch is *m_ele ( global pitch, not a relative delta )
pitch+= (-mousePositionRelativeToLastFrameY); // User input modifies pitch
yaw+= (-mousePositionRelativeToLastFrameX); // User input modifies yaw
if (pitch<-90.0) pitch=-90.0; // Clamp pitch
else if (pitch>90.0) pitch=90.0;
btQuaternion qQ = btQuaternion(btRadians(yaw),btRadians(pitch),0); // Instead we use an additional temporary quaternion, whose ctr with setEuler(...) is very reliable
q.setRotation(qQ); // and use it to modify the camera matrix (q) directly (because it's SEMI-physic)
// This code is a W.I.P. snippet that should "lead" the camera linear velocity in the
// new direction of the camera (if the camera is moved by inertia and you rotate it, you
// expect that some of its global velocity turns, as it's you that drive the camera...)
// Turn existing camera linear velocity (it's stored in world space):
oldQ = oldQ.inverse() * q; // This matrix should give the differential orientation of the camera... well, let's hope so!
btVector3 linearVelocity=this->getLinearVelocity();
linearVelocity = oldQ.getColumn(0)*linearVelocity.x() + oldQ.getColumn(2)*linearVelocity.z(); // We take off the y component and "turn" the x and z components
linearVelocity.setY(this->getLinearVelocity().y()); //We only turn XZ components to avoid unwanted up/down movements
this->setLinearVelocity(0.2f*this->getLinearVelocity()+0.8*linearVelocity); // We do a wise mix
}
bool cameraPositionModified = (cameraRelativeTranslationVector!=btVector3(0.,0.,0.));
if (cameraPositionModified) {
this->setDamping(0.15,0.0); // Ideally it should be left to zero (better input range), but it's better to leave some damping on the camera always, since it can be moved by collisions that we do not handle.
btQuaternion q;
semiPhysicCameraOrientation->getRotation(q);
this->setLinearVelocity(0.4f*this->getLinearVelocity()+0.6*65*m_speed*quatRotate(q,cameraRelativeTranslationVector));
}
}
void btDefaultCamera::onTranslationalKeyReleased() {
this->setDamping(0.65f,.0); // Modify the first argument to increase damping strength.
this->applyDamping(1.2); // Decrease the argument to increase the camera "stopping time".
}
Hope you enjoy it
