Display seq 2D images in 3D space with Qml [closed] - qt

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 days ago.
Improve this question
I developed software with python and Qml and I want to display a sequence of 2D images (100 slices) in a 3D space with Qml in this software. I think Qt3D or QtQuick 3D modules are proper for that purpose because the following code displays an image in 3D space but cannot figure out how to display a sequence of images.
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick3D 1.14
Window {
id: window
width: 640
height: 640
visible: true
color: "black"
Rectangle {
id: qt_logo
width: 230
height: 230
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 10
color: "black"
property int angle: 0
layer.enabled: true
Image {
anchors.fill: parent
source: "qt_logo.png"
}
}
View3D {
id: view
anchors.fill: parent
camera: camera
renderMode: View3D.Overlay
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 200, -300)
rotation: Qt.vector3d(30, 0, 0)
}
DirectionalLight {
rotation: Qt.vector3d(30, 0, 0)
}
Model {
id: cube
visible: true
position: Qt.vector3d(0, 0, 0)
source: "#Rectangle"
materials: [ DefaultMaterial {
diffuseMap: Texture {
id: texture
sourceItem: qt_logo
flipV: true
}
}
]
rotation: Qt.vector3d(0, 0, 0)
}
}
}
Edit: I searched a little more and I found the texture3D in the Qt3d module could be a better option for my purpose. But I can't find any example of texture3D in qml. Now the following questions are my problems? 1. How I can generate a texture3D from a stack of 2D images? 2. How I can display a texture3D in qml. 3. Can I generate input data manually for Texture3D (Like 3D array)?
Thank you for your help.

If you're using Texture you can set sourceItem to place any 2D component, including, Rectangle and Image onto a 3D object, such as a "#Cube".
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D
Page {
background: Rectangle { color: "#848895" }
Node {
id: standAloneScene
DirectionalLight { ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) }
Node {
id: node
Model {
source: "#Cube"
materials: [
DefaultMaterial {
diffuseMap: Texture {
sourceItem: MyItem { }
}
}
]
}
}
OrthographicCamera {
id: cameraOrthographicFront
lookAtNode: node
y: 800; z: 1000
}
}
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
}
}
// MyItem.qml
import QtQuick
import QtQuick.Controls
Rectangle {
width: 256
height: 256
color: "#78a"
Repeater {
model: 5
Image {
x: index * 20 + 20
y: index * 20 + 20
width: 128
height: 128
source: "https://stephenquan.github.io/images/qt/madewithqt.png"
}
}
}
You can Try it Online!

Related

QML: Move the rectangle outside the window

Is it possible to move the rectangle outside the window? The only thing I came up with is to write custom logic that will resize the top window when moving the rectangle outside the window.
Current behavior (imgur .gif):
Current behavior
Desired behavior (imgur .png):
Desired behavior
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
id: root
width: 300
height: 500
visible: true
flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WA_TranslucentBackground
color: "#00000000"
Rectangle {
id: draggable
color: "blue"
x: 100
y: 100
width: 100
height: 100
MouseArea {
anchors.fill: parent
property real lastMouseX: 0
property real lastMouseY: 0
onPressed: {
lastMouseX = mouseX
lastMouseY = mouseY
}
onMouseXChanged: {
draggable.x += (mouseX - lastMouseX)
}
onMouseYChanged: {
draggable.y += (mouseY - lastMouseY)
}
}
}
Rectangle {
color: "blue"
x: 100
y: 300
width: 100
height: 100
// ...
}
}
Windows can be children of other Windows. The Window behavior is still subject to certain platform-dependent behavior, but on a Desktop environment child Windows should still be able to move outside the parent Window. So simply changing your Rectangle to be a Window will give you the desired effect.
Window {
id: root
Window {
id: draggable
...
}
}

QML ApplicationWindow zooms in unintentionally and doesn't show all components

