If I just need the phyiscs (collision, reaction etc.) what should I do?

Dec 13, 2007 at 9:03 AM
Hi,

I really like this framework after looking through the code. I am wondering how should I go about integrating this with my current project ( I wish I had started with your framework though...). For my FYP project I have to integrate a physics library of my choice into my existing code, and I already have a free moving FPS camera, a third person camera, heightmap terrain, 3d movement of object and collision with heightmap. I have been looking through the example application and think that all I need will be

  • The physics component
  • The quadtree component
  • The rigid objects shape collison

If I am not using the GameScreen component of the framework, I just have to manually call the update of rach of those component, am I right to assume that?

I am thinking that since I already have my own entity code (using a component-based system), I could just include, say, the CollisonSphere into my entity, and use the simulation to set the existing position/velocity/speed of the entity. Am I right to assume this?

Any other advice will be appreciated!

Thanks in advance!
Coordinator
Dec 13, 2007 at 9:06 PM
Hi extrakun,
I think that we're on the same page as far as integrating physics into your existing project, but I'll explain a bit in detail just in case:

First, I would probably first try to just include the project Oops.Xna.Framework as a reference into your solution, unmodified. You can get rid of the classes you don't need later if that's important.

Since you already have an "entity" class, just include a reference to a CollisionShape (i.e, CollisionSphere or CollisionBox) instance, like you stated:

public class YourEntityComponent
{
	...
 
	private CollisionShere collisionShape;
 
	public YourEntityComponent()
	{
		// Create the collision shape for your entity.
		this.collisionShape = new CollisionSphere();
 
		// Initialize the collision shape properties.
		this.collisionShape.Radius = 5.0f;
		this.collisionShape.CategoryFlags = 1;
		this.collisionShape.CollisionFlags = 1;
 
		// Create the rigid body for your entity.  Pass in "this" to parameter to get to your
		// entity class from this rigid body instance.
		RigidBody rigidBody = new RigidBody(this);
 
		// Initialize the rigid body parameters.
		rigidBody.Position = new Vector3(10.0f, 10.0f, 10.0f);
		rigidBody.Orientation = Quaternion.Identity;
		rigidBody.Friction = 1.0f;
		rigidBody.Restitution = 0.8f;
		rigidBody.LinearDamping = 0.7f;
		rigidBody.AngularDamping = 0.5f;
		rigidBody.Acceleration = new Vector3(0.0f, -9.8f, 0.0f);
 
		// Initialize mass properties of the rigid body.
		float mass = 4.0f * 0.3333f * (float)Math.PI * 
			this.collisionShape.Radius * 
			this.collisionShape.Radius * 
			this.collisionShape.Radius;
		rigidBody.SetMass(mass);
		rigidBody.SetInertiaTensor(MatrixExtension.CreateSolidSphereInertiaTensor(mass, this.collisionShape.Radius));
 
		// Make sure the rigid body is ready for action.
		rigidBody.SetEnabled(true);
 
		// Associate the rigid body to the collision shape.
		this.collisionShape.RigidBody = rigidBody;
 
		// Initialize the collision shape and associated rigid body.
		this.collisionShape.RigidBody.CalculateDerivedData();
		this.collisionShape.CalculateInternals();	
	}
 
	public CollisionSphere CollisionShape
	{
		get { return this.collisionShape; }
	}
 
	...
}

