Page 1 of 1

Concave sphere problems.

Posted: Wed Mar 16, 2011 5:41 pm
by Spankenstein
Looking through the demos and the notes I've decide to create a concave shape using the 'DynamicCompoundEntry' class.

Following the notes and your advice on triangles I have tried many ways to create a concave sphere composed of triangles but none of them have been successful.

Code: Select all

        public ConcaveSphere(Game1 game, float radius)
        {
            this.game = game;

            CustomModel model = game.Models["Sphere"];

            int numTriangles = model.ModelData.Triangles.Length;

            float scale = 2f * radius;

            Matrix scaleTransform = new Matrix();
            scaleTransform.M11 = scale;
            scaleTransform.M12 = scale;
            scaleTransform.M13 = scale;
            scaleTransform.M21 = scale;
            scaleTransform.M22 = scale;
            scaleTransform.M23 = scale;
            scaleTransform.M31 = scale;
            scaleTransform.M32 = scale;
            scaleTransform.M33 = scale;
            scaleTransform.M44 = 1f;

            List<DynamicCompoundEntry> triangles = new List<DynamicCompoundEntry>(numTriangles);

            for (int i = 0; i < numTriangles; ++i)
            {
                // [Non Recentered Triangle]
                TriangleShape tri = new TriangleShape();

                tri.VertexA = model.ModelData.Triangles[i].A;
                tri.VertexB = model.ModelData.Triangles[i].B;
                tri.VertexC = model.ModelData.Triangles[i].C;

                // [Scaled Non Recentered Triangle]
                //tri.VertexA = Vector3.Transform(model.ModelData.Triangles[i].A, scaleTransform);
                //tri.VertexB = Vector3.Transform(model.ModelData.Triangles[i].B, scaleTransform);
                //tri.VertexC = Vector3.Transform(model.ModelData.Triangles[i].C, scaleTransform);

                // [Recentered Triangle]
                //Vector3 centre;

                //TriangleShape tri = new TriangleShape(
                //    model.ModelData.Triangles[i].A,
                //    model.ModelData.Triangles[i].B,
                //    model.ModelData.Triangles[i].C,
                //    out centre
                //    );

                //TriangleShape tri = new TriangleShape(
                //    Vector3.Transform(model.ModelData.Triangles[i].A, scaleTransform),
                //    Vector3.Transform(model.ModelData.Triangles[i].B, scaleTransform),
                //    Vector3.Transform(model.ModelData.Triangles[i].C, scaleTransform)
                //    );

                tri.Sidedness = TriangleSidedness.Counterclockwise;

                triangles.Add(
                    new DynamicCompoundEntry(
                        tri,
                        100f
                    )
                );
            }

            body = new CompoundBody(triangles);

            game.Space.Add(body);
        }

The non recentered triangle without scaling will pass through walls also (maybe due to triangle sidedness?). If the triangle sidedness is a problem how can I contain objects inside a concave body and still have the outside of the concave body collide with the environment? Double sided triangles force the contained bodies outside the concave body.

The non recentered triangle can't be scaled without causing NaN errors in the space:
Function does not accept floating point Not-a-Number values.
The recentered triangle will draw incorrectly but I am unsure as to how to reposition the triangle with the 'out center' parameter.

I am drawing the compound shape like so

Code: Select all

        public void Draw()
        {
            int numShapes = compoundbody.Shapes.Count;

            for (int i = 0; i < numShapes; ++i)
            {
                TriangleShape t = body.Shapes[i].Shape as TriangleShape;

                Vector3 v0 = Vector3.Transform(t.VertexA, compoundbody.WorldTransform);
                Vector3 v1 = Vector3.Transform(t.VertexB, compoundbody.WorldTransform);
                Vector3 v2 = Vector3.Transform(t.VertexC, compoundbody.WorldTransform);

                game.WireShapeDrawer.DrawWireTriangle(v0, v1, v2, Color.White);
            }
        }
How can I correctly create a concave sphere that can be scaled and drawn correctly?

Re: Concave sphere problems.

Posted: Wed Mar 16, 2011 8:02 pm
by Norbo
Here's a slightly modified version of your code that I got to work in the demos:

Code: Select all

            Vector3[] vertices;
            int[] indices;
            TriangleMesh.GetVerticesAndIndicesFromModel(game.Content.Load<Model>("sphere"), out vertices, out indices);


            float radius = .5f;
            var scaleTransform = Matrix.CreateScale(2 * radius);

            List<DynamicCompoundEntry> triangles = new List<DynamicCompoundEntry>(indices.Length / 3);

            for (int i = 0; i < indices.Length; i += 3)
            {
                // [Recentered Triangle]
                Vector3 centre;
                TriangleShape tri = new TriangleShape(
                    Vector3.Transform(vertices[indices[i]], scaleTransform),
                    Vector3.Transform(vertices[indices[i + 1]], scaleTransform),
                    Vector3.Transform(vertices[indices[i + 2]], scaleTransform),
                    out centre
                    );

                //Depending on the winding of the model, using clockwise or counterclockwise will permit
                //objects to move freely from the inside to the outside, or from the outside inside.
                //Doublesided stops both ways.  (It's the default too, so setting this isn't really necessary)
                tri.Sidedness = TriangleSidedness.DoubleSided;
                //By now, if we checked the triangle shape's vertices, they would be in the triangle's local space.
                //If we added centre to the vertices, they would be in the original world space locations.
                //Knowing that, we can pass the centre to the DynamicCompoundEntry's position and they will be in the correct location.
                triangles.Add(
                    new DynamicCompoundEntry(
                        tri,
                        centre,
                        1f
                    )
                );
            }

            var body = new CompoundBody(triangles);

            Space.Add(body);
