Introduction

Welcome to my first wiki attempt. I am going to share with you my understanding of how to setup a vehicle to be driven with TV3D 6.5. I will also go through the setup of the physics engine. The code here is written in Visual C# 2005 but should be easy enough to convert to other languages. I will unfortunatly not be able to give a comment on every line but where i think it is valid i will try and give a small explanation.

Requirements

For those without a project and wish to test with vehicle physics i have created an introductory project for you to download. You will need to add your beta code in the frmCanvas_Load and re-connect the reference to your MTV3D65.DLL file.

Vehicle Starter Kit Intro

  • WASDQE to move the camera
  • Mouse to Look

Setup Physics

Add a TVPhysics object to the public declarations

public TVPhysics physics;

Create our TVPhysics object in the frmCanvas_Load

physics = new TVPhysics();

while we are in this section add your Username and Beta code to:

NOTE for the new TV3D65 You can remove this line as you will be now using the licenseSign which can be downloaded from Truevision3D.com downloads

//Not Required For New TV3D65 release 3 September 2007 onwards
tv.SetBetaKey("UserName", "BetaCode");

Scroll down until you find the Public void InitPhysics() section and add the following

physics.Initialize();
physics.SetSolverModel(CONST_TV_PHYSICS_SOLVER.TV_SOLVER_EXACT);
physics.SetFrictionModel(CONST_TV_PHYSICS_FRICTION.TV_FRICTION_EXACT);
physics.SetGlobalGravity(new TV_3DVECTOR(0, -9.8f, 0));

With our physics all setup we now need to run the physics for every frame. scroll down untill you find the Public void GameLoop(). Add the following code just above the Checkinput(); function

physics.Simulate(tv.TimeElapsed() * 0.0025f);

This is all we need to use the physics engine of TV3D 6.5 however we do need add the actual objects that will interact with each other.

Adding Your First Physics Body

Before we can interact with objects using the TV3D 6.5 physics we need to add the physics bodies to our physics engine. Our first physics body we need to create is for our landscape, after all we need something to stand on.

Scroll to the top where the TVLandscape Land has been declared and add the following variable just underneith.

int pbLand;

This will be used to identify the landscape physics objects inside the physics engine. Think of the physics engine as a seperate world the real world where everything can interact. if you don’t add your objects to this world then it doesn’t exist. Anyway moving on.

Scroll down until you find the private void InitLandscape() function and add the folowing to the bottom of this function.

pbLand = physics.CreateStaticTerrainBody(Land);

This will create the terrain/landscape into our physics world and return us a reference to our pbLand variable. we can use this pbLand variable to access the landscape in the physics world.

At this point we have completed creating a landscape/terrain in our physics next we can start adding other objects namely our vehicle.

Adding The Vehicle

We have now our physics all setup and a landscape to move on, all we need now is a vehicle to drive on our landscape. this is broken down to make life a little easier. first we need to actually create the vehicle meshes to be used, then we will need to add the vehicle physics to make them interact with our landscape. From there we can move onto driving the vehicle and phyiscs materials.

Create The Vehicle

If you have downloaded the VehicleStartKit Intro these files already exist in your project folder along with all the textures.

Requirements

We will need 3 TVM Meshes

  • Chassis.tvm
  • Wheel_l.tvm
  • Wheel_r.tvm

and 4 BMP Textures

  • ChassisSTi.bmp
  • Undercarriage.bmp
  • Wheel.bmp
  • Windows.bmp

Create Vehicle Materials

Before we create our vehicle mesh we will need to load some textures and create some materials to make the vehicle look a little nicer.

At the top in the variable section add the following to the Materials section just under the int matLand;

int matVehicleBody;
int matWindow;
int matWheels;

Locate the private void InitMaterials() function and create our materials at the top of the function under the matLand = materialfactory.....

matWindow = materialfactory.CreateMaterial("CarWindows");
matVehicleBody = materialfactory.CreateMaterial("matVehicleBody");
matWheels = materialfactory.CreateMaterial("matWheels");

Now we can create the materials for our vehicle. At the bottom of the private void InitMaterials() function add the following