When you create the physics component, you can just add it to your Game's Component collection, which will call Update for you. Make sure to implement the IPhysicsIntegrator, ICollisionGenerator and IQuadTreeComparer<CollisionShape> interfaces (I'll explain next). I'll also create the quad tree instance here for space partitioning. Make note that any position or orientation changes should be made BEFORE the physics component updates. See the Update method below:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	private PhysicsComponent physics;
 
	// Quad-tree that partitions collision shapes.  This class uses the IQuadTreeComparer<T> implemented 
	// by this GameScreen class.
	protected QuadTree<CollisionShape> space;
 
	public YourGame()
	{
		// Create the physics component.
		this.physics = new PhysicsComponent(this, this, this);
 
		// Add the physics component to the game's component collection.
		this.Components.Add(this.physics);
 
		// Create and initialize the quad-tree space.  Play with the depth parameter 
		// to see how it affects performance.
		this.space = new QuadTree<CollisionShape>(new Vector3(200.0f, int.MaxValue, 200.0f), 4, this);
 
		...
	}
 
	public override Initialize()
	{
		// Initialize the physics component.  The only parameter that can't be modified during the game loop is 
		// collision capacity.  It will have no affect.
		this.physics.CollisionCapacity = 512;
		this.physics.PenetrationCorrectionTolerance = 0.01f;
		this.physics.VelocityCorrectionTolerance = 0.01f;
		this.physics.MaximumPenetrationResolutionIterations = 1024;
		this.physics.MaximumVelocityResolutionIterations = 1024;
 
		// TODO : Add your entity's collision shapes to the quad tree.  I'm assuming that they are just in a collection field of 
		// your game class already created and populated.  Modify, if that's not the case.
		this.space.Reset();
		for each (YourEntityComponent entity in this.entities)
		{
			this.space.Add(entity.CollisionShape);
		}
 
		...
 
		// Call inherited method.
		base.Initialize();
	}
 
	public override Update(GameTime gameTime)
	{
		// TODO : Add any changes to your entities' position, orientation, velocity, torque, here.  If you entity component already
		// has Position and Orientation properties, you'll want to delegate assignment to the rigid body's properties as well...or 
		// Just use the rigid body's properties for your entity's position and orientation.  
		// If at all possible, make position/orientations using force/torque.  If that won't work, try modifying the 
		// Velocity or Rotation.  Direct manipulation of the Position and Orientation properties should be your last result. 
		// Something like:
		this.entities[0].CollisionShape.RigidBody.ApplyForce(<some vector>);
		this.entities[0].CollisionShape.RigidBody.ApplyTorque(<some vector>);
 
		...
 
		// Call inherited method.  The physics component will be update here.
		base.Update(gameTime);
	}
}

Then, implement the IPhysicsIntegrator interface in your game class:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	#region IPhysicsIntegrator Members
 
	void IPhysicsIntegrator.PreStep(float elapsed)
	{
		// Just pre step all entities.
		for each (YourEntityComponent entity in this.entities)
		{
			entity.CollisionShape.RigidBody.PreStep(elapsed);
		}
	}
 
	void IPhysicsIntegrator.Integrate(float elapsed)
	{
		// Just integrate all entities.
		for each (YourEntityComponent entity in this.entities)
		{
			entity.CollisionShape.RigidBody.Integrate(elapsed);
			entity.CollisionShape.CalculateInternals();
		}
	}
 
	#endregion
 
	...
}

The ICollisionGenerator interface implementation should just delegate the collision generation to the quad-tree:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	#region ICollisionGenerator Members
 
	void ICollisionGenerator.Generate(CollisionContext context)
	{
		// Use space partitioning to compare collision shapes.  Update re-partitions all the collision shapes, if necessary.
		// Compare compares the collision shapes based on partitioning, using the implemented IQuadtreeComparer<T> of this class.
		this.space.Update();
		this.space.Compare(context);
	}
 
	#endregion
 
	...
}

