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?
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.
Using motors exclusively as a movement device, the machine slows down as it reaches the goal and never exactly gets there.
This sounds like the motor is
overdamped. Pushing the motor closer to critical damping may help.
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.
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?
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.
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);
In the above, the box will fall on the platform and the platform will hardly register the event thanks to its near-rigid control (the platform is very capable of resisting the motion). Despite that rigidty, the box does not get crushed.
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);
Suddenly, it's back to being very similar to the original setup. The platform is quite capable of resisting the motion without crushing the object.
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.