Spec-Zone.ru › Qt 6.0

Сцены Qt Quick 3D с 2D-содержимым

2D-элементы в 3D-мире

Qt Quick 3D предлагает эффективный способ создания и отрисовки сцен, объединяющих 3D и 2D элементы.

Что мы подразумеваем под объединённой 3D-2D сценой?

По своей природе объект View3D, представляющий 3D-видовое окно в 2D-сцене, может легко комбинироваться с элементами Qt Quick, такими как Rectangle, Image, Text, расположенными вокруг, под или над элементом View3D, который сам по себе является элементом Qt Quick Item.

Рассмотрим следующий пример:

import QtQuick
import QtQuick3D

Rectangle {
    gradient: Gradient {
        GradientStop { position: 0; color: "steelblue" }
        GradientStop { position: 1; color: "black" }
    }
    Text {
        text: "Hello 2D World"
        font.pointSize: 32
        color: "red"
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
    }
    Item {
        width: 400; height: 400
        anchors.centerIn: parent
        View3D {
            anchors.fill: parent
            environment: SceneEnvironment { backgroundMode: SceneEnvironment.Color; clearColor: "lightGray" }
            PerspectiveCamera { z: 600 }
            DirectionalLight { }
            Model {
                source: "#Cube"
                materials: PrincipledMaterial { baseColor: "green"; metalness: 0.0; roughness: 0.0 }
                eulerRotation: Qt.vector3d(30, 45, 0)
            }
        }
    }
}

Здесь 3D-сцена — это область с серым фоном. Остальная часть окна состоит из 2D-элементов Qt Quick. Они могут перекрывать View3D, но не являются частью 3D-мира, не используют 3D-систему координат и не участвуют в преобразованиях 3D-сцены.

Что если нам нужно разместить 2D-элементы внутри 3D-мира таким образом, чтобы они действительно участвовали во всех 3D-преобразованиях? Например, можем ли мы разместить элементы Rectangle и Text внутри 3D-мира так, чтобы они следовали за вращением куба и всегда располагались над ним?

В следующих разделах мы рассмотрим, как этого можно добиться. Хотя в примере используются Rectangle и Text, можно использовать любой контент Qt Quick, включая Qt Quick Controls, Shape, ShaderEffect, ParticleSystem.

Примечание: Существуют и другие подходы к интеграции 2D-содержимого с 3D-объектами. Добавление 2D-элементов к 3D-узлам позволяет свободно комбинировать 2D и 3D объекты в 3D-мире, но не позволяет отображать 2D-содержимое на поверхности 3D-объекта. Если цель — текстурирование 3D-сетки содержимым, сгенерированным Qt Quick, используйте свойство sourceItem Texture.

2D-содержимое Qt Quick, используемое как карта текстур Элементы Qt Quick в 3D-сцене

Добавление 2D-элементов к 3D-узлам

Ключевым моментом является возможность Object3D принимать в качестве дочерних объектов Item и обрабатывать их особым образом. Object3D — это базовый класс для типа Node. Это означает, что любой Node, а также такие типы, как Model, принимают дочерние элементы Item.

Начиная с Qt 6.0, добавление 2D-элемента к 3D-узлу больше не приводит к отрисовке 2D-содержимого в OpenGL-текстуру, Vulkan-изображение или что-то подобное. Вместо этого, по умолчанию 2D-элементы отрисовываются вместе с остальной частью 3D-сцены в том же пассе отрисовки. К 2D-элементам применяются все 3D-преобразования. Преобразования наследуются от обертывающего Node.

import QtQuick
import QtQuick3D

Rectangle {
    gradient: Gradient {
        GradientStop { position: 0; color: "steelblue" }
        GradientStop { position: 1; color: "black" }
    }
    Text {
        text: "Hello 2D World"
        font.pointSize: 32
        color: "red"
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
    }
    Item {
        width: 400; height: 400
        anchors.centerIn: parent
        View3D {
            anchors.fill: parent
            environment: SceneEnvironment { backgroundMode: SceneEnvironment.Color; clearColor: "lightGray" }
            PerspectiveCamera { z: 600 }
            DirectionalLight { }
            Model {
                Node {
                    y: 150
                    Rectangle {
                        anchors.horizontalCenter: parent.horizontalCenter
                        color: "white"
                        width: text3d.width
                        height: text3d.height
                        Text {
                            id: text3d
                            text: "Hello 3D World"
                            font.pointSize: 32
                        }
                    }
                }
                source: "#Cube"
                materials: PrincipledMaterial { baseColor: "green"; metalness: 0.0; roughness: 0.0 }
                eulerRotation: Qt.vector3d(30, 45, 0)
            }
        }
    }
}

По сравнению с первым фрагментом, у узла Model теперь есть дочерний узел с преобразованием, размещающим его немного над положением куба. 150 относится к центру куба в 3D-пространстве координат.

Model {
    Node {
        y: 150

Затем есть элемент Rectangle. При добавлении его под Node, границы 3D и 2D миров пересекаются внутренне, но это остается прозрачным для разработчика приложения. Невидимый content item генерируется автоматически, позволяя Rectangle ссылаться на parent и выполнять привязку. 3D-преобразование от Node применяется ко всему 2D-поддереву. В примере это означает, что вращение будет соответствовать вращению куба.

Node {
    y: 150
    Rectangle {
        anchors.horizontalCenter: parent.horizontalCenter

Пространства координат в 2D и 3D

2D-элементы по-прежнему используют систему координат Qt Quick: ось Y направлена сверху вниз, а единицы соответствуют пикселям. 3D-узлы, с другой стороны, используют 3D-систему координат: ось Y направлена вверх, а единицы соответствуют сантиметрам, и на них влияет перспективная проекция камеры Camera.

По умолчанию верхний левый угол верхнего элемента размещается в начале координат Node. Это означает, что верхний элемент в 2D-поддереве часто будет задавать привязку, например anchors.centerIn: parent, или, как в примере, привязку горизонтального центра к горизонтальному центру родителя, тем самым центрируя 2D-содержимое по горизонтали над 3D-узлом.

Дополнительные соображения

  • Хотя 2D-элементы отрисовываются вместе с 3D-объектами, они не участвуют в освещении и не будут отбрасывать тени.
  • Обрезка может работать непредсказуемо и должна быть избегаема. Если обрезка необходима для дизайна 2D-элементов, приложение должно явно вернуться к отрисовке в текстуру. Этого можно достичь, добавив layer.enabled: true к верхнему Item под 3D-узлом.
  • Начиная с Qt 6.0, ввод с клавиатуры, мыши и сенсорного экрана не передается 2D-элементам, поэтому они не будут интерактивными.
  • Хотя добавление дерева 2D-элементов в 3D-сцену относительно недорого, следует избегать чрезмерного количества (сотни или более) 2D-поддеревьев внутри 3D-сцены, так как в больших количествах это может привести к увеличению использования памяти и графических ресурсов. Обратите внимание, что это относится к количеству отдельных Item поддеревьев под 3D-узлами, а не к общему количеству 2D-элементов в этих поддеревьях. Например, фрагмент QML выше содержит только одно 2D-поддерево.

См. также Пример Qt Quick 3D - элементы Quick.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qtquick3d-2d.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API