Next, implement the IQuadTreeComparer<CollisionShape> interface. This is where collisions are determined:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	#region IQuadTreeComparer<CollisionShape> Members
 
	bool IQuadTreeComparer<CollisionShape>.Compare(CollisionShape obj, object state)
	{
		// TODO : This would probably be where you would compare your entity's collision shape (i.e., the "obj" parameter) to
		// your world (i.e., heightmap, plane, whatever) and generate collisions.
		return true;
	}
 
	bool IQuadTreeComparer<CollisionShape>.Compare(CollisionShape x, CollisionShape y, object state)
	{
		// Get the collision context.
		CollisionContext context = state as CollisionContext;
 
		// Since there are only four shapes implemented in the physics component (plane, sphere, box, wedge),
		// the collision method is determined with type checking.
		if (x is CollisionWedge)
		{
			if (y is CollisionSphere) ((CollisionWedge)x).Collide((CollisionSphere)y, context);
			else if (y is CollisionBox) ((CollisionWedge)x).Collide((CollisionBox)y, context);
			else if (y is CollisionWedge) ((CollisionWedge)x).Collide((CollisionWedge)y, context);
		}
		else if (x is CollisionSphere)
		{
			if (y is CollisionSphere) ((CollisionSphere)x).Collide((CollisionSphere)y, context);
			else if (y is CollisionBox) ((CollisionBox)y).Collide((CollisionSphere)x, context);
			else if (y is CollisionWedge) ((CollisionWedge)y).Collide((CollisionSphere)x, context);
		}
		else if (x is CollisionBox)
		{
			if (y is CollisionSphere) ((CollisionBox)x).Collide((CollisionSphere)y, context);
			else if (y is CollisionBox) ((CollisionBox)x).Collide((CollisionBox)y, context);
			else if (y is CollisionWedge) ((CollisionWedge)y).Collide((CollisionBox)x, context);
		}
 
		return true;
	}
 
	bool IQuadTreeComparer<CollisionShape>.Contains(QuadTreeNode<CollisionShape> node, CollisionShape obj)
	{
		// This is called when a new item is added to quadtree or the quadtree is updated.
		return node.Bounds.Contains(obj.AABB) == ContainmentType.Contains;
	}
 
	#endregion
 
	...
}

To Draw your entities, use your entity's CollisionShape's Transform property for the World matrix in your effects. I'm assuming that a BasicEffect instance is being used for drawing in the code below and all parameters are already correctly set (i.e., View and Projection):

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	public override void Draw(GameTime gameTime)
	{
		// Initialize the basic effect for this iteration.
		this.basicEffect.Begin();
 		this.basicEffect.CurrentTechnique.Passes[0].Begin();
            
		// Draw all the entities.
		for each (YourEntityComponent entity in this.entities)
		{
			this.basicEffect.World = entity.CollisionShape.Transform;
			...
			this.basicEffect.CommitChanges();
 
			TODO : Draw entity.
			entity.Draw();
		}
 
		// End the basic effect processing.
		this.basicEffect.CurrentTechnique.Passes[0].End();
		this.basicEffect.End();
 
		// Call inherited method.
		base.Draw(gameTime);
	}
 
	...
}

That should get you started I think. Let me know if you have anymore questions. Good luck!


Dec 14, 2007 at 6:47 AM
Edited Dec 14, 2007 at 11:05 AM
OMG, thanks for the detailed information!

If I managed to port it over, I'll be sure to write a tutorial or something to show the process so that others can port over easily too.

Edit: I am still in the process of doing the porting over the weekend. Thanks again!

Edit 2: I have some issues about the applyForce and applyTorque. Basically, the entity is player-controlled, with A and D changing the orientation, and W/S applying the force. So I will work out a right, up and forward vector from this and use that to update the entity's position. So I suppose, from your explanation, I could just update my own Position and Orientation property (which is actually 3 vectors, up, right and forward), and when updating the force of the rigid body, I just use the the forward vector * velocity?

How then should I deal with the torque?

Also, supposing I am storing my own position and orientation properties, when should I take the values from the RigidBody and apply it to my own entities?

Thanks in advance!
Dec 14, 2007 at 1:34 PM
Sorry to trouble you again.

