Help me with maths

Grab your favourite IDE and tinker with the innards of game engines

Help me with maths

Postby Spike on Fri Jul 23, 2010 11:44 am

It was 3 years ago sice I had my last algebra class so hope you can help me.

What I want is to keep an object always upright at it's floor. In this example, vUp should try to be as similar as Normal.

Image

Here's my piece of code, it's not working well:

Code: Select all
void CMKSKartMovement::CalculateAngularVelocity( void )
{
   CMKSKart *mksKart = GetKart();
   if( !mksKart )
      return;

   CMKSPlayer *mksPlayer = GetKart()->GetDriver();
   if( !mksPlayer )
      return;

   IPhysicsObject *physKart = mksKart->VPhysicsGetObject();
   if(!physKart)
      return;

   Vector vGroundNormal = mksKart->GetGroundNormal();
   Vector vUp = mksKart->GetUp();

   float dotprod = DotProduct( vUp, vGroundNormal );
   if(dotprod > 1.0f)
      dotprod = 1.0f;
   
   float angle = RAD2DEG(acos(dotprod));
   
   AngularImpulse angVelocity;
   
   angVelocity = vGroundNormal - vUp;
   angVelocity.NormalizeInPlace();
   angVelocity *= angle;

   mksKart->SetAngularVelocity( angVelocity );
}
User avatar
Spike
May Contain Skills
May Contain Skills
 
Joined: Wed Sep 17, 2008 7:10 pm

Re: Help me with maths

Postby Spike on Mon Aug 02, 2010 7:13 pm

Ok, I really need to know how to make it. I've modified the code, but still not working. I think I'm not getting the correct Torque direction, because when i test it rolls instead of trying to stay upright.

CMKSKartMovement inherits from CBaseAnimating
Code: Select all
void CMKSKartMovement::CalculateAngularVelocity( void )
{
   CMKSKart *mksKart = GetKart();
   if( !mksKart )
      return;

   IPhysicsObject *physKart = mksKart->VPhysicsGetObject();
   if(!physKart)
      return;
   Vector vUp = mksKart->GetUp();
   Vector vRight = mksKart->GetForward();
   Vector vFwd = mksKart->GetForward();
   Vector vVelocity = mksKart->GetAbsVelocity();

   Vector vNormal;
   float flDist;
   float flTime;
   if(mksKart->IsOnGround())
      vNormal = mksKart->GetGroundNormal();
   else
      vNormal = mksKart->GetLandingNormal();

   float cosRightAngle = DotProduct(vRight,vNormal);
   float cosFwdAngle = DotProduct(vFwd,vNormal);

   float rightAngle = RAD2DEG(acos(cosRightAngle));
   float flAngRightPerSec = ( 90 - rightAngle );

   float fwdAngle = RAD2DEG(acos(cosFwdAngle));
   float flAngFwdPerSec = ( 90 - fwdAngle );

   Vector vRightTorque = vFwd * flAngRightPerSec;
   Vector vFwdTorque = vRight * flAngFwdPerSec * 100;

        physKart->ApplyTorqueCenter(vRightTorque);
   physKart->ApplyTorqueCenter(vFwdTorque);
   
}
User avatar
Spike
May Contain Skills
May Contain Skills
 
Joined: Wed Sep 17, 2008 7:10 pm

Re: Help me with maths

Postby coder0xff on Mon Aug 02, 2010 8:05 pm

I don't understand your English in the first post at all, but I'm guessing you want it to always sit flat on the ground.

The second implementation won't work because applying force based on correcting a position causes an oscillating system (like a bouncing hydraulic in garrys mod). You wanna stick to setting the angular velocity.

The first implementation doesn't work because angular velocity vectors must be perpendicular to the plane of rotation. So angVelocity = vGroundNormal - vUp is incorrect. I don't know what the names of the functions are, but:

angVelocity = CrossProduct(vUp, vGroundNormal) * DotProduct(vUp, vGroundNormal) * velocityMultiplier

The CrossProduct will give you the axis of rotation. I'm not good with the right hand rule, so it may actually be CrossProduct(vGroundNormal, vUp), which inverts the direction basically. Also, if velocityMultiplier is higher than the FPS it'll make the simulation unstable because it will pass up the target orientation each frame, making it vibrate violently. In my sims, I usually check the amount of time that's elapsed since the last think, compute the FPS, and limit the velocityMultiplier by it. That way even if you get a sudden FPS drop, you don't lose stability.

If you want an even better system, you can compute a quaternion from the current orientation, and the target orientation, and do a spherical linear interpolation (SLERP) and compute the interpolation value as something like (1-correctionRate)^ElapsedTime. correctionRate is a value from 0 to 1, where 0 is no correction is made, and 1 is correction is made immediately. The Source Engine does provide functions for SLERP. This method is implicitly integrated (whereas the others are explicit), so it won't suffer from instability at any frame rate - an ideal physics simulation.
User avatar
coder0xff
Veteran
Veteran
 
