Hollow objects. Is there an option available other than...

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Hollow objects. Is there an option available other than...

Post by Spankenstein »

How can I have a hollow object, where any objects inside that object, are constrained by the hollow object.

For example, if I have a large hollow sphere, how can I keep a group of smaller spheres inside that sphere?

I know that this can be achieved with mesh cooking, but can this be done without resorting to this approach?

Thanks

EDIT:

I should point out that this large sphere will be moving (think rattle) and will therefore not be static.

Will I have to define it as a set of triangle entities?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

A CompoundBody of Triangle entities would be the preferred method currently. In v0.15.0, it will be easier to create a custom shape and custom collidable objects. In that system, it won't be too hard to make a 'real' hollow sphere. More complicated hollow shapes would be significantly harder without resorting to combinations of convex objects.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: Hollow objects. Is there an option available other than...

Post by Spankenstein »

Norbo wrote:A CompoundBody of Triangle entities would be the preferred method currently.
Awesome, I'll try that out once I've slept tonight.

Apologies if this isn't the place to ask but how do I make a monetary donation towards the development of this software?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

Apologies if this isn't the place to ask but how do I make a monetary donation towards the development of this software?
Thanks for the offer, but we currently don't accept donations. If you'd like to help, you can use/license our current and future products and services :)
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

I am reviving this thread to see what would be the best practice in the latest version.

In my case, I am doing 3D printing either onto a platform or into a dish, and want to make either a cube (former case) or cylinder (latter case) be the constraint for valid regions to position an STL file in the designer software I am developing.

In both cases it would make sense to make the enclosure be a completely formed cylindrical or rectangular cuboid since printing higher than the height of this enclosure would be unadvised (it is for bioprinting).

We will want to in the end be able to specify the diameter and height of the containment cylinder, or width, length and height of the containment cuboid, and have the placement of STLs to be constrained within this area, and would be the default visualization in Helix 3D before the STLs were added and placed.

What approach would you recommend for making these containers with BEPU? Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

There are no 'implicit' concave shapes like hollow cylinders, but they can be approximated by a triangulated surface represented by a mesh (presumably a StaticMesh, if there is no need for it to move).

And while a box can be represented by a mesh too, it could also be represented by 6 regular convex boxes positioned and sized to form the enclosure. That would be marginally faster.

However, contact-based approaches are mainly suitable for surface collision detection and response, not so much containment tests. If it's possible for a test candidate to be completely outside, a simple surface won't have any collision to detect. While it's possible to create solid regions (fattened boxes or a MobileMesh with solidity), if you need to test for complete containment, the easiest option would probably be to test every vertex position against the convex container region analytically.
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

Thanks - indeed I was able to use the Static Mesh to map to a hollow cylinder mesh programmatically created so I have control over every parameter, even taper like a cross section of a cone.

I'm tempted to go the mesh route for box shapes as well to achieve consistency, and so the container is only considered as a single collidable rather than six, just like the cylindrical mesh.

The good news is that there is no need for containment tests since the STLs will always be placed at the origin to start with. Either they will fit if they were proportioned correctly in the CAD software or they won't. I suppose it would be good to offer recentering in the case that a large translation moves the object outside of the container and entirely out of the viewport, getting lost somehow.