It looks like the primary issue in the original version was the incorrect scaling matrix.
The non recentered triangle without scaling will pass through walls also (maybe due to triangle sidedness?). If the triangle sidedness is a problem how can I contain objects inside a concave body and still have the outside of the concave body collide with the environment? Double sided triangles force the contained bodies outside the concave body.
If you want it to both collide with the environment and things inside, then double sided is the only option. The other options are one-sided. Double sided should not result in things being actively pushed out of the sphere, though; that was probably related to the geometry being different than expected.

To draw the shape, it would probably be easiest to just draw the original model using the compound body's position and orientation. You'd have to keep in mind the position of the CompoundBody, though. It's 'recentered' too, in a way; to draw the model properly you'll have to include an offset equal to the negated initial Position of the compound body.

The BEPUphysicsDrawer's DisplayCompoundBody class shows how you could create the representation based on child information as well.

Finally, while fiddling with this, I found two bugs. First, raycasts against triangle shapes owned by entities don't work right. Second, only in release mode, there can be a sorting issue with the compound body hierarchy's construction. The first bug has been fixed and I'm working on the second; I suppose I'll get to test out the new development pipeline today :)

Re: Concave sphere problems.

Posted: Wed Mar 16, 2011 11:52 pm
by Spankenstein
Thanks for the help Norbo, I have it working and drawing correctly now :)
Double sided should not result in things being actively pushed out of the sphere, though; that was probably related to the geometry being different than expected.
If I add to the angular velocity each frame when a key is pressed

Code: Select all

            else if (hid.IsKeyDown(PlayerIndex.One, Keys.Up))
            {
                v.X = 0;
                v.Y = 10f;
                v.Z = 0;
          
                concaveSphere.CompoundBody.AngularVelocity += v * dt_Seconds;
            }
then objects contained in the sphere are thrown out of the sphere

http://screencast.com/t/nFhxZl2F1T

Is there a way to make the triangles one sided for all objects inside the sphere and the one sided (wound opposite) for objects outside the sphere (other than creating two hollow spheres)?

Re: Concave sphere problems.

Posted: Thu Mar 17, 2011 12:33 am
by Norbo
then objects contained in the sphere are thrown out of the sphere
Yup, that's pretty inevitable with infinitely thin triangles, and 'long' timesteps relative to the angular velocity.

Some options are (some of these are repeats of last time):
-Decrease the time step duration.
-Decrease the velocities involved.
-(Edit) Increase the CollisionResponseSettings.MaximumPositionCorrectionSpeed and CollisionResponseSettings.PenetrationRecoveryStiffness.
-Add a protective distance range constraint that prevents contact jiggle from contributing to the fly-out.
-Add another shell to the shape. The outer one could be double sided, while the inner one is one-sided (allowing things in, but not out). The outer one should not be too far away; less than half the minimum radius of objects that need to stay within the inner sphere.

Combining those approaches would result in a pretty stable configuration. A constraint + outer double sided shell might give the objects enough room to be corrected by the various anti-penetration forces from collisions and the constraint.

v0.16.0 is slated to include dynamic meshes with solidity, which could help quite a bit. The thickness of a solid sphere's shell would have to increase relative to the velocity/timestep ratio though; with a high enough velocity, you can always cause things to go flying.

By the way, v0.15.1 is out fixing the bugs I referred to earlier.

Re: Concave sphere problems.

Posted: Thu Mar 17, 2011 12:41 am
by Spankenstein
Add another shell to the shape. The outer one could be double sided, while the inner one is one-sided (allowing things in, but not out). The outer one should not be too far away; less than half the minimum radius of objects that need to stay within the inner sphere.
This is what I was thinking about at the end of my last reply.

Could I get away with creating just a sphere shape (not a compound body) for the outer shape and telling all the entities inside the inner shell to ignore the outer shape? This would save on computational cost.

Excellent work on the new update, I shall grab it after some sleep :)

Re: Concave sphere problems.

Posted: Thu Mar 17, 2011 12:47 am
by Norbo
Could I get away with creating just a sphere shape (not a compound body) for the outer shape and telling all the entities inside the inner shell to ignore the outer shape? This would save on computational cost.
While that is doable (compound children can have different collision rules), it wouldn't do much to help keep objects inside by itself. It would allow you to set the inner sphere to one-sided, but that would have to be paired with a constraint to make sure the objects don't keep going once they've exited the inner sphere. That's definitely an option.