Saturday, September 12th, 2009

XNA: The basic physics of JigLibX

podstawy-jiglibx XNA itself, does not offer classes to help us in the calculation of physics. Although it is possible to detect the same collision, but that is how objects behave when it is detected, depends only on code written by us. Unless we use ready-made libraries for the servants. I took the most popular wallpaper XNA'ową OpenSource library - JigLibX .

What can you achieve?

Referring to the movies to the authors, two examples:

... And an example created by the same authors JigLibX:


More videos on the project site .

Creating a project

The first thing you should do is to download from the Download section, the latest source JigLibX'a. After unpacking, we create a new project (in my case XNA 3.1 project), click on the Solution Explorer on the main root of our project (Solution NazwaNaszegoProjektu), right-click and select Add> Existing Project

jiglibx-dodawanie-projektu1

Adding existing project to the existing

then select the folder where you unpacked previously downloaded a physics engine: JigLibX> JigLibX.csproj.

jiglibx-dodawanie-projektu

Adding existing project to the existing

If you chose when creating the project, the project for XNA version 3.1, you must now do the project JigLibX upgrade to version 3.1. We do this by right-clicking on the project root JigLibX> Upgrade Solution. We do this to later be able to add the project main project references JigLibX'a. Otherwise, this is not possible, since at present it is intended for version 3.0. Changes in version 3.1 are not large enough, however, to fully correct the library is operated under this version of XNA.

Then, right click on the root of our main project (in my case it is called FizykaZJigLibX)> Add reference> Projects> JigLibX. In the tree of our project, the folder references should appear JigLibX. Now we have access to that namespace.

The addition of physics of the system

First, it will be necessary to add the appropriate namespace in your Game1.cs.

  using JigLibX.Physics;
 using JigLibX.Geometry;
 using JigLibX.Collision; 

We can therefore use the classes written by the creators of JigLibX'a. For starters, in the constructor of our class, we create two objects.

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

 PhysicsSystem PhysicsSystem world = new ();
 CollisionSystemSAP world.CollisionSystem = new ();
 } 

The object world, which PhysicSystem instance, initiate all necessary variables and the controller will sense the events taking place inside our application. Events related to physics. In the next line, to the properties CollisionSystem, we assign a CollisionSystemSAP created object, which is necessary to detect any collisions. This class uses an algorithm "sweep and prune" for collision detection, which in this example, will be sufficient, but if looking to the folder in the project JigLibX Collision, we see that we are able to take advantage of other ready-classes, using different algorithms, eg based on the grid (grid). If you omit this step that we could not react to collisions, and the facilities would simply pass by them without any reaction.

You should do one thing, namely, to regularly update our facility that stores the logic of physics. To do this, just the Update method, add the following code:

  timeStep = float (float) gameTime.ElapsedGameTime.Ticks / TimeSpan.TicksPerSecond;
 PhysicsSystem.CurrentPhysicsSystem.Integrate (timeStep); 

Because PhysicsSystem.CurrentPhysicsSystem is a component of the static, it is available from anywhere in our project, which undoubtedly increases the convenience of this solution.

The creation of an actor class

Actor class, it will actually serve to create the object, which will set the parameters defining the object in our application, and which are necessary for any calculations on collisions with the environment.

Let's create a class BoxActor.cs so by clicking on the root of our project> Add> Class ..

jiglibx-boxactor-class

Create a class BoxActor.cs

Put the following code inside the file BoxActor.cs:

 using System; using Microsoft.Xna.Framework, using Microsoft.Xna.Framework.Graphics, using JigLibX.Math, using JigLibX.Physics, using JigLibX.Geometry, using JigLibX.Collision; namespace {public class FizykaZJigLibX BoxActor: DrawableGameComponent {private Vector3 position; private Vector3 scale; private _body Body; public Body Body {get {return _body;}} private CollisionSkin _skin; public CollisionSkin Skin {get {return _skin;}} public BoxActor (Game game, Vector3 position, Vector3 scale): base (game) {this.position = position; this.scale = scale;}}} 

BoxActor class inherits from the class DrawableGameComponent because the actor must be drawn on the screen, so we can see what happens. Pole position holds information about a central point inside the Box, and the scale - its dimensions. Body is to be understood as a variable that stores information about the movement and rotation of our object. Skin is responsible for detecting collisions.

