zzzzrrr wrote:Since the solver is updating position, why also constrain linear velocity? Why not update linear velocity as show on line 13 in the algorithm presented in section 3.1, and also do the same for angular velocity once you solve for the change in orientation?
I simply meant that if you wish to, you can solve at both the position and velocity level in two separate phases, as in Box2D -- this is one possible method to add velocity-level constraints to PBD. This will probably end up being identical to Box2D with NGS position solving.
zzzzrrr wrote:
This is an interesting idea. I also simply measured the angle between the point of contact before and after position correction, which is less work computationally than solving equation (9) with the gradient of C = atan2(d1) - atan2(d0).... Is this not a good method?
I don't understand what you mean by "measured the angle between the point of contact"; is this for friction? Do you mean than, rather than decomposing collision constraints into two axial/linear constraints -- one along the surface normal and the other along the tangent -- you're instead using two polar constraints, i.e distance and angle?
zzzzrrr wrote:
I've been using MPR (
http://code.google.com/p/mpr2d/), to try something new, which gives me the deepest point of penetration (p), the surface point (q) which is closest to
p and the surface normal (n) at this position. Then I use the constraint, C = (p - q) dot n, as shown in section 3.4, to solve for dP and dQ. This actually gives me very good results when bodies have no angular momentum; I can stack many objects (boxes) with very good stability - visually I detect absolutely no bounce....
The main problem with collisions from my experience is that, since position and velocity are coupled, this can add energy -- when you separate penetrating objects you introduce some outward velocity. Since the solver is always moving objects, this means that you can't simply generate collision constraints at the start of the frame (as in Box2D for instance) because later on during solving some new collisions may have been created.
For instance, you'd like your simulation to be something like this:
Code: Select all
Step_Simulation()
{
step world forward in time
find all colliding pairs A,B
for(n iterations)
{
Solve_Joints()
for(each pair): Solve_Collision(A,B)
}
}
However this can cause problems because the solving process can create collisions, which you won't find until next step -- at which points objects are penetrating and pushing them out will add energy to the system.
Something like this will work better:
Code: Select all
Step_Simulation()
{
step world forward in time
for(n iterations)
{
Solve_Joints()
for(each body A)
for(each body B)
if(A collides with B): Solve_Collision(A,B)
}
}
will behave better, however:
a) you're now doing a full pass of collision detection at each solver iteration
b) it's still not a perfect solution, because collisions solved later may violate collisions solved earlier (i.e there may still be some residual penetration at the start of the next frame).
c) you can't use any "all-pairs" collision detection method (which are typically faster than pair-by-pair) since you're moving each pair
c) it's not actually possible to do this (as far as I can tell) if you want to avoid O(n^2) collision tests; since A can be moved after the first B, you basically need to re-query your structure every time you move A.. at least, I haven't found a nice way to use broadphase collision systems. Such a way might exist though, and I'm just missing something.
Currently we're doing this:
Code: Select all
Step_Simulation()
{
step world forward in time
find all *potentially* colliding pairs A,B
for(n iterations)
{
Solve_Joints()
for(each pair):
if(A collides with B): Solve_Collision(A,B)
}
}
This is basically caching the results of broadphase so that the spatial query system (grid, SAP, etc) doesn't have to be recalculated every time an object is moved. However, the "potentially" colliding pairs (in our current implementation, all objects within some distance d of body A are considered potentially colliding with A) are much more numerous than the actually colliding pairs, and you still need to do narrow-phase collision tests before solving. Also you're still not guaranteed to catch all collisions since the solver may still move A more than d during solving, creating un-predicted collisions.
If you're not seeing problems of this sort, I'd be _very_ interesting in learning specifically how you're processing collisions, since this has so far been the #1 pain of position-based methods.
zzzzrrr wrote:
However, once I induce angular momentum and solve for change in orientation, and update angular velocity, resting contacts bounce and vibrate all over the place - there doesn't seem to be any loss in kinetic energy. Is this where friction should come into play?
I'm not sure -- in our case stacks were stable without friction (they would eventually slide/slip apart though), but we're not using proper rigid bodies. I suspect that friction would only help hide whatever the fundamental problem is in this case. Are you modelling bounce/restitution?
We simply decided to forget about bounce and only model totally inelastic collisions to start with, since bounce can always be modelled via gameplay logic (i.e when collision is detected, create a velocity constraint for next frame); in our game the vast majority of objects shouldn't bounce anyway.