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.
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!