I was porting halfway when I run into one potential obstacle - I am storing my orientation as three vectors - Up, Right and Direction. How do I translate that to quaternion, and back?
Coordinator
Dec 14, 2007 at 7:30 PM
When pressing W/S, calling the ApplyForce/ApplyForceImpulse method of the entity's associated rigid body might be your best bet. Remember the force will be applied in world-space, not local-space, so you would have to determine the forward/backward vector like you stated. When pressing A/D, again call the ApplyTorque/ApplyTorqueImpulse method of the entity's associated rigid body, probably using an upwards vector as it's direction and whatever magnitude. I'm assuming below that you want to move the first entity in an "entities" collection:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	public override Update(GameTime gameTime)
	{
		// Apply force to move forwards/backwards.
		Vector3 force = Vector3.Zero;
		if (keyboardState.IsKeyDown(Keys.W) force = this.entities[0].Forward * FORCE_MAGNITUDE;
		if (keyboardState.IsKeyDown(Keys.S) force = this.entities[0].Forward * -FORCE_MAGNITUDE;
		this.entities[0].CollisionShape.RigidBody.ApplyForce(force);
 
		// Apply torque to turn left/right.
		Vector3 torque = Vector3.Zero;
		if (keyboardState.IsKeyDown(Keys.A) torque = this.entities[0].Up * TURN_MAGNITUDE;
		if (keyboardState.IsKeyDown(Keys.D) torque = this.entities[0].Up * -TURN_MAGNITUDE;
		this.entities[0].CollisionShape.RigidBody.ApplyTorque(torque);
 
		...
 
		// Call inherited method.  The physics component will be update here.
		base.Update(gameTime);
	}
	
	...
}

When, integrating, the forces/torque/accelerations get integrated into adjustments to velocity and rotation of the rigid body, which, then, get applied to the position and orientation. So, after integration you could update your entity's position and orientation properties with it's associated collision shape's Transform property. This could happen above in the Update method AFTER the base.Update(...) method call or during integration, like below:

public class YourGame : Game, IPhysicsIntegrator, ICollisionGenerator, IQuadTreeComparer<CollisionShape>
{
	...
 
	#region IPhysicsIntegrator Members
 
	...
 
	void IPhysicsIntegrator.Integrate(float elapsed)
	{
		// Just integrate all entities.
		for each (YourEntityComponent entity in this.entities)
		{
			entity.CollisionShape.RigidBody.Integrate(elapsed);
			entity.CollisionShape.CalculateInternals();
 
			// Update the entity's position and orientation.
			entity.Position = entity.CollisionShape.Transform.Translation; // Might need to use the negation of .Translation.
			entity.Forward = entity.CollisionShape.Transform.Forward; // Might need to use .Backward.
			entity.Right = entity.CollisionShape.Transform.Right;
			entity.Up = entity.CollisionShape.Transform.Up;
		}
	}
 
	#endregion
 
	...
}

Realize that the orientation (forward/right/up) of the entity doesn't have to be set exactly like it's associated rigid body or collision shape. If all you are interested in is linear movement (i.e., just position, not rotation), you could base the orientation of your entity on the velocity of the rigid body or even have no association at all between the orientations of the entity and it's associated rigid body/collision shape.

Hope that helps!!
Dec 15, 2007 at 2:19 AM

Hi,

Once again, thanks for the helpful and detailed explanation.

So if I am understanding correctly, I don't have to mess with the RigidBody's position and orientation at all, and can just use the Transform of the RigidBody.

The one thing that I don't understand is when to pass to the RigidBody my entity's transform. Is it in PreStep()?

Likewise, as my own entities has its own mass, acceleration and friction setting, when do I transfer them to the RigidBody, and when do I transfer them back? I am assuming that it is PreStep() again?
Coordinator
Dec 15, 2007 at 8:42 PM
Correct. The Transform property of the CollisionShape is derrived from it's associated RigidBody's Position and Orientation property. If there is no Offset transformation on the CollisionShape, these properties represent the same value.

Any changes to the RigidBody's properties - such as force, torque, rotation, velocity, postion, orientation, mass, acceleration, and friction should happen before collision detection occurs, or, generally, before the PhysicsComponent's Update method gets called. You should make any transfer of values from your entity to it's associated RigidBody in the your game's Update method, before the base implementation of Update gets called. See the Update method in my last post.

Likewise, if you need to transfer the position/orientation/velocity/rotation changes due to physics processing back to your entity, that needs to be done after integration, or after the PhysicsComponent's Update method gets called. In the post above, the tranfer occurs in Integrate method implemented by your game class. This can, also, occur in your game's Update method after the base implementation of Update gets called.

Hope that helps!
Dec 16, 2007 at 3:21 AM
Hi, you have been very helpful!

Just one last thing to clarify: When passing information to the rigid body, may I just directly set the rigid body's Transform, instead of Orientation and Position?

Coordinator
Dec 17, 2007 at 4:50 PM
You'll have to set the Position and Orientation properties of RigidBody, not the Transform property. The Transform property is just a derived value, created from the Position and Orientation properties.
Dec 18, 2007 at 2:10 PM
Edited Dec 18, 2007 at 2:10 PM
Hi,

I managed to get the physics and quad-spacing framework integrated! But there seems to be three problem

The first problem is that the entity seems to be sinking into the terrain. I scale the original bounding sphere of the entity by scaling its model, so I probably should check if I have done the scaling correctly (Now I just do boundingsphere.radius *= scaleFactor). On the whole, the
entities are being bound to the terrain; it just that part of them are sinking in.

The second problem is that I have a water plane, and I don't know how to compare the object with a terrain and a plane at the same time

The third problem is that for orientation. I managed to get rotation on the X axis right, but rotation on the Y axis is somewhat wrong.

This is my code for setting the orientation
{
rotationMatrix_ =
Matrix.CreateFromAxisAngle(Parent.Right, facing_.Y) *
Matrix.CreateRotationY(facing_.X);
}

And this is how I pass it into the rigid body
{
collisionShape.RigidBody.Orientation *= Maths3DHelper.MatrixToQuaternion(rotationMatrix_);

}

I am not sure if I am passing the orientation correctly; I am still new to quaternions, so any advice will be appreciated.

PS. I am sorry, but how do I specify a code block?
Coordinator
Dec 19, 2007 at 1:26 PM
  1. You may need to make your CollisionSphere's Radius property larger, like you stated. If it looks like your entities are sinking slowly then poping back up over and over, you may need to up the PhysicComponent CollisionCapacity property or Iteration counts.
  2. I'm not sure what you mean here. Please, add a bit more detail to the issue.
  3. If I'm guessing correctly, facing_ is a Vector3 that represents your entities forward vector. I'll also assume that your up vector is {0,1,0} or Vector3.Up. You can pass these vectors, along with a zero vector for position, to the new Matrix.CreateWorld method to get a rotation matrix. Then, use Quaternion.CreateFromRotationMatrix to convert. When applying your rotation matrix to the rigid body's Orientation above, you're multiplying the new orientation by the current. I think this just needs to be a simple assignment.

FYI : To specify a code block use two "curly" brackets:

{{
// code here
}}
Dec 19, 2007 at 3:36 PM
Hi,

Thanks for the advice. For issue #3, the facing_ vector3 is the amount rotated by the player in the current update (badly named, my apologies). The code for the setting of the direction vector is this:
 
// Create rotation matrix from the facing
            // Note: For UI-controlled entity, facing is modified by the UI behaviour
            rotationMatrix_ =
                Matrix.CreateFromAxisAngle(Parent.Right, facing_.Y) *
                Matrix.CreateRotationY(facing_.X);
 
            // Rotate orientation vectors
            Parent.direction = Vector3.TransformNormal(Parent.direction, rotationMatrix_);
            Parent.up = Vector3.TransformNormal(Parent.up, rotationMatrix_);
 
            // Re-calculate Right
            Parent.Right = Vector3.Cross(Parent.direction, Parent.up);
 
            // The same instability may cause the 3 orientation vectors may
            // also diverge. Either the Up or Direction vector needs to be
            // re-computed with a cross product to ensure orthagonality
            Parent.up = Vector3.Cross(Parent.Right, Parent.direction);

But at any rate, would passing the direction vector to the Matrix.CreateWorld(), with a position of (0,0,0), and then converting it to a quaternion, still work?

I tired using a simple assignment before, but somehow I could rotate only a bit on the Y axis before being forced back into the original orientation.
Coordinator
Dec 19, 2007 at 7:19 PM
Hi,

The Matrix.CreateWorld method won't work in your case. Take a look at RigidBody.Integrate(). I'm applying the current rotation to a rigid body's orientation like this:

            // Update the orientation by the rotation.
            Quaternion rotationQ = new Quaternion(this.Rotation * elapsed, 0.0f);
            Quaternion.Multiply(ref rotationQ, ref this.Orientation, out rotationQ);
            this.Orientation += rotationQ * 0.5f;

I think this is what your wanting. Hope that works!!
Dec 20, 2007 at 6:24 PM
Great, thanks for the tip. I will go back and rework the code.

As for issue 2, I actually have a height map for the terrain, and have a plane where I have a reflective water surface. I would like the entity (which is a hovercraft) to stay afloat of the water. Is there a way to handle this, or should I resort to my own methods?
Coordinator
Dec 20, 2007 at 8:47 PM
You can use a CollisionPlane for the water. See Example 1. If the CollisionPlane should be treated more as a rectangle, you can disgard the collision in your ICollisionCallback implementation if the Position of the hovercraft is not within a certain x and z range.
Dec 21, 2007 at 3:53 PM
Well, this does work, with some strangeness

Quaternion rotationQ = new Quaternion(new Vector3(this.facing_, 0f), 1f);
Quaternion.Multiply(ref rotationQ, ref collisionShape.RigidBody.Orientation, out rotationQ);
collisionShape.RigidBody.Orientation += rotationQ;

In my code, my facing_ is just a Vector2 'cos I am only keeping track of rotation around the X axis and the Y axis.

The thing is, the controls are flipped. Left and right now rotates on the Y axis and Up and Down rotate on the Left.

    if (currentKeyboardState.IsKeyDown(Keys.Left))
                rotationAmount.X = 1.0f;
            if (currentKeyboardState.IsKeyDown(Keys.Right))
                rotationAmount.X = -1.0f;
            if (currentKeyboardState.IsKeyDown(Keys.Up))
                rotationAmount.Y = -1.0f;
            if (currentKeyboardState.IsKeyDown(Keys.Down))
                rotationAmount.Y = 1.0f;

I know that I can just flip the control and go away happy :) But I would just like to understand the maths behind all this madness...
Dec 9, 2009 at 2:35 PM

Hi,

Does this thread still contain valid information?

I am trying to integrate the physics only to my game, but I can't find QuadTree class. Also I don't really see the relationship between meshes, rigid bodies, collision groups, how are they related, how do they interact, etc.

Thanks for helping me.

 

Dec 9, 2009 at 2:54 PM

Actually I am getting an Exception:

GameServiceNotFound: IViewPointService. Here is my code, just a very very simple try:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Oops.Xna.Framework.Physics;
using Oops.Xna.Framework.Input;
using Oops.Xna.Framework.Physics.CollisionSystems;
using Oops.Xna.Framework.UI;
using Oops.Xna.Framework.Viewpoint;

namespace OppsTest
{

    public class Game1 : Microsoft.Xna.Framework.Game

    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D texture;
        Model model;
        CollisionMesh mesh;
        PhysicsComponent physics;

        Vector3 cameraPosition = new Vector3(0.0f, 2000.0f, 3500.0f);
        Vector3 cameraLookAt = new Vector3(0.0f, 150.0f, 0.0f);
        Matrix cameraProjectionMatrix;
        Matrix cameraViewMatrix;

        ViewpointComponent viewpoint;
        UIComponent uiComponent;


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

            this.viewpoint = new ViewpointComponent(this);
            this.physics = new PhysicsComponent(this, new SweepAndPruneCollisionSystem());
            //this.physics = new PhysicsComponent(this.Game, new GridCollisionSystem(20.0f));
            this.uiComponent = new UIComponent(this);

            // Add the components to the screen's game component collection.
            this.Components.Add(this.viewpoint);
            this.Components.Add(this.physics);
            this.Components.Add(this.uiComponent);
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            this.model = Content.Load<Model>(@"Models\Ship");

            cameraViewMatrix = Matrix.CreateLookAt(
               cameraPosition,
               cameraLookAt,
               Vector3.Up);

            cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45.0f),
                graphics.GraphicsDevice.Viewport.AspectRatio,
                1.0f,
                10000.0f);

            this.mesh = new CollisionMesh(new CollisionMeshProxy(model));

            CollisionGroup collisionGroup = new CollisionGroup();
            collisionGroup.CollisionShapes.Add(this.mesh);

            mesh.CollisionGroup.RigidBody.ApplyWorldForce(new Vector3(0.0f, 10.0f, 0.0f));
            this.physics.CollisionSystem.CollisionGroups.Add(collisionGroup);
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            this.physics.EndUpdate();
            this.physics.BeginUpdate(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            DrawModel(model, Matrix.CreateTranslation(mesh.Position));

            base.Draw(gameTime);
        }

        private void DrawModel(Model model, Matrix world)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.World = transforms[mesh.ParentBone.Index] * world;

                    // Use the matrices provided by the chase camera
                    effect.View = cameraViewMatrix;
                    effect.Projection = cameraProjectionMatrix;
                }
                mesh.Draw();
            }
        }
    }
}

