Physics - Resolving kinematic collisions (SOLVED)

Hello,

I’m still studying the runner tutorial.

I’ve copied/pasted a bit quickly the collision part, and now i’m returning on it.

The handle_geometry_contact function gave me a hard time.

local function handle_geometry_contact(self, normal, distance)
    -- project the correction vector onto the contact normal
    -- (the correction vector is the 0-vector for the first contact point)
    local proj = vmath.dot(self.correction, normal)
    -- calculate the compensation we need to make for this contact point
    local comp = (distance - proj) * normal
    -- add it to the correction vector
    self.correction = self.correction + comp
    -- apply the compensation to the player character
    go.set_position(go.get_position() + comp)
    -- check if the normal points enough up to consider the player standing on the ground
    -- (0.7 is roughly equal to 45 degrees deviation from pure vertical direction)
    if normal.y > 0.7 then
        self.ground_contact = true
    end
    -- project the velocity onto the normal
    proj = vmath.dot(self.velocity, normal)
    -- if the projection is negative, it means that some of the velocity points towards the contact point
    if proj < 0 then
        -- remove that component in that case
        self.velocity = self.velocity - proj * normal
    end
end

The problem is i don’t understand this function.
For setting the context: I have very poor knowledge in math in general, including geometry.
I know Pythagoras theorem, the trigonometric circle, what is a vector and basic operations with them (matrix transformations, length, dot and vectorial product).

For example, in the code above, i don’t know what is a «0 vector» (for me , it’s … a point).
I understand that it’s a question of computing an angle between two colliding objects (the dot product), but then i’m lost. Is the normal.y test is for testing a fall from a platform ?

What would you recommend to me for acquiring the basis and understanding code like this ? I’ve understood the advantages of kinematics objects over a cinematic (newtonians) objects, for a platformer, at least. But that’s all :slight_smile:

Thank you for reading.

Did you read the kinematic collision section of the physics manual? It goes through this with diagrams and stuff (though the code is slightly different). There’s also a link to it in a sidebar note in the runner tutorial.

The correction vector is how you need to move the character so it’s no longer overlapping any colliding objects. If you look in update, the correction vector gets reset every frame (vmath.vector3() == (0, 0, 0)). The language in the comment is a bit weird, it just means that for the first contact in the current frame, self.correction == (0, 0, 0). You can have multiple contacts per frame, so the business with self.correction ensures that you don’t over-compensate for that. It will not be (0, 0, 0) for the second, third, and fourth contacts, etc.

local proj = vmath.dot(self.correction, normal)

You said you know what dot products are. So this gets the length of self.correction along normal. For the first contact each frame, self.correction is (0, 0, 0), so proj will also be 0. If this is not the first contact this frame, proj will be the distance along normal that has already been compensated for by previous contact calculations.

local comp = (distance - proj) * normal

Without proj, this is just distance * normal, the vector offset of the collision (i.e. how deep * the direction in which the character is overlapping the object). Subtracting proj is just eliminating the overlap between previous correction vectors that happened this frame.

Yup. The normal is the vector perpendicular to a plane’s surface, like a spear you stuck in the ground. It’s normalized, so its length is 1. So, if the Y component of that vector is greater than 0.7 then it’s facing roughly upward—within about 45 degrees of vertical. So any surface contact within that range it will count as a ground contact.

45-degree vector

5 Likes

Well , at first, thank you @ross.grams ! You really helped me a lot understand this !

Of course, i had read the kinematic section of the documentation, but was quite lost in translation :wink:

With your explanations, the vector projection page of Wikipedia and another reading of the Defold kinematic section, i think i have managed to understand.

I was puzzled by the correction vector too, before i’ve understood it’s the vector used for projection of already applied vectors. And then, the projected vector is substracted to the remaining moving vector. And indeed, i didn’t knew that the contact message could be treat several time a frame, you did right to mention it!
I was thinking that only one message could be treated by frame.

Your comment should be added to the tutorial!

Thank you for helping, i’m sure someone else will benefit from you post :slight_smile:

2 Likes

Sounds like the language in that manual could be better. I’ll have a look unless someone wants to push a PR. :slight_smile:

1 Like

Good idea!

1 Like

You can receive multiple messages per frame. There are some very high limits on the number of messages that will be processed each frame, but no message will get lost and they will reach their destinations eventually. As for physics and collision messages you’ll only ever get a single collision_response per frame and one or more contact_point_response, all depending on the nature of the collision and the shapes involved.

1 Like