Введение в Qt Quick3D

  • Tutorial
Этот пост участвует в конкурсе „Умные телефоны за умные посты“
Не так давно фреймворк Qt Quick обзавелся дополнением Qt Quick3D, позволяющим полноценно работать с 3D объектами (поддерживается импорт из 3D Max и Blender), совершать над ними различные трансформации, анимации, применять эффекты, ну и вообще по полной использовать возможности лежащего в основе OpenGL. Работает всё это под Symbian, MeeGo, Windows\Linux\MacOs (ну и вообще везде, где Qt есть). В этом топике мы попробуем технологию «на зуб». Писать что-то сложное и серьёзное не хочется, поэтому мы сделаем хабрахолодильник, из которого по клику будет вылетать НЛО.
Сразу результат:


Что нам понадобится


Качаем и устанавливаем Qt Creator, Qt library, Qt Quick3D и Blender. Еще нам понадобятся 3D-модели, которые мы будем использовать. Я взял вот этот холодильник и эту летающую тарелку (всё бесплатное). Ну и логотип Хабра бессовестно стащил.

Поехали


Итак, запускаем Qt Creator и создаём новый проект: Файл->Новый файл или проект->Проект Qt Quick->Интерфейс пользователя на Qt Quick.



Вводим имя проекта, расположения папки, все остальные опции оставляем по-умолчанию.



Новосозданный проект выглядит как-то так:



Оставим пока его в покое.

Подготовка моделей


Открываем Blender и готовим в нём модели, которые мы будем использовать. Я не буду детально описывать работу в Blender (всё-таки, это не по нему урок, да и не спец я в Blender). Вот вкратце, что мы сделаем:
  1. Откроем модели холодильника и НЛО.
  2. Поместим НЛО в холодильник.
  3. Поцепим на холодильник логотип Хабра.
  4. Экспортируем из Blender отдельно НЛО (которое сейчас в холодильнике), дверцу холодильника (она нужна нам отдельно, чтобы её можно было открывать) и его корпус без дверцы. И того у нас должно быть на выходе 4 файла: ufo.3ds, door.3ds, refr.3ds + файл текстуры. Скопируем все эти файлы в папку проекта.


Hello world


Возвращаемся в Qt Creator к нашему проекту. При его создании в файл HabraHolod.qml был записан такой себе «Hello world», но он никакого отношения к Qt Quick3D не имеет, а потому мы его удалим. Начнём писать свой qml-код с нуля. В первой итерации он будет вот таким:
import Qt3D 1.0

Viewport {
    Mesh { id: refrigirator; source: "refr.3ds" }
    Mesh { id: ufo; source: "ufo.3ds" }
    Mesh { id: bottom_door; source: "door.3ds" }

    Item3D { mesh: refrigirator }
    Item3D { mesh: ufo;}
    Item3D { mesh: bottom_door; }
}

Давайте пройдемся по коду. В первой строке мы импортируем пакет Qt3D, который, если Вы всё установили верно, должен найтись и взяться за работу по отображению 3D-объектов. Если же Вы, как и я, что-то на этапе установки запороли (у меня была установлена другая версия библиотек Qt), то вот очень толковая статья, описывающая что и куда нужно положить руками, чтобы всё работало и еще одна, объясняющая как скомпилировать Qt Quick3D вручную.

Далее мы создаём элемент Viewport — это контейнер, в который можно добавлять 3D-объекты и задавать некоторые параметры их отображения (освещение, позицию камеры и т.д.). Дальше мы импортируем 3 наших 3ds-файла (каждый — в отдельный мэш) и создаём 3 элемента Item3D (обратите внимание на их связку с мэшами по свойству id).

Если Вы нажмёте Ctrl+R (запуск), то даже сможете увидеть результат:



Что-то странное, да? :) На самом деле всё работает верно. Всё дело в том, что пока ни окно нашего приложения, ни параметры 3D-сцены не настроены и поэтому мы смотрим на наши объекты в малюсенькое окошко с непонятной позиции. Если Вы вручную сделаете окно побольше и воспользуетесь скролингом, то увидите нашу сцену примерно такой:



Начало неплохое — в 10 строк кода у нас уже есть приложение, кое-как отображающее группу 3D-объектов (а ну-ка, сколько строк будет в нём, если написать его на С++\Java\.NET\Ваш_язык?).

