Simple vehicle implementation

Discuss any questions about BEPUphysics or problems encountered.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Simple vehicle implementation

Post by mateod »

Hi,

This is my first attempt in 3d graphics, and I wanna create simple car game. I know that bepu provides Vehicle object, but I have no idea how to start with it. Basically, I would like to achieve something similar to this: http://www.youtube.com/watch?v=lR0NjIAm ... r_embedded.
I started my work with:

Code: Select all

Vector3[] rawVertices = new Vector3[terrain.vertices.Length];

            for (int i = 0; i < terrain.vertices.Length; i++)
            {
                rawVertices[i] = terrain.vertices[i].Position;
            }

            // car contents here


            var bodies = new List<CompoundShapeEntry>
            {
                new CompoundShapeEntry(new BoxShape(2.5f, 10f, 4.5f), new Vector3(0, 1000, 0), 60),
                new CompoundShapeEntry(new BoxShape(2.5f, 10f, 2f), new Vector3(0, 1000, .5f), 1)
            };
            var body = new CompoundBody(bodies, 61);
            body.CollisionInformation.LocalPosition = new Vector3(0, 1000f, 0);
            body.Position = new Vector3(0, 1000, 0); //At first, just keep it out of the way.
            Vehicle = new Vehicle(body);
            
            space = new Space();
            space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);

            var mesh = new StaticMesh(rawVertices, terrain.indices, new AffineTransform(new Vector3(0, 0, 0)));
            space.Add(mesh);

            space.Add(Vehicle);
but don't know what to do next - how to draw wheels, and how to draw vehicle at all? Some source code (but simpler than the one in demo) would be great.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

A few notes about that posted code:
1) Positioning the compound shapes at 1000 units up is redundant with setting the position of the body to 1000 units up. The CompoundBody constructor computes a Position from the shape positions and masses, and the shapes are recentered in local space. For simplicity, I'd recommend keeping the shape configuration in whatever convenient local space you want and then setting the body.Position to teleport it somewhere.
2) body.CollisionInformation.LocalPosition offsets the shape of the entity from the center of mass of the entity. Setting it to (0,1000,0) will make the shape appear 1000 units away from the center of the entity. Usually, LocalPosition is left at zero. The VehicleInput offsets the shape very slightly upward to effectively lower the center of mass, making the car less likely to tip over when cornering.
3) The vehicle has no wheels yet.

The VehicleInput class in the demos shows a complete configuration. It may look daunting, but it's fundamentally not all that bad- just plopping some wheels together. If you have a specific question about the configuration I'll try to help.
how to draw wheels, and how to draw vehicle at all?
The physics engine has no concept of graphics and doesn't do anything related directly to rendering. It does, however, expose bits of data which you can use in your graphics engine. An entity, which a vehicle's body is, has a WorldTransform (created directly from its Position and Orientation) and other properties which you can use to transform your graphic. When positioning graphics objects, you may find the graphics object is offset from the real shape. Shape recentering is the likely explanation.

Every Wheel in the Vehicle.Wheels collection has a Shape. The Shape has a WorldTransform property which can be used as a basis for the graphics. However, this is just a convenience property. To see it in use, check out the VehicleInput class in the BEPUphysicsDemos. The Update method's first few lines position the wheel graphics according to the vehicle's wheel transforms.

If you're just starting out, I would strongly recommend splitting the learning process a bit. Trying to dive in head first with rendering and physics together usually overcomplicates things since it's hard to know where exactly a problem is. Making a graphics prototype without any simulation component narrows down the possible failure modes. Similarly, learning the simulation mechanics is probably best done by fiddling with stuff in the demo where rendering is all taken care of for you.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Thank you for your reply! I gave a vehicle demo a shot, but now I have a different problem. Every time i try to run my project, i get error message:
{"The type initializer for 'BEPUphysicsDrawer.Models.ModelDrawer' threw an exception."}
and this actually points at this part of code (in InterfaceModelDrawer.cs)

Code: Select all

