PhysicsSystem and own model

Jan 17, 2010 at 12:59 PM

So, next problem...
I want to design my level (indoor) with 3ds Max. So far no problem. But how can i add some physics to this model? is there any possibility to roll with my ball "in" this model? (the rooms)

Thanks,
Fabi

Coordinator
Jan 17, 2010 at 11:54 PM

Basically, you want to use JigLibX's TriangleMesh to build a CollisionSkin for it.

I had some code lying around to do just this, but can't seem to find it right now.

You can read some of JigLibX's docs and try to figure it out while I try to find that old code if you like.

Cheers!

 

Coordinator
Jan 18, 2010 at 3:22 AM

Okay, I found the old code. It uses a collision mesh to define a JigLibX CollisionSkin with one triangle per TriangleMesh. If your model's vertices are not in PositionNormalTexture format, you'll either have to adjust the vertex format in the code below or maintain a separate collision mesh apart from the actual art model. Having one triangle per TriangleMesh is extremely important as it won't work any other way. It looks inefficient, but it's tested to be fast enough.

          CollisionSkin skin = new CollisionSkin(body);

            ModelMesh mesh = Model.Meshes[0];

            VertexBuffer vertexBuffer = mesh.VertexBuffer;
            VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[vertexBuffer.SizeInBytes / VertexPositionNormalTexture.SizeInBytes];
            vertexBuffer.GetData(vertices);

            IndexBuffer indexBuffer = mesh.IndexBuffer;
            if (indexBuffer.IndexElementSize != IndexElementSize.SixteenBits)
                throw new Exception("Expecting 16 bit indices in collision mesh.");
            short[] indices = new short[indexBuffer.SizeInBytes / sizeof(short)];
            indexBuffer.GetData(indices);

            List<Vector3> vertexList = vertices.Select(x => x.Position).ToList();
            for (int i = 0; i < indices.GetLength(0); i += 3)
            {
                List<TriangleVertexIndices> indexList = new List<TriangleVertexIndices>();
                indexList.Add(new TriangleVertexIndices(indices[i], indices[i + 2], indices[i + 1]));
                TriangleMesh triangleMesh = new TriangleMesh();
                triangleMesh.CreateMesh(vertexList, indexList, 1, 1);
                if (ScaleWorld != Vector3.One) throw new Exception("Expecting mesh to be unscaled.");
                Matrix orientationWorld;
                GetTransformWorld(out orientationWorld);
                triangleMesh.Transform = new Transform(PositionWorld, orientationWorld);
                skin.AddPrimitive(triangleMesh, new MaterialProperties(0.8f, 0.8f, 0.7f));
            }

            body.CollisionSkin = skin;

Let me know if you have any questions!

Jan 18, 2010 at 2:32 PM

Now I have a new model and want to add the physics. On the last model your code some kind of worked but now it just happens nothing... The ball in the scene is falling straight through my model...
Additionaly I recognized more then one mesh in my model, one mesh for each quad, so just using Model.Meshes[0] can't work I think...

This is the code I use at the moment:

private Body CreateBody(IOxComponent component)
        {
            var model = (StandardModel)component;
            var tmpbody = new Body();
            var skin = new CollisionSkin(tmpbody);

            //ModelMesh mesh = model.Model.Meshes[0];
            foreach (ModelMesh mesh in model.Model.Meshes)
            {
                VertexBuffer vertexBuffer = mesh.VertexBuffer;
                var vertices =
                    new VertexPositionNormalTexture[vertexBuffer.SizeInBytes/VertexPositionNormalTexture.SizeInBytes];
                vertexBuffer.GetData(vertices);

                IndexBuffer indexBuffer = mesh.IndexBuffer;
                if (indexBuffer.IndexElementSize != IndexElementSize.SixteenBits)
                    throw new Exception("Expecting 16 bit indices in collision mesh.");
                var indices = new short[indexBuffer.SizeInBytes/sizeof (short)];
                indexBuffer.GetData(indices);

                List<Vector3> vertexList = vertices.Select(x => x.Position).ToList();
                for (int i = 0; i < indices.GetLength(0); i += 3)
                {
                    var indexList = new List<TriangleVertexIndices>
                                        {new TriangleVertexIndices(indices[i], indices[i + 2], indices[i + 1])};
                    var triangleMesh = new TriangleMesh();
                    triangleMesh.CreateMesh(vertexList, indexList, 1, 1);
                    if (model.ScaleWorld != Vector3.One) throw new Exception("Expecting mesh to be unscaled.");
                    Matrix orientationWorld;
                    model.GetTransformWorld(out orientationWorld);
                    triangleMesh.Transform = new Transform(model.PositionWorld, orientationWorld);
                    skin.AddPrimitive(triangleMesh, new MaterialProperties(0.8f, 0.8f, 0.7f));
                }
            }

            tmpbody.CollisionSkin = skin;
            tmpbody.Immovable = true;

            Vector3 position = Component.PositionWorld;
            Matrix orientation = Component.OrientationWorld;
            tmpbody.MoveTo(position, orientation);
            tmpbody.EnableBody();
            
            return tmpbody;
        }

 

private readonly Body body;

        public LevelCollisionScript(IOxEngine engine, string parameters, Transfer<IOxComponent> component)
            : base(engine, parameters, component)
        {
            body = CreateBody(component.Value);
        }

Any ideas how to get this code working?

Please execuse my lack of knowledge concerning 3D programming... I'm used to 2d ;)

Fabi

Jan 18, 2010 at 4:16 PM

Okay, with some tweaking and this "Autobox"feature everythings alright now =)

Thank you =)

Fabi

Jan 25, 2010 at 11:28 PM

Diamondback,

Would you mind posting the code that you ended up with for this? I'm at a bit of an impass trying to implement the same thing.

Jan 26, 2010 at 2:34 PM

No problem, you can download the complete scriptfile for the level here. Physics work very well with this code and my .x file.

Jan 27, 2010 at 2:46 PM

Hmmm. It turns out I'm using that same CreateBody function from above, but it's not working for me. The model I'm creating a body for is just the basic Ox cube model. If I comment out the foreach loop and instead use a Box primitive instead of the trianglemeshes, collisions work fine. I also found that if I use the trianglemeshes my collision skin has a surface area of 0 (makes sense since the collisions aren't working!). Do you know of any reason why this would be happening for me?