Screwy Collisions Upon Adding a Joint?

Oct 3, 2010 at 9:31 PM
Edited Oct 4, 2010 at 7:22 AM

Hi!

Love the engine; keep up the good work!

I am sure I am missing something very obvious: but for some reason, as soon as I add a constraint to the physics manager, it essentially disables those bodies' gravity, and goofs up collision.  I am throwing things at the bodies with joints, and they will nudge from the collision, but the things I'm throwing almost "pathfind" around the bodies.  Too bad 3D pathfinding isn't what I wanted!

I'll update as I take guesses...

Cheers.

Coordinator
Oct 4, 2010 at 2:22 AM

I haven't been seeing that problem in the holodeck sample (ragdolls and sample scene #8 seem to work) so it must be happening under certain circumstances. Can you paste some code to repro the problem? Thanks

Oct 4, 2010 at 7:04 AM
Edited Oct 4, 2010 at 8:10 AM

UPDATE: I have been stepping through every line of the simulation.  In the PointConstraint.ProcessVelocity function, I was getting impulses of not a number (NaN).  I found that it was getting a single update of zero as the time slice when the game was loading up, which evaluated to NaNs.  Once I told my game to only integrate if the time slice is greater than zero, suddenly my rag doll worked!

Since I have your attention, would you take a look at my manual creation of physics objects?  Mine can't come from the pipeline without duplicating model files, which is silly talk.  While what I have works... it seems kinda crazy, particularly for my boxes:

        ConvexHull3D hull = new ConvexHull3D(vertices);
        CompiledPolyhedron compiled = hull.ToPolyhedron();
        PolyhedronPart part = new PolyhedronPart(compiled);        
        //without the following line, the box had all Vector3.Zeros as coordinates.
        Transform identity = new Transform(1f, Vector3.Zero, Quaternion.Identity); part.ApplyTransform(ref identity); myBody.Skin.Add(part, material); SetMass(DefaultMass); }

Cheers.

Coordinator
Oct 4, 2010 at 9:28 PM

Weird, didn't know that a time slice of zero could be passed in, but that would definitely result in strange behavior.

Your code looks fine to me (and you mention that it works, which is good!). You might be able to use myBody.SetWorld() instead of creating the transform and using ApplyTransform(). They should have the same effect, I think, but SetWorld() would work universally, even in cases where the body has multiple parts.

ConvexHull3D can be pretty expensive if the model is complex, since I just use a simple gift-wrapping algorithm, so there could be an impact at runtime if you have lots of models. You might be able to skip that class if you want to pre-compute the convex set of vertices (which you obviously already have with a box) and face indices to pass into the CompiledPolyhedron constructor. CompiledPolyhedron is a necessary class since it computes and stores the edge/face information necessary to optimize collision detection later.

Oct 5, 2010 at 2:02 AM
Edited Oct 5, 2010 at 2:46 AM

Thank you for the suggestion, I'll take that into account once I start repeating the same model repeatedly.

I am doing some rapid prototyping, so hopefully you don't mind me asking some more questions:

1.  I am having a lot of things fall through a collision mesh, particularly if the object has a half-way decent velocity.  I see the PhysicsManager has a lot of properties I can tweak.  What scale were you imagining for the default values?  I assume one unit = one meter, but just checking.  I have roughly three units per one meter, and knowing your scale that will help me tweak those values.  If you have any other suggestions, I'll take them!  :-)

2.  My ragdoll has some extremely "spongy" joints--they separate a lot from where they are supposed to be.  Like, the top of the arm is about half way down the body... :-(.  The longer the objects sit, the worse it gets.  Right now, I am holding the ragdoll's head like a string puppet. Any ideas?

3. Where can I add additional collision exceptions outside of attaching the two bodies to joints?

I am very thankful for all the help you have offered!

Cheers.

Coordinator
Oct 5, 2010 at 3:26 AM

1. Yeah, one unit per one meter is what I've been assuming. The collision detection for fast-moving objects definitely isn't perfect, especially for the more complicated object types. Stamping out all the little quirks is really hard. Are you having problems specifically with poly-poly collisions or poly-mesh? You could try playing around with the SweepThreshold value (which is in the same units as distance in the game world). 

2. Are you seeing this behavior with the sample ragdoll? (Launch holodeck.exe and press R to spawn them). If limbs are separating too much, you can try tweaking PositionCorrectionFactor and PositionCorrectionIterations (and maybe LinearErrorTolerance). Increasing those values will cause more correction, at the cost of some stability.

3. You could attach a delegate to the OnCollision field of RigidBody and return true to suppress collisions between two objects. This will suppress a collision for the duration of contact until they separate again.

Oct 5, 2010 at 3:56 AM
Edited Oct 6, 2010 at 4:22 PM

This post is the definition of a "living document!"  :-P

1.  Poly-mesh collisions are the most wonky that I've seen.  Poly-poly seems to be working pretty well.

EDITED:

2.  No, your sample ragdoll seems to work perfectly.

3.  Does the trick; now my ragdoll can't trip up on himself.

Again, thanks for the help!

EDIT:

4.  If I set the mass properties of the head to be MassProperties.Immobile, everything attached directly or indirectly does not fall either.  So, for example, I set my head sphere to be MassProperties.Immobile, and now the body and limbs had no gravity.  Is that on purpose?

5.  I occasionally get a NullReferenceException by the following code:

private class ConstraintComparator : Comparer<Constraint>
{
	public override int Compare(Constraint x, Constraint y)
	{
		if (x is ContactConstraint ^ y is ContactConstraint)
		{
			return x is ContactConstraint ? 1 : -1;
		}
		float d = MathHelper.Min(x.BodyA.World.Position.Z, x.BodyB != null ? x.BodyB.World.Position.Z : 0f) -
			MathHelper.Min(y.BodyA.World.Position.Z, y.BodyB != null ? y.BodyB.World.Position.Z : 0f);
		return d == 0f ? 0 : (d > 0f ? 1 : -1);
	}
}

Where x is null, and y is a UniversalJoint.  It gets the null reference line on calculating d.

6.  I think I know what I need to do.  So, I was manipulating positions and orientations rather directly via SetWorld.  I was doing that every tick to the head of my ragdoll, so I could dangle him like a puppet.  Unfortunately for the poor physics system, it thought it was still falling.  This created the disconnect between the joints which I wasn't changing the position of, and the head that was being "frozen" into place manually.  It only hit me a few minutes ago: "duh, your picking and dragging of objects is exactly the same as me holding the head of my ragdoll in place."  So, thus, I have found the GrabConstraint.  I have tried it out and seems to work great!

9.  The polyhedron to mesh collision is really really iffy at times...  I have stuff falling through /constantly./  Ideas, suggestions, tips?

Cheers.