Collision Mesh and Model Mesh A Bit Off

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Hello,

I'm trying to just make use of the mesh collision features of the engine, but I seem to be having problems getting the collider to match up with the model. I'm making a space game and I just need meshes for the giant, static ships.

Code: Select all

private ConvexHull meshCollider;

        public CollisionMesh(Model _model, Vector3 _position, Quaternion _rotation)
        {
            position = _position;
            Vector3[] vertices;
            int[] indices;
            TriangleMesh.GetVerticesAndIndicesFromModel(_model, out vertices, out indices);
            meshCollider = new ConvexHull(vertices);
            meshCollider.Position = _position;
            meshCollider.Orientation = _rotation;
            meshCollider.BecomeDynamic(1);
        }
I basically only need to do Mesh to Sphere collisions. When my Spheres collide with the Mesh, they seem to do so at strange locations. They're close, but it's not when my ship or bullet pierces a face like I'd want.

Am I positioning them wrong? Or is meshCollider.CollisionInformation.Events.InitialCollisionDetected the wrong time to be calling my onCollide?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

Convex hulls recenter their vertices into local space. To get the graphic to match up with the collision shape properly, the graphic must be offset a bit to match.

This goes into more depth:
http://bepuphysics.codeplex.com/wikipag ... ecentering

By the way, it is more efficient to provide the constructor the mass rather than setting it after the fact.
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Also, is there a way to draw the ConvexHull?

And what's the difference between the ConvexHull and MobileMeshShape?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

Also, is there a way to draw the ConvexHull?
The BEPUphysicsDrawer would do the trick. You can grab it from the main source download.
And what's the difference between the ConvexHull and MobileMeshShape?
A convex hull takes a set of points and wraps it, eliminating any internal points and concavity.

A MobileMeshShape is an actual mesh, composed of triangles. Note that it's generally good idea to use an approximation instead of a mobile mesh; approximations are generally quite a bit faster. Also, if the mesh never moves, use StaticMesh instead.
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Ah, thank you!
A MobileMeshShape is an actual mesh, composed of triangles. Note that it's generally good idea to use an approximation instead of a mobile mesh; approximations are generally quite a bit faster. Also, if the mesh never moves, use StaticMesh instead.
I tried that and I want to use the StaticMesh, but then my

Code: Select all

public override void addCollisionEvent(InitialCollisionDetectedEventHandler<EntityCollidable> _function)
        {
            meshCollider.CollisionInformation.Events.InitialCollisionDetected += _function;
        }
won't work for the StaticMesh
nor will

Code: Select all

public override BEPUphysics.ISpaceObject getPhysicsCollider()
        {
            return meshCollider;
        }
I have spheres, boxes, and meshes all inheriting from the same base class.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

The deferred event failure for the StaticMesh is due to a known bug in v1.1; it should be fixed in the development version. Using the immediate version of the event will also work, though then care must be taken to avoid asynchronous access.

The StaticMesh is an ISpaceObject, so that getPhysicsCollider should be fine. In what way does it not work?

The fact that the StaticMesh is not an entity may not fit well into your existing classes. The StaticMesh is not an Entity, and so is incapable of motion. If you want to keep a unified architecture with the expectation that there will be mobile meshes, then going with the MobileMesh would be okay, though they are less efficient than static meshes (which only really matters if you are hitting CPU bottlenecks).
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Norbo wrote:The fact that the StaticMesh is not an entity may not fit well into your existing classes. The StaticMesh is not an Entity, and so is incapable of motion. If you want to keep a unified architecture with the expectation that there will be mobile meshes, then going with the MobileMesh would be okay, though they are less efficient than static meshes (which only really matters if you are hitting CPU bottlenecks).
Yeah, I'm only going to have like 10 of them max on screen at any time, so I guess the MobileMesh might not be so bad. And they are made during load time so.

Is there a way to calculate the offset? I haven't finished reading all the links from the Shape Recentering page so maybe it's in there. If so, sorry for asking.

Thanks so much for the speedy replies!

Code: Select all

meshCollider.CollisionInformation.LocalPosition = meshCollider.Position;
Is this correct?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

Is this correct?
That will offset the collision shape to match the graphic (assuming the meshCollider.Position is being accessed immediately after a MobileMesh constructor) instead of offsetting the graphic to match the collision shape. The graphic would align, but then the center of mass will not be physical. It will rotate around the model's origin instead.