I have one other question - what is the best practice for having the physics collision entity follow the position of the graphical object around? I noted that this library was built around XNA/MonoGame but I am using Helix. Right now I am destroying and recreating entities mapped to the updated position of the object every time Render is called (objects don't move frequently except when manually repositioned, so I am not really noticing yet how expensive this approach is).

I would much prefer some way of having the physics entity listen to the updated coordinates of the graphical object and reposition itself accordingly. We may later want to support resizing objects as well, so entities would also have to listen for updated size values and shrink/grow accordingly.

Thanks again.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

If the object is an actual Entity, then setting the Position or Orientation properties would be the most direct way to reposition it. Note that the Entity.WorldTransform setter is a convenience wrapper around Position and Orientation, so it assumes the given transform is rigid; any scaling or shearing will be lost and instead be interpreted as a weird orientation.

Resizing isn't really a physical operation in the context or rigid bodies, so it's not uniformly supported. Different objects have different ways of resizing on what kind of object it is- a simple BoxShape can have its dimensions changed directly, while a MobileMeshShape is actually immutable. The MobileMeshShape immutability could be worked around with some effort in the source, but it would be a bit tedious (which is part of the reason that it's immutable).

If you don't care about velocity based movement, InstancedMesh might be a good choice. Since it's not a dynamic object and doesn't have to worry about responding to collisions, its WorldTransform property can be set to any affine transform, including shear and nonuniform scaling. That will trigger a bounding box update, but that's way faster than rebuilding a mesh hierarchy from scratch. Note that kinematic and static objects like the InstancedMesh default to a collision group that doesn't perform collision detection with other static or kinematic objects, so you'll probably want to set the mesh.CollisionRules.Group to something else (maybe CollisionRules.DefaultDynamicCollisionGroup, or just a new group since they default to colliding with everything).
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

Thanks. I do have it somewhat working with PairCreated and PairRemoved events, but only between simple Boxes. I am having a lot more trouble with my StaticMesh as in that case I want to test if it contains all of the other Entities, but I will leave that aside for now.

A more pressing matter is the fact that I am getting events triggered when entities are exactly side-by-side but not overlapping. In my use case, I want to treat this as if it is perfectly normal. Is there some way I can tweak the settings so that events are only triggered if entities are truly overlapping, instead of simply positioned exactly side by side?

I notice that the entities can actually be a tiny bit apart and still trigger the event. The margin is about 1/10th of a world unit. How can I adjust this?
My actual handler is not going to force the objects to not overlap, it is simply going to color them red and flag an IsCollided boolean to true until the problem is fixed manually by the user. Their discretion on placement of objects is paramount since the application is 3D printing, but we do not want to allow a build to proceed unless no objects are overlapping.

Thanks
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

PairCreated and PairRemoved operate at the level of CollisionPairHandlers which exist if there is any (expanded) AABB overlap even if there is no fine grained shape overlap.

If you are interested in the actual shape overlap, I would recommend checking the contacts. You could do this using events, e.g. ContactCreated, but I often find it simpler to just directly check the contact collections:

Code: Select all

            foreach(var pair in entity.CollisionInformation.Pairs)
            {
                foreach(var contactInfo in pair.Contacts)
                {
                    if(contactInfo.Contact.PenetrationDepth > 0)
                    {
                        Console.WriteLine("Entity is overlapping something!");
                    }
                }
            }
The above also verifies that each contact's penetration depth is positive. The engine will sometimes create and maintain contacts with negative penetration depth for speculative collision response, but their existence does not imply overlap.

If you need tight tolerances on collision detection, there are a couple of other things to note:
-If there are situations where objects are being moved nondynamically by very tiny amounts, cached contact refreshing may result in small errors. To avoid this, it may be a good idea to clear the contact set after any movement by calling pair.ClearContacts in a loop like above. (This will tend to cause jittering for dynamic objects, though- contact caching is important for 'normal' simulations.)
-Convex shapes often use a 'collision margin' to allow faster algorithms to be used during collision detection. This expands or rounds out the shape a bit. If you can handle the slight performance hit, setting the CollisionDetectionSettings.DefaultMargin to 0 before creating any convex shapes might be a good idea.
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

Thank you - this worked. I had to include a small epsilon value rather than 0 to get desired behavior, since we are erring on the side of generosity (a 10mm x 10mm cube should be placeable directly next to another without collision detection, but due to floating point error margins a value of 0 is not tolerant enough).

Now I am focusing again on the StaticMesh for the cylinder. Everything is fine on the drawing side - I can draw any type of cylinder I desire, tapered, conical cross-section, etc. Ideally I want to be able to generate a perfectly fitting collision mesh for any container shape I programmatically construct. I'll share some code of the first container I am trying to start with, a regular cylinder with open top and bottom (I can generate a collider for the flat bottom easily separately, and want to leave the top open so that "dropping" new objects into the container does not generate a collision).

Since I am neither using XNA nor MonoGame, I realize I am at a bit of a disadvantage to have a way of actually seeing what I am doing w.r.t. the collision mesh generated for this cylinder. I have verified that my rotation matrix is correct, but I am getting bizarre collision patterns that I can't make heads or tails of. I believe I have a good chance for solving this for all container shapes if I can solve it for one.

So if you have any idea what might be wrong with the following approach, I'd be much obliged. There's a lot of tediousness and potential for error in converting values between the WPF Media3D library and BEPU's internal library (vertices, indices, matrices, etc.). I suspect my basic construction of the StaticMesh is wrong in some way.

Code: Select all

       
        private ModelVisual3D GenerateGeometry()
        {
            TubeMesh hollowCylinderMesh = new TubeMesh
            {
                Length = 12.35,
                Radius = 12,
                Slices = 36,
                Stacks = 1
            };

            GeometryModel3D geometryModel = new GeometryModel3D();
            geometryModel.Geometry = hollowCylinderMesh.Geometry;

            Color renderColor = Color.FromArgb(80, 0, 255, 255);
            SolidColorBrush renderBrush = new SolidColorBrush(renderColor);

            DiffuseMaterial material = new DiffuseMaterial(renderBrush);
            geometryModel.Material = material;

            RotateTransform3D rotateTransform3D = new RotateTransform3D();

            AxisAngleRotation3D myAxisAngleRotation3D = new AxisAngleRotation3D
            {
                Axis = new Vector3D(1, 0, 0),
                Angle = 90
            };

            rotateTransform3D.Rotation = myAxisAngleRotation3D;

            geometryModel.Transform = rotateTransform3D;

            Model3DGroup model3DGroup = new Model3DGroup();
            model3DGroup.Children.Add(geometryModel);

            ModelVisual3D modelVisual3D = new ModelVisual3D { Content = model3DGroup };

            //Everything below gets the collision mesh for the cylinder 
            //while we still have direct access to its geometry
            Vector3[] vertices = new Vector3[hollowCylinderMesh.Geometry.Positions.Count];
            int[] indices = hollowCylinderMesh.Geometry.TriangleIndices.ToArray();

            int i = 0;

            foreach (Point3D point in hollowCylinderMesh.Geometry.Positions)
            {
                Vector3 vertex = new Vector3();
                vertex.X = Convert.ToSingle(point.X);
                vertex.Y = Convert.ToSingle(point.Y);
                vertex.Z = Convert.ToSingle(point.Z);
                vertices[i] = vertex;
                i++;
            }

            AffineTransform collisionTransform = new AffineTransform();

            Matrix3D rotationMatrix = CalculateRotationMatrix(90, 0, 0);
            collisionTransform.Matrix = new BEPUutilities.Matrix(
                Convert.ToSingle(rotationMatrix.M11),
                Convert.ToSingle(rotationMatrix.M12),
                Convert.ToSingle(rotationMatrix.M13),
                0,
                Convert.ToSingle(rotationMatrix.M21),
                Convert.ToSingle(rotationMatrix.M22),
                Convert.ToSingle(rotationMatrix.M23),
                0,
                Convert.ToSingle(rotationMatrix.M31),
                Convert.ToSingle(rotationMatrix.M32),
                Convert.ToSingle(rotationMatrix.M33),
                0,
                0, 0, 0, 1);

            //CollisionMesh instantiated as a side-effect of generating the container
            mContainerCollisionMesh = new StaticMesh(vertices, indices, collisionTransform);

            return modelVisual3D;;
        }

        Matrix3D CalculateRotationMatrix(double x, double y, double z)
        {
            Matrix3D matrix = new Matrix3D();

            matrix.Rotate(new System.Windows.Media.Media3D.Quaternion(new Vector3D(1, 0, 0), x));
            matrix.Rotate(new System.Windows.Media.Media3D.Quaternion(new Vector3D(0, 1, 0) * matrix, y));
            matrix.Rotate(new System.Windows.Media.Media3D.Quaternion(new Vector3D(0, 0, 1) * matrix, z));

            return matrix;
        }
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

PS: I'm beginning to suspect that my units are not matching up. This would explain why objects which move around might collide "properly" (their collision objects are offset proportionally to one another, but do not actually fit their respective objects in the same units/coordinates), but objects which move around do not collide properly with those that do not - the scale of the collision objects are fairly different from the actual drawn shapes themselves, and may also be translated differently from one another at construction time. They may have a different sense of where the origin is in World Space.

I'm scratching my head to figure out the best approach to tackle these issues. I would really love to find a way to draw these BEPU collision objects with WPF Media.3D. I am basing a drawing library off the one available below, so I am wondering if there is a way I can map the construction/translation/rotation/etc. of a BEPU collision object to something from this library to actually draw it as a debug tool the way BEPU normally uses XNA/MonoGame for debug drawing.

http://www.charlespetzold.com/3D/
https://www.microsoft.com/mspress/compa ... 735623941/

As you can see from my example code in the post above, these objects are created by specifying values like Length (Width, Height), Radius, Slices and Stacks at construction time.
kcoul
Posts: 7
Joined: Wed Feb 22, 2017 9:44 pm

Re: Hollow objects. Is there an option available other than...

Post by kcoul »

ok, just working my way through this here in case it helps anyone else trying to connect BEPU to WPF. I have managed to debug draw for simple Boxes and it does look like the proportions are correct, however the translation is too low on the Z axis by half of the box's dimensions. I'll have to see if I can debug draw more complex objects as well if I can find a way to translate values obtainable from BEPU over to what the Petzold library likes as construction parameters.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Hollow objects. Is there an option available other than...

Post by Norbo »

It sounds like at least part of the issue you're hitting is the fact that all entity shapes are centered on their local center of mass. So a box's local origin is right in the middle of the volume, not at the bottom. For more information, check out the Shape Recentering documentation.

Non-entity objects like the InstancedMesh do not perform any kind of recentering since they do not move dynamically.

As for mesh oddities, here are a couple of possible issues off the top of my head:
1) BEPUphysics matrices assume vector premultiplication. That is, result = v * M, instead of result = M * v. If the source of the rotation uses a different convention, it will need to be transposed.
2) Mesh index windings determine whether a triangle collides in a given direction. If a mesh has inconsistent index windings, one triangle might be solid in one direction while its neighbor is solid in the other. That can produce really wonky looking results. Setting the mesh.Sidedness to DoubleSided can work around this, but for performance and quality it's usually a good idea to use a one sided mode with consistent windings.
Post Reply