Jump to content
  • Advertisement

Randy Gaul

Member
  • Content count

    386
  • Joined

  • Last visited

Community Reputation

2789 Excellent

2 Followers

About Randy Gaul

  • Rank
    Member

Recent Profile Visitors

8489 profile views
  1. Randy Gaul

    What goes into a "Transform" structure in C/C++?

    Box2D has no scaling because scaling is not useful for a physics engine most of the time. Unity has scaling, because their transform is a general purpose tool to place anything anywhere with any rotate/scaling/translation.
  2. Randy Gaul

    Incorrect angular collision response

    I wrote qu3e, so if you're confused on how something relates to your code snippet, you can just ask here
  3. Randy Gaul

    Incorrect angular collision response

    Your tensors don't look right. You need to use R * I * R^T (or flipped about depending on your notation ordering). The rest more or less looks correct. Be sure to double check it against a known reference code (like Box2D *Lite* or qu3e).
  4. Randy Gaul

    Improving sleep system

    That is correct. Box2D's scheme will not put them to sleep. There are a lot of potential strategies for optimization for the islands not moving much. Caching manifolds or other caching systems can be used to try and skip narrow phase. The island building scheme can maybe be customized in some way to somehow skip non-moving bodies (like the beginning of a domino chain). But I think a caching mechanism would be better suited for this kind of problem, while leaving the island sleeping as a simple algorithm. Just my opinion.
  5. Randy Gaul

    Improving sleep system

    Have you research Box2D's sleep mechanism? The idea is sleep an entire island of bodies by crawling an island graph, and computing the maximum linear/angular velocities. A timers is accumulated while the max are underneath a threshold (one threshold for linear, and one for angular velocity). Once the timer reaches a threshold, the island is put to sleep. Islands are awoken by force events or other user events, and if another collider enters the broadphase bounding shape for any of the island entries.
  6. Randy Gaul

    Modeling restitution

    So I asked Dirk specifically, and he says LCP formulation cannot solve Newton cradle, and this is specifically a well-known topic in literature. I believe he referred to work by Kauffman. Basically affirming what d07RiV and myself were talking about earlier.
  7. Randy Gaul

    Modeling restitution

    If by "this" you meant magically move energy in the system in a realistic manner, then no they definitely can not. But if you meant, it's possible to tune the setup to make a Newton's cradle, then of course that's possible. But the behavior is not a natural emergence that can be easily replicated in other situations...
  8. Randy Gaul

    Modeling restitution

    Well maybe Dirk has an opinion, but I'm pretty sure modern physics engines are just modelling the constraints and calling it "good enough". Since typically in a scene with more than two rigid bodies human intuition isn't actually all that great at noticing situations without a real solution. Sequential impulses, being iterative, can find the minimum even in overdetermined or otherwise not directly solvable situations, making it "look nice" in most situations. Even in real life a newton's cradle can fairly easily start behaving like your webpage simulation, and does not behave perfectly for long. One other thing worth experimenting with, if you have the time, is to use soft contact constraints. Since in real life the balls are not perfectly rigid, maybe you can tune the cradle's soft contact settings and get closer to the behavior you like. Of course this isn't going to get you a general "perfect solution", but could be fun to try. I personally have never implemented a soft contact constraint, so I'm not sure exactly what that would look like.
  9. Randy Gaul

    Modeling restitution

    Yes this is expected. Sequential impulses will smear the velocities across the system in a manner dependent on your order of constraint solving. If you imagine there are four balls, each penetrating equally to their neighbor, and then think of how many different solutions could be valid here, there are infinite. So long as in the next step energy is conserved and the constraints are satisfied, this means the solver converged. The balls may teeter mostly to the left, mostly to the right, or almost all energy could be transferred to strictly an end ball. This sort of thing reminds me of the "pool ball problem". Two pool balls are on a pool table touching tangentially. A third ball with some velocity strikes just between both balls. In a sequential solver one constraint must be satisfied before the other. The order of operations will result in two different solutions. Solving for a "real-life" solution can be difficult as well, since the system formed will be overdetermined with no direct solution.
  10. Randy Gaul

    Modeling restitution

    Would be cool to see a visualization of velocity propagation against different numbers of iterations on the first frame of collision with all spheres. Where has all the velocity gone with one iteration? With ten? With ten thousand? The non-penetration constraints only say that the spheres can not inter-penetrate. It says nothing about where specifically all the energy in the system goes, and there can indeed be many "valid" solutions. Another idea, just to get your cradle looking good: You can try separating the stand-still spheres ever so slightly. This way only one collision is solved in isolation at a time, and will prevent the solver from smearing your energy backwards through the system over many iterations. This might be sort of tricky with discrete collision, but with a continuous stepper should make for a really good looking cradle.
  11. Randy Gaul

    Modeling restitution

    Hmm. In that case maybe you should try the shock propagation idea, where you lock a rigid body after it has been solved. This way you can ensure energy travels through the system in one direction. Otherwise sequential impulses might just spread around the velocity in an unrealistic way. It would be nice to see a graph or visualization of the propagation in any case.
  12. Randy Gaul

    Modeling restitution

    Your problem is likely that velocity is not propagating across the balls within a single timestep. So what happens is you get one collision over one timestep, then a bounce, and so on and so forth. This will quickly lead to many balls bouncing in many directions. In real life velocity can propagate near instantaneously through all balls. You will need to do something like: build a graph of all balls in contact, and iterate many times over this graph while enforcing your constraints. Sequential impulses should be able to converge, so long as you build a system of all balls and let the system propagate velocities over the bodies through many iterations. One trick that most physics engines have used for a while now, is to let rigid bodies penetrate slightly with a slop parameter. This parameter lets the narrow phase detect that two volumes intersect, without forcing the solver to move geometry out of an intersecting configuration. Often times when the configuration is no longer intersecting, internal graph data structure edges are broken, and the system is fragmented, unable to converge globally. Hope this makes sense!
  13. Randy Gaul

    3D Manifold Collision Response

    It might not take you months. If you look carefully in the first link, here is the collision response code. It looks nearly identical in 3D. void Arbiter::PreStep(float inv_dt) { const float k_allowedPenetration = 0.01f; float k_biasFactor = World::positionCorrection ? 0.2f : 0.0f; for (int i = 0; i < numContacts; ++i) { Contact* c = contacts + i; Vec2 r1 = c->position - body1->position; Vec2 r2 = c->position - body2->position; // Precompute normal mass, tangent mass, and bias. float rn1 = Dot(r1, c->normal); float rn2 = Dot(r2, c->normal); float kNormal = body1->invMass + body2->invMass; kNormal += body1->invI * (Dot(r1, r1) - rn1 * rn1) + body2->invI * (Dot(r2, r2) - rn2 * rn2); c->massNormal = 1.0f / kNormal; Vec2 tangent = Cross(c->normal, 1.0f); float rt1 = Dot(r1, tangent); float rt2 = Dot(r2, tangent); float kTangent = body1->invMass + body2->invMass; kTangent += body1->invI * (Dot(r1, r1) - rt1 * rt1) + body2->invI * (Dot(r2, r2) - rt2 * rt2); c->massTangent = 1.0f / kTangent; c->bias = -k_biasFactor * inv_dt * Min(0.0f, c->separation + k_allowedPenetration); if (World::accumulateImpulses) { // Apply normal + friction impulse Vec2 P = c->Pn * c->normal + c->Pt * tangent; body1->velocity -= body1->invMass * P; body1->angularVelocity -= body1->invI * Cross(r1, P); body2->velocity += body2->invMass * P; body2->angularVelocity += body2->invI * Cross(r2, P); } } } void Arbiter::ApplyImpulse() { Body* b1 = body1; Body* b2 = body2; for (int i = 0; i < numContacts; ++i) { Contact* c = contacts + i; c->r1 = c->position - b1->position; c->r2 = c->position - b2->position; // Relative velocity at contact Vec2 dv = b2->velocity + Cross(b2->angularVelocity, c->r2) - b1->velocity - Cross(b1->angularVelocity, c->r1); // Compute normal impulse float vn = Dot(dv, c->normal); float dPn = c->massNormal * (-vn + c->bias); if (World::accumulateImpulses) { // Clamp the accumulated impulse float Pn0 = c->Pn; c->Pn = Max(Pn0 + dPn, 0.0f); dPn = c->Pn - Pn0; } else { dPn = Max(dPn, 0.0f); } // Apply contact impulse Vec2 Pn = dPn * c->normal; b1->velocity -= b1->invMass * Pn; b1->angularVelocity -= b1->invI * Cross(c->r1, Pn); b2->velocity += b2->invMass * Pn; b2->angularVelocity += b2->invI * Cross(c->r2, Pn); // Relative velocity at contact dv = b2->velocity + Cross(b2->angularVelocity, c->r2) - b1->velocity - Cross(b1->angularVelocity, c->r1); Vec2 tangent = Cross(c->normal, 1.0f); float vt = Dot(dv, tangent); float dPt = c->massTangent * (-vt); if (World::accumulateImpulses) { // Compute friction impulse float maxPt = friction * c->Pn; // Clamp friction float oldTangentImpulse = c->Pt; c->Pt = Clamp(oldTangentImpulse + dPt, -maxPt, maxPt); dPt = c->Pt - oldTangentImpulse; } else { float maxPt = friction * dPn; dPt = Clamp(dPt, -maxPt, maxPt); } // Apply contact impulse Vec2 Pt = dPt * tangent; b1->velocity -= b1->invMass * Pt; b1->angularVelocity -= b1->invI * Cross(c->r1, Pt); b2->velocity += b2->invMass * Pt; b2->angularVelocity += b2->invI * Cross(c->r2, Pt); } }
  14. Randy Gaul

    3D Manifold Collision Response

    Would it be enough? Well maybe. You won't have any nice stacking behavior, and you can have some jitter problems. But it is possible to hack around these problems.
  15. Randy Gaul

    3D Manifold Collision Response

    Links in my first post are all about sequential impulses
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!