...
public InstancedModelDrawer(Game game)
            : base(game)
        { ...
This is a bit strange to me, because I copied source from demo and here is what I do in my LoadContent method:

Code: Select all

ModelDrawer = new InstancedModelDrawer(this); // in Initialize();
protected override void LoadContent()
            { 
            // some code here

            Vector3[] rawVertices = new Vector3[terrain.vertices.Length];

            for (int i = 0; i < terrain.vertices.Length; i++)
            {
                rawVertices[i] = terrain.vertices[i].Position;
            }

            space = new Space();
            space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);

            var mesh = new StaticMesh(rawVertices, terrain.indices, new AffineTransform(new Vector3(0, 0, 0)));
            space.Add(mesh);

            var wheelModel = Content.Load<Model>("carWheel");
            var wheelTexture = Content.Load<Texture2D>("wheel");
            vehicle = new VehicleInput(new Vector3(100, 0, 0), space, camera, ModelDrawer, wheelModel, wheelTexture);
            space.Add(vehicle);
Any idea why it can't start? Oh, and I use of course BEPUPhysicsDrawer from demo source.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

Nothing jumps out as wrong there. Common errors related to the BEPUphysicsDrawer are a missing InstancedEffect.fx or a computer which can't use the InstancedModelDrawer which currently requires SM3 compatability. However, I would not expect those issues to cause a type initializer error. Isolating the issue a bit more might help.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Actually i had InstancedEffect.fx missing, but I added it to my project (the game project, not the BEPUPhysicsDrawer) and it still doesn't work.
And you said that it requires Shader 3, but running demo source leads to having the project compiled, same computer.
Maybe I'm doing something wrong with including this effect?

I also tried to create a new project that uses vehicle only, but it also throws me the same error:

Code: Select all

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Space space;

        //car

        protected VehicleInput vehicle;
        public ModelDrawer ModelDrawer;

        Camera camera;

        public KeyboardState KeyboardState;

        public MouseState MouseState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            camera = new Camera(this, new Vector3(0, 3, 10), 5);
            ModelDrawer = new InstancedModelDrawer(this);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);

            space.Add(new Box(new Vector3(0, 0, 0), 100f, 100f, 100f));
            space.Add(new Box(new Vector3(0, 10, 0), 20f, 10f, 10f, 10f));

            var wheelModel = Content.Load<Model>("carWheel");
            var wheelTexture = Content.Load<Texture2D>("wheel");
            vehicle = new VehicleInput(new Vector3(0, 0, 0), space, camera, ModelDrawer, wheelModel, wheelTexture);  
        }
        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
// EDIT:

I found some more detailed information about exception, but I don't really know what that might mean:
{"The type initializer for 'BEPUphysicsDrawer.Models.ModelDrawer' threw an exception."}

[Data] {System.Collections.ListDictionaryInternal}

{"Could not load file or assembly 'BEPUphysics, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31f6a8732a21de19' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)":"BEPUphysics, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31f6a8732a21de19"}
Last edited by mateod on Thu May 03, 2012 6:27 pm, edited 1 time in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

Is there anything in the inner exception? These types of errors usually have a child exception that you can look at for a useful stack trace.

I would also recommend checking out one of the simpler documentation demos that use the BEPUphysicsDrawer as an example of how to integrate it. The MultithreadingDemo is one of the simplest: http://bepuphysics.codeplex.com/wikipag ... umentation
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Yes, sorry for not posting it on the begining:
{"The type initializer for 'BEPUphysicsDrawer.Models.ModelDrawer' threw an exception."}

[Data] {System.Collections.ListDictionaryInternal}

{"Could not load file or assembly 'BEPUphysics, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31f6a8732a21de19' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)":"BEPUphysics, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31f6a8732a21de19"}
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

That means the BEPUphysicsDrawer was looking for a BEPUphysics assembly, but the one it found wasn't the one it expected. It might be an older version.

One likely option would be rebuilding BEPUphysics and the BEPUphysicsDrawer together to ensure that the BEPUphysicsDrawer is looking for the right version of BEPUphysics.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Ok, so right now, summing up I'm supposed to:

- add the reference to my game to BEPUphysicsDrawer (as a subproject of solution from the demo)
- add reference to BEPUPhysics.dll (to my game).

And that's it? I saw that in demo programs which contained BEPUPhysicsDrawer.dll but I have no idea where I can get it from.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

I saw that in demo programs which contained BEPUPhysicsDrawer.dll but I have no idea where I can get it from.
That's just a precompiled version that I create when I update the documentation demos. You can do the same thing by building the latest version of the BEPUphysics solution and going into the compiled directory and grabbing the BEPUphysics.dll and BEPUphysicsDrawer.dll.

So, one option is:
1) Grab a BEPUphysics.dll and a compatible BEPUphysicsDrawer.dll (by building the BEPUphysics solution or otherwise).
2) Add the BEPUphysics.dll to your project's references.
3) Add the BEPUphysicsDrawer.dll to your project's references.

Another option is:
1) Grab a BEPUphysics.dll, whatever version it might be.
2) Add the BEPUphysics.dll to your project's references.
3) Add the BEPUphysicsDrawer source to your game's solution and add a reference to that project to the game project that's in the same solution.
4) Add your BEPUphysics.dll to the BEPUphysicsDrawer project's references.

Another option is:
1) Grab the BEPUphysics source project and include it in your solution.
2) Grab the BEPUphysicsDrawer source project and include it in your solution.
3) Add the BEPUphysics project as a reference to the BEPUphysicsDrawer project.
4) Add the BEPUphysics project and the BEPUphysicsDrawer projects as references in your game project in the same solution.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Cool, everything works like a charm now! Thank you for your help, mate! :)
But returning to the car problem, there seems to be a little bit different problem - the code I provided above doesn't make the car appear. Sure, everything else is working, but car is still invisible (i put position to 0, 1000, 0 as my terrain is that high). vehicle.Activate() in loading content doesn't affect that. Any clue what I messed up this time? :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

Has the vehicle's entity body been added to the ModelDrawer? Also, make sure to call the ModelDrawer.Update in your Update (and Draw in the Draw :)).

By the way, since single precision floating point numbers have more values closer to zero, it would be a good idea to roughly center your simulation around (0,0,0). Being out at (0,1000,0) almost certainly won't cause noticeable problems (seeing those usually requires around ~100,000 units away from the origin), but it's something to keep in mind.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Well, the only thing I'm doing now is in LoadContent method:

Code: Select all

 var wheelModel = Content.Load<Model>("carWheel");
            var wheelTexture = Content.Load<Texture2D>("wheel");
            vehicle = new VehicleInput(new Vector3(0, 1000, 0), space, camera, ModelDrawer, wheelModel, wheelTexture);
In Initialize() I initialize ModelDrawer and I put

Code: Select all

space.Update();
            ModelDrawer.Update();
in Update method +

Code: Select all

ModelDrawer.Draw(((FreeCamera)camera).View, (((FreeCamera)camera).Projection));
in Draw(). I thought that vehicle is being added thanks to the second parameter of VehicleInput, isn't it?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Simple vehicle implementation

Post by Norbo »

The VehicleInput constructor does not add the vehicle body to the ModelDrawer. It does indirectly add it to the space, though.

In the BEPUphysicsDemos, there's a loop after each demo configuration which goes through every entity in the space and adds it to the ModelDrawer. Without that loop, each object needs to be added to the ModelDrawer individually.
mateod
Posts: 22
Joined: Thu May 03, 2012 1:42 pm

Re: Simple vehicle implementation

Post by mateod »

Ok, I checked if there are entity of car in space.Entities. I printed them on the screen and it turned out that there are four entities. They are falling from the height I set, but model is still invisible. I am starting to think that maybe it's caused by camera or something? Oh, and now in LoadContent() I call

Code: Select all

ModelDrawer.Add(vehicle);
vehicle.Activate();
I tried many other combinations, but I guess there is still something missing in my code...
Post Reply