Coordinator
Dec 9, 2009 at 5:44 PM

I didn't run into the same issue.  Here are steps I took to try and reproduce:

  • Downloaded and extracted change set 43328. 
  • Opened OopsSolution.
  • Created a new 3.1 Windows XNA Game project called OopsTest inside the solution.
  • Copied your code over the generated Game1 code.
  • Ran the code, got a "null" exception on line "mesh.CollisionGroup.RigidBody.ApplyWorldForce(new Vector3(0.0f, 10.0f, 0.0f));".
  • Commented out this line and ran again.  Success (albeit, with a different model).

I also made sure I set my configuration to build Debug and x86.  After following these steps, are you still having the issue?

Dec 11, 2009 at 7:28 AM

Hi!

I did the same steps, and now it works. Funny.

And is the above discussion still valid about integrating the engine only? Because I cannot find the QuadTree class.

Thanks for your help.

 

Coordinator
Dec 11, 2009 at 9:07 AM

The above discussion is very outdated.  It's much simpler to get the physics component up and running now.  The QuadTree class has been removed and in it's place a CollisionSystem class with a derived class called QuadtreeCollisionSystem.  I would use the SweepAndPruneCollisionSystem, like you have, though.  It's faster and more reliable.

If you're looking for a CollisionShape that represents a heightmap, that functionality doesn't exist right now in the framework.  It would be easy to add though if you're up for it.  I plan on re-introducing it, I just haven't had a need to do so for my game development yet.  My plan would be as follows:

  • Create a CollisionHeightmap class from CollisionShape and override necessary methods.
  • Create a SphereHeightmapCollisionDetector
  • Create a BoxHeightmapCollisionDetector.
  • Modify CollisionDetector to include the new detectors above.