//Car Windows
materialfactory.SetAmbient(matWindow, 1, 1, 1, 1);
materialfactory.SetDiffuse(matWindow, 1, 1, 1, 1);
materialfactory.SetSpecular(matWindow, 0.8f, 0.8f, 0.8f, 1);
materialfactory.SetPower(matWindow, 10);
materialfactory.SetOpacity(matWindow, 1f);
 
//Vehicle Body
materialfactory.SetAmbient(matVehicleBody, 0.2f, 0.2f, 0.2f, 1);
materialfactory.SetDiffuse(matVehicleBody, 0.9f, 0.9f, 0.9f, 1f);
materialfactory.SetSpecular(matVehicleBody, 1f, 1f, 1f, 1);
materialfactory.SetPower(matVehicleBody, 100);
materialfactory.SetEmissive(matVehicleBody, 0, 0, 0.1f, 1);
 
//Wheels
materialfactory.SetAmbient(matWheels, 0.8f, 0.8f, 0.8f, 1);
materialfactory.SetDiffuse(matWheels, 0.2f, 0.2f, 0.2f, 1f);
materialfactory.SetSpecular(matWheels, 0.2f, 0.2f, 0.2f, 1);
materialfactory.SetPower(matWheels, 200);
materialfactory.SetEmissive(matWheels, 0f, 0f, 0, 1);

These materials will just make the vehicle look a little shiny we now need to create the textures to use for our vehicle.

Load Vehicle Textures

Locate the private void InitTextures() function and add the following code to the top of the function.

#region Car
//Create Very Small Colored Texture For Windows
int i = texturefactory.CreateTexture(1, 1, true, "TintedWindows");
texturefactory.SetPixel(i, 0, 0, Color.DarkGray.ToArgb()); //Color.DarkGray.ToArgb()
 
//Vehicle
texturefactory.LoadTexture(@"Textures\Windows.bmp", "Windows");
texturefactory.LoadTexture(@"Textures\UnderCarriage.bmp", "UnderCarriage");
texturefactory.LoadTexture(@"Textures\ChassisSTI.bmp", "ChassisSTI");
texturefactory.LoadTexture(@"Textures\Wheel.bmp", "Wheel");
#endregion

Here you may have noticed the creation of a single pixel texture. we can use this texture to create tinted/colored windows of and make them transparent for better effects.

Load Vehicle Meshs

After we have created the vehicle materials and textures we can now load the actual TVM meshes for our vehicle. Add the following to the public variable list at the top.

TVMesh m_chassis;
TVMesh m_fl;
TVMesh m_fr;
TVMesh m_rl;
TVMesh m_rr;

we now can create the vehicle meshes. locate the private void InitObjects() function and add the following code to the top of the function.

#region Car
//Chassis
m_chassis = scene.CreateMeshBuilder("mChassis");
m_chassis.LoadTVM(@"Models\chassis.tvm", false, false);
m_chassis.SetShadowCast(true, true);
m_chassis.SetTexture(globals.GetTex("ChassisSTI"), 0);
m_chassis.SetTextureEx(0, globals.GetTex("Windows"), 1);
m_chassis.SetTextureEx(1, globals.GetTex("TintedWindows"), 1);
m_chassis.SetTexture(globals.GetTex("UnderCarriage"), 2);
m_chassis.SetMaterial(matWindow, 1);
m_chassis.SetAlphaTest(true, 0, true, 1);
m_chassis.SetBlendingMode(CONST_TV_BLENDINGMODE.TV_BLEND_ADD, 1);
m_chassis.SetCullMode(CONST_TV_CULLING.TV_DOUBLESIDED);
m_chassis.SetShadowCast(true, true);
            
//Front Left Wheel
float scale = 1f;
m_fl = scene.CreateMeshBuilder("mfl");
m_fl.LoadTVM(@"Models\wheel_l.tvm", true, true);
m_fl.SetScale(scale, scale, scale);
m_fl.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_MANAGED);
m_fl.SetMaterial(matWheels);
m_fl.SetTexture(globals.GetTex("Wheel"));
m_fl.SetCullMode(CONST_TV_CULLING.TV_DOUBLESIDED);
m_fl.SetShadowCast(true, true);
            
