Two collision detection systems

May 24, 2009 at 10:25 AM

Hi!

This is not a strictly Farseer issue but I think you can help me. For my 2.5D platforms game i'm using Farseer for dynamics and collisions with mobile platforms, but for static geometry (a whole 3D model) i'm using a BSP tree to check collisions. The problem is that when I detect a collision with BSP and correct a body's position Farseer keeps accelerating it as if it is still falling until velocity grows in such a way it tunnels the geometry.

Any ideas on how to implement this or on how to tweak Farseer bodys to act right in this scenario?

Thanks.

Developer
May 24, 2009 at 3:28 PM

Try using an impulse to correct the velocity after correcting the position. This will not be easy tune as it's a fairly bad hack. Why not use a 3D physics engine?

May 24, 2009 at 9:03 PM

 

I will try with the impulse, thanks. The project is a 2D platformer with 3D rendering and multiple layer, basically a Little-Big-Planet-like-thing, that's why a 2D physics engine fits best.

Developer
May 24, 2009 at 11:35 PM

LBP actually uses a 3D engine. They just limit there characters to certain 2D planes. Are you using animated 3D models?

May 25, 2009 at 8:55 AM

 

I know nothing about LBP's engine but what I've seen on videos. Analyzing these videos I've seen that entities do not cross layers (just the players seem to do it), only rotate over X axis, etc. Also on wikipedia (http://en.wikipedia.org/wiki/LittleBigPlanet) I saw some shoots of LBP prototype where it seems it's a 2D based (with 2D physics) game with 3D representation.

Yeah, I'm using animated 3D models.

Developer
May 25, 2009 at 8:32 PM

Have you though about keeping all the collision in Farseer's 2D plane? That is what I am planning on doing with my side-scrolling tank game. I hope to make animated geometries. But we'll see how is works out. Good luck.

May 25, 2009 at 9:58 PM

 

Yes, keeping collisions in Farseer's 2D plane is an option but it requires extra level editing for creating the "bounding" geometry. I will give it a try anyway.

Thank you very much for the tips ;)  I'll feedback with the results.

May 26, 2009 at 10:30 AM

I'm doing a slightly similar thing. The terrain is all 3D with the 2D zones exported from 3dsMax by my artist buddy. I thought about having multiple layers - it'd be a cool feature. If I end up doing it, I'd probably have a PhysicsSimulation object per layer and somehow let the player cross the layers.

May 26, 2009 at 3:51 PM

 

Hi roonda:

Nice trick about creating 2D regions in Max and exporting them with the level model, this way you avoid the need for later editing. What kind of mesh/shape do you use inside Max to describe these regions? How do you import them into your engine?

You don't need to have multiple PhysicsSimulator, one per layer: you just need one and then use geom.CollisionCategories and geom.CollidesWith properties to indicate the layer where each object resides. For instance, objects on layer 1 have geom.CollisionCategories = geom.CollidesWith = 1. This way you can have up to 6 layer (there are 6 collision categories only). Objects can be in more than one layer combining CollisionCategories.

The problem cames when moving the player from one layer to another where an object already exists...

May 30, 2009 at 7:53 AM
Edited May 30, 2009 at 7:55 AM

 

Hi again, roonda:

I'm following your approach, exporting 2D shapes from 3D Max and importing them as geoms but I have a problem: exported shapes are in world coordinates. When I import them as geoms, vertices are translated to local coordinates, having the center of the object in local 0,0 so, every shape that takes part of the scene appear centered on 0,0. This way I don't know how to recreate the original scene. How are you doing it ?

Here you can see what I export from 3D Max

http://yfrog.com/153dmaxj

And here what I get ingame:

http://yfrog.com/0zingamexj

Ideas?

Thanks.

May 30, 2009 at 12:11 PM

 

OK. I think I got it: I must get the centroid of the vertices BEFORE using them to create the geom. This way I can use the resulting vector to reposition (geom.body.position=centroid) the shape on world coordinates. After using vertices to create the geom, vertices.GetCentroid() returns some kind of local offset, so it doesn't help for this.

May 31, 2009 at 1:48 PM

A quick note about collison export with 3dsmax (how we do it ;) ):

