We I have a set of contact data from the collision detector, and have the rigid-body equations of motion, including torques and forces. We are now ready to combine the two and have rotating objects respond to contacts.
Impulses and Impulsive Torques
Different objects have a different resistance to being deformed and a different tendency to return to their original shape. If there is a tendency to return to their original shape, then the force begins to accelerate them apart until they are no longer deformed. To simulate this we instantly change the velocity of each object in the collision. The change in velocity is called an “ impulse”.
Now that we are dealing with rotating rigid bodies. If you bounce an object that is spinning on the ground, you will notice that the object not only starts to move back upward, but its angular velocity will normally change too. The collision affects bothlinear and angular velocities. Any force acting on an object generates both linear and angular acceleration.
An instantaneous change in velocity.In the same way that we have
\[f = m\ddot{p} \qquad \qquad [1.1] \]for forces,we have
\[g = m\dot{p} \qquad \qquad [1.2] \]一般时使用p而不是使用g,但是为了防止和位置(p)冲突所以使用了g。这个impulse和force是等价的。一些作用力不只是通过加速度来体现出来,有些是通过速度而不是加速度体现的。其实 \(\dot{p}应该是速度的改变吧,此处有疑问\)
Impulsive Torque
.
The linear component is given by
\[\ddot{p} = \frac{1}{m}f \qquad \qquad [1.3] \]and the angular component by the torque
\[\tau = P_{f} \times f \qquad \qquad [1.4] \]where the torque generates angular acceleration by
\[\ddot{\theta} = I^{-1}\tau \qquad \qquad [1.5] \]In the case of the collision it stands to reason that the collision will generate a linear change in velocity (the impulse) and an angular change in velocity. An instantaneous angular change in velocity is called an “impulsive torque”.
\[u = I\dot{\theta} \qquad \qquad [1.6] \]where the \(u\) is the impulsive torque. \(I\) is the inertia tensor, and $ \dot{\theta}$ is the angular velocity.该公式对应了上面的[1.2] (个人感觉此处应该是angular velocity的改变值)
This is the direct equivalent of equation 7.5, which dealt with linear impulses.And correspondingly the change in angular velocity $\Delta \dot{\theta} $ is
Impulses behave just like forces (就是Impulses和forces是一样的,都会产生linear 和angular分量,而Torque仅仅是关于angular的问题,不要混淆哦). In particular for a given impulse there will be both a linear component and an angular component.The impulsive torque generated by an impulse (impluse也会产生impulsive torque) is given by
\[u = P_{f}\times g \qquad \qquad [14.2] \]for collisions the point of application \(P_{f}\)is given by the contact point and the origin of the object:
\[P_{f} = q - p \qquad \qquad [1.8] \]where \(q\)is the position of the contact in world coordinates and \(p\) is the position of the origin of the object in world coordinates.
Rotating Collisions
The effect of the impulse at the collision is to have the points of each object in collision bounce apart. The movement of the colliding objects at the collision point still follows the same equations that we met in chapter 7. In other words, if we tracked the two collision points (one from each object) around the time of the collision, we’d see that their separating velocity is given by
\[v_{s}' = -cv_{s} \]where \(v_{s}\) is the relative velocity of the objects immediately before the collision, is the relative velocity after the collision, and c is the coefficient of restitution. The constant c depends on the materials of both objects involved.
Depending on the characteristics of the objects involved, and the direction of the contact normal, this separation velocity will be made up of a different degree of linear and rotational motion. Figure shows different objects engaged in the same collision.In each part of the figure the closing velocity and the coefficient of restitution at the point of contact are the same, so the separating velocity is the same too.
- The first object is lightweight and is colliding almost head on. For any force that is generated during the collision the corresponding torque will be small, because f is almost parallel to pf . Its bounce will be mostly linear, with only a small rotational component.
- The second object is heavier but has a very small moment of inertia about the Z axis. It is colliding off center. Here the torque generated will be large, and because the moment of inertia is very small, there will be a big rotational response. The rotational response is so large, in fact, that the linear component isn’t large enough to bounce the object upward. Although the point of contact bounces back up (at the same velocity as the point of contact in each other case), it is the rotation of the object that is doing most of the separating, so the linear motion continues downward at a slightly slower rate. You can observe this if you drop a ruler on the ground in the configuration shown in figure 14.2. The ruler will start spinning away from the point of contact rapidly, but as a whole it will not leap back into the air. The rotation is taking the bulk of the responsibility for separating the points of contact.
- The third object in the figure collides in the same way as the second. In this case, however, although the mass is the same, its moment of inertia is much greater. It represents an object with more mass in its extreme parts. Here the compression force causes a much lower amount of rotation. The linear impulse is greater and the impulsive torque is smaller. The object bounces linearly and the compression force reverses the direction of rotation, but the resulting angular velocity is very small.
Handling Rotating Collisions
Just as for particle collisions, we need two parts to our collision response.
-
First we need to resolve the relative motion of the two objects by applying impulse and impulsive torque. When we process a collision for velocity, we need to calculate four values: the impulse and impulsive torque for both objects in the collision.
-
Because we only check for collisions at the end of each frame, objects may have already passed into one another.So, second, we need to resolve any interpenetration that has occurred.
Collision Impulses
To resolve the relative motion of the two objects we need to calculate four impulses: linear and angular impulses for each object.
To calculate the impulse and impulsive force on each object we go through a series of steps:
- We work in a set of coordinates that are relative to the contact.
- We work out the change in velocity of the contact point on each object per unit impulse.
- We will know the velocity change we want to see (in the next step), so we invert the result of the last stage to find the impulse needed to generate any given velocity change.
- We work out what the separating velocity at the contact point should be, what the closing velocity currently is, and the difference between the two. This is the desired change in velocity.
- From the desired change in velocity we can calculate the impulse that must be generated.
- We split the impulse into its linear and angular components and apply them to each object
Change To Contact Corrdinates
Recall that each contact has an associated contact point and contact normal. If we use this point as the origin, and the contact normal as one axis, we can form an orthonormal basis around it: a set of three axes. Just as we have a set of
world coordinates and a set of local coordinates for each object, we will have a set of contact coordinates for each contact.
Since we are ignoring friction for now, we create an arbitrary set of axes by starting with the Y axis pointing down the world Y axis, The X axis we know already: it is the contact normal generated by the collision detector.
Velocity Change By Impulse
The Linear Component
The Linear Component
The linear component is very simple. The linear change in velocity for a unit impulse will be in the direction of the impulse, with a magnitude given by the inverse mass:
For collisions involving two objects, the linear component is simply the sum of the two inverse masses:
\[\Delta \dot{p}_{d} = m_{a}^{-1} + m_{b}^{-1} \]The Angular Component
We’ll need to bring together three equations we have met at various points in the book. For convenience we’ll use \(q_{real}\) for the position of the contact relative to the origin of an object: $ q_{real} = q − p $
- equation 14.2 tells us the amount of impulsive torque generated from a unit of impulse:
where \(d\) is the direction of the impulse (in our case the contact normal).
- equation 14.1 tells us the change in angular velocity for a unit of impulsive torque:\[\Delta \dot{ \theta } = I^{-1}u \]
- And finally, equation 9.5 tells us the total velocity of a point.
Vector3 torquePerUnitImpulse = relativeContactPosition % contactNormal;
Vector3 rotationPerUnitImpulse = inverseInertiaTensor.transform(torquePerUnitImpulse);
Vector3 velocityPerUnitImpulse = rotationPerUnitImpulse % relativeContactPosition;
Impulse Change By Velocity
For frictionless collisions this step is incredibly simple. If we have a single value for the velocity change per unit impulse (call it \(d\)), then the impulse needed to achieve a given velocity change is
\[g = \frac{v}{d} \qquad \qquad [14.3] \]where \(v\) is the desired change in velocity and \(g\) is the impulse required.
Calculating The Desired Velocity Change
This stage of the algorithm has two parts. First we need to calculate the current closing velocity at the contact point. Second we need to calculate the exact change in velocity we are looking for.
Calculating the Closing Velocity
As we saw earlier, velocity has both a linear and an angular component. We calculate its linear velocity and the linear velocity of the contact point due to rotation alone.
We can retrieve the linear velocity from an object directly; it is stored in the rigid body. To retrieve the velocity due to rotation we need to use equation 9.5 again. The total velocity of the contact point for one object is given by
Vector3 velocity = body->getRotation() % relativeContactPosition;
velocity += body->getVelocity();
This gives us a total closing velocity in world coordinates. We need the value in contact coordinates because we need to understand how much of this velocity is in
the direction of the contact normal and how much is at a tangent to this. The components of the velocity that are not in the direction of the contact normal represent how fast the objects are sliding past one another: they will become important when
we consider friction.The conversion uses the basis matrix in the now familiar way:
contactVelocity = contactToWorld.transformTranspose(velocity);
Calculating the Desired Velocity Change
As I mentioned at the start of the chapter, the velocity change we are looking for is given by the same equation we used for particles:
\[v'_{s} = -cv_{s}\Rightarrow \Delta v_{s} = -v_{s} - cv_{s} = -(1 + c)v_{s} \]The value of the coefficient depends on the materials involved in the collision.
Calculating The Impulse
With the desired velocity change in hand, the impulse is given by equation 14.3.
Because we are not concerned with friction, we are only concerned with the impulse in the direction of the contact normal. In contact coordinates the contact normal is the X axis, so the final impulse vector is:
where \(g\) is the impulse,as earlier.
Applying The Impulse
To apply the impulse, we use equations 7.5 and 14.1. The first tells us that linear impulses change the linear velocity of the object according to the formula
\[\dot{p} = \frac{f}{m} \]So the velocity change for the first object in the collision will be
Vector3 velocityChange = impulse * body[0]->getInverseMass()
The rotation change is given by equation 14.1:\(\Delta \dot{\theta} = I^{-1}u\) ,We first need to calculate the impulsive torque, \(u\), using equation 14.2 again:
\[u = q_{rel} \times g \]Vector3 impulsiveTorque = impulse % relativeContactPosition;
Vector3 rotationChange = inverseInertiaTensor.transform(impulsiveTorque)
Resolving Interpentration
We have covered the procedure for representing the change in velocity when a collision happens. If the objects in our simulation were truly solid, this would be all that is needed.
Unfortunately the objects can pass into one another before we detect that a collision has occurred. The simulation proceeds in time steps, during which no checking takes place. By the end of a time step when collision detection occurs, two objects can have touched and passed into one another. We need to resolve this interpenetration in some way; otherwise objects in the game will not appear solid.
Choosing A Resolution Method
For rotating rigid bodies the situation is a little more complex. There are several strategies we could employ to resolve interpenetration.
Linear Projection
We could use the same algorithm as before: changing the position of each object so that it is moved apart in the direction of the contact normal. The amount of movement should be the smallest possible such that the objects no longer touch. For collisions involving two objects the amount each one moves is proportional
to its inverse mass.
Unfortunately it isn't very realistic. This is in contrast to the third part of the figure that shows how a real box would behave.
Velocity-Based Resolution
Another strategy used in some physics engines is to take into account the linear and angular velocities of the objects in the collision.At some point in their motion the two objects will have just touched. After that
time they will continue interpenetrating to the end of the time step. To resolve the interpenetration we could move them back to the point of first collision. We can approximate it by considering only the contact point on each object as generated by the collision detector. We can move these two points back alongthe paths they followed until they no longer overlap in the direction of the contact normal
Nonlinear Projection
Rather than just moving the objects back linearly, we use a combination of linear and angular movement to resolve the penetration.
The theory is the same: we move both objects in the direction of the contact normal until they are no longer interpenetrating. The movement, rather than being exclusively(独占的,唯一的) linear, can also have an angular component.
Unlike linear projection, the balance between linear and angular velocity will depend on the inverse inertia tensor of each object. An object with a high moment of inertia tensor at the contact point will be less likely to rotate, so will take more of its motion as linear motion.
Relaxation
Relaxation resolves only a proportion of the interpenetration at one go. Relaxation is useful when there are lots of contacts on one object. As each contact is considered and resolved, it may move the object in such a way that other objects are now interpenetrated. For a brick in a wall, any movement in any direction will cause it to interpenetrate with another brick. This can cause problems with the order in which interpenetration resolution is carried out, and can leave the simulation with contacts that still have noticeable penetration.
By performing more interpenetration resolution steps, but having each one only resolve a proportion of the interpenetration, a set of contacts can have a more equitable say over where an object ends up. Each gets to resolve a little, and then the others take their turns. This typically is repeated several times. In situations where previously there would have been one or two contacts with obvious interpenetration, this method shares the interpenetration among all the conflicting contacts, which may be less noticeable.
Unfortunately relaxation also makes it more likely that interpenetration is noticeable at the end of an update when there are few collisions. It is beneficial to have all contacts share a small degree of interpenetration when the alternative is having one very bad contact, but in most cases it is undesirable and a full-strength resolution step is more visually pleasing.
Implementing Nonlinear Projection
We start knowing the penetration depth of the contact.Our goal is to find the proportion of this movement that will be contributed by linear and angular motion for each object.
We first make an assumption: we imagine the objects we are simulating were pushed together so that they deformed. this deformation causes a force that pushes the objects apart. This force, according to D’Alembert’sprinciple, has both linear and angular effects.
Calculating the Components
For velocity we were interested in the amount of velocity change caused by the rotation change from a single unit of impulse. This quantity is a measure of how resistant the object is to being rotated when an impulse or force is applied at the contact point.
To resolve penetration we use exactly the same sequence of equations. We find the resistance of the object to being moved in both a linear and angular way.
Recall that the resistance of an object to being moved is called its "inertia". So we are interested in finding the inertia of each object in the direction of the contact normal. This inertia will have a linear component and a rotational component.
The linear component of inertia is, as before, simply the inverse mass. The angular component is calculated using the same sequence of operations that we used previously.
// We need to work out the inertia of each object in the direction
// of the contact normal, due to angular inertia only.
for (unsigned i = 0; i < 2; i++)
{
if (body[i])
{
Matrix3 inverseInertiaTensor;
body[i]->getInverseInertiaTensorWorld(&inverseInertiaTensor);
// Use the same procedure as for calculating frictionless
// velocity change to work out the angular inertia.
Vector3 angularInertiaWorld = relativeContactPosition[i] % contactNormal;
angularInertiaWorld = inverseInertiaTensor.transform(angularInertiaWorld);
angularInertiaWorld = angularInertiaWorld % relativeContactPosition[i];
angularInertia[i] = angularInertiaWorld * contactNormal;
// The linear component is simply the inverse mass.
linearInertia[i] = body[i]->getInverseMass();
// Keep track of the total inertia from all components.
totalInertia += linearInertia[i] + angularInertia[i];
}
}
At the end of this loop we have the four values (two for single-body collisions) that tell us the proportion of the penetration to be resolved by each component ofeach rigid body. The actual amount each object needs to move is found by
real inverseInertia = 1 / totalInertia;
linearMove[0] = penetration * linearInertia[0] * inverseInertia;
linearMove[1] = -penetration * linearInertia[1] * inverseInertia;
angularMove[0] = penetration * angularInertia[0] * inverseInertia;
angularMove[1] = -penetration * angularInertia[1] * inverseInertia;
Applying the Movement
Applying the linear motion is simple. The linear move value gives the amount of motion required, and the contact normal tells us the direction in which the movement should take place:
body[i]->position += contactNormal * linearMove[i];
The angular motion is a little more difficult. We know the amount of linear movement we are looking for; we need to calculate the change in the orientation quaternion that will give it to us.
We do this in three stages.
- First we calculate the rotation needed to move the contact point by one unit.[rotation ---> move one unit]
- Second, we multiply this by the number of units needed (i.e.,the angularMove value). [ angularMove * rotation -> needed rotation ]
- Finally we apply the rotation to the orientation quaternion. [needed rotation -> orientation quaternion]
We can calculate the direction in which the object needs to rotate, using the same assumption that the rotation is caused by some kind of impulse. If an impulse were exerted at the contact point, the change in rotation would be
\[\Delta \dot{\theta} = I^{-1}u = I^{-1} (q_{rel} \times g) \]where \(q_{rel}\) is the relative position of the contact point, \(u\) is the impulsive torque generated by the impulse, and g is the impulse in the direction of the contact normal, as before. In code, this is
Vector3 inverseInertiaTensor;
body->getInverseInertiaTensorWorld(&inverseInertiaTensor);
Vector3 impulsiveTorque = relativeContactPosition % contactNormal;
Vector3 impulsePerMove =inverseInertiaTensor.transform(impulsiveTorque);
This tells us the impulsive torque needed to get one unit of motion. To find the rotation needed to get one unit of movement we simply multiply through by the inertia:
Vector3 rotationPerMove = impulsePerMove * 1/angularInertia;
The rotationPerMove vector now tells us the rotation we need to get one unit of movment. And we know the total movement we want is angularMove, so we know the total rotation to apply is
Vector3 rotation = rotationPerMove * angularMove
Avoiding Excessive Rotation
There are two issues to address with the algorithm presented so far.The first is an assumption that slipped in without being commented on, and the second is a potential problem that can cause instability and odd-looking behavior. Both are related to objects being rotated too much as they are moved out of penetration.
Figure shows an object that has been severely interpenetrated. If the moment of inertia of the object is small but its mass is large, then most of the extraction will be down to angular movement. Clearly, no matter how much angular movement is imposed, the contact point will never get out of the object. The example is extreme, of course, but the problem is very real.
The instant an object begins rotating from an impulsive torque, the contact point will also begin to move. For both issues we need to limit the amount of rotation that can be part of our penetration resolution. Keeping this value small means that our small-rotation assumption is valid, and that we minimize the chance of causing other interpenetrations while resolving one.
We can simply check that the values of angularMove are not too great. If they are, we can transfer some of the burden from them onto the corresponding linearMove component.
Some developers use a fixed amount: not allowing the angular move value to be greater than 0.5, for example. This works well as long as the objects in the simulation are all roughly the same size. If some objects are very large, then a suitable limit for
them may be unsuitable for smaller objects, and vice versa.
It is also possible to express the limit in terms of a fraction of a revolution that the object can make. We could limit the rotation so that the object never turns through more than 45◦, for example. This accounts for differences in size, but it is more complex to work out the equivalent angular move for a specific angle of
rotation. A simple alternative is to scale the angular move by the size of the object (where the size of the object can be approximated by the magnitude of the relative contact position vector). Therefore larger objects can have more angular movement.
☀️
The Collision Resolution Process
I mentioned in the introduction to the book that the
标签:14,objects,object,Collision,contact,impulse,velocity,resolution,linear From: https://www.cnblogs.com/ultramanX/p/18070671