cirosantilli / cirosantilli.github.io

Source for: https://cirosantilli.com and https://ourbigbook.com/cirosantilli Build HTML with https://github.com/ourbigbook/ourbigbook with "npm install && npx ourbigbook ." You can use this issue tracker for anything you want to tell me, even if it is not related to the repo. I also use this repo as generic issue tracker for myself.
https://cirosantilli.com
Creative Commons Attribution Share Alike 4.0 International
42 stars 9 forks source link

Why don't 2D bodies with a ConstraintPrismatic2D collide in Urho3D despite SetCollideConnected(true)? #55

Open cirosantilli opened 4 years ago

cirosantilli commented 4 years ago

https://stackoverflow.com/questions/47782981/why-dont-2d-bodies-with-a-constraintprismatic2d-collide-in-urho3d-despite-setco

For other types of constraints, e.g. ConstraintRope2D, SetCollideConnected(true) has the expected effect.

However, for ConstraintPrismatic2D, I can't make the bodies collide when the constraint is applied.

To test this out, take 5e8a2756db27ff88098cab351822c6f2f1ed9ea9 and hack the sample Source/Samples/32_Urho2DConstraints/Urho2DConstraints.cpp so that the prismatic constraint allows both bodies to touch:

// Create a ConstraintPrismatic2D
CreateFlag("ConstraintPrismatic2D", 2.53f, 3.0f); // Display Text3D flag
Node* boxPrismaticNode = box->Clone();
tempBody = boxPrismaticNode->GetComponent<RigidBody2D>(); // Get body to make it static
tempBody->SetBodyType(BT_STATIC);
Node* ballPrismaticNode = ball->Clone();
boxPrismaticNode->SetPosition(Vector3(3.3f, 2.5f, 0.0f));
ballPrismaticNode->SetPosition(Vector3(3.3f, 2.0f, 0.0f));

ConstraintPrismatic2D* constraintPrismatic = boxPrismaticNode->CreateComponent<ConstraintPrismatic2D>();
constraintPrismatic->SetOtherBody(ballPrismaticNode->GetComponent<RigidBody2D>()); // Constrain ball to box
constraintPrismatic->SetAxis(Vector2(0.0f, 1.0f)); // Slide from [0,0] to [1,1]
constraintPrismatic->SetAnchor(Vector2(3.3f, 2.5f));
constraintPrismatic->SetLowerTranslation(-1.0f);
constraintPrismatic->SetUpperTranslation(0.5f);
constraintPrismatic->SetEnableLimit(true);
constraintPrismatic->SetMaxMotorForce(1.0f);
constraintPrismatic->SetMotorSpeed(0.0f);
constraintPrismatic->SetCollideConnected(true);

Now, the anchor and dynamic bodies can be superposed with the mouse, and they don't collide despite constraintPrismatic->SetCollideConnected(true);.

I have also uploaded a minimalistic test on GitHub: https://github.com/cirosantilli/Urho3D-cheat/blob/e6cc904660fcf89ec558415d7da1f191f38b42f1/prismatic_collide_connected.cpp

Collision works as expected for ConstraintRope2D, which has SetCollideConnected(true); set by default, in the same example if you move the bodies with the mouse.

If I test the same thing on the Box2D testbed, by hacking the Prismatic.h testbed example at f655c603ba9d83f07fc566d38d2654ba35739102 slightly to contain:

#ifndef PRISMATIC_H
#define PRISMATIC_H

// The motor in this test gets smoother with higher velocity iterations.
class Prismatic : public Test
{
public:
    Prismatic()
    {
        b2Body* ground = NULL;
        {
            b2BodyDef bd;
            ground = m_world->CreateBody(&bd);

            b2EdgeShape shape;
            shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
            ground->CreateFixture(&shape, 0.0f);
        }

        {
            b2PolygonShape shape;
            shape.SetAsBox(1.0f, 1.0f);

            b2BodyDef bd;
            bd.type = b2_dynamicBody;
            bd.position.Set(0.0f, 0.0f);
            bd.angle = b2_pi;
            bd.allowSleep = false;
            b2Body* body = m_world->CreateBody(&bd);
            body->CreateFixture(&shape, 5.0f);

            b2PrismaticJointDef pjd;

            // Bouncy limit
            b2Vec2 axis(0.0f, 1.0f);
            axis.Normalize();
            pjd.Initialize(ground, body, b2Vec2(0.0f, 0.0f), axis);

            // Non-bouncy limit
            //pjd.Initialize(ground, body, b2Vec2(-10.0f, 10.0f), b2Vec2(1.0f, 0.0f));

            pjd.motorSpeed = 10.0f;
            pjd.maxMotorForce = 10000.0f;
            pjd.enableMotor = true;
            pjd.lowerTranslation = -20.0f;
            pjd.upperTranslation = 20.0f;
            pjd.enableLimit = true;
            pjd.collideConnected = true;

            m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd);
        }
    }

    void Keyboard(int key)
    {
        switch (key)
        {
        case GLFW_KEY_L:
            m_joint->EnableLimit(!m_joint->IsLimitEnabled());
            break;

        case GLFW_KEY_M:
            m_joint->EnableMotor(!m_joint->IsMotorEnabled());
            break;

        case GLFW_KEY_S:
            m_joint->SetMotorSpeed(-m_joint->GetMotorSpeed());
            break;
        }
    }

    void Step(Settings* settings)
    {
        Test::Step(settings);
        g_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motors, (s) speed");
        m_textLine += DRAW_STRING_NEW_LINE;
        float32 force = m_joint->GetMotorForce(settings->hz);
        g_debugDraw.DrawString(5, m_textLine, "Motor Force = %4.0f", (float) force);
        m_textLine += DRAW_STRING_NEW_LINE;
    }

    static Test* Create()
    {
        return new Prismatic;
    }

    b2PrismaticJoint* m_joint;
};

#endif

then those bodies do obey pjd.collideConnected = true; as expected.

Also asked at: https://discourse.urho3d.io/t/why-dont-2d-bodies-with-a-constraintprismatic2d-collide-in-urho3d-despite-setcollideconnected-true-ask-question/3840