//Front Right Wheel
m_rl = scene.CreateMeshBuilder("mrl");
m_rl.LoadTVM(@"Models\wheel_l.tvm", true, true);
m_rl.SetScale(scale, scale, scale);
m_rl.SetMaterial(matWheels);
m_rl.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_MANAGED);
m_rl.SetTexture(globals.GetTex("Wheel"));
m_rl.SetCullMode(CONST_TV_CULLING.TV_DOUBLESIDED);
m_rl.SetShadowCast(true, false);
m_rl.SetShadowCast(true, true);
 
//Rear Left Wheel
m_fr = scene.CreateMeshBuilder("mfr");
m_fr.LoadTVM(@"Models\wheel_r.tvm", true, true);
m_fr.SetScale(scale, scale, scale);
m_fr.SetMaterial(matWheels);
m_fr.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_MANAGED);
m_fr.SetTexture(globals.GetTex("Wheel"));
m_fr.SetCullMode(CONST_TV_CULLING.TV_DOUBLESIDED);
m_fr.SetShadowCast(true, false);
 
//Rear Right Wheel
m_rr = scene.CreateMeshBuilder("mrr");
m_rr.LoadTVM(@"Models\wheel_r.tvm", true, true);
m_rr.SetScale(scale, scale, scale);
m_rr.SetMaterial(matWheels);
m_rr.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_MANAGED);
m_rr.SetTexture(globals.GetTex("Wheel"));
m_rr.SetCullMode(CONST_TV_CULLING.TV_DOUBLESIDED);
m_rr.SetShadowCast(true, false);
m_rr.SetShadowCast(true, true);
 
m_chassis.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_MANAGED);
m_chassis.SetMaterial(matVehicleBody);
m_chassis.ComputeNormals();
m_chassis.ComputeBoundings();
m_chassis.SetScale(scale, scale, scale);
#endregion

Add Vehicle Physics

We first need to create a few variable to hold our physics body identifiers just like our landscape physics body. add the following to the variable section at the top.

int pbi_chassis;
int flw;
int frw;
int rlw;
int rrw;
int car_ID;
float steerAngle;

In the above section of code you will notice a couple of extra variables car_ID and steerAngle the car_ID is used for the vehicle creation and the steerAngle we can use to move steer the vehicle. flw,frw,rlw,rrw are the physics bodies for each wheel.

We can now create our vehicle physics (at last you maybe saying). Location the InitObjects() function and add this the bottom of the function.

//Add The Physics to the chassis
pbi_chassis = physics.CreateMeshBody(1500, m_chassis, CONST_TV_PHYSICSBODY_BOUNDING.TV_BODY_CONVEXHULL); //1500
physics.SetAutoFreeze(pbi_chassis, false);
physics.SetBodyPosition(pbi_chassis, 0f, 8, 0f);
physics.SetBodyRotation(pbi_chassis, 0f, 0f, 0f);
 
//Create The Vehicle
car_ID = physics.CreateVehicle(pbi_chassis);
 
//Do Suspention Settings
float susheight = 0.5f; //distance from chassis to wheel 0.5f
float susplen = 1f; // 10
float susshock = 40f; //Springiness of suspension 10
float susspring = 300f; //Stiffness of suspension 400
flw = physics.AddVehicleWheelEx(car_ID, 25f, 0.5f * scale, 0.372f * scale, new TV_3DVECTOR(1, 0, 0), -0.8f * scale, -susheight * scale, 1.25f * scale, 1, 0, 0, susplen, susshock, susspring, m_fl); //fl
frw = physics.AddVehicleWheelEx(car_ID, 25f, 0.5f * scale, 0.372f * scale, new TV_3DVECTOR(1, 0, 0), 0.8f * scale, -susheight * scale, 1.25f * scale, 1, 0, 0, susplen, susshock, susspring, m_fr); //fr
rlw = physics.AddVehicleWheelEx(car_ID, 25f, 0.5f * scale, 0.372f * scale, new TV_3DVECTOR(1, 0, 0), -0.8f * scale, -susheight * scale, -1.425f * scale, 1, 0, 0, susplen, susshock, susspring, m_rl); //rl
rrw = physics.AddVehicleWheelEx(car_ID, 25f, 0.5f * scale, 0.372f * scale, new TV_3DVECTOR(1, 0, 0), 0.8f * scale, -susheight * scale, -1.425f * scale, 1, 0, 0, susplen, susshock, susspring, m_rr); //rr
 
