First of all, I'm a beginner in game physics, and I think this is a relatively easy problem that I'm not grasping.
Short Version:
I have a box(representing a ship on water) going forward with a constant thrust and I need to be able to steer it with the arrow keys so that it rotates and moves along a curved path. My code is not working and I'm obviously not understanding how to achieve this using Bullet-Physics.
Long version:
I'm creating a top-down-view naval game and I'm having a hard time trying to figure out how to use Bullet-physics to steer entities. I'm trying to make it feel somehow realistic by using a physics library.
I'm using SFML to prototype and test Bullet-physics. I have a 2D box representing a ship and during the main loop I'm updating its position and heading this way:
box_bt->getMotionState()->getWorldTransform(trans);
box_sprite.setPosition(trans.getOrigin().getX(), trans.getOrigin().getY());
box_sprite.setRotation(RadToDeg(trans.getRotation().getAngle()));
relevant code:
(...)
btTransform trans;
while (window.isOpen())
{
dynamicsWorld->stepSimulation(1 / 60.f, 10);
// Apply drag force
box_bt->applyCentralForce(getDrag(box->getLinearVelocity().y()));
box_bt->getMotionState()->getWorldTransform(trans);
box_sprite.setPosition(trans.getOrigin().getX(), trans.getOrigin().getY());
box_sprite.setRotation(RadToDeg(trans.getRotation().getAngle()));
if (Force < 0)
Force = 0;
// Method to apply thrust force along the Y axis relative to the rigidbody
// from: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=2366
btVector3 relativeForce = btVector3(0, -Force, 0);
btMatrix3x3& boxRot = box_bt->getWorldTransform().getBasis();
btVector3 correctedForce = boxRot * relativeForce;
box_bt->applyCentralForce(correctedForce);
(...)
if (event.key.code == sf::Keyboard::Up)
{
Force += 1000;
}
if (event.key.code == sf::Keyboard::Down)
{
Force -= 1000;
}
if (event.key.code == sf::Keyboard::Right)
{
box_bt->applyTorque(btVector3(0, 0, 1000));
}
if (event.key.code == sf::Keyboard::Right)
{
box_bt->applyTorque(btVector3(0, 0, -1000));
}
//draw box
}
I'm using applyTorque but I'm not sure if that is the best method to steer a ship in this case.
For the water drag/resistance force I'm using the simplified formula:
Force = vel*(k1*vel + k2*vel^2) where k1 and k2 being tweakable "drag coefficients."
btScalar getDrag(btScalar velocity)
{
btScalar k1 = 0.06f;
btScalar k2 = 0.03f;
return velocity * ((k1 * velocity) + (k2 * (velocity*velocity))) * 100;
}
I tried to get the drag force on all three axes but when I use the following code the ship doesn't behave right:
btVector3 getDragVec(const btVector3& velocity)
{
btVector3 Rt(0, 0, 0);
btScalar k1 = 0.06f;
btScalar k2 = 0.03f;
Rt.setX(velocity.getX() * ((k1 * velocity.getX()) + (k2 * (velocity.getX()*velocity.getX()))) * 100); // 100 for scaling
Rt.setY(velocity.getY() * ((k1 * velocity.getY()) + (k2 * (velocity.getY()*velocity.getY()))) * 100);
Rt.setZ(velocity.getZ() * ((k1 * velocity.getZ()) + (k2 * (velocity.getZ()*velocity.getZ()))) * 100);
return Rt;
}
Both thrust and drag work well when moving forward, but once I try to introduce the steering part it rotates the box but it doesn't follow a curved path, the angles keep "flipping" once it gets to a certain limit, and the x-axis speed increases too much compared to the rotation.
Thank you for any insight!