Collision between multiple objects

I am writing a simple physical system for fun, and I ran into a problem that made me stuck.

The basic algorithm is now:

  • Move object
  • Check for conflicts
  • If a collision occurs
    • Move the subject to a minimum distance to resolve the collision.
    • Adjust speed based on normals, masses, etc.

I have one moving body moving towards two, static, massless bodies.

Figure one

The moved object is transferred in one step to collide with one of the bodies.

Figure two

I answer by finding the smallest distance that I can move so that they no longer collide. In this case, this means moving the dynamic body down. However, now he is faced with another field.

Figure three

I repeat the same thing with this field, trying to move the dynamic block so that it no longer collides, but pushes it back into the first square. This is repeated forever. Is my algorithm fundamentally wrong?

+4
source share
2 answers

Instead of moving down once a collision is detected, it would be better to return in the direction you came from . Thus, you have a guarantee that in the end you should be in a state where there are no collisions, assuming that the initial state did not have collisions.

We need to figure out how much we need to reduce (scale) v to place it at the intersection of objects. The abbreviation v will have the correct magnitude, so if we move backward in the -v direction by this magnitude, we will no longer intersect.

Suppose the intersection consists of the x_intersection and a y_intersection . To find out how much we need to move backwards so as not to intersect anymore, we need to scale the original vector v = (v_x, v_y) . If x_intersection is a smaller intersection, then we scale v to x_intersection / v_x and return our object back to -v * x_intersection / v_x . This means that we are returning to -(x_intersection, x_intersection * v_y/v_x) . If y_intersection is a smaller intersection, then we scale v to y_intersection / v_y and move our object back to -v * y_intersection / v_y = -(y_intersection * v_x/v_y, y_intersection) .

So, I would say that the steps in your algorithm could be:

  • Move an object using some displacement vector v
  • Check all conflicts.
  • If a collision occurs

    • For all collision objects, find the minimum scaling v , with which we will need to go back. This scaling can calculate at least two relationships

       given v = (v_x, v_y) min_i = min(x_intersection / v_x, y_intersection / v_y) 
    • Find the minimum scaling ratio for all objects.

       min_o = min(min_i) for all i 
    • Move the object back in the direction of the vector obtained by scaling the direction of negative movement with a minimum ratio. This is v2 = (min_o*-v) , where v2 is the vector we use to move backward.

  • Go back to step 2

For example: first select w :

w

Then select u2 :

u2

Done:

enter image description here

+3
source

One possible solution that can be reliable regarding the problem you described (completely untested):

  • Move object to full time step dt

  • Check for conflicts with other objects, this may be several objects

  • Calculate the “exposure time” by interpolation, which is some real number less than a time step. Do this for each object that you encounter, and select the minimum. This gives you time for the first collision t_col < dt .

  • Repeat the last step, but now move the object only for t_col so that it hits the object precisely and then starts the switching speed and other physics related to the collision. Now you can complete this step if you are lazy (perhaps well, since dt should be small) or continue moving for another dt - t_col and see if you dt - t_col something else.

This is not something that I just invented now, but is similar to the zero-cross detection that Simulink uses to simulate just this kind of intermittent problem.

+1
source

Source: https://habr.com/ru/post/1500194/


All Articles