//Change the car's center of mass / make it drive better
physics.SetBodyCenterOfMass(pbi_chassis, new TV_3DVECTOR(0, -1.0f, 10f));
 
//Add wheel frictions
//Note that this code will also stop sliding on slopes
float sideslip = 0.1f;
float sideslipcoef = 0f;
float maxlongslide = 10000f;
float maxlongslidecoef = 0f;
physics.SetVehicleWheelParameters(car_ID, flw, sideslip, sideslipcoef, maxlongslide, maxlongslidecoef);
physics.SetVehicleWheelParameters(car_ID, frw, sideslip, sideslipcoef, maxlongslide, maxlongslidecoef);
physics.SetVehicleWheelParameters(car_ID, rlw, sideslip, sideslipcoef, maxlongslide, maxlongslidecoef);
physics.SetVehicleWheelParameters(car_ID, rrw, sideslip, sideslipcoef, maxlongslide, maxlongslidecoef);
 

The settings for the physics.SetVehicleWheelParameters are roughly as follows

  • car_ID - The main vehicle identifier
  • flw - The wheel we wish to set
  • sideslip - Amount until the vehicle will slide sideways
  • sideslipcoef* - Unknown always use 0 (zero)
  • maxlongslide* - Amount until the vehicle will loose grip
  • maxlongslidecoef - Unknown always use 0 (zero)

by setting both sideslipcoef and sideslipcoef this actually stops the vehicle from sliding down hills when you are stopped even if the handbrake is ON.

We still need to render our vehicle. Locate the GameLoop() function and add the following code under the Land.Render()

m_chassis.Render();
m_fl.Render();
m_fr.Render();
m_rl.Render();
m_rr.Render();

Your vehicle is now be fully rendered and will fall to the ground on its wheels in the next section we will add acceleration, brake and hand brake to our vehicle.

Add Vehicle Movement

Our vehicle looks all pretty stood there not doing very much so lets give it some life and add some movement including.

  • Acceleration
  • Brake
  • Steering
  • Handbrake

Locate the CheckInput() function and add the following just above the Mouse section

 
//Accelerate and Brake
float CarPower = 3000; //3000
 
if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_UPARROW)) //Accellerate
{
    physics.SetVehicleWheelTorque(car_ID, rlw, CarPower,-1000);
    physics.SetVehicleWheelTorque(car_ID, rrw, CarPower,-1000);
}
else
{
    if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_DOWNARROW))
    {
        physics.SetVehicleWheelTorque(car_ID, rlw, -CarPower,-1000);
        physics.SetVehicleWheelTorque(car_ID, rrw, -CarPower,-1000);
    }
    else
    {
        physics.SetVehicleWheelTorque(car_ID, flw, 0, -10000);
        physics.SetVehicleWheelTorque(car_ID, frw, 0, -10000);
        physics.SetVehicleWheelTorque(car_ID, rlw, 0, -10000);
        physics.SetVehicleWheelTorque(car_ID, rrw, 0, -10000);
    }
}
 
//Steering
if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_LEFTARROW))
{
    steerAngle-= 10;
    if (steerAngle < -45)
        steerAngle = -45;
 
    physics.SetVehicleWheelSteering(car_ID, flw, steerAngle);
    physics.SetVehicleWheelSteering(car_ID, frw, steerAngle);
}
else
{
    if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_RIGHTARROW))
    {
        steerAngle+=10;
        if (steerAngle > 45)
           steerAngle = 45;
 
        physics.SetVehicleWheelSteering(car_ID, flw, steerAngle);
        physics.SetVehicleWheelSteering(car_ID, frw, steerAngle);
    }
    else
    {
        steerAngle = 0;
 
        physics.SetVehicleWheelSteering(car_ID, flw, steerAngle);
        physics.SetVehicleWheelSteering(car_ID, frw, steerAngle);
    }
}
 
