Converting 2d coordinates to 3d coordinates in Qml qt3d - qt

I have a window size width: 1500 height: 780, I would like to render the 3d object with 2d co-ordinates, giving z=1 as dummy value. Following is the qml code.(If i have to render at x=0,y=0 3d should object should render exactly the same place where the Rectangle in qml renders i.e window coordinates)
Entity {
id: root
property real x: 2.0
property real y: 0.0
property real z: 0.0
property real scale: 1
property var mainCam
property var forwardRenderer
property Material material
components: [ trefoilMeshTransform, mesh, root.material ]
Transform {
id: trefoilMeshTransform
property real userAngle: 900.0
translation:Qt.vector3d(0,1,1)
property real theta: 0.0
property real phi:0.0
property real roll: 0.0
rotation: fromEulerAngles(theta, phi, roll)
scale: root.scale
}
Mesh {
id: mesh
source: "assets/obj/cube.obj"
}
}
The code is exactly the same as wireframe example, including the camera settings. I tried to use the qt3d unproject api in qml but ended up unsuccessfully . Can you please help me with the clue?

Please read this document about How to convert world to screen coordinates and vice versa this is good for understanding some logics.
and also this.
In qt3d I get 3d coordinate by using RayCaster and ScreenRayCaster
it gives you the local position and world position and screen x , y
see this site from kdab and its example
RenderSettings{
//all components that you need like viewport , InputSettings ,...
ScreenRayCaster {
id: screenRayCaster
onHitsChanged: printHits("Screen hits", hits)
}
}
MouseHandler {
id: mouseHandler
sourceDevice: MouseDevice {}
onReleased: { screenRayCaster.trigger(Qt.point(mouse.x, mouse.y)) }
}
function printHits(desc, hits) {
console.log(desc, hits.length)
for (var i=0; i<hits.length; i++) {
console.log(" " + hits[i].entity.objectName, hits[i].distance,
hits[i].worldIntersection.x, hits[i].worldIntersection.y, hits[i].worldIntersection.z)
}
}

Related

QT-QML: How to create image (line) and work on it

