3

I have recently started playing with the Qt Framework 3D Module. I however was unable to find any good example for animation in C++ most of them being in QML. I am trying to apply an animation I imported from blender( simple cube translation) using the Qt3d animation exporter blender plugin. I however don't know how to handle it. I tried using a QAnimationClipLoader and a QClipAnimator but to be honest I am going basically blind in this. Can anyone help me ? Just in case I added the code I used.

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QBoxLayout>

#include <Qt3DCore>
#include <Qt3DRender>
#include <Qt3DExtras>
#include <Qt3DAnimation>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

//Container window and 3d view
Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
QWidget *container = QWidget::createWindowContainer(view);
QSize screenSize = view->screen()->size();
container->setMinimumSize(QSize(200, 100));
container->setMaximumSize(screenSize);

//Main widget
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(widget);
QVBoxLayout *vLayout = new QVBoxLayout();
vLayout->setAlignment(Qt::AlignTop);
hLayout->addWidget(container, 1);
hLayout->addLayout(vLayout);

//To control input
Qt3DInput::QInputAspect *input = new Qt3DInput::QInputAspect;
view->registerAspect(input);

// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();

// Camera
Qt3DRender::QCamera *cameraEntity = view->camera();

cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
cameraEntity->setPosition(QVector3D(0, 0, 20.0f));
cameraEntity->setUpVector(QVector3D(0, 1, 0));
cameraEntity->setViewCenter(QVector3D(0, 0, 0));

//Light
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
light->setColor("white");
light->setIntensity(1);
lightEntity->addComponent(light);
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
lightTransform->setTranslation(cameraEntity->position());
lightEntity->addComponent(lightTransform);

//Load mesh

Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh();
mesh->setSource(QUrl::fromLocalFile("Data/Models/Wolf_One_obj.obj"));


Qt3DCore::QTransform *meshTransform = new Qt3DCore::QTransform();
meshTransform->setScale(5.f);
//meshTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 0.0f, 0.0f), 45.0f));
meshTransform->setTranslation(QVector3D(-5.0f, 4.0f, -1.5));
Qt3DExtras::QPhongMaterial *wolfMaterial = new Qt3DExtras::QPhongMaterial();
wolfMaterial->setDiffuse(QColor(QRgb(0xa69929)));

Qt3DCore::QEntity *meshEntity = new Qt3DCore::QEntity(rootEntity);
meshEntity->addComponent(mesh);
meshEntity->addComponent(meshTransform);
meshEntity->addComponent(wolfMaterial);

// Sphere shape data
Qt3DExtras::QSphereMesh *sphereMesh = new Qt3DExtras::QSphereMesh();
sphereMesh->setRings(20);
sphereMesh->setSlices(20);
sphereMesh->setRadius(2);

// Sphere mesh transform
Qt3DCore::QTransform *sphereTransform = new Qt3DCore::QTransform();

sphereTransform->setScale(1.3f);
sphereTransform->setTranslation(QVector3D(-5.0f, -4.0f, 0.0f));

Qt3DExtras::QPhongMaterial *sphereMaterial = new Qt3DExtras::QPhongMaterial();
sphereMaterial->setDiffuse(QColor(QRgb(0xa69929)));

//Animation
Qt3DAnimation::QAnimationClipLoader* m_animationClipLoader = new Qt3DAnimation::QAnimationClipLoader(QUrl::fromLocalFile("Data/Animations/simplemove.json"));
Qt3DAnimation::QClipAnimator *m_animator = new Qt3DAnimation::QClipAnimator;
m_animator->setClip(m_animationClipLoader);
m_animator->setLoopCount(3);
m_animator->start();


// Sphere
Qt3DCore::QEntity* m_sphereEntity = new Qt3DCore::QEntity(rootEntity);
m_sphereEntity->addComponent(sphereMesh);
m_sphereEntity->addComponent(sphereMaterial);
m_sphereEntity->addComponent(sphereTransform);
m_sphereEntity->addComponent(m_animator);

// For camera controls
Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
camController->setCamera(cameraEntity);

// Set root object of the scene
view->setRootEntity(rootEntity);


widget->show();
widget->resize(1200, 800);

return a.exec();
}

Hey, I edited the code of the application.It still doesn't work but I made some changes to try and follow the documentation.

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QBoxLayout>