//Car Handbrake
if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_RIGHTCONTROL))
{
    physics.VehicleWheelHandBrake(car_ID, rlw, 1, 2000);
    physics.VehicleWheelHandBrake(car_ID, rrw, 1, 2000);
}
 

You are now ready to drive but there is one more section you should take a look into before you continue, Physics Materials.

Create Physics Materials

Physics materials are not like normal material that we used to create the shiney surface of the vehicle. Physics materials tells us how each object will interact with other objects.

We need to create two physics materials 1 for the terrain/landscape and 1 for the vehicle now at this moment in time there is no seperate physics materials that can be added to each wheel of the vehicle, when the TV Developers update this i will update these pages.

we first need to create a couple of variables to hold our material identifiers. At the top in our variable section add the following variables.

int pmatTerrain;
int pmatChassis;

we can now use these variable to create and manipulate our physics materials Locate the InitPhysicsMaterials() function and add the following

//TerrainLandscape
pmatTerrain = physics.CreateMaterialGroup("Terrain");
physics.SetMaterialInteractionFriction(0, pmatTerrain, 0.9f, 1f);
physics.SetMaterialInteractionSoftness(0, pmatTerrain, 1f);
physics.SetMaterialInteractionBounciness(0, pmatTerrain, 0.1f);
physics.SetBodyMaterialGroup(pbLand, pmatTerrain);
 
//Chassis   
pmatChassis = physics.CreateMaterialGroup("Chassis");
physics.SetMaterialInteractionFriction(pmatChassis, pmatTerrain, 0.3f, 0.17f);
physics.SetMaterialInteractionBounciness(pmatChassis, pmatTerrain, 0.1f);
physics.SetMaterialInteractionSoftness(pmatChassis, pmatTerrain, 1000f);
physics.SetBodyMaterialGroup(pbi_chassis, pmatChassis);

These material settings allow us to change the way that the vehicle will move around our terrain/landscape also this will make the vehicle slide or stick like glue.

Additional

Here are a couple of extra functions to help with the vehicle if you happen to turn it onto its roof.

Locate the CheckInput() function and add the following code just above the Mouse section

if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_P))
{
    physics.VehicleReset(car_ID);
    physics.SetBodyRotation(pbi_chassis, 0, 0, 0);
    physics.SetBodyPosition(pbi_chassis, physics.GetBodyPosition(pbi_chassis).x,physics.GetBodyPosition(pbi_chassis).y + 0.2f, physics.GetBodyPosition(pbi_chassis).z);
}
 
if (input.IsKeyPressed(CONST_TV_KEY.TV_KEY_O))
{
    physics.VehicleReset(car_ID);
    physics.SetBodyPosition(pbi_chassis, 0f, 5, 0f);
    physics.SetBodyRotation(pbi_chassis, 0f, 0f, 0f);
}
 
 

This will allow you so reset the vehicle to a start location Key: O or reset the vehicle onto its wheel at its current location Key: P

Conclusion

You should now be able to drive the vehicle around the plane grass area,

your full list of keys is

  • WASDQE Move Camera
  • Mouse Look
  • Arrow Keys Drive the vehicle
  • Right CTRL handbrake
  • O Reset Vehicle To Start
  • P Reset vehicle On Its Wheels

Notice the clear glass look on the vehicle this is due to that single pixel texture we created.

Here is the completed project for you all.

Vehicle Starter Kit

I would also like to credit and thanks whoever actually created the Impreza model however i don’t know there name but thank you.

Here is a VB6 Conversion from rogangriffin Thanks for your contribution.

VB6 Vehicle Starter Kit

Here is a CPP Conversion from petroz Thanks for your contribution.

CPP Vehicle Starter Kit

Enjoy driving around.

Lyrical

 
tutorialsarticlesandexamples/vehicle_starter_kit.txt · Last modified: 2013/11/22 13:32