How applied a multiple textures images or one image into a cube in qt 6 with qml?

Hello I am learning Qt 3d in version 6.4.2 using QTCreator and qml and after researching in the official qt documentation and even here in stack overflow I did not find a way to put several images as faces of a cube or one texture image mapped in, I tried using CubeMapTexture but I get an error, I also tried with the material but I couldn't either

here is a minimal code to reproduce

import QtQuick
import QtQuick3D
import QtQuick3D.Effects
import QtQuick3D.Helpers
import QtQuick.Controls
import QtQuick.Layouts

Window {
    id: window
    width: 1280
    height: 720
    visible: true
    title: "Example"
    color: "#848895"

    SplitView {
        id: splitView
        anchors.fill: parent

        View3D {
            id: viewport
            SplitView.fillHeight: true
            SplitView.fillWidth: true
            SplitView.minimumWidth: splitView.width * 0.5
            environment: SceneEnvironment {
                property bool enableEffects: false
                antialiasingMode: SceneEnvironment.MSAA
                antialiasingQuality: SceneEnvironment.High
                lightProbe: Texture {
                    source: "maps/OpenfootageNET_garage-1024.hdr"
                }
                effects: enableEffects ? [bloom, scurveTonemap] : []
                backgroundMode: SceneEnvironment.SkyBox

                SCurveTonemap {
                    id: scurveTonemap
                }
                HDRBloomTonemap {
                    id: bloom
                }
            }

            Node {
                id: originNode
                PerspectiveCamera {
                    id: cameraNode
                    z: 600
                    clipNear: 1
                    clipFar: 10000
                }
            }

            PrincipledMaterial {
                id: basicMaterial
                baseColorMap: CubeMapTexture{
                    source: "maps/side.png"
                }
            }

            Model {
                id: cube
                source: "#Cube"
                materials: basicMaterial
                pickable: true
            }


            OrbitCameraController {
                origin: originNode
                camera: cameraNode
            }

            MouseArea {
                id: pickController
                anchors.fill: parent
                onClicked: function(mouse) {
                    let pickResult = viewport.pick(mouse.x, mouse.y);
                    if (pickResult.objectHit) {
                        let pickedObject = pickResult.objectHit;
                        // Move the camera orbit origin to be the clicked object
                        originNode.position = pickedObject.position
                    }
                }
            }

        }
    }
}

The error using CubeMapTexture is this "Sampler qt_BaseColorMap_sampler expects a 2D texture but the associated texture is a cube map. This will lead to problems." but in other ways I can't put multiple textures in the cube or just one texture and map it.

Upvotes: 0

Views: 511

Answers (1)

Stephen Quan
Stephen Quan

Reputation: 26214

For the Texture consider using sourceItem. That will allow you to use traditional 2D components such as Image as your texture. In my example, I've used SVG images so that I can quickly apply a mixture of vector graphics to my textures. For you, you don't have to limit yourself to using Image as your sourceItem. You can choose, any 2D component, e.g. Item, Rectangle, Text, Label, Canvas, Shape, etc.

      materials: [
           DefaultMaterial {
                diffuseMap: Texture {
                    sourceItem: Image {
                        anchors.centerIn: parent
                        width: 224
                        height: 224
                        source: "Dice1.svg"
                        sourceSize: Qt.size(width, height)
                        cache: false
                    }
                }
            }
        ]

If you use "#Cube", the Material(s) you use will be the same on all 6 sides. If you switch to using 6 "#Rectangle"s, you can use a different material for each rectangle. We can use this technique to create a 6-sided dice. Each face of the dice is rendered with its own SVG image:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D
Page {
    id: page
    background: Rectangle { color: "#848895" }
    header: Frame {
        background: Rectangle { color: "#eee" }
        CheckBox { id: chkLabels; text: qsTr("Labels"); checked: true }
    }
    Node {
        id: standAloneScene
        DirectionalLight { ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) }
        Node {
            id: node
            Repeater3D {
                model: [
                    ["Dice1.svg", 0, 0 ],
                    ["Dice6.svg", 0, 180 ],
                    ["Dice3.svg", 0, 90 ],
                    ["Dice4.svg", 0, -90 ],
                    ["Dice2.svg", 90, 0 ],
                    ["Dice5.svg", -90, 0 ],
                ]
                delegate: Node {
                    eulerRotation.x: modelData[1]
                    eulerRotation.y: modelData[2]
                    Model {
                        source: "#Rectangle"
                        materials: [
                            DefaultMaterial {
                                diffuseMap: Texture {
                                    sourceItem: Item {
                                        anchors.centerIn: parent
                                        width: 224
                                        height: 224
                                        Image {
                                            anchors.fill: parent
                                            source: modelData[0]
                                            sourceSize: Qt.size(width, height)
                                            cache: false
                                        }
                                        Label {
                                            visible: chkLabels.checked
                                            anchors.horizontalCenter: parent.horizontalCenter
                                            anchors.bottom: parent.bottom
                                            anchors.bottomMargin: 10
                                            text: modelData[0]
                                            color: "white"
                                            Rectangle {
                                                anchors.fill: parent
                                                anchors.margins: -5
                                                color: "blue"
                                                border.color: "yellow"
                                                radius: 5
                                                z: -2
                                            }
                                        }
                                    }
                                }
                            }
                        ]
                        z: 50
                    }
                }
            }
        }
        OrthographicCamera {
            id: cameraOrthographicFront
            lookAtNode: node
            y: 800; z: 1000
            property double sc: 300/Math.max(Math.min(page.width, page.height), 1)
            scale: Qt.vector3d(sc, sc, 1)
        }
    }
    View3D {
        anchors.fill: parent
        importScene: standAloneScene
        camera: cameraOrthographicFront
    }
    NumberAnimation {
        target: node
        property: "eulerRotation.y"
        loops: Animation.Infinite
        running: true
        from: 720; to: 0
        duration: 10000
    }
    NumberAnimation {
        target: node
        property: "eulerRotation.x"
        loops: Animation.Infinite
        running: true
        from: 360; to: 0
        duration: 10000
    }
}

// Dice1.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="16" cy="16" r="4" fill="#800"/>
</svg>

// Dice2.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice3.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="16" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice4.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#800"/>
<circle cx="24" cy="8" r="3" fill="#800"/>
<circle cx="8" cy="24" r="3" fill="#800"/>
<circle cx="24" cy="24" r="3" fill="#800"/>
</svg>

// Dice5.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#ccc"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="16" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
<circle cx="24" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice6.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#ccc"/>
<circle cx="8" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="24" cy="16" r="3" fill="#ccc"/>
<circle cx="24" cy="24" r="3" fill="#ccc"/>
</svg>

You can Try it Online!

Upvotes: 1

Related Questions