In addition to the description of the process in the documentation, the GraphicMatchingDemo may help.
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Norbo wrote:
Is this correct?
The graphic would align, but then the center of mass will not be physical. It will rotate around the model's origin instead.
That's fine, I'd rather it rotated around its Maya center. Also, thanks for the demo. Hopefully I can get it working so I can see if everything's correct.

Thanks so much!
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Hey, actually I just had two more questions.

Turns out the

Code: Select all

new AffineTransform(_rotation, _position)
works perfectly fine, and I don't need to do anything with local space. It's centered and everything already.

The problem seems to stem from trying to move it. It'd be great if I could just give it a new AffineTransform since that seems to work, but I don't see it so my

Code: Select all

public override Vector3 setPosition(Vector3 _position)
and any rotation method don't work. And that was my problem earlier it seems because disabling it fixed everything. My ships don't move right now anyway, but I'd like it if they had that option down the line. Do you know what I might be doing wrong? Setting the Position causes it to not work; the WorldMatrix also doesn't work either.

Also,
I'm trying to get data from the delegate using EntityCollidable eCollidable, Collidable collidable, CollidablePairHandler pairHandler so I tried extending the Sphere, Box, and MobileMesh, but it seems

Code: Select all

public class SpaceSphere : Sphere
will never work with

Code: Select all

public virtual void collisionEvent(EntityCollidable eCollidable, Collidable collidable, CollidablePairHandler pairHandler)
        {
            float damage = 0;
            if (eCollidable is SpaceSphere)
...
It says it'll never evaluate to that type, but SpaceSphere extends Sphere extends Entity extends BEPUphysics.Collidables.MobileCollidables.EntityCollidable so I figured it would work, but it doesn't appear to when I run.

My big problem is that second issue.

Also, is there scaling?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

Do you know what I might be doing wrong? Setting the Position causes it to not work; the WorldMatrix also doesn't work either.
It depends on what "doesn't work" means, but I suspect it is related to recentering again. Setting an entity's position moves the entity such that the center of mass is located at the new position. If the center of mass isn't where you expect on the object, then setting the position won't put the shape where you expect.

If you only need a rigid subset of affine transforms (position and orientation only), the Entity's Position and Orientation will do the trick. The values you set must take into account the recentering effect, though. Note that other properties like the WorldTransform and OrientationMatrix are convenience properties derived from the Position and Orientation properties.

The initial AffineTransform is just applied to the vertex data when building the shape. Recentering will occur on the post-transformed vertices to bring everything into local space so that the entity Position and Orientation will behave as expected.
It says it'll never evaluate to that type, but SpaceSphere extends Sphere extends Entity extends BEPUphysics.Collidables.MobileCollidables.EntityCollidable so I figured it would work, but it doesn't appear to when I run.
Sphere is a convenience prefab Entity type, and Entity does not inherit from EntityCollidable. Entity objects use EntityCollidables as collision proxies in the collision detection pipeline. The EntityCollidable associated with an Entity is returned by the entity.CollisionInformation property.

Further, I generally recommend not extending Entity classes or Collidable classes unless you plan on implementing and handling distinct custom collision behaviors.

All BroadPhaseEntry objects (which include Collidable objects, which include EntityCollidable objects) have a Tag property. So, you could set an Entity.CollisionInformation.Tag to some gameplay logic object. In the event, you can analyze the Tag to get your information. Also note that the Entity has its own Tag which is separate from the Entity.CollisionInformation.Tag, and that EntityCollidables have an Entity property which contains the entity they are associated with.
Also, is there scaling?
You can scale a MobileMeshShape when you construct it with the AffineTransform. All the shapes have various forms of sizing (radius for spheres, radius/length for capsules, etc.), though there is not a single universal scaling behavior. ConvexShapes can be nested within TransformableShapes to provide them with universal scaling, but this adds a tiny bit of overhead and wipes out any special case collision detection behavior that might exist (a BoxShape nested in a TransformableShape will not/can not use the box-box special case when colliding with another BoxShape).

Scaling after an object is created is possible for certain shapes, but it will require some recomputation to find the new physical data. Additionally, scaling objects is a form of nonphysical motion and collision response may not behave like you expect during periods of continuous scaling. (For example, if an object was scaled up such that it enclosed another object, they will be in penetration; they will separate over time according to the penetration resolution system.)
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Norbo wrote:
Do you know what I might be doing wrong? Setting the Position causes it to not work; the WorldMatrix also doesn't work either.
The initial AffineTransform is just applied to the vertex data when building the shape. Recentering will occur on the post-transformed vertices to bring everything into local space so that the entity Position and Orientation will behave as expected.
I guess I still don't understand the difference between the AffineTransform and Position. My efforts to get the difference between the model's center and the center of mass are failing, too.
Norbo wrote: All BroadPhaseEntry objects (which include Collidable objects, which include EntityCollidable objects) have a Tag property. So, you could set an Entity.CollisionInformation.Tag to some gameplay logic object. In the event, you can analyze the Tag to get your information. Also note that the Entity has its own Tag which is separate from the Entity.CollisionInformation.Tag, and that EntityCollidables have an Entity property which contains the entity they are associated with.
That's it! Thank you!
Norbo wrote: Scaling after an object is created is possible for certain shapes, but it will require some recomputation to find the new physical data. Additionally, scaling objects is a form of nonphysical motion and collision response may not behave like you expect during periods of continuous scaling. (For example, if an object was scaled up such that it enclosed another object, they will be in penetration; they will separate over time according to the penetration resolution system.)
Seems a bit too complicated. That's okay.

Thank you! Everything seems to be working!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

I guess I still don't understand the difference between the AffineTransform and Position.
The AffineTransform passed into the constructor of the MobileMeshShape scoots the shape's vertex data around in a very general way. An affine transform can include any linear transform and translation. This is a superset of rigid transforms (which only include position and orientation). So you can squish the mesh data, shear it, scale it, or whatever.

This gives you more runtime control over the shape of a mesh before giving the shape to an entity.

An Entity only has a rigid transform (Position and Orientation). The entity's Position and Orientation bring the MobileMeshShape from its shape local space into world space. ("Shape local space" includes the affine transform applied to the mesh vertex data, and the recentering translation.)
My efforts to get the difference between the model's center and the center of mass are failing, too.
The GraphicsMatchingDemo and Shape Recentering documentation linked earlier go through the process.

To paraphrase:
-If you make a shape that requires recentering directly, like the MobileMeshShape or ConvexHullShape, there is a constructor which outputs the shape's computed center position.
-If you make a prefab entity type like MobileMesh or ConvexHull, the immediately-post-constructor value of the Position is the shape's computed center position. The prefab entity constructors use the shape constructors which output the position.
Seems a bit too complicated. That's okay.
I should note that the physical recomputation part is automatic; it's just a performance concern. But yes, it's generally better to keep things simple by avoiding post-construction scaling if possible.
Shadow0144
Posts: 14
Joined: Sat Mar 24, 2012 3:22 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Shadow0144 »

Norbo wrote: An Entity only has a rigid transform (Position and Orientation). The entity's Position and Orientation bring the MobileMeshShape from its shape local space into world space. ("Shape local space" includes the affine transform applied to the mesh vertex data, and the recentering translation.)
It seems switching from MobileMeshSolidity.Solid to MobileMeshSolidity.Counterclockwise did the trick.

Code: Select all

AffineTransform transform = new AffineTransform(Quaternion.Identity, Vector3.Zero);
meshCollider = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Counterclockwise, 1);
meshCollider.CollisionInformation.Tag = this;
meshCollider.CollisionInformation.LocalPosition = meshCollider.Position;
meshCollider.Position = _position;
meshCollider.Orientation = _rotation;
Whenever I tried