We use editable splines with interpolation set to "corner", then before exporting I reset the pivot to the shapes center (there's a button for that) and with a little max script, I move the shape to the origin, export the vertices as XML + the old position offset (after that one can set the shape back to its original position...)

 

And then in the game, assumed that you got your vertex data loaded, we create the shapes like following:

Body body = BodyFactory.Instance.CreateBody( farseerSvc.PhysicsSim, 1.0f, 1.0f );
body.Position = position; //the offset position
body.IsStatic = true;
new BodyComponent( ret, body );

Vector2 centroid = vertices.GetCentroid();
Geom geom = GeomFactory.Instance.CreatePolygonGeom( factorySvc.FarseerSvc.PhysicsSim,
    body, vertices, centroid, 0.0f, 0.0f );
var geomComp = new GeomComponent( ret, geom );

 

Hope that helps.
If you're interested in the relevant parts of the max script just tell me!

Jun 1, 2009 at 8:23 AM
Edited Jun 1, 2009 at 2:12 PM

Hi david,

Sorry for the delayed response - been a busy weekend. It sounds like you've figured it out now, but we are using a series of Editable Splines exported as a List<Vector2[]> in IntermediateSerializer XML format. Heres a bare bones version of our export script.

-----------------------------------------------------------------

-- Export selected Edit Spline object to XNA XML List<Vector2[]>

--Load the xml assemply
dotNet.loadAssembly "system.xml"
--Create an xml document object.
xmlDoc=dotNetObject "system.xml.xmlDocument"

contentElem=xmlDoc.createElement "XnaContent"
xmlDoc.appendChild contentElem

contentElem.setAttribute "xmlns:Generic" "System.Collections.Generic"
contentElem.setAttribute "xmlns:Framework" "Microsoft.Xna.Framework"

assetElem=xmlDoc.createElement "Asset"
contentElem.appendChild assetElem

assetElem.setAttribute "Type" "Generic:List[Framework:Vector2[]]"

for i in 1 to (numSplines $) do
(
    s = ""
    for j in 1 to (numKnots $ i) do
    (
        vec = getKnotPoint $ i j
        s = s + (twoDP vec.x) + " " + (twoDP vec.z) + " "
    )
   
    itemElem = xmlDoc.CreateElement "Item"
    itemElem.InnerText = s
    assetElem.AppendChild itemElem
)

--Save the xmlDoc object to a file.
xmlDoc.save ((getDir #scripts)+"\\testVecArrays.xml")
--Open the file in Max to see the result.
edit ((getDir #scripts)+"\\testVecArrays.xml")

 

Once you export your xml, you can load in XNA with the XML importer:

List<Vector2[]> geomPolys = Content.Load<List<Vector2[]>>("GeomPolys");

Each Vector[] corresponds to a Geom and you were exactly right about first getting the centroid of the geoms. I also stumbled on this at first... It does seem unusual but I'm sure there must be a good reason for it to reposition your geom to zero. I pass the centroid straight to CreateGeom for the position.

            foreach (Vector2[] verts in geomPolys)
            {
                Vertices farseerVerts = new Vertices(verts);
                Geom geom = GeomFactory.Instance.CreatePolygonGeom(
                    Screen.PhysicsSim2D, Body,
                    farseerVerts, farseerVerts.GetCentroid(),
                    0f, Settings.CollisionGridSize);

                geom.Tag = this;

            }

 

Hope that helps. Maybe this thread should be the start of a How To: 3dsMax to Farseer collisions?

 

 

 

Jun 1, 2009 at 11:00 AM

It's definately an interesting approach! :)

I did it more "hardcore" by creating my XML document via "strings", and not the 3dsmax xml functions (probably because we had a different file format in the beginning).
I wasnt even aware of how easy one can import XML data via the content pipeline, that looks really sweet!

What I don't like with the XNA XML format though, is that it's sort of space wasting. At least the samples from the adventure-starting kit or what that's called, where you get a formatting like

<vertex>
<x>10</x>
<y>34</y>
</vertex>

instead of
<vertex x="10" y="34" />

Thats why we also have our own XML sax parser.

It would be interesting now: do you know if it is possible to parse xml data like in my shorter notation?
If so, I would definatly consider to kick our parser out and use the built in stuff :)

Jun 1, 2009 at 2:20 PM

Actually the IntermediateSerializer is pretty good (search Shawn Hargreaves blog for good articles on it). I'm not sure if that starter kit uses it, but I by default a Vector2 is <myvec>4.3 4.1</myvec> and an array Vector2[2] would be <mypoints>0 0 1 1</mypoints>. So you can imagine it works well if you store your geom verts as Vector2[]s. There's no attribute names in there bloating it at all. Not so good for human readability, but who needs that anyway  :)

Jun 2, 2009 at 10:56 AM

 

roonda, giggsy: thank you very much for your explanations: they are very clarifying.

I finally ended using splines too. As I know nothing about Max Script I export to .OBJ format, very simple and easy to parse. Every shape is on it's place when I export (world coordinates). At runtime, I parse the .OBJ file, import the shapes as Vertices (Vector2[]) and before creating the geom I store the Vertices centroid as the final geom.body.position and then I create the geom, and miraculously everything comes to it's place :)

Probably I'll be taking the intermediate serializer .XML approach as soon as I have some time to spend.

Thank you again for your great help.