Creating Body and CollisionSkin

The next step will be adding at the end of BoxActor class constructor, the following code:

  _body = new Body ();
 _skin = new CollisionSkin (_body);
 _body.CollisionSkin = _skin; 

For _body variable, assign an instance of Body, which will store basic information about the state in which the object is located. _skin Will have information about the "shell" of our facility, which will be created based on previously set _body. Finally, it is still set CollisionSkin property for _body.

Now, decide what shape, will have our actor. Depends on how it will behave on the stage. Look for the Primitives class found in JigLibX> Primitives.

In our case, we want our object to behave like a box, so we use this class Box, by adding the following code at the end of the class constructor BoxActor.

  Box box = new Box (Vector3.Zero, Matrix.Identity, scale);
 _skin.AddPrimitive (box, new MaterialProperties (0.8f, 0.8f, 0.7f)); 

In the above, we created a new object of class Box, whose parameters in the constructor stand for: The position of the center of our Box, Box orientation (identity matrix means no rotation, etc.), and a scale that will be set when constructing the object BoxActor.

The second line, colliding with the surface adds to our facility so that it can react with other objects. The first parameter is an object type with which we deal, the second parameter specifies the behavior of the material (friction and elasticity).

Determining the mass of the object

To determine the mass of the object, which in addition the center of gravity, will vary depending on the direction of the forces that will affect this object, the authors JigLibX, created the following method that was added to the class BoxActor.

  SetMass private Vector3 (float mass)
 {
     PrimitiveProperties primitiveProperties = new PrimitiveProperties (
         PrimitiveProperties.MassDistributionEnum.Solid,
         PrimitiveProperties.MassTypeEnum.Mass, Mass);

     float junk;
     Vector3 com;
     Matrix IT;
     Matrix itCoM;

     Skin.GetMassProperties (primitiveProperties, out junk, out com, out it, out itCoM);

     Body.BodyInertia = itCoM;
     Body.Mass = junk;

     com return;
 } 

At the end of the constructor of the same class, we determine the mass as follows:

  Com = SetMass Vector3 (1.0f); 

And that's when it comes to taking over the mass of our object :) . Of course, nothing prevents that, during the application, can change the mass of the object.

Setting the right place Box'aw

In this step, we set our Box on the item you will be given in the constructor during the creation of our actor. This is necessary to fit the body of our facility, as well as collision surface according to the same object that the effect was adequate and realistic.

At the end of BoxActor constructor, add the following code:

  _body.MoveTo (position, Matrix.Identity);
 _skin.ApplyLocalTransform (new Transform (-com, Matrix.Identity));
 _body.EnableBody (); 

The first line moves the "body" of our actor on a specific item. The second parameter of MoveTo method, indicates the orientation of the object.

The second line sets the collision area respectively the center of gravity of the property.

The last line, enables the simulation to _body and also an actor. This line is necessary because the simulation is disabled by default.

Creation of the World.

All settings related to the frameworks have been set, so you can go to create the World. At the end of the constructor in the main file of our project game1.cs, add the following code:

  fallingBox = new BoxActor (this, new Vector3 (5, 20, 5), new Vector3 (2, 2, 2));
 immovableBox = new BoxActor (this, new Vector3 (0, -5, 0), new Vector3 (10, 10, 10));
 immovableBox.Body.Immovable = true;
 Components.Add (fallingBox);
 Components.Add (immovableBox); 

Component is still to be added on all methods in the class Game1:

  BoxActor fallingBox;
 BoxActor immovableBox; 

The first two lines make up our actors. The parameters in the constructor, stand for: the first - instance in which the actor created, in this case, our application main class Game1, the second - the position, the third parameter is the size of the item.

The third line means that the second object is motionless, and as seen in the parameters passed to the constructor, it will be much higher (5x) than the first object.

The fourth and fifth line created by us will add objects to a collection of components that will be drawn automatically by the Game class, which inherits after your application.

Drawing

We now turn to the last stage, that is, discarding the result to the screen is actually pretty words, you draw the scene. But first, we must add the model box, which we use in our project. Sample model from the Innovative Games , you can download here .