Joined: Fri Jun 13, 2008 1:51 am

Re: Help me with maths

Postby Spike on Mon Aug 02, 2010 10:34 pm

Thanks coder, I'm going to implement your first idea, I don't need it to be complex, I'm coding it for Mario Kart Source mod, not for Gran Turismo 5 lol.

A question I have about your formula is the cross product, in in the example of the image it will make the kart roll and not pitch, am I correct?

For making it pitch is CrossProduct(vRight, vGroundNormal) ???

Also the dot product will be 1 when both are equal, shouldn't it be (1 - DotProduct(...)) so it only changes the angles when they are not equal?
User avatar
Spike
May Contain Skills
May Contain Skills
 
Joined: Wed Sep 17, 2008 7:10 pm

Re: Help me with maths

Postby coder0xff on Mon Aug 02, 2010 10:56 pm

you're right, it should be 1 - DotProduct

As for your image, I have no idea which is pitch and roll, but vUp is all you should need. If vUp is pointing slightly forward, then the cross product will be to the side (because the axis for pitch is to the side), if vUp is pointing slightly to the side, then the cross product will be to the front or back (because the axis for roll is forward or back. In short, CrossProduct(vUp, vGroundNormal) determines the correct rotation axis, regardless of pitch, roll, etc. You don't need vRight at all. Also forgot to mention that the output of CrossProduct must be normalized before using it. And of course, if vUp == vGroundNormal, The cross product will be zero length, so don't try to normalize it (no velocity is needed).

Edit: Gahhh, actually... nevermind the dot product and normalizing the cross product, it's redundant.

Just do:
velocityAng = CrossProduct(vUp, vGroundNormal) * velocityMultiplier.

I have to ask... is SetAngularVelocity based on Euler angles, or is it actually taking a angular velocity vector? It should be the later, but I could totally see valve doing it as euler angles, which would mess all this up.
User avatar
coder0xff
Veteran
Veteran
 
Joined: Fri Jun 13, 2008 1:51 am

Re: Help me with maths

Postby Spike on Tue Aug 03, 2010 2:55 pm

Thanks again coder.

Valve angles are Euler angles: http://developer.valvesoftware.com/wiki/Angle , don't know if it answers your question.

I've implemented it but it'd not working ok. The angular velocity seems to only be affecting the kart when it's on the ground, if it's on the air it won't rotate at all.
User avatar
Spike
May Contain Skills
May Contain Skills
 
Joined: Wed Sep 17, 2008 7:10 pm

Re: Help me with maths

Postby coder0xff on Tue Aug 03, 2010 6:55 pm

Yeah, I know that they use Euler angles, its just that angular velocity should never be represented using Euler angles in a physics engine. Hopefully they didn't break Havok that much. If it works on the ground though, then it should be ok.

As for the in the air thing, that doesn't sound like a problem with the math but that it's not getting the ground normal correctly. Try trapping it in the debugger and examine the vGroundNormal.
User avatar
coder0xff
Veteran
Veteran
 
Joined: Fri Jun 13, 2008 1:51 am

Re: Help me with maths

Postby Spike on Tue Aug 03, 2010 11:21 pm

Ok coder, I've found the error.

What causes the kart to not rotate on the air is the Drag code inside IPhysicsObject, it seems to override the angular velocity.

The only way to fix it without dissabling drag is to use Torques, I will find a way so it doesnt bounce, so for example if both vectors are similar (dotprod ~= 0) then I don't apply any torque.
User avatar
Spike
May Contain Skills
May Contain Skills
 
Joined: Wed Sep 17, 2008 7:10 pm

Re: Help me with maths

Postby coder0xff on Wed Aug 04, 2010 12:06 am

Trust me - that's not the solution you want. Oscillation is caused by the fact that once you reach dotprod~=0 you still have angular momentum. That means it passes up the target, and the torques must overcome that velocity before it even starts to correct. The system never stabilizes. (There are ways to compensate, but this is not the problem domain for it)

Instead, modify the code so that IPhysicsObjects drag doesn't apply to your CMKSKartMovement class. You could do something as simple as adding a virtual function to IPhysicsObjects:

virtual bool IPhysicsObject:DoApplyAngularDrag()
{
return true;
}

and have your CMKSKartMovement class override the function to return false. The value of this function is checked in the drag code, and it skips angular drag if this function returns false.
User avatar
coder0xff
Veteran
Veteran
 
Joined: Fri Jun 13, 2008 1:51 am

Return to Programming

Who is online

Users browsing this forum: No registered users

cron