#include <Qt3DCore>
#include <Qt3DRender>
#include <Qt3DExtras>
#include <Qt3DAnimation>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //Container window and 3d view
    Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
    view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
    QWidget *container = QWidget::createWindowContainer(view);
    QSize screenSize = view->screen()->size();
    container->setMinimumSize(QSize(200, 100));
    container->setMaximumSize(screenSize);

    //Main widget
    QWidget *widget = new QWidget;
    QHBoxLayout *hLayout = new QHBoxLayout(widget);
    QVBoxLayout *vLayout = new QVBoxLayout();
    vLayout->setAlignment(Qt::AlignTop);
    hLayout->addWidget(container, 1);
    hLayout->addLayout(vLayout);

    //To control input
    Qt3DInput::QInputAspect *input = new Qt3DInput::QInputAspect;
    view->registerAspect(input);

    // Root entity
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();

    // Camera
    Qt3DRender::QCamera *cameraEntity = view->camera();

    cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    cameraEntity->setPosition(QVector3D(0, 0, 20.0f));
    cameraEntity->setUpVector(QVector3D(0, 1, 0));
    cameraEntity->setViewCenter(QVector3D(0, 0, 0));

    //Light
    Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
    light->setColor("white");
    light->setIntensity(1);
    lightEntity->addComponent(light);
    Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
    lightTransform->setTranslation(cameraEntity->position());
    lightEntity->addComponent(lightTransform);

    //Load mesh

    Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh();
    mesh->setSource(QUrl::fromLocalFile("Data/Models/Wolf_One_obj.obj"));


    Qt3DCore::QTransform *meshTransform = new Qt3DCore::QTransform();
    meshTransform->setScale(5.f);
    //meshTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 0.0f, 0.0f), 45.0f));
    meshTransform->setTranslation(QVector3D(-5.0f, 4.0f, -1.5));
    Qt3DExtras::QPhongMaterial *wolfMaterial = new Qt3DExtras::QPhongMaterial();
    wolfMaterial->setDiffuse(QColor(QRgb(0xa69929)));

    Qt3DCore::QEntity *meshEntity = new Qt3DCore::QEntity(rootEntity);
    meshEntity->addComponent(mesh);
    meshEntity->addComponent(meshTransform);
    meshEntity->addComponent(wolfMaterial);

    // Sphere shape data
    Qt3DExtras::QSphereMesh *sphereMesh = new Qt3DExtras::QSphereMesh();
    sphereMesh->setRings(20);
    sphereMesh->setSlices(20);
    sphereMesh->setRadius(2);

    // Sphere mesh transform
    Qt3DCore::QTransform *sphereTransform = new Qt3DCore::QTransform();

    sphereTransform->setScale(1.3f);
    sphereTransform->setTranslation(QVector3D(-5.0f, -4.0f, 0.0f));

    Qt3DExtras::QPhongMaterial *sphereMaterial = new Qt3DExtras::QPhongMaterial();
    sphereMaterial->setDiffuse(QColor(QRgb(0xa69929)));

    //Animation
    Qt3DAnimation::QAnimationClipLoader* m_animationClipLoader = new Qt3DAnimation::QAnimationClipLoader;
    m_animationClipLoader->setSource(QUrl::fromLocalFile("Data/Animations/simplemove.json"));
    m_animationClipLoader->setEnabled(true);
    Qt3DAnimation::QClipAnimator *m_animator = new Qt3DAnimation::QClipAnimator;
    Qt3DAnimation::QChannelMapping *m_mapping = new Qt3DAnimation::QChannelMapping;
    m_mapping->setChannelName("Location");
    m_mapping->setTarget(sphereTransform);
    m_mapping->setProperty("translation");
    Qt3DAnimation::QChannelMapper *m_channelMapper = new Qt3DAnimation::QChannelMapper;
    m_channelMapper->addMapping(m_mapping);
    m_animator->setClip(m_animationClipLoader);
    m_animator->setLoopCount(3);
    m_animator->setChannelMapper(m_channelMapper);
    //m_animator->start();


    // Sphere
    Qt3DCore::QEntity* m_sphereEntity = new Qt3DCore::QEntity(rootEntity);
    m_sphereEntity->addComponent(sphereMesh);
    m_sphereEntity->addComponent(sphereMaterial);
    m_sphereEntity->addComponent(sphereTransform);
    m_sphereEntity->addComponent(m_animator);

    // For camera controls
    Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
    camController->setCamera(cameraEntity);

    // Set root object of the scene
    view->setRootEntity(rootEntity);
    //Qt3DRender::QObjectPicker *m_objectPicker = new Qt3DRender::QObjectPicker(rootEntity);
    //m_objectPicker->connect(m_objectPicker, SIGNAL(pressedChanged(bool)), m_animator, SLOT(setRunning(bool)));
    widget->show();
    m_animator->setEnabled(true);
    //m_animator->setRunning(true);
    bool test = m_animator->isEnabled();
    m_animator->start();
    widget->resize(1200, 800);

    return a.exec();
}

