Jump to content
  • Advertisement
Sign in to follow this  
Finalspace

Explosive tangent impulses causes extreme rotation

This topic is 1555 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,

 

i got my html5/javascript 2D Sequential-Impulse based physics engine working - yay - but got issues with some weird behaviours :-(

It looks stable, but contacts creates explosive tangent impulses which increases the angular velocity.

 

Here are a video of some stacking circles which shows the weird effect (after forcing the collapse, the circles rotation goes faster and faster.

 

Another video showing the issue on a smaller scale:

 

I nearly use the same approach as box2d - except i added the position correction directly to the velocity bias. The friction code is identical and should be a direct port with one minor difference: i calculate the tangent normal once in the contact initialization - because the normal does not change for each contact/frame.

 

Source for contact solver + initialization:

http://pastebin.com/70pz2YXG

 

No idea what causing these problems. I also tried to use a static/dynamic friction method, but had some more worse effects.

 

Would be really great, if you can help me to identify the issue.

 

Thanks in regards,

Final

Share this post


Link to post
Share on other sites
Advertisement

Looks like a wrong sign issue... maybe you can add debug visuals for the forces involved.

Share this post


Link to post
Share on other sites

I added simple contact force visualization which shows the final accumulated normal and tangent impulses.

 

See the following videos:

 

Should be able to compare your stuff with Box2D Lite.

 

I have already compared the solver stuff and have nearly an identical port now, but with some small differences:

 

box2d:

                contact.velocityBias = this.baumGarte * dtInv * Math.min(0.0, contact.penetration + this.allowedPenetration);
 

my (added negative sign + penetration are switched):

                contact.velocityBias = -this.baumGarte * dtInv * Math.min(0.0, -contact.penetration + this.allowedPenetration);
 

Maybe my contact generation is not correct? For this case, i also created a video to show the contact generation. I love creating videos :D

Share this post


Link to post
Share on other sites

The circle-circle friction seems to be inverted. In the first video you can see, when the circle that gets pushed up falls onto the fast spinning circle, it starts to turn in the wrong direction,

Share this post


Link to post
Share on other sites

After analyzing box2d lite again, i added normal visualization and as i suspected, all normals are always the correct surface normals from the surface.

In my case - sometimes its correct, sometimes its not and i has to do with my contact generation.

 

For example, a simple halfspace and circle contact is created in my system like this:

 

- Get the distance vector between any point on the halfspace (in my case this is the halfspaces center - because its defined as normal * -distance) and the position of the circle.

- Now make a vector projection on the planes collision normal against this distance vector and invert the result

- If this projection is greater than the radius - we create a contact, otherwise not

- Contact point is circle position + planes collision normal * negative projection.

- Penetration is circle radius - projection

- The result contact normal is the inverted plane collision normal (If i use the actual plane normal, the relative velocity projection fails in the solver and the circle falls through the plane. (Even with the basic impulse like this: j = -(1.0 + restitution) * velAlongNormal )

 

I am not sure, what i am doing wrong here.

 

I also double checked my broadphase system which do simply two for loops, the outer goes from zero to the body count. The inner goes from the outer + 1 to the body count - These should create unique pairs always - of course static vs static are skipped as well.

 

Secondly i run the actual contact generation function from a jump table based on the bodies shape type:

        function flipContacts(list, count) {
            if (count > 0) {
                for (var i = list.size()-1; i > list.size()-1-count; i--){
                    var contact = list.item(i);
                    math.vec2MultScalar(contact.normal, contact.normal, -1);
                    var tmp = contact.bodyA;
                    contact.bodyA = contact.bodyB;
                    contact.bodyB = tmp;
                }
            }
            return count;
        }

        function createContactCircleToHalfSpace(a, b, list) {
            var aDef = a.shape;
            var bDef = b.shape;

            var normal = bDef.normal;
            var pos = a.position;
            var pC = b.position;

            var sub = Vec2Pool.get();
            math.vec2Sub(sub, pC, pos);
            var proj = -math.vec2Dot(normal, sub);
            if (proj >= aDef.radius) {
                return 0;
            }

            var contact = list.add();
            contact.bodyA = a;
            contact.bodyB = b;
            contact.penetration = aDef.radius - proj;
            math.vec2MultScalar(contact.normal, normal, -1);
            math.vec2AddMultScalar(contact.contactPoint, pos, normal, -proj);
            return 1;
        }

        function createContactHalfSpaceToCircle(a, b, list) {
            return flipContacts(list, createContactCircleToHalfSpace(b, a, list));
        }

        var contactFunctions = [];

        function addContactFunction(typeA, typeB, func) {
            if (typeof contactFunctions[typeA] == "undefined") {
                contactFunctions[typeA] = [];
            }
            contactFunctions[typeA][typeB] = func;
        }

        addContactFunction(ShapeType.Circle,ShapeType.HalfSpace, createContactCircleToHalfSpace);
        addContactFunction(ShapeType.HalfSpace,ShapeType.Circle, createContactHalfSpaceToCircle);


As you can see, the createContactHalfSpaceToCircle method is called when, bodyA is a halfspace and bodyB is a circle (inverted implementation of createContactCircleToHalfSpace) - therefore i flip the generated contacts (bodyA is bodyB and vice versa + invert the contact normal)

Edited by Finalspace

Share this post


Link to post
Share on other sites

k i think i need to start this from the beginning, therefore i made a really simple one-file javascript demo which shows 2 circles and a plane, with one iteration and accumulation disabled + no tangent impulses or rotations whatever. Seems to be working fine, but the contact normal for plane against circle is just wrong - i need to invert the plane normal as resulting contact normal - otherwise the circle falls through the plane. Why does this happens?

 

http://jsfiddle.net/6egN3/1/

Edited by Finalspace

Share this post


Link to post
Share on other sites

i fixed the flipped plane normal issue - the plane needs to be always the first body, not the circle - the relative velocity was negative all the time.

But now the bodies sinks into each other over time - even its now a port of box2d lite with much simpler geometry.

 

Here you can see the sinking (Takes a while to take place):

http://jsfiddle.net/6egN3/2/

Edited by Finalspace

Share this post


Link to post
Share on other sites

I recommend starting from Box2D *Lite*. Then you can start playing around from a working solution. Regarding the changes you made to Box2D I wonder what problem you try to solve and where you think your solution is better. I personally would only make such changes if it solves a particular problem while not breaking anything else.

Share this post


Link to post
Share on other sites

Its just i want to learn how a physics engine really works (i have bought several books for this), what are the maths behind and understand it in a simple way, so that i can implement it myself. In the last couple of months i looked deep in the box2d and box2d lite source nearly every day, tried to understand and visualize it - if i can visualize something - i can implement it. In the last few years i got highly interested in creating physics simulations, therefore i have read tons of papers, several books, tutorials - to learn all the math/methods behind it and now i am in the process of creating things - of course my final goal is to create a game based on that. But i think you are right, i think i will port box2d lite to javascript (dont like the existing ports) and expand it to my needs.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!