Friday, March 4, 2016

30. XNA Vehicle Physics Test 4


       In this update, I am continuing to modify and expand the JigLibX (Jiggle Library X) Physics Engine. Recently I added an exhaust particle effect to the vehicle. You can download the XNA 4.0  version of JigLibX below.



       This particle effect streams behind the vehicle when the player presses the gas so often. I will change the color of the smoke to grey. The standard vehicle class in my game engine has a hand brake that locks the rear wheels, thereby creating some drag and slowing the car down. That part is realistic. What isn't realistic is the rear wheels still have full traction. If you've ever pulled a hand brake in a car while moving you've notice that the rear end loses traction and wants to swing around causing a spin. It can be useful for making tight 180 degree turns, orienting your car coming into a turn and for good 'ol fashioned fun. This is why I kept this feature. 


Adding the smoke particle

Vector3 OffsetAmount = new Vector3(0, 0, -3);

Vector3 OffsetPosition = Car.carObject.Car.Chassis.Body.Position +
    (Car.carObject.Car.Chassis.Body.Orientation.Right * OffsetAmount.Z) +
    (Car.carObject.Car.Chassis.Body.Orientation.Up * OffsetAmount.Y) -
    (Car.carObject.Car.Chassis.Body.Orientation.Forward * OffsetAmount.X);


ParticleComponent.smokeParticles.AddParticle(OffsetPosition, Vector3.Zero);


       OffsetAmount is a Vector3 that is the relative offset you want, in this case 3 units behind the center of the car. OffsetPosition is the final, global, relative position, that you can then pass into your particle system or something. It took some trial and error to get all of these working correctly, but I've tested it in several positions and it seems to work OK. And the last line tells my ParticleComponent to add a particle at the specified position and initial velocity - replace it with your own particle code to get a nice stream of particles behind your car. I plan on adding a similar particle effect to the actual engine when the vehicle takes damage. For example, if the engine is emitting grey smoke, the damage to the vehicle is rather light. But if the smoke is black, the vehicle is heavily damaged and requires repair. The next particle effect I will be working on is adding a dust trail streaming behind the tires.


Change the Gravity 
       One thing I forgot to mention in my previous vehicle physics post was how I changed the gravity. Inside the Physics System Class (PhysicsSystem.cs), scroll down and change the gravity variable from -10 to -30. 

        public PhysicsSystem()  
        {  
            CurrentPhysicsSystem = this;  
            Gravity = -30.0f * Vector3.Up;  
        } 

This will make the car and the physics in general less like the "moon's gravity" and more like the Earth's gravity.


Add Rotational Friction to the Wheels
       Now open up the Wheels.cs file. Before, if you were on level ground, you could coast forever after letting off the throttle.

     if (driveTorque == 0)
    {
        angVel *= .97f;
    }  

Put this in Update() in the Wheels.cs right above angVel += driveTorque * dt / inertia:

                 if (driveTorque == 0)
                {
                    float axleFriction = 5; // higher number = more rotational friction
                    if (angVel > axleFriction)
                    {
                        if (angVel > 0) angVel -= axleFriction;
                        else angVel += axleFriction;
                    }
                    else angVel = 0;
                }

If you want to add more friction, multiply by a smaller number. For less friction, use a bigger number that's less than 1. Also, to help counteract any bumps on the track, I decreased the wheel's damping fraction.


Improve JigLibX's Performance 
       I have highly modified the Jiggle Physics Library to run on XNA 4.0 and MonoGame. I am extending and improving it in many ways. Many indie game developers chose BEPU rather than JigLibX when developing their games for Xbox 360. One of the major reasons why was the fact that JigLibX's performance on Xbox 360 was extremely slow which decreased the game's frame rate. To help with JigLibX's physics performance on Xbox 360 as well as other less advanced hardware, I am changing its foreach statements to for and I will be adding separate loading threads to help improve the low frame-rate issues. JigLibX also makes extensive use of the "float" object. I mention this because the Xbox 360 has some issues processing floating points. So I am changing out all the floats to avoid major physics performance issues.


How to Get Rid of of the Infamous Wobble at High Speed
       One of the major issues people encountered using JigLibX was once the vehicle got to a certain speed, it started to rock side to side, with no obvious way to stop it. Nikescar came up with a solution to fix this issue. If you would like to see this problem for yourself, adjust the wheelFriction to 5.0f and wheelDampingFrac to 0.3f. The car should start wobbling at max speed.

       Each Update( ) is called at a different time for each wheel. One wheel gets slowed down and the other wheels stay at the current speed. Next, the update from one of the three wheels from the last frame gets slowed down and the remaining wheels go at the same speed. If you do this sixty times a second, you will get quick declaration corners of the car causing the wobbling. After a lot of trial and error, here is how you can fix this.

This problem occurs when the andVel reaches maxAngVel in the Update( ) method of the Wheel.cs:

angVel = MathHelper.Clamp(angVel, -maxAngVel, maxAngVel);

Either delete or comment out this line and it will take care of the problem. However, this creates another problem because now you won't be able to set a limit for the top speed.

In the Wheel.cs, add this with the rest of them:

public float AngVel
        {
            get { return angVel; }

        }


Then just after this under PostPhysics( ) in the Car.cs:

for (int i = 0; i < wheels.Count; i++)
                wheels[i].Update(dt);


add this:

for (int i = 0; i < wheels.Count; i++)
            {
                if (wheels[i].AngVel >= topSpeed)
                    destAccelerate = 0;
            }


This should fix it. Now you can freely setup your car without having to worry about the limitations of the infamous wobble. Lastly, to see how I implemented the skybox, check out my blog post here. Thanks for reading and if anyone has found this blog post helpful, please comment below.


No comments:

Post a Comment