I also add the .json generated code for reference

{
  "animations": [
    {
      "animationName": "CubeAction",
      "channels": [
        {
          "channelComponents": [
            {
              "channelComponentName": "Location X",
              "keyFrames": [
                {
                  "coords": [
                    0.0,
                    0.0
                  ],
                  "leftHandle": [
                    -0.39041149616241455,
                    0.0
                  ],
                  "rightHandle": [
                    0.39041149616241455,
                    0.0
                  ]
                },
                {
                  "coords": [
                    1.0,
                    0.0
                  ],
                  "leftHandle": [
                    0.6095885038375854,
                    0.0
                  ],
                  "rightHandle": [
                    1.4066786766052246,
                    0.0
                  ]
                },
                {
                  "coords": [
                    2.0416666666666665,
                    0.0
                  ],
                  "leftHandle": [
                    1.6349879900614421,
                    0.0
                  ],
                  "rightHandle": [
                    2.448345343271891,
                    0.0
                  ]
                }
              ]
            },
            {
              "channelComponentName": "Location Z",
              "keyFrames": [
                {
                  "coords": [
                    0.0,
                    -7.051087379455566
                  ],
                  "leftHandle": [
                    -0.39041149616241455,
                    -7.051087379455566
                  ],
                  "rightHandle": [
                    0.39041149616241455,
                    -7.051087379455566
                  ]
                },
                {
                  "coords": [
                    1.0,
                    -0.11975812911987305
                  ],
                  "leftHandle": [
                    0.6095885038375854,
                    -2.7274463176727295
                  ],
                  "rightHandle": [
                    1.4066786766052246,
                    2.596583843231201
                  ]
                },
                {
                  "coords": [
                    2.0416666666666665,
                    6.575384140014648
                  ],
                  "leftHandle": [
                    1.6349879900614421,
                    6.575384140014648
                  ],
                  "rightHandle": [
                    2.448345343271891,
                    6.575384140014648
                  ]
                }
              ]
            },
            {
              "channelComponentName": "Location Y",
              "keyFrames": [
                {
                  "coords": [
                    0.0,
                    0.0
                  ],
                  "leftHandle": [
                    -0.39041149616241455,
                    0.0
                  ],
                  "rightHandle": [
                    0.39041149616241455,
                    0.0
                  ]
                },
                {
                  "coords": [
                    1.0,
                    3.835103988647461
                  ],
                  "leftHandle": [
                    0.6095885038375854,
                    3.835103988647461
                  ],
                  "rightHandle": [
                    1.4066786766052246,
                    3.835103988647461
                  ]
                },
                {
                  "coords": [
                    2.0416666666666665,
                    -0.025578022003173828
                  ],
                  "leftHandle": [
                    1.6349879900614421,
                    -0.025578022003173828
                  ],
                  "rightHandle": [
                    2.448345343271891,
                    -0.025578022003173828
                  ]
                }
              ]
            }
          ],
          "channelName": "Location"
        }
      ]
    }
  ]
}

2 Answers2

1

According to the (shitty) Qt3D documentation of the animation module, you need to assign a QChannelMapper to the channelMapper property of the QClipAnimator that specifies what properties on the target to animate with which keys of the animation.

You can get the idea from this video:

enter image description here

Maybe also keep in mind that the animation runs out of loops if you start it right away. Maybe start it after displaying the 3D view. But this is of course not the main issue here.

Florian Blume
  • 3,237
  • 17
  • 37
  • I changed the code and added the changes made in the original post. Still doesn't work though – Lawliet Darujin May 05 '18 at 11:43
  • From the looks of it, the Qt3DWindow does not add a QAnimationAspect by default. So maybe try to create one and register it with the view. Other than that, you could try the simple animation from here: https://doc.qt.io/qt-5.10/qt3d-simple-cpp-example.html to check whether animations work at all. – Florian Blume May 07 '18 at 11:32