If you need help with this let me know.  You could probably base a lot of you collision code on existing CollisionShape/CollisionDetector classes.  Good luck!

Dec 11, 2009 at 11:13 AM

Hi,

No, I don't need height maps, I need only that compound bodies collide with each other. So I guess I need to build up my meshes using primitives. Am I right?

As I saw in the code there is only mesh -> box, and mesh -> sphere collision detector, so meshes should be used only as static immovable objects?

Otherwise this stuff is great, very nice work, and the support you provide (maybe alone) is also cool!

Thanks a lot, if I manage to finish my beta, I link it here as a working sample :)

Coordinator
Dec 11, 2009 at 7:05 PM

Yep. I would make your "world" a CollisionMesh (can't be moved) and your movable entities CollisionSpheres or CollisionBoxes.  You can use CollisionSpheres and CollisionBoxes for the "world" as well but you'd have to place them and make them static.  Good luck on your beta!

Feb 22, 2010 at 11:13 AM

Why can't the CollisionMesh's move? I'm having trouble using my own custom meshes for the level of my game. I want the player to collide with the walls and the models are all in fbx format. The player seams to collided to early, all the time or not at all depending on the mesh I use.

Coordinator
Feb 24, 2010 at 4:50 PM

the CollisionMesh can't move because of the processing involved.  It would take too long.  Instead, represent your meshes with CollisionSpheres and CollisionBoxes to approximate the shape.

Most of the time the reason CollisionMesh isn't being "collided with" correctly is because the mesh isn't being drawn at the same position/orientation/size as the CollisionMesh.  You might look into this to see if it might be your issue.  Good luck!