1
\$\begingroup\$

I'm currently making a (basic) physics engine in Python in which I want a polygon to bounce off the ground (\$y=0\$).

When a vertex hits the ground, I apply the (linear) impulse $$\overrightarrow{P}\left(0,\;\frac{-(1+\epsilon)\overrightarrow{n}\cdot\overrightarrow{v}}{\frac{1}{m} + \overrightarrow{n}\cdot\left(I^{-1}(\overrightarrow{r}\times\overrightarrow{n})\right)\times\overrightarrow{r}}\right)$$ (where \$\overrightarrow{n}(0,1)\$ is the normal on the floor, \$\overrightarrow{r}\$ is a vector going from the center of mass to the contact point and \$\epsilon\in[0,1]\$ is an elasticity constant)

In my code:

class POLYGON:
    def bounce(self):
        #Checks whether the polygon is under the ground and rebounces it if necessary

        #Finds the nodes with y <= 0
        low_nodes = []
        for node in self.nodes:
            if node[1] < 0:
                low_nodes.append(node)

        if len(low_nodes) > 0:
            #Translates the polygon above the ground
            lowest_node = low_nodes[np.argmax(low_nodes,axis=0)[1]]
            self.translate([0, (1+restituence_constant)*(-lowest_node[1])])

            #Makes a list of the (linear) velocities of all low nodes
            speed = []
            for node in low_nodes:
                speed.append(self.getLinearVelocity(node))

            for (i,node) in enumerate(low_nodes):
                r = node - self.pos

                ut = -(1+restituence_constant) * speed[i][1]
                lt = 1/self.mass + 1/self.rot_inertia * cross(r[0], r)[1]
                j = ut/lt
                impulse = [0, j/len(low_nodes)]
                self.applyLinearImpulse(impulse, node)

As a side note: I make the list of linear velocities of the nodes in advance because those are influenced by applying impulses.
Also, it is necessary to divide the length of the magnitude of the impulse by the number of 'low nodes'.

When there is only one vertex hitting the ground, this all works fine.
But in the case of an edge-ground collision, I find the impulses to be too small.

When I drop the square with nodes \$(\pm100,\pm100)\$, it doesn't even bounce!
However, when I drop the polygon with nodes \$(\pm10,-100)\$ and \$(\pm100,100)\$ on its 'small side', the impulse ís big enough to make it bounce back.
Therefore, I conclude that the issue is caused by the vertices being too far from the center of mass in the \$x\$-direction.

My question is: how can I resolve this issue?
My first idea was to replace the impulses at the vertices by one linear impulse at the middle of the edge. However, this seems a bit 'hacky' and mathematically incorrect.
Can you please help me out?


EDIT:
To help you understand what I'm saying, I measured the bounce height of some 'truncated triangles'. I worked on a 900pxl high screen and dropped the polygons from the middle (so the bottom nodes were at a height of 350pxl).

enter image description here enter image description here enter image description here enter image description here enter image description here

relative heights (pxl): 150, 144, 72, 14 and 0

I also figured out that this problem occurs because the impulses are too low to flip the velocity.
(Even if I don't divide the impulses by the number of low nodes, they are too weak to lift the square off the ground.)

\$\endgroup\$
  • \$\begingroup\$ Do you have any screenshots in order to better visualize this issue? \$\endgroup\$ – ja72 Jul 31 at 17:30
  • \$\begingroup\$ Added them. Hope it helps ;) \$\endgroup\$ – Jonas De Schouwer Jul 31 at 18:49
  • \$\begingroup\$ They all have the same center of mass (horizontally) and so the pressure applied to a small surface creates more repulsive force than hitting it 'flat on' \$\endgroup\$ – BugSquasher Jul 31 at 21:42
  • \$\begingroup\$ That's not true. And still, the delivered impulse should be strong enough to keep the polygon above the ground. \$\endgroup\$ – Jonas De Schouwer Jul 31 at 21:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.