Идём дальше


Итак, объекты наши, конечно, отображаются, но как-то не так, не там и пока не двигаются. Будем это дело понемногу улучшать. Во-первых, добавим в код корневой элемент Rectangle (для этого нам придётся импортировать модуль QtQuick 1.0), который позволит нам задать размер окошка:
import QtQuick 1.0
import Qt3D 1.0

Rectangle {
    color: "black"
    width: 400
    height: 600

    Viewport {
        anchors.fill: parent

        Mesh { id: refrigirator; source: "refr.3ds" }
        Mesh { id: ufo; source: "ufo.3ds" }
        Mesh { id: bottom_door; source: "door.3ds" }

        Item3D { mesh: refrigirator }
        Item3D { mesh: ufo;}
        Item3D { mesh: bottom_door; }
    }
}

Для Rectangle мы задали начальные размеры и цвет, а для Viewport — сказали, что он должен быть растянут на весь размер родителя. Результат:



Окошко верного размера, но смотрим мы на объект всё еще откуда-то снизу. Поправим положение камеры. Для этого задейстуем свойство camera у нашего Viewport:
camera: Camera {
    id: viewCamera
    eye: Qt.vector3d(15,10,40)
    center: Qt.vector3d(-2,10,0)
}

Полный код на данном этапе

Свойство eye определяет, где находится камера, а center — точку, на которую она смотрит. Текущий результат:



А ведь уже неплохо! Если бы мы хотели просто посмотреть на 3D объект в Qt Quick3D — можно было бы на этом и закончить. Но нет! Наша цель — движение.

Обработчик клика


Итак, у нас есть отображающаяся модель холодильника, которая на самом деле 3 модели в одной сцене. Постараемся сделать так, чтобы по клику дверца открывалась и оттуда вылетало НЛО. Прежде всего — обработчик клика. Это просто, добавляем к Viewport элемент MouseArea, растянутый на весь размер родителя. По клику пропишем пока выход (просто чтобы проверить, что работает):
MouseArea {
	anchors.fill: parent
	onClicked: {
		Qt.quit();
	}
}

Полный код на данном этапе

Запускаем, кликаем — программа завершается. Работает.

Трансформации и анимации


Начнем с открывающейся дверки. Для того, чтобы её открыть и закрыть, нам нужно сделать следующие вещи:

1. Создать элемент Rotation3D, описывающий, как именно (вокруг каких осей) будет вращаться некий объект.
Rotation3D {
    id: doorOpen
    angle: 0
    axis: Qt.vector3d(0, 1, 0)
    origin: Qt.vector3d(-3, 0,  0)
}

2. Создать элемент SequentialAnimation, суть которого будет в двух вызовах Rotation3D (один-для открытия дверки, второй — для закрытия) с разными направлениями поворота.
SequentialAnimation { id: doorOpenAndClose;
    NumberAnimation { target: doorOpen; property: "angle"; from: 0; to : -80.0; duration: 800;  easing.type: Easing.OutBounce}
    NumberAnimation { target: doorOpen; property: "angle"; from: -80; to : 0.0; duration: 1200; easing.type: Easing.OutCubic}
            }

3. Привязать элемент Rotation3D к Item3D, соответствующему нашей дверке.
 Item3D { mesh: bottom_door; transform: [doorOpen] }

4. Вызвать из обработчика клика промежуточную функцию, которая запустит анимацию.
MouseArea {
    anchors.fill: parent
    onClicked: {
        fullScene.openDoor();
    }
}
		...
Item3D {
	id: fullScene

	function openDoor()	{
		doorOpenAndClose.loops = 1;
		doorOpenAndClose.start();
	}
	...
}

Полный код на данном этапе

Запускаем, кликаем. Бинго!



Дверца открывается и показывает внутри наше НЛО (пока вполне себе мирно висящее). Задача анимации вылета НЛО один-в-один аналогична открытию дверцы. Поэтому без лишних комментариев финальный код:

import QtQuick 1.0
import Qt3D 1.0