0

I think you should register animation aspect in your main function :

{
    Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
...
    view->registerAspect(new Qt3DAnimation::QAnimationAspect());
...
}

My code that work correctly:

    Qt3DCore::QEntity *createScene()
{
    // Root entity
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;

    //Load mesh

    Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh(rootEntity);
    mesh->setSource(QUrl::fromLocalFile(":/res/egg/egg.obj"));

    Qt3DExtras::QPhongMaterial *wolfMaterial = new Qt3DExtras::QPhongMaterial(rootEntity);
    wolfMaterial->setDiffuse(QColor(QRgb(0xa69929)));

    Qt3DCore::QEntity *meshEntity = new Qt3DCore::QEntity(rootEntity);
    meshEntity->addComponent(mesh);
    meshEntity->addComponent(wolfMaterial);

    Qt3DCore::QTransform *meshTransform = new Qt3DCore::QTransform(rootEntity);

    //Animation
    auto *animator = new Qt3DAnimation::QClipAnimator(meshEntity);
    auto* clip = new Qt3DAnimation::QAnimationClipLoader(
                QUrl::fromLocalFile(":/res/jumpinganimation.json"), animator);

    animator->setClip( clip );


   Qt3DAnimation::QChannelMapping *m_mappingLocation = new Qt3DAnimation::QChannelMapping;
   m_mappingLocation->setChannelName("Location");
   m_mappingLocation->setTarget(meshTransform);
   m_mappingLocation->setProperty("translation");

   Qt3DAnimation::QChannelMapping *m_mappingRotation = new Qt3DAnimation::QChannelMapping;
   m_mappingRotation->setChannelName("Rotation");
   m_mappingRotation->setTarget(meshTransform);
   m_mappingRotation->setProperty("rotation");

   Qt3DAnimation::QChannelMapping *m_mappingScale = new Qt3DAnimation::QChannelMapping;
   m_mappingScale->setChannelName("Scale");
   m_mappingScale->setTarget(meshTransform);
   m_mappingScale->setProperty("scale3D");

   Qt3DAnimation::QChannelMapper *m_channelMapper = new Qt3DAnimation::QChannelMapper;
   m_channelMapper->addMapping(m_mappingLocation);
   m_channelMapper->addMapping(m_mappingRotation);
   m_channelMapper->addMapping(m_mappingScale);

   animator->setLoopCount(Qt3DAnimation::QAbstractClipAnimator::Infinite);
   animator->setChannelMapper(m_channelMapper);

   meshEntity->addComponent(meshTransform);
   animator->setRunning(true);
    return rootEntity;
}

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);
    Qt3DExtras::Qt3DWindow view;

    Qt3DCore::QEntity *scene = createScene();

    // Camera
    Qt3DRender::QCamera *camera = view.camera();
    camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    camera->setPosition(QVector3D(0, 0, 40.0f));
    camera->setViewCenter(QVector3D(0, 0, 0));

    // For camera controls
    Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(scene);
    camController->setLinearSpeed( 50.0f );
    camController->setLookSpeed( 180.0f );
    camController->setCamera(camera);

    //point light 1
    Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(scene);
    Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
    light->setColor("white");
    light->setIntensity(1);
    lightEntity->addComponent(light);
    Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
    lightTransform->setTranslation(camera->position());
    lightEntity->addComponent(lightTransform);


    //point light 2
    Qt3DCore::QEntity *lightEntity2 = new Qt3DCore::QEntity(scene);
    Qt3DRender::QPointLight *light2 = new Qt3DRender::QPointLight(lightEntity2);
    light2->setColor("yellow");
    light2->setIntensity(1);
    lightEntity2->addComponent(light2);
    Qt3DCore::QTransform *lightTransform2 = new Qt3DCore::QTransform(lightEntity2);
    lightTransform2->setTranslation(QVector3D(5.0f, 5.0f, -3.0f));
    lightEntity2->addComponent(lightTransform2);

    view.setRootEntity(scene);
    view.registerAspect(new Qt3DAnimation::QAnimationAspect());
    view.show();

    return app.exec();
}
hassan deldar
  • 293
  • 1
  • 11