Here is a summary of what I did in the last two weeks!
- Reviewed theory on separating velocity, restitution, contact normals and impulses in order to implement contact/collision resolution for particles.
- Reviewed resolution of collisions, resolving for both velocity and interpenetration due to collisions.
- Implemented a particle contact resolver which resolves contacts by prioritizing them appropriately.
- Implemented logic for accounting for resting contacts in the contact resolution in order to prevent jittering of particles.
- Implemented contact generators which will queue contacts to the world. Implemented contact generators for rods and cables. Visualized them in a demo with particles connecting a rod and hanging through cables under the influence of gravity.
- Structured and finished the mass-aggregate engine with memory management of particles, force generators and contact generators.
- Reviewed concepts of physics such as Euler angles, axis-angles, quaternions, angular velocity, angular acceleration and center of mass.
- Started working on the architecture of rigid body dynamics.
I had discussed in my previous post that in nature, all collisions are resolved as if they were spring-like forces. However, modelling collision resolution in form of spring like forces isn’t any useful to us as it either produces completely unacceptable results as we cannot implement extremely stiff springs (in case of solids) in any engine. This is where the role of impulse comes in. Till now I have been modelling spring forces which would affect the acceleration of an object, which should in turn affects its velocity and position. However, if we use an impulse instead, I can overcome the issue regarding stiff springs. An impulse a force which acts on a object for a very small time which results in an instantaneous change in velocity. Mathematically, it is the product of the force and the change in time over which it is acting on the object. Furthermore, this is equivalent to the product of mass and change in velocity i.e. change in momentum.
Any collision would be generated in form a objects called Particle contacts which will be resolved by a ParticleContactResolver. A particle contact will have the contact normal and restitution alongwith the particle pointers in its data.
The contact resolver routine iterates through all the contacts produced in a physics update call in order to resolve contacts based on their priority. The priority is decided on which contact has interpenetrating particles with the minimum separating velocity. And contacts are resolved in the order of maximum priority first, since the contact resolver routine has limited number of iterations it may use while resolving contacts in order to have a good performance during the physics update.
Once the resolver routine finds a contact that should be resolved, it calls the resolve method on the ParticleContact. This takes place in form of resolving velocity, followed by resolving of interpenetration. Resolving velocity involves estimation of new velocities based on the separation velocity and coefficient of restitution for the contact. While resolving for interpenetration involves updating of positions accounting for the relative masses of the two particles in order to separate the two particles along the contact normal.
In resolving the velocity for a contact, added additional logic to check if the velocity of the particles in contact are only due to the forces acting on them (such as gravity), if yes then the separating velocity should be 0 since the two participants in the contact are in contact and at rest with respect to one another. The importance of this logic can be visualized in form of a book resting on a table. If the velocity is updated each frame due to contact resolving, then the book would bounce off the table, enter the table and be resolved for interpenetration in the upcoming frames. This jittering can be prevented through this logic.
Contact generators act as collision-like things in a particle system. Logically speaking, the concept of contact normals and interpenetration is kind of absurd for particles. But treating these constraints we can simulate particle pairs which behave as rods, cables, etc.
I have implemented two types of contact generators. Rods and cables. A cable generates a contact if the two particles end up having a distance between them more than the length of the cable. This contact has a inverted contact normal which leads to resolution which pulls the two particles rather than separating them. Similarly, the rod generator generates a contact if the distance between particles is not equal to the length of the rod, also, in this case, the coefficient of restitution for the generated contact is 0, thus resulting in no separating velocity. Hence, there is just a position fix-up based on interpenetration in this case.
Both the contact generators end up queuing the generated contacts to the world which are handled by the contact resolver associated with the world.
Memory Management – Mass Aggregate Engine
The memory taken by the particles, force generators and contact generators are owned by the ParticleWorld.
However, I have implemented logic for the user to have their own preference while working with any of the above. They may choose to delete any of the objects when they want to and they will be unregistered from the world. Thus, the user may create force generators like gravity and forget about them since the world would manage their memory. However, if they choose to delete it at point of time, the world will be notified about the deletion of the force generator.
With the implementation of the memory logic, and changes in the update call for the particle world while accounting for the generated contacts and their resolution, the mass aggregate physics engine has been completed.