Rectangle {
    color: "black"
    width: 400
    height: 600

    Viewport {
        anchors.fill: parent
        MouseArea {
            anchors.fill: parent
            onClicked: {
                fullScene.openDoor();
            }
        }

        camera: Camera {
            id: viewCamera
            eye: Qt.vector3d(15,10,40)
            center: Qt.vector3d(-2,10,0)
        }

        Item3D {
            id: fullScene
            function openDoor(){
                doorOpenAndClose.loops = 1;
                doorOpenAndClose.start();

                ufoFlyOutAndTeleportBack.loops = 1;
                ufoFlyOutAndTeleportBack.start();
            }

            Mesh { id: refrigirator; source: "refr.3ds" }
            Mesh { id: ufo; source: "ufo.3ds" }
            Mesh { id: bottom_door; source: "door.3ds" }

            Item3D { mesh: refrigirator }
            Item3D { mesh: ufo; transform: [ufoFlyOut]}
            Item3D { mesh: bottom_door;  transform: [doorOpen] }

            // ------------------ Transform + Animations ------------------
            Rotation3D {
                id: doorOpen
                angle: 0
                axis: Qt.vector3d(0, 1, 0)
                origin: Qt.vector3d(-3, 0,  0)
            }

            Rotation3D {
                id: ufoFlyOut
                angle: 0
                axis: Qt.vector3d(0, 3, -1)
                origin: Qt.vector3d(10, 0,  0)
            }

            SequentialAnimation { id: doorOpenAndClose;
                NumberAnimation { target: doorOpen; property: "angle"; from: 0; to : -80.0; duration: 800; easing.type: Easing.OutBounce}
                NumberAnimation { target: doorOpen; property: "angle"; from: -80; to : 0.0; duration: 1200; easing.type: Easing.OutCubic}
            }

            SequentialAnimation { id: ufoFlyOutAndTeleportBack;
                NumberAnimation { target: ufoFlyOut; property: "angle"; from: 0; to : 100.0; duration: 1700; easing.type: Easing.OutCurve}
                NumberAnimation { target: ufoFlyOut; property: "angle"; from: 100; to : 0.0; duration: 0; easing.type: Easing.OutCubic}
            }
        }
    }
}

и еще раз результат:


Все исходники проекта можно взять тут.

