2D コンテンツによる Qt Quick 3D シーン

3D ワールドの 2D アイテム

Qt Quick 3Dは、3Dと2Dの要素を組み合わせたシーンの効率的な作成とレンダリングを提供します。

3Dと2Dを組み合わせたシーンとはどういう意味でしょうか?

Item本来、View3D オブジェクトは、2D シーン内の 3D ビューポートを表し、View3D アイテムの周り、下、または上に、矩形、画像、テキストなどの Qt Quick アイテムを簡単に組み合わせることができます。

次の例を見てください:

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シーンの変形に関与しません。

3Dワールドの中に2Dアイテムがあり、3Dトランスフォームに参加したい場合はどうすればいいでしょうか?例えば、RectangleText のアイテムが、立方体の回転に従い、常に立方体の上に配置されるように、3Dワールド内に配置することはできるでしょうか?

以下のセクションでは、これを実現する方法を見ていきます。この例では、RectangleText を使用していますが、Qt Quick Controls、ShapeShaderEffectParticleSystem を含む Qt Quick コンテンツは、この方法で使用することができます。

注: 2Dコンテンツと3Dオブジェクトを統合する方法は、他にもあります。3Dノードに2Dアイテムを追加することで、3D世界の2Dオブジェクトと3Dオブジェクトを自由に組み合わせることができますが、3Dオブジェクトの表面に2Dコンテンツをレンダリングすることはできません。Qt Quickで生成したコンテンツで3Dメッシュにテクスチャを貼ることが目的であれば、代わりにTexturethe sourceItem property

テクスチャマップとして使用されるQt Quickコンテンツ3D シーン内の Qt Quick アイテム

3D ノードに 2D アイテムを追加する

Object3D Item Object3D は タイプの基本クラスです。これは、 や、 のような型が、 の子を受け入れることを意味します。Node Node Model Item

Qt 6.0から、3Dノードに2Dアイテムを追加しても、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 が自動的に生成され、矩形はparent を参照し、アンカーリングを行うことができます。ノードからの3D変換は、2Dサブツリー全体に適用されます。この例では、回転が立方体の回転に一致することを意味します。

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

2D と 3D の座標空間

2D アイテムは引き続き Qt Quick の座標系を使用します:Y軸は上から下へ、単位はピクセルです。一方、3Dノードは3D座標系を使用します:Y軸は上を向き、単位はセンチメートルに対応し、Camera の透視投影の影響を受けます。

トップアイテムの左上隅は、デフォルトでノードの原点に配置されます。つまり、2Dサブツリーのトップレベル・アイテムは、anchors.centerIn: parent などのアンカーを指定したり、例のように水平方向の中心を親の水平方向の中心に固定することで、2Dコンテンツを3Dノードの水平方向の中心に配置したい場合がよくあります。

さらなる考慮事項

  • 2Dアイテムは3Dオブジェクトとインラインでレンダリングされますが、ライティングには参加せず、影を落とすこともありません。
  • Clipping が期待通りに動作しない可能性があるため、避けるべきです。2Dアイテムのデザインにクリッピングが不可欠な場合、アプリケーションは明示的にテクスチャへのレンダリングにフォールバックする必要があります。これは、3D ノードの下のトップレベル に を追加することで実現できます。Item layer.enabled: true
  • Qt 6.2では、入力は必要に応じて2Dアイテムに渡されます。ポインティングデバイスからの入力は、宣言されたItemのchildrenRect
  • 3Dシーンに2Dアイテム・ツリーを追加するのは非常に簡単ですが、3Dシーン内に2Dサブツリーを大量に(数百以上)追加するのは避けるべきです。これは、3Dノードの下にあるItem サブツリーの数であり、サブツリー内の2Dアイテムの総数ではないことに注意してください。例えば、上のQMLスニペットには2Dサブツリーが1つしか含まれていません。

Qt Quick 3D - Quick Items ExampleおよびQQuickItem::mapFromGlobal()も参照して ください。

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。