Improving collision between dynamic and kinematic entities
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Improving collision between dynamic and kinematic entities
So, the only dynamic objects in my game are the boxes that you move through the level, and the rest of the objects are kinematic. Unfortunately, this means the boxes have a tendancy to clip through the kinematics, especially when the kinematics are moving the boxes through pushing them (which is almost all of them). I tried increased the boxes' mass to an ungodly huge number (int.MaxValue - 1, to be exact) because I remember you saying an object with a large mass depending on one with a small mass makes collision squishy, but it only slightly improved the issue. Is there something else I could use besides kinematic enities? For example, could I make them dynamic but not affected by gravity and still have them not move when colliding with boxes (either without extra code or perhaps with a very rigid constraint)? Then I could set their mass to, like, ten, and the boxes to one, and that wouldn't be squishy (I might have to do some things with collision groups to keep them from responding from unlikely collision with each other, though). Anyways, any other ideas? Thanks!
Re: Improving collision between dynamic and kinematic entiti
The issue of mass ratios comes into play when a heavy dynamic object is dependent upon a light dynamic object. This is a difficult situation for the solver to handle, but given enough time (Space.Solver.IterationLimit), it will improve. The problem is, the number of iterations needed to improve a big ratio like 100:1 might be prohibitively expensive.So, the only dynamic objects in my game are the boxes that you move through the level, and the rest of the objects are kinematic. Unfortunately, this means the boxes have a tendancy to clip through the kinematics, especially when the kinematics are moving the boxes through pushing them (which is almost all of them). I tried increased the boxes' mass to an ungodly huge number (int.MaxValue - 1, to be exact) because I remember you saying an object with a large mass depending on one with a small mass makes collision squishy, but it only slightly improved the issue.
However, the issue of kinematics crushing dynamic objects is different. Kinematic objects have effectively infinite mass. There's no real-world analog for them. Kinematics simply cannot be pushed back by any amount of force. Increasing a dynamic object's mass or increasing the number of solver iterations may alter the termination state of the involved constraints, but it can't address the core problem. A finite mass is still less than infinite mass and nothing can push back against that infinite mass. It's easy enough to create a completely unsolvable system with moving kinematics. This means that no matter how many iterations are run, it cannot converge to a solution because no solution exists. In these situations, the dynamic body gets 'crushed' and wiggles around helplessly, usually getting launched or squeezed out at some point.
Making the machinery dynamic and weak enough to avoid crushing the boxes would do the trick. Since the boxes can fight back against the machinery (making it a solvable system), they won't get completely crushed.Is there something else I could use besides kinematic enities? For example, could I make them dynamic but not affected by gravity and still have them not move when colliding with boxes (either without extra code or perhaps with a very rigid constraint)? Then I could set their mass to, like, ten, and the boxes to one, and that wouldn't be squishy (I might have to do some things with collision groups to keep them from responding from unlikely collision with each other, though). Anyways, any other ideas? Thanks!
There are a variety of ways to make the machinery dynamic. The most obvious and direct option is to actually make them real contraptions bound together with motors and other constraints with specific motor strengths. Collision rules would indeed be useful for managing interactions. The RobotArmDemo shows the configuration of a complex articulated structure with constraints and collision rules.
The simplest type of machines, like rollers (if you decide to switch them to dynamic from kinematic as well), would likely make use of things like the SingleEntityLinear/AngularMotors. Simple moving platforms could also get away with just those motors, though for things where you don't need or desire physical weakness, kinematics are still a good thing to use. Faking things may also be useful sometimes (e.g. a 'pushing volume' as opposed to 100 individually rotating, motor-controlled rollers).
Finally, an important note to remember: a 'very rigid constraint' can crush a light dynamic object almost as effectively as a moving kinematic entity. Dynamic objects aren't a magic bullet; the value of dynamic machinery is that it can be weakened away from infinite forces so that the solver can actually figure out a solution.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
Alright, that's a fantastic explanation.Norbo wrote: However, the issue of kinematics crushing dynamic objects is different.
That doesn't seem like it would be too hard, being that most of my machines are only one or two meshs... Although it might be more difficult to add in rollers.Norbo wrote: There are a variety of ways to make the machinery dynamic. The most obvious and direct option is to actually make them real contraptions bound together with motors and other constraints with specific motor strengths. Collision rules would indeed be useful for managing interactions. The RobotArmDemo shows the configuration of a complex articulated structure with constraints and collision rules.
Well, the problem is that I don't need nor desire physical weakness, but not infinite mass. I'm not sure what you mean by "pushing volume," is it, like, an invisible entity that pushes the objects in lieu of rotating rollers?Norbo wrote:for things where you don't need or desire physical weakness, kinematics are still a good thing to use. Faking things may also be useful sometimes (e.g. a 'pushing volume' as opposed to 100 individually rotating, motor-controlled rollers).
Thanks for the input. I'm gonna try just making dynamic entities that aren't affected by gravity but have a 20:1 mass ratio or so (cause that's how real-life machines work, but with a far higher ratio), and if that doesn't work I'll start playing with motors and constraints. Being that machines are activated fairly often and have a rather specific path to adhere to, I'm thinking even if they are displaced by a few tenths, they'll correct themselves next time they're activated, but we'll see. It could be kind of interesting to apply some springs or something to make buckets and other machinery bounce slightly as if they were absorbing shock. Either way, I think I've got enough to go on, and I'll be sure to ask if I have questions about motors and constraints. Thanks!
Re: Improving collision between dynamic and kinematic entiti
Be careful here- anything which does not have the necessary weakness will run into the exact same issues as infinite mass. The problem is that the solver cannot find a solution in the time allowed. Kinematics in an impossible configuration are the worst case, but an extremely strong machine can have a similar effect (since you probably don't want to run the needed number of iterations to solve it fully).Well, the problem is that I don't need nor desire physical weakness, but not infinite mass.
For example, imagine a door which opens and closes to let boxes pass through. If it closes and there's a box in the way, both a kinematic door and an extremely forceful dynamic door (either extremely high mass or controlled by a very strong motor) will crush the obstructing box. The desired result in that case is to instead behave like a reasonable door in real life which stops when it hits an obstruction. That's the kind of 'weakness' I mean; not a soggy waffle. Imagine the difference in strength between an automatic door to a store (appropriately 'weak' constraint) and a pneumatic metal-shaping press (rigid constraints/kinematics).
By pushing volume, I mean anything which pushes objects directly rather than using actual entities to do the job. Like picking all objects within a bounding box and pushing them to the right. This type of thing could replace individual rollers and a few other simple machines.I'm not sure what you mean by "pushing volume," is it, like, an invisible entity that pushes the objects in lieu of rotating rollers?
A literal 'pushing volume' could be made with the space.BroadPhase.QueryAccelerator.GetEntries method to find nearby boxes. Another option would be to push all objects that are touching an object, causing a conveyor belt effect. Both of these, and many other options accomplishing similar effects, would be faster than a bunch of individually motorized rollers.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
Alright, thanks.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
I've been working on this for a few days now, and I can't get it to work right. At first I was thinking I'd attach a SingleEntityLinearMotor and a SingleEntityAngularMotor to each entity I needed to move, and then set the goals of them based on my needs. Unfortunately, transitioning from QuaternionSlerpCurves to motors isn't easy, so I thought I'd keep things as they were and instead just make motors that constrict the entities when they're stationary. This, however, causes problems with setting and unsetting the activity of the motors at the right times. Can you recommend anything? I have machines that specifically translate, ones that rotate (sometimes with an offset), and then various machines based on the concept of keyframes that are a combination of the two. Pretty much it boils down to not being able to figure out a good way to determine when the machine is at its endpoint. Using motors exclusively as a movement device, the machine slows down as it reaches the goal and never exactly gets there. Using velocity as a movement device and motors as a constriction device runs into the problem of not always going far enough (and it doesn't quite work as well as the other method). Also, I can't find a way to make the motors strong enough to resist pushing by the boxes but not strong enough to crush them... What was the mass ratio at which collision becomes squishy?
Re: Improving collision between dynamic and kinematic entiti
Note that the EntityRotator and EntityMover use motors internally when controlling dynamic entities. If you'd like to use curves with them, they will handle the motors for you. There doesn't need to be a transition once an endpoint is reached.Unfortunately, transitioning from QuaternionSlerpCurves to motors isn't easy, so I thought I'd keep things as they were and instead just make motors that constrict the entities when they're stationary. This, however, causes problems with setting and unsetting the activity of the motors at the right times. Can you recommend anything?
This sounds like the motor is overdamped. Pushing the motor closer to critical damping may help.Using motors exclusively as a movement device, the machine slows down as it reaches the goal and never exactly gets there.
It is true that the motor may not achieve the final goal due to numerical differences, though. However, the difference will very rapidly drop to inconsequential levels in a well-tuned motor.
It is not strictly a mass ratio issue. Mass ratios are just one case where the core issue becomes noticeable. Giant forces being pushed through insubstantial nodes will make solving difficult regardless of the cause. So, an extremely strong motor acting upon two similarly light objects can still cause crushing.Also, I can't find a way to make the motors strong enough to resist pushing by the boxes but not strong enough to crush them... What was the mass ratio at which collision becomes squishy?
So, here's an example:
Code: Select all
//Make an immobile barrier for a platform to rise into, attempting to crush a poor box.
Box ceiling = new Box(new Vector3(0, 20, 0), 50, 1, 50);
Space.Add(ceiling);
//Create a platform to drop another box onto. This platform will move up, eventually smashing into the ceiling.
Box movingPlatform = new Box(new Vector3(0, 0, 0), 5, 1, 5, 10);
Space.Add(movingPlatform);
var angularMotor = new SingleEntityAngularMotor(movingPlatform);
//This defaults to velocity motor. Switch it to servo to keep the orientation steady.
//(Could also set the inertia tensor inverse to zeros for the purposes of this demo.)
angularMotor.Settings.Mode = MotorMode.Servomechanism;
Space.Add(angularMotor);
var linearMotor = new SingleEntityLinearMotor(movingPlatform, movingPlatform.Position);
//This motor propels the moving platform ceilingward.
linearMotor.Settings.VelocityMotor.GoalVelocity = new Vector3(0, 2, 0);
Space.Add(linearMotor);
//Drop this box onto the moving platform.
Box freeBox = new Box(new Vector3(0, 10, 0), 1, 1, 1, 10);
Space.Add(freeBox);
However, if the freeBox's mass is changed to 0.1f instead of 10, it will get completely crushed. It is a 'weak link' in the conceptual dependency graph- an extremely light object between a completely immobile object and a tightly controlled, heavier object. This is nearly the worst case (second only to being crushed by a second kinematic entity).
Now, if you also change the platform's mass to 0.1f so that both the free box and the constrained platform have the same mass, you'll notice the the box does not get crushed so completely, but it's still struggling. So it's not just mass ratios at play here. What did change is the mass relative to the strength of the constraint. The constraint is 100x stronger relative to the mass of the objects, in other words.
So, a final change- what if the free box and the moving platform both have 0.1f mass as before, but now the linear constraint is weakened by 100x?
Code: Select all
//Make an immobile barrier for a platform to rise into, attempting to crush a poor box.
Box ceiling = new Box(new Vector3(0, 20, 0), 50, 1, 50);
Space.Add(ceiling);
//Create a platform to drop another box onto. This platform will move up, eventually smashing into the ceiling.
//Note the low mass.
Box movingPlatform = new Box(new Vector3(0, 0, 0), 5, 1, 5, .1f);
Space.Add(movingPlatform);
var angularMotor = new SingleEntityAngularMotor(movingPlatform);
//This defaults to velocity motor. Switch it to servo to keep the orientation steady.
//(Could also set the inertia tensor inverse to zeros for the purposes of this demo.)
angularMotor.Settings.Mode = MotorMode.Servomechanism;
Space.Add(angularMotor);
var linearMotor = new SingleEntityLinearMotor(movingPlatform, movingPlatform.Position);
//This motor propels the moving platform ceilingward.
linearMotor.Settings.VelocityMotor.GoalVelocity = new Vector3(0, 2, 0);
//Weaken the constraint.
linearMotor.Settings.VelocityMotor.Softness *= 100;
Space.Add(linearMotor);
//Drop this box onto the moving platform.
//Note the low mass.
Box freeBox = new Box(new Vector3(0, 10, 0), 1, 1, 1, .1f);
Space.Add(freeBox);
For servo constraints which target a specific goal, the equivalent to increasing the softness would be decreasing the stiffness and damping coefficients. (In fact, the softness of a velocity constraint is directly equal 1 / damping constant.)
Given a good configuration of these stiffness and damping coefficients, the objects should resist motion without crushing anything.
Re: Improving collision between dynamic and kinematic entiti
I should also mention that servo-mode constraints have a motor.Settings.Servo.BaseCorrectiveVelocity in addition to the usual spring-like behaviors that you can use to specify an arbitrary base speed of correction. This is another way to mitigate convergence times.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
Mkay. I'll take note of this and see if I can't get it to work... I'll also look at EntityMover and EntityRotator again and see if I can't get it to work.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
So, I got the rotation to work except for one thing... The bucket I was using as an example earlier is the one I'm using for testing, and the base part rotates fine but the glass part just goes beserk when I activate the machine. They use the same code... They just set the goal of their SingleEntityAngularMotors to curve.Evaluate(pathTime). Got any idea why this would produce such wildly different behavior?
Re: Improving collision between dynamic and kinematic entiti
Nothing jumps to mind, sorry. The usual recommendations about isolation and reproduction apply.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
Alright. Must be something obvious, then.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
By the way, Entity.AngularDamping has a typo... Says "continuong" if I'm not mistaken.
Re: Improving collision between dynamic and kinematic entiti
Noted and fixed for the next versiong.
-
- Posts: 172
- Joined: Sat Sep 24, 2011 7:31 am
Re: Improving collision between dynamic and kinematic entiti
You're a funny man.Norbo wrote:Noted and fixed for the next versiong.
Anyway, I pretty much got everything to work, but I need some help tweaking the SingleEntityLinearMotors. They tend to fling boxes, because they move very rapidly. I've come to the conclusion the stiffness and damping have some sort of ratio, so I tried dividing each constant by an arbitrary number (up to 30), but it didn't seem to help. I set the MaxCorrectiveVelocity to distance.Length() / time, but that didn't really help either. I think the mass of my boxes is 1, and the machines are 10, or something like that... What would be good numbers for the stiffness and damping?