Полезные материалы по теме

  1. Представление Qt Quick3D и ссылки на загрузку под разные платформы
  2. Клёвый туториал по созданию модели машинки
  3. Официальная документация по Qt Quick3D
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 58
  • +13
    А симпатично вышло, с холодильничком. И правда, как подумаю, сколько такое писать на чистом С++ — это ужас. Всё, вот прямо завтра сажусь изучать Qt Quick.
    • +2
      Действительно впечатляет, что-то Qt Quick 3D прошел не много мимо меня. Надо бы заняться этим вопросом.
      @tangro спасибо за статью.
      • +2
        Всегда рад оказаться полезным.
      • +1
        Если на Qt3D, на основе которого сделан Qt Quick3D, то больше в 2-3 раза.
        • +1
          Зачем на чистом С++, когда можно подцепить тот же OpenGL? Строчек кода может быть и выйдет немного больше (потратится на всякие декларации и инициализацию переменных), а так все абсолютно идиентично
          • 0
            Мне кажется даже с прицепленным OpenGL будет в несколько раз больше кода. А это время, что, как мы знаем, нынче самый ценный ресурс.
            • 0
              И не близко. В n раз больше будет, сами обработки контекста и окна займут кучу времени и кода.
          • +2
            Спасибо, весьма интересно! А не пробовали запускать на мобильных устройствах? Как там, интересно, с производительностью у QtQuick 3D?
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Извините, реального устройства у меня, к сожалению, пока нет.
              • +2
                >>сколько строк будет в нём, если написать его на С++\Java\.NET\Ваш_язык
                Если написать библиотеку, размером с QtQuick3D — то три :)
                А а деле: синтаксис мне очень понравился. Этакий программирующий JSON
                • +1
                  Да, ты прав, а еще есть прикольный язык Java 3D, очень давно думал по нему написать статью, но кармы не хватает ( Если вдруг произойдет чудо, то обязательно отпишу! Вообще, 3D-технологии — это то, что хоть как-то заставляет меня сидеть днями и программировать ))
                  • +1
                    Плюсанул Вам карму. По идее теперь Вы можете писать в блог Java.
                  • 0
                    >А а деле: синтаксис мне очень понравился. Этакий программирующий JSON

                    «Программирующий JSON» называется JavaScript ;)
                    • 0
                      ECMA-Script, тогда уж.
                      • +1
                        Я исходил из аббревиатуры JSON.
                  • +1
                    Давно хотел попробовать поиграть с OpenGL в Qt, но останавливало то, что там действительно уйма кода на С++ будет. Спасибо огромное за статью, теперь буду более внимательно смотреть в сторону QtQuick и QtQuick 3D.
                    • +1
                      Спасибо, клевая статья.
                      Кстати, а как у QtQuick3D сейчас с производительностью?
                      И еще интересует какой сейчас статус у QtQuick3D. Насколько он функционально полон и чист от багов. Был на секции по нему в этом году на Qt DevDays, но, к сожалению, понял для себя, что слишком мало знаю о 3д, чтобы полностью понимать о чем там говорили (да и уйти пришлось под конец). И как-то в итоге не уловил текущий его статус.
                      • 0
                        Вполне себе рабочая штука, есть сборки под все платформы, производительность нормальная, возможности описаны в статье (и чуть больше можно увидеть на этом видео). Пользуйтесь на здоровье.
                      • +2
                        В принципе, такого же результата можно добиться и с помощью WPF, однако синтаксис QtQuick мне намного приятнее. Спасибо вам за статью — будем экспериментировать )
                        • 0
                          Вот если б во времена появления WPF была такая альтернатива, то я б все-таки выбрал Qt. В WPF 3D очень тяжелая (тут я имел в виду декларативный подход с XAML — не программирование через DirectX).
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • 0
                            ААаааааа, я тоже хочу такого разбора темы моей конкурсной статьи :( Люди, ау, ну сделайте это…
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • 0
                                Дак вы спрашивайте что непонятно. Я все буду рад объяснить более подробно.
                                А то пост написал и как в пустоту, успели даже AccuWeather обсудить, а по теме почти ничего нет.
                            • +1
                              Ваш комментарий на отдельный пост тянет.
                            • 0
                              Эта статья типо копия туториала, который был опубликован у троллей в labs, только на русском и про холодильник. Ну дословно же с тем, что на видео, но только про холодильник… печалька(
                              • +3
                                Ну это как слово «хлеб» с 4 ошибками, когда «пиво» получается. В обеих статьях используется Qt Creator, Qt Quick3D, подготовка моделей в Блендере, QML — ну вот и всего общего. Модели свои, обработка своя, код свой, видео своё. Я прям не знаю, как можно статью по Quick3D написать не похоже на тот туториал. А на него я честно в конце ссылочку дал.
                                • –2
                                  Извиняюсь, ссылку сначала не увидел. Но это не слово «хлеб» с 4мя ошибками в слове «пиво». Это скорее посмотрел туториал, и написал свой, такой же с блекджеком и… нет, просто с блекджеком.
                                  Я прям не знаю, как можно статью по Quick3D написать не похоже на тот туториал.

                                  Идей для туториалов может быть множество. В самом репозитории демок много. Совершенно не обязательно статья должна быть похожей. Здесь, к примеру, человек весьма интересно написал о проблемах.
                                  • 0
                                    Вы правы, что идей много и о проблемах можно писать, но я хотел написать именно вводную статью по технологии. Простую (проще и меньше указанного Вами демо), на русском языке, без углубления в детали (ну зачем новичку сразу рассказывать о косяках с нормалями). Что вышло, то вышло. Не спорю, что можно написать и о другом — но это уже будут другие статьи.
                              • +2
                                AFAIK, Планируется сделать QtQuick 3D штатным модулем Qt 5.x, альфу которого обещают в конце года.
                                labs.qt.nokia.com/wp-content/uploads/2011/05/Qt5.pdf
                                page 5
                                • 0
                                  Логичный шаг.
                                  • +1
                                    да, он будет входить туда
                                    • +1
                                      В репах QtQuick3D видел, что сейчас активно ведется работа по поддержке QML2 в нем.
                                    • –1
                                      Сразу столько статей, сразу Qt Quick такой хороший, как телефон пообещали…
                                      • 0
                                        Он всегда был хороший. Я на нём писать начал, ещё когда он был бетой.
                                        • 0
                                          дык, QtQuick реально хорош (или ты не согласен?), просто не всегда об этом писать хочется (или не всегда есть что), а тут дополнительная стимуляция.
                                          • 0
                                            Завидно? :)

                                            А если по делу, чем конкретно вас не устраивает Qt Quick?
                                            • +1
                                              неправда, статьи не только по квику (хотя он мне и нравится). Что у меня (по внутренностям Харматтана), что у Васса (по НФЦ) темы совсем не связанные с Qt Quick
                                              • –2
                                                Я, вообще-то, люблю Qt Quick и скорее всего подольше многих из вас его знаю, но это просто стыд, когда статьи идут только после обещанного девайса :( За неделю больше, чем за полтора года…

                                                Неужели ради интереса изучения нового и желания поделиться с другими трудно статью написать?..
                                                • +1
                                                  Ну во-первых, не очень хорошо так говорить про людей, которых не знаешь " скорее всего подольше многих из вас его знаю". А во-вторых, далеко не все пишут на хабр, чо. Я по большей части на свой уютный бложек перебрался. Знаю что часть народа сделали также.
                                                  • +3
                                                    Ух ты, будем мериться у кого знания длиннее?
                                                    • +1
                                                      Давайте ;) Нам про QML рассказывали парни из Nokia (специально приезжали демонстрировать) ещё когда он только готовился к выпуску и не был анонсирован публично ;)
                                                      • +1
                                                        Так не честно ;) А кстати это, было примерно когда, я так понимаю, самое начало 2010 или конец 2009 года? А то уже начинает казаться, что QML с нами всегда.
                                                  • +3
                                                    Во-первых, чем для конечного читателя статья на конкурс отличается от статьи «просто так»?
                                                    Во-вторых, у меня вот полсотни статей «просто так», и одна на конкурс. И что?
                                                    • +1
                                                      Я даже не сказал «получше», а вы, товарищи, уже так реагируете!

                                                      Смысл был в том, что я давно с самого начала слежу за интересом к Qt Quick, и вот в такие вот моменты становится обидно, честно!
                                                      • 0
                                                        Ну раз следите, значит должны знать что статей на самом деле много в сети. В том числе и на русском языке. Или вы ограничиваетесь только Хабром?
                                                        • 0
                                                          «Обидно, что статьи появляются только на конкурс! Уж лучше бы вообще тогда не появлялись!» — так, что ли, по-вашему?
                                                          • 0
                                                            Конечно нет, о чем Вы :) Пользы от них не меньше, просто сам факт обязательной материальной мотивации расстраивает меня
                                                            • 0
                                                              Ни один человек не будет делать что-либо без мотивации. Мотивация бывает разная. На Хабре их несколько: 1) карма+рейтинг, 2) значочки в профиле, 3) ППА (программа поощрения авторов), теперь вот ещё и конкурс. Для кого-то достаточно первых, для кого-то нет, поэтому нужны дополнительные.

                                                              Я так понимаю, вы аналогичным образом выступаете против статей, участвующих в ППА? Ну а фигли — ради денег ведь пишут!
                                                              • 0
                                                                У меня мотивация в основном была такая: «Хочешь в чём-то разобраться, попробуй объяснить это другим». Можно добавить в список )
                                                                • 0
                                                                  Разумеется, мой список не полный. В него можно ещё добавить «стремление потешить ЧСВ», «желание потроллить приверженцев чего-либо», «прорекламировать продукт/услуги» и так далее…
                                                                  • 0
                                                                    О, как же это я забыл про ЧСВ и троллинг? :) Надо добавить тоже, да.
                                                    • 0
                                                      Спасибо за статью.

                                                      Из Maya сцены не импортирует, да? Придётся через колладу всё это проворачивать.
                                                      • 0
                                                        Не удержался
                                                        www.youtube.com/watch?v=cmb6pTj67Nk
                                                        • –1
                                                          Как-то оно подозрительно напоминает библиотеку FireMonkey, продвигаемую нынче с Delphi… Случаем, не ею авторы вдохновлялись?
                                                          • +1
                                                            QtQuick появился в задумке задолго до покупки Qt Nokia. QtScript, логическим продолжением коего он является, был в Qt версии с 3й. Анимации разрабатывались 2,5 года назад, как и StateMachine. А FireMonkey, что это вообще такое? Появилась она совсем недавно, на сколько я знаю.

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.