So I'm trying to create an application in QML, and doing so by using an ApplicationWindow. The following code is in main.qml, where some of the components are defined in other files (they are not essential for this problem):
import QtQuick 2.12
import QtQuick.Extras 1.4
import QtQuick.Controls 2.5
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.3
import QtDataVisualization 1.3
import Qt3D.Core 2.9
import Qt3D.Render 2.9
import QtCharts 2.3
ApplicationWindow {
id: window
width: 1280
height: 720
//visibility: ApplicationWindow.FullScreen
visible: true
color: "#444444"
Speedometer {
id: speedometer
x: 49
y: 144
width: 306
height: 320
minValue: 0
maxValue: 600
visible: true
}
Thermometer {
id: thermometer
x: 1170
y: 233
scale: 2
minValue: 0
maxValue: 50
visible: true
}
Slider {
id: slider
from: 0
to: 100
x: 28
y: 594
width: 1224
height: 98
font.pointSize: 14
hoverEnabled: false
enabled: false
live: true
snapMode: Slider.NoSnap
value: 0
visible: true
Behavior on value {
NumberAnimation {
duration: 200
}
}
background: Rectangle {
x: slider.leftPadding
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: slider.availableWidth
height: implicitHeight
radius: 2
color: "#999999"
}
handle: Rectangle {
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: "#0099ff"
}
}
Timer {
interval: 200
running: true
repeat: true
property var distance: Math.random
onTriggered: update()
}
function update(){
var distance = (Math.random() * 0.03) + 0.1;
var speed = (distance * 50) / 0.02;
slider.value = slider.value + distance;
speedometer.value = speed;
thermometer.value = Math.random() * 25 + 25;
}
DataManager {
id: manager
onNewVelocity: {
lineSeries.append(velocity.x, velocity.y)
chartView.title = name
}
}
Timer {
id: timer
repeat: true
interval: 1
onTriggered: {
manager.dummyData();
}
}
Chart {
id: chart
height: 250
width: 250
x: 1000
}
Text {
id: labelText
color: "white"
width: 300
height: 100
}
Button {
id: startThread
text: "Start"
onClicked: {
timer.start()
}
}
Button {
id: stopThread
text: "Stop"
x: 200
onClicked: {
timer.stop()
}
}
Button {
id: clearGraph
text: "Clear"
x: 100
onClicked: {
lineSeries.clear()
}
}
}
The content itself isn't that important, but the thing that is, is the fact that when I personally run the project, the application window doesn't show what it is supposed to. And I'd like to emphasize: I'm collaborating with others on this exact project, and when they run the exact same code as me, they get different results.
The first image is what I get when running the code:
The second image is what they get, and what is actually supposed to show when running the code:
So I've been trying to search Google for every possible solution, but have found nothing. I've reinstalled Qt and QtCreator, but to no prevail. We are running the exact same thing, but I'm the only one that don't see all components show up. The first image is way more zoomed in than the latter, and I'd really like if anyone knew how to fix this. I've struggled to find anything that could help so far
(Extra note: the code I ran didn't include the graph as it wasn't up to date with current version on git, but the other things remain the same. So the bar below and the thermometer component on the right SHOULD be visible, but they're not).
I eventually found a solution to what seems to be a bug from Qt's end. I had to launch QtCreator via a qtcreator.bat file in the same directory as qtcreator.exe with the following content:
#echo off
set QT_SCALE_FACTOR_ROUNDING_POLICY=Round
set QT_AUTO_SCREEN_SCALE_FACTOR=0
qtcreator.exe
When I now run the project, it shows the correct scale :)

QML 3D - change size (expand/reduce) of model rendered in UI to fit in the current window

I am rendering a 3D model using Mesh by reading from a .obj file, and I am trying to change its size dynamically to take the parent window's dimensions. Is there a way to resize the object? Currently when I run the app the model takes roughly half the height and one-third of the width of the main-window, and I am not sure where it picks it up from.
I have tried to use viewportRect in ForwardRenderer but that did not change the display. I was also trying to figure out if zooming with the camera would be possible, but from what I saw in the docs the zoom scale factor needs hardcoded integer values and again I need it to be dynamic.
The current display is like this -
Here is my code -
main.qml
Rectangle {
id: rootWindow
color: "black"
Visualizer {}
}
Visualizer.qml
import Qt3D.Core 2.12
import Qt3D.Render 2.12
import Qt3D.Extras 2.12
import Qt3D.Input 2.12
import QtQuick.Scene3D 2.12
import QtQuick 2.12 as QQ2
Scene3D {
id: scene3d
anchors.fill: parent
focus: true
aspects: ["input", "logic"]
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
Entity {
id: sceneRoot
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
nearPlane: 0.1
farPlane: 1000.0
position: Qt.vector3d(0.0, 0.0, 40.0)
upVector: Qt.vector3d(0.0, 1.0, 0.0)
viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
}
FirstPersonCameraController {
camera: camera
}
components: [
RenderSettings {
activeFrameGraph: ForwardRenderer {
camera: camera
clearColor: "transparent"
Viewport {
id: viewport
normalizedRect: Qt.rect(0, 0, 1, 1)
}
}
},
InputSettings {
id: inputSettings
}
]
PhongMaterial {
id: material
}
Mesh {
id: sphereMesh
// source: "images/face3d/face_bse_mesh.obj"
source: "images/robo-obj-pose4/source/d2f0cff60afc40f5afe79156ec7db657.obj"
}
Transform {
id: modelTransform
property real userAngle: 0.0
matrix: {
var m = Qt.matrix4x4()
m.rotate(userAngle, Qt.vector3d(0, 1, 0))
// m.translate(Qt.vector3d(20, 0, 0))
return m
}
}
QQ2.NumberAnimation {
target: modelTransform
property: "userAngle"
duration: 10000
from: 0
to: 360
loops: QQ2.Animation.Infinite
running: true
}
Entity {
id: sphereEntity
components: [sphereMesh, material, modelTransform]
}
OrbitCameraController{
id: orbitCamera
camera: camera
}
}
}
So after a lot of asking around I have found the solution to this. It's a fairly simple enough trick.
You just need to add the following code in the Mesh, and that takes care of resizing the model in it's containing window.
Mesh {
----
onStatusChanged: {
if(status == Mesh.Ready)
camera.viewAll()
}
}
Sometimes while rendering the model its edges tend to go beyond the boundaries of the parent window. Adding some anchors.margins in the root Scene3D usually takes care of that.

