2
votes

I use Box2D as phisics engine and QtQuick as visualizer.

I setted up simple scene with falling small rectangles and platform to test collisions

// the platform block    
Body {
        id: block
        bodyType: Body.Kinematic
        width:200
        height:20
        transformOrigin: Body.Center
        fixtures: Box {
            anchors.fill: parent
            friction: 1
            density: 1
        }
        Rectangle {
            anchors.fill: parent
            color: "yellow"
            border.color: "blue"
        }
        MouseArea {
            anchors.fill: parent
            onClicked: {
                block.rotation += 20
            }
        }
    }

In QML I can set center of rotation:

transformOrigin: Body.Center

By default transformOrigin is top-left corner of object and in this case everything paintet fine. But when i move origin to center in QML it is going wrong as decribed at attached image

http://www.ruslan.pw/box2d.png

This is part of code when it get coords from Box2D and paint QML object

//getting coordination and angle of Box2D object
const b2Vec2 position = mBody->GetPosition();
const float32 angle = mBody->GetAngle();
const qreal newX = position.x * scaleRatio;
const qreal newY = -position.y * scaleRatio;
const qreal newRotation = -(angle * 360.0) / (2 * b2_pi);

// paint QML object at received coords
setX(newX);
setY(newY);
setRotation(newRotation);

The problem is than Box2D rotates object with origin in top-left corner but QML object painted with origin in his center. So QML object is not syncronized with Box2D and falling rectangle painter in wrong place. I maked printscreen but actually box of Box2D is not visible, I added it to understand the problem.

And my question - how can I set origin point in Box2D?

1

1 Answers

1
votes

To keep the code simple, and because qml-box2d is an unfinished library, transformOrigin set to TopLeft (the default for a Body) is currently the only supported value.

However, a Box2D body doesn't need to have a size itself. Only the size of its fixtures is relevant. If you set a 0-size on the body its transformOrigin no longer matters. If you then center the fixture on the body, the rotation of the body effectively applies to the center of the fixture.

I've adapted your simple scene using this approach as follows:

// the platform block    
Body {
    id: block
    bodyType: Body.Kinematic
    fixtures: Box {
        id: boxFixture
        anchors.centerIn: parent
        width:200
        height:20
        friction: 1
        density: 1
    }
    Rectangle {
        anchors.fill: boxFixture
        color: "yellow"
        border.color: "blue"
    }
    MouseArea {
        anchors.fill: boxFixture
        onClicked: {
            block.rotation += 20
        }
    }
}

Of course, ideally qml-box2d would eventually handle all possible values of transformOrigin regardless of the size of the body.