After unpacking the file and copied two of the contained files (with the model and texture) should be in the Solution Explorer, right-click the Content folder (in our project) and select Add> Existing Item ... and select the model file. Fbx and Repeat step, selecting a file from the texture.

jiglibx-content

After the addition of Folder Content model and texture

The class BoxActor, create a new method that will load our model:

  protected override void LoadContent ()
 {
     model = Game.Content.Load ("boxModel");
 } 

and add over all methods in this class, the declaration of a variable model:

  private Model model; 

Then add the same class, the following method:

 GetWorldMatrix private Matrix () {return Matrix.CreateScale (scale) * _skin.GetPrimitiveLocal (0). Transform.Orientation * _body.Orientation * Matrix.CreateTranslation (_body.Position);} 

It returns an array of our complex world, which we obtain by multiplying the matrices in sequence: the scale of the collision surface, and really the angle at which it is located, the "body" of the object (the angle), and the position of the "body" of the object.

We will need more projection and view matrices, which will add to the main application class (in the file game1.cs):

  private Matrix _view;
 public Matrix View
 {
     get
     {
         _view return;
     }
 }

 private Matrix _projection;
 public Matrix Projection
 {
     get
     {
         _projection return;
     }
 } 

In the Game1 class constructor, let's set at the end of the projection matrix by adding the following line:

  Matrix.CreatePerspectiveFieldOfView _projection = (
     MathHelper.ToRadians (45.0f),
     (Float) graphics.PreferredBackBufferWidth / (float) graphics.PreferredBackBufferHeight,
     0.1F,
     1000.0f
 ); 

I will not describe the parameters of the matrix of the projection, because I assume that at this stage they are quite clear, but if not, I invite you to this article on msdn'ie .

Left we have set the view matrix, we will do it in the method Update, Game1.cs file by adding the following line of code:

  Matrix.CreateLookAt _view = (
     new Vector3 (0, 10, 20),
     fallingBox.Body.Position,
     Vector3.Up
 ); 

This line will cause the center of the screen, there will be our falling object. During the fall, we'll see how, come into collision with an object that has been immobilized.

Finally, it remains for us to add a method for BoxActor Draw, which is automatically called for this object to draw.

  public override void Draw (GameTime gameTime)
 {
     BasicWorldGame game = (BasicWorldGame) Game;

     Matrix [] transforms = new Matrix [model.Bones.Count];
     model.CopyAbsoluteBoneTransformsTo (transforms);

     WorldMatrix = GetWorldMatrix Matrix ();

     foreach (ModelMesh mesh in model.Meshes)
     {
         foreach (BasicEffect effect in mesh.Effects)
         {
             effect.EnableDefaultLighting ();
             effect.PreferPerPixelLighting = true;
             effect.World = transforms [mesh.ParentBone.Index] * worldMatrix;
             effect.View = game.View;
             effect.Projection = game.Projection;
         }
         mesh.Draw ();
     }
 } 

With the first line, you'll have access to view and projection matrices, creating a reference to the main subject of our application. The rest of the code, is typical for rendering objects with BasicEffect class. The only important thing is to use the world matrix, the matrix which is calculated in real time, and actually JigLibX calculated for us.

The article is based on the documentation found here , but there are indications that the text reproduced here is obsolete, and written by me version should work better. Perhaps this is due to incomplete compatibility with XNA 3.1, but from what I looked at the methods, one of them has been reduced from three to two parameters. JigLibX version 0.3.1 (as of September 11, 2009).

The finished project to download (XNA 3.1) (2.1 MB)

Compiled demo (XNA 3.1) (0.3 MB)


Related entries

Categories: . net / c # / XNA
You can follow any responses to this entry through the feed RSS 2.0 . You can also write your own comments , or to link to this post on your page.

3 comment / s

September 12, 2009
BartekB

Well I'll tell you that is not here to comment, post on a high level as usual.


September 15, 2009

a very interesting entry, do not play with the graph, but I read it with pleasure. Thanks!


January 1, 2012

Following my monitor, thousands of people in the world get the personal loans from various Creditors. Thus, there's good possibilities to find a commercial loan in every country.


  • Obraz CAPTCHY
    Refresh Image
    *

    Spam Protection by WP-SpamFree