How to transform the center of a QQuickItem to a new center

I have a Qt QML application. Following is the complete code of the application:
Code:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: app_main_window
visible: true
width: 800
height: 600
title: qsTr("Hello QML")
Rectangle {
id: my_item_1
x: 100
y: 100
width: 100
height: 100
color: "grey"
visible: true
z: 1
}
Rectangle {
id: my_item_2
x: 400
y: 400
width: 100
height: 100
color: "grey"
visible: true
z: 1
MouseArea {
anchors.fill: parent
onClicked: {
// How can I change the center of my_item_1 to some arbitrary new center. lets say app_main_window's center. this involves another question. how can I get app_main_window's center?
}
}
}
}
Question:
My question is simple. How can change the center of any QQuickitem to a new center? So in above case how can change the center of my_item_1 to a new center (Qt.point(some_x_center, some_y_center)) when my_item_2 gets a click event.
Additionally, is possible to get another item's center? Like app_main_window or my_item_2's center to apply to the target my_item_1?
PS:
I have made the code simple to make the question objective. I have quite a complicated logic in my actual code where I need to realign something like my_item_1 to a new center without usage of anchors as the QQuickitem I am trying to do that with is scaled and panned into a new point.
If anchors can't be used, you have to calculate manually the center and assign it.
Quick example:
Item
{
anchors.fill: parent
Rectangle
{
id: nonParentOrSibling
width: 200
height: 200
x: 350
y: 240
color: "red"
}
}
Rectangle
{
id: rectToMove
width: 100
height: 100
y: 200
color: "blue"
MouseArea
{
anchors.fill: parent
onClicked:
{
var itemCenter = Qt.point(nonParentOrSibling.x + nonParentOrSibling.width / 2, nonParentOrSibling.y + nonParentOrSibling.height / 2)
rectToMove.x = itemCenter.x - rectToMove.width / 2
rectToMove.y = itemCenter.y - rectToMove.height / 2
}
}
}
Note that this is a one time moving only, and the rectangle won't move if the target is moved.
To make it follow the target you have to rebind it with Qt.binding.
If rectToMove is not in the same coordinate system as nonParentOrSibling, you can use Item.mapToItem() and mapFromItem() to adapt the coordinates.

Creating a horizontal Tumbler or circular SwipeView in QML

I'd like to replace a SwipeView with an Tumbler in QML as I prefer the notion, that there is no first and no last Item.
The problem is, I can't find any other way to get this Tumbler tumble horizontally instead of vertically, but to rotate it by -90° and then rotate the Items back by +90°
This is my code so far, and works as expected:
import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
Row {
id: buttons
spacing: 2
Button {
text: '0'
onClicked: tumbl.currentIndex = 0
}
Button {
text: '1'
onClicked: tumbl.currentIndex = 1
}
Button {
text: '2'
onClicked: tumbl.currentIndex = 2
}
Button {
text: '3'
onClicked: tumbl.currentIndex = 3
}
}
Tumbler {
id: tumbl
rotation: -90 // <---- Rotate there
anchors {
top: buttons.bottom
left: buttons.left
right: buttons.right
bottom: parent.bottom
}
model: 4
delegate: Rectangle {
rotation: 90 // <---- Rotate back
color: 'red'
border.width: 15
Text {
anchors.centerIn: parent
text: index
}
}
visibleItemCount: 1
Component.onCompleted: contentItem.interactive = false
}
}
You can see the two lines, in which I do the rotation marked with a comment.
Does anybody know a way to either produce this circular behavior with a SwipeView or to change the tumble-orientation of the tumbler without this rotation trick?

Resources