Code: Select all

meshCollider = new MobileMesh(vertices, indices, new AfflineTransform(Quaternion.Identity, Vector3.Zero), MobileMeshSolidity.Solid, 1);
I got a ton of lag I didn't get with

Code: Select all

meshCollider = new MobileMesh(vertices, indices, new AfflineTransform(_rotation, _position), MobileMeshSolidity.Solid, 1);
without changing anything else for some reason. But I don't need the solidarity anyway.

Thanks so much for being super helpful and responsive!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Mesh and Model Mesh A Bit Off

Post by Norbo »

It seems switching from MobileMeshSolidity.Solid to MobileMeshSolidity.Counterclockwise did the trick.
To avoid some possible confusion, one-sided meshes still use shape recentering, just like solid meshes.

If changing it from solid to one-sided fixed something, that implies that the mesh was somehow confusing the solidity computation (e.g. the mesh was open). Solid meshes are quite a bit more expensive, though. If you can get away with one sided meshes (or even cheaper approximations), it is a good idea to do so.
I got a ton of lag I didn't get with ...without changing anything else for some reason.
Lag associated with mobile meshes is usually caused by collisions with other objects (as they are otherwise very cheap). If the only difference between two meshes is their positions and orientations, then chances are, something is interacting with one of the configurations and not the other. If it's a significant amount of lag, then it is likely another complicated shape.
Post Reply