[gameprogrammer] RayCast vehicle - I think it's almost done
- From: "Edilson Vasconcelos de Melo Junior" <dirso@xxxxxxxxxxxxxxxxxx>
- To: <gameprogrammer@xxxxxxxxxxxxx>
- Date: Sun, 23 Sep 2007 12:05:03 -0300
Hi,
I think I'm almost there, the suspension is working fine, and I also think
I'm considering all forces, including the normals (since the wheels don't
exist physicly, I add this force manually as the wheels were there applying
this forces over the body - the point where the forces are applied is
susAct, locally, and posSusAct, its global coordinates).
Anyway, this code, i think, should works fine, I'm killing lateral forces
and when I steer the wheels I apply a perpendicular force to that wheels to
kill that acceleration too and that way I think the car should make the
turn, but it isn't and that's the reason of my post.
But that's not what happens :( It actually starts "shaking" and making turns
right then left then right again and so on not repecting my inputs, I think
it might be a problem with the math, wrong angle calculation and velocity
components.
Here is the main code, any help will be appreciated
Thanks,
Dirso
[code]Ogre::Quaternion quat = getOrientation();
Ogre::Vector3 velocityVector(me->getVelocity());
Ogre::Real mass = _loader._carMass;
Ogre::Vector3 com = me->getCenterOfMass() + _loader._CoM;
// that's because Newton give me getCenterOfMass as an offset of the
original CoM
// gravity force
Ogre::Vector3 Fg = Ogre::Vector3(0,-9.8, 0) * mass;
me->addForce(Fg);
// local vars
Ogre::Real deltaT = me->getWorld()->getTimeStep();
// for each wheel calculates all forces on each wheel
for(RayCastTireListIt it = _tires.begin(); it != _tires.end(); it++)
{
// draw the rotation
Quaternion WheelYaw((*it)->_steer * mSteerAngle, _worldOr);
// suspension
Ogre::Vector3
posSusAct((*it)->_wheelSusAct->getWorldPosition());
Ogre::Real r = (*it)->_radius;
Ogre::Real rayLength = r + (*it)->_susLength;
Ogre::Vector3 uVector(quat*_worldOr);
OgreNewt::BasicRaycast ray(mWorld, posSusAct, posSusAct -
uVector*rayLength);
OgreNewt::BasicRaycast::BasicRaycastInfo info =
ray.getFirstHit();
//
Ogre::Vector3 susAct = (*it)->_wheelSusAct->getPosition();
Ogre::Vector3 dWheel1 = (*it)->_wheelNode->getPosition();
Ogre::Vector3 dWheel2;
if(info.mBody)
{
// orientation vector
Ogre::Vector3 rVector(quat*WheelYaw*(*it)->_pin);
Ogre::Vector3 wheelVelocity(velocityVector + (susAct
- com)*me->getOmega());
Ogre::Vector3 wheelVelocityN(wheelVelocity);
Ogre::Real velocityLen(wheelVelocityN.normalise());
Ogre::Real cos1(rVector.dotProduct(wheelVelocityN)),
cos2(uVector.dotProduct(wheelVelocityN)),
sin1(Math::Sqrt(1 - cos1*cos1)),
cosUp(uVector.dotProduct(_worldOr));
if(cos2 < 0.0) sin1 = -sin1;
// calculate the new position of the wheel
dWheel2 = susAct - (info.mDistance*rayLength -
r)*uVector;
// calculate the suspension force
Ogre::Real dist1 =
MathHelperClass::getDistance(dWheel2, susAct),
dist2 =
MathHelperClass::getDistance(dWheel1, susAct);
Ogre::Real Fs = (*it)->_susSpring*((*it)->_susLength
- dist1),
Fd = (dist2 - dist1)*(*it)->_susShock;
Ogre::Vector3 Fn(-Fg*Math::Abs(cosUp)/4.0);
Ogre::Vector3 Ft(Fn + quat*(Fd + Fs)*_worldOr);
// drive force
if(((*it)->_drive > 0.01) && (wheel_torque > 0.01))
{
Ogre::Vector3
driveForce(quat*_carAccelDir *
((*it)->_drive * wheel_torque
/ (*it)->_radius) );
Ft += driveForce;
}
// calculate the steering forces
Ogre::Vector3
friction(velocityLen*sin1*rVector*mass/4.0);
friction.y = 0.0f;
Ft += friction;
// set the final force
me->addLocalForce(Ft,
(*it)->_wheelSusAct->getPosition());
}
else
{
dWheel2 = susAct - uVector*(*it)->_susLength;
}
(*it)->_wheelNode->setPosition(dWheel2);
(*it)->setOmega(getVelocity() / (*it)->_radius);
mCurrRotZ += Ogre::Radian((*it)->getOmega()*deltaT);
Quaternion WheelRotation(mCurrRotZ, (*it)->_pin);
(*it)->_wheelNode->setOrientation(WheelYaw*WheelRotation);
}[/code]
Other related posts:
- » [gameprogrammer] RayCast vehicle - I think it's almost done