I need to create and move an image on Qt but i cannot understand how to do that.
The image is just a line like the following:
The result that I'd like to obtain is to have a line which I can shift right or left (it should continue even outside the canvas for some cm) and color the line(or glowing it white with another background) when I call a function.
To do that im using a qml file in qt and I'm creating this line by using the Canvas object, but it is far away from the image showed before:
Canvas {
id: mycanvas
width: 1000; height: 600
contextType: "2d"
property var l_mez: 273
property var pp: 245
Path {
id: myPath
startX: 100; startY: 300
PathCurve { x: (100+(mycanvas.l_mez/2)); y: (300+mycanvas.pp/2) }
PathCurve { x: 100+(mycanvas.l_mez*3/2)-40; y: 300-mycanvas.pp/2+15 }
PathCurve { x: 100+(mycanvas.l_mez*3/2)+40; y: 300-mycanvas.pp/2+15 }
PathCurve { x: 100+(mycanvas.l_mez*2); y: 300}
PathCurve { x: 100+(mycanvas.l_mez*5/2); y: 300+mycanvas.pp/2 }
PathCurve { x: 100+(mycanvas.l_mez*7/2); y: 300-mycanvas.pp/2 }
}
onPaint: {
var ctx = getContext("2d");
ctx.strokeStyle = "grey";
ctx.path = myPath;
ctx.lineWidth =9
ctx.stroke();
}
The result is :
The question is, how can i properly draw the line on the first image?
I was thinking I could just create the image and import it but then I could not shift it and change the color of the line as I prefer.
Thanks for the help
PathCurve is really overspecifying the curve in your example which is where the waviness is coming from. I would instead use alternating PathLine and PathArc to achieve that look.
Note, you could do this with an image also if you were willing to give up on changing the line color. You can load your sample image above twice and place them next to each other so that they seamless connect. You would place them both inside of one Item and turn on clipping.
Then you translate them both left or right to give the sense of movement. When you get to the far end of the images in either direction you just jump the translation back by the image width and keep going.
It will look seamless and smooth to the user. Especially if you use an XAnimator as those run in a separate thread.

Implementing 3D Shader to 2D Object with Qt?

I am trying to implement the following shader from here:
https://gamedev.stackexchange.com/questions/68401/how-can-i-draw-outlines-around-3d-models
my base is a 2D Image that has preapplied shaders.
I was unsure how to apply this
glDrawBuffer( GL_COLOR_ATTACHMENT1 );
Vec3f clearVec( 0.0, 0.0, -1.0f );
// from normalized vector to rgb color; from [-1,1] to [0,1]
clearVec = (clearVec + Vec3f(1.0f, 1.0f, 1.0f)) * 0.5f;
glClearColor( clearVec.x, clearVec.y, clearVec.z, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
So I didn't, this is what my QML code looks like:
ShaderEffect {
id: outline
anchors.fill: swirls
visible: true
property variant source: swirls
//property variant source: mascot
// first render target from the first pass
property variant uTexColor: swirls
// second render target from the first pass
property variant uTexNormals: swirls
property variant uResolution: Qt.vector2d(960, 640) //screen resolution
property variant delta: Qt.size(0.1 / width, 0.2 / height)
fragmentShader: "qrc:effects/shaders/outline.frag"
layer.enabled: true
layer.effect: OpacityMask {
maskSource: swirls
}
}
I don't know much about normal diffuse maps and have no idea what
in vec2 fsInUV;
is which seems to be important to getting this to work. I am trying to create sprite like outlines around a circle I have made with opacity mask + shaders (it's animated to look like water with shaders)
The original user for the shaders is inactive and I'm not familiar with how QML implements Shaders, as I'm very unfamiliar with Shaders in general.

Connect a slider to control zoom on qml Camera

I am using Camera to take movies.
I want to use a slider to zooming video like zoom of google map.
I've found another Question on SO but the proposed solution works for click whereas I would like to develop a solution for slider.
I wrote code that is not working correctly.
I have not found error, but video size will be very large, then I do not see video.
I try to set digitalZoom for camera but I have this error:
The camera doesn't support zooming. .I know my camera does not support "DigitalZoom" and "OpticalZoom". I want to find a way to zoom in on video taken from camera.
My camera is dino ccd.
Excuse me friends, I can not add comment, I have this error: "You must have 50 reputation to comment".
VideoOutput {
id: viewfinder
source: camera
anchors.fill: parent
focus : true
transform: [
Scale {
id: zoomScale
},
Translate {
id: zoomTranslate
}
]
//Keys.onLeftPressed: viewfinder.seek(viewfinder.position - 5000)
//Keys.onRightPressed: viewfinder.seek(viewfinder.position + 5000)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onClicked: {
var zoomIn = mouse.button === Qt.LeftButton;
zoomScale.origin.x = mouse.x;
zoomScale.origin.y = mouse.y;
}
}
Slider {
id:zoomVideo
orientation: Qt.Vertical
minimumValue: 0
maximumValue: 100
stepSize: 10
onValueChanged: {
zoomScale.xScale = zoomVideo.value
zoomScale.yScale = zoomVideo.value
}
}
}
Are you trying to implement a zoom-in/zoom-out functionality using slider just like a normal mobile camera app does, if yes then consider the below untested code snippet because currently I don't have a machine with Qt IDE installed, but it should help you to understand the concept.
Camera {
id: camera
digitalZoom:zoomSlider.value
//if opticalZoom is supported uncomment below line
//opticalZoom:zoomSlider.value
// rest of your settings
}
VideoOutput {
id: viewfinder
source: camera
anchors.fill: parent
focus : true
}
Slider {
id:zoomSlider
orientation: Qt.Vertical
minimumValue: 0
maximumValue: camera.maximumDigitalZoom //or camera.maximumOpticalZoom
stepSize:camera.maximumDigitalZoom/10 // going through 10 steps
value:1.0 // initial zoom level
anchors{
left:parent.left
leftMargin:5
verticalCenter:parent.verticalCenter
}
}
and also I would like you to have a look at the official documentation for these types.Slider, Camera . If you need further clarifications post comments below.

ListView scrolling animation

I want to implement a scrolling animation for QML ListView. Here is a sample image:
Can anybody advise me for implementing this?
Thank you.
The ViewTransition provides a lot of interesting examples on how to animate a ListView for operations like populate (the transition for the initial items at component creation), add, remove (self-explanatory) as well as other operations.
Given a ListView you define an element Transition for each operation you want to animate. The animation framework can be exploited to create compound animations, by simply combining the basic animations to create the (more or less) complex behaviour you are interested in (see also here for an actual example).
Here a definition for a ListView (the first linked document provides some nice images):
ListView {
// data model, delegate, other usual stuff here...
// transitions for insertion/deletation of elements
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 500 }
NumberAnimation { property: "scale"; easing.type: Easing.OutBounce; from: 0; to: 1.0; duration: 750 }
}
addDisplaced: Transition {
NumberAnimation { properties: "y"; duration: 600; easing.type: Easing.InBack }
}
remove: Transition {
NumberAnimation { property: "scale"; from: 1.0; to: 0; duration: 200 }
NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 200 }
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutBack }
}
}
Finally, note that some behaviours can be obtained by using Shaders and combining animation on the elements and transitions on the delegate/elements of the delegate. A nice example is Tweet Search, in which a shading effect (see [ShaderEffect][5]) on the bar item is combined with a simple Transition on ListView add.
EDIT
Provide a customized scrolling like in the examples requires to take in account the position of the Items inside the ListView. A key to a working solution is to find a way to calculate the current position of the Item inside the visible part of the view and use that value to calculate the appropriate transformation. ListView derives from Flickable which has several useful properties for this purpose.
However, the y property of the Item is referred to the overall height of the content inside the ListView. To have its position w.r.t. the beginning of the visible area we can use the contentY property. A picture is worth a thousand words in this case:
The difference between y and contentY provides a value which can be used to calculate the required transformation factor (maybe in relation to the height of the ListView). Indeed, as the ListView is flicked, the two values and their difference change and so changes the transformation factor for a specific Item.
Such transformation covers only part of the problem. Once the flicking/movement ends the Items animation must be "finished" to make all the visible items usable. For this purpose we can exploit Binding and its when property to activate the finishing animation only when required, i.e. when flicking or dragging ends.
Given all this (boring) introduction, let's take in account the second animation (the simpler one). Here we can use scale to obtain the desired effect. The delegate code inside the ListView looks like the following:
ListView {
id: list
model: 100
spacing: 10
delegate: Rectangle {
id: itemDelegate
property int listY: y - list.contentY // stores the difference between the two values
width: parent.width
height: 50
border.color: "lightgray"
color: "red"
Binding {
target: itemDelegate
property: "scale"
value: 1 - listY / list.height / 2 // the "scale" property accepts values in the range [0, 1]
when: list.moving || list.flicking || list.dragging // ...when moved around
}
Binding {
target: itemDelegate
property: "scale"
value: 1 // flick finished --> scale to full size!
when: !(list.moving || list.dragging) // not moving or dragging any more
}
Behavior on scale {
NumberAnimation { duration: 100; to: 1}
enabled: !(list.flicking || list.dragging) // active only when flick or dragging ends!
}
}
}
The first Binding define the scaling factor on the basis of listY whereas the second one set the scaling to 1 but only when the ListView is not moving. The final Behavior is necessary to smooth the transition to the fully scaled Item.
The third effect can be obtained in a similar fashion with a Rotation:
ListView {
anchors.fill: parent
id: list
spacing: 10
model: 100
delegate: Rectangle {
id: itemDelegate
property int listY: y - list.contentY
property real angleZ: (90 * listY) / list.height // 0 - 90 degrees
transform: Rotation { origin.x: width / 2; origin.y: 30; axis { x: 1; y: 0; z: 0 } angle: angleZ}
//transform: Rotation { origin.x: 0; origin.y: 30; axis { x: 1; y: 1; z: 0 } angle: angleZ} <--- I like this one more!
width: parent.width
height: 50
border.color: "lightgray"
color: "red"
Binding {
target: itemDelegate
property: "angleZ"
value: 0
when: !(list.moving || list.dragging)
}
Behavior on angleZ {
NumberAnimation {duration: 200; to: 0}
enabled: !(list.flicking || list.dragging)
}
}
}
This time I've choosen to (arbitrarily) use only one Binding. The same could have been made for the first example, i.e. we could have written in the first delegate scale: 1 - listY / list.height / 2.
Following a similar approach you can also create the first animation and others. For the first animation I think that combining a Rotation with a Translate should suffice.
After many hours of work, research and #BaCaRoZzo's great help (Thanks #BaCaRoZzo), I finally found the right solution. Just use Component.onCompleted() event handler to run the animation associated with each delegate.
Here is an example, enjoy!
import QtQuick 2.3
ListView {
anchors.fill: parent
id: list
model: 100
cacheBuffer: 50
delegate: Rectangle {
id: itemDelegate
Component.onCompleted: showAnim.start();
transform: Rotation { id:rt; origin.x: width; origin.y: height; axis { x: 0.3; y: 1; z: 0 } angle: 0}// <--- I like this one more!
width: parent.width
height: 50
color: index % 2 === 0 ? "#EEE" : "#DDD"
SequentialAnimation {
id: showAnim
running: false
RotationAnimation { target: rt; from: 180; to: 0; duration: 800; easing.type: Easing.OutBack; property: "angle" }
}
}
}
A PathView displays data from models created from built-in QML types like ListModel and XmlListModel, or custom model classes defined in C++ that inherit from QAbstractListModel.
The view has a model, which defines the data to be displayed, and a delegate, which defines how the data should be displayed. The delegate is instantiated for each item on the path. The items may be flicked to move them along the path.

QML NumberAnimation.duration behaviour

I'm trying to make a player move smoothly towards a destination in QML. I'm using a NumberAnimation to animate the x,y position changes. The NumberAnimation's duration should be proportional to the distance the player has to travel, so that the player moves at the same speed regardless of how far away they are from their destination.
import QtQuick 1.1
Item {
width: 720
height: 720
MouseArea {
anchors.fill: parent
onClicked: {
var newXDest = mouse.x - player.width / 2;
var newYDest = mouse.y - player.height / 2;
var dist = player.distanceFrom(newXDest, newYDest);
// Make duration proportional to distance.
player.xMovementDuration = dist; // 1 msec per pixel
player.yMovementDuration = dist; // 1 msec per pixel
console.log("dist = " + dist);
player.xDest = newXDest;
player.yDest = newYDest;
}
}
Rectangle {
id: player
x: xDest
y: yDest
width: 32
height: 32
color: "blue"
property int xDest: 0
property int yDest: 0
property int xMovementDuration: 0
property int yMovementDuration: 0
function distanceFrom(x, y) {
var xDist = x - player.x;
var yDist = y - player.y;
return Math.sqrt(xDist * xDist + yDist * yDist);
}
Behavior on x {
NumberAnimation {
duration: player.xMovementDuration
// duration: 1000
}
}
Behavior on y {
NumberAnimation {
duration: player.yMovementDuration
// duration: 1000
}
}
}
Rectangle {
x: player.xDest
y: player.yDest
width: player.width
height: player.height
color: "transparent"
border.color: "red"
}
}
My problem can be demonstrated by running the application above and following these steps:
Click on the bottom right hand corner of the screen.
Immediately click in the centre (or closer towards the top left) of the screen.
On the second click (while the rectangle is still moving), it seems that the rectangle's number animation is stopped (which is what I want) but it assumes the position of the destination (not what I want). Instead, I want the animation to stop and the rectangle to assume the position at which it was stopped, then to continue on to the new destination.
The correct behaviour - ignoring that the movement speed becomes disproportional - can be seen by setting both of the NumberAnimation.durations to 1000.
I think that you are looking for SmoothedAnimation. There are only two types of animation that deal nicely with the destination changing before the animation is completed. That is SmoothedAnimation and SpringAnimation. Both of these use the current position and velocity to determine the position in the next frame. Other animation types move the position along a predetermined curve.
Simply changing NumberAnimation to SmoothedAnimation makes your example look correct to me.

Resources