Demonstrates combining Qt Quick and three.js rendering.
The Planets example demonstrates how to implement an application that combines the use of three.js library-based Canvas3D rendering with Qt Quick 2D elements. The example shows the eight planets of our Solar System with the Sun.
The planets are rotating around the Sun based on their orbit at a given time. The rotation starts at 2000 Jan 0.0 UT. The planet positions are calculated based on the formulas found here: http://www.stjarnhimlen.se/comp/ppcomp.html and http://www.davidcolarusso.com/astro/.
The Qt Quick Implementation planets.qml of the example renders the 3D content using Canvas3D type. The type calls
JavaScript code that uses three.js
to initialize, paint, and resize the 3D view.
Canvas3D { id: canvas3d anchors.fill: parent onInitializeGL: { GLCode.initializeGL(canvas3d, eventSource, mainview); } onPaintGL: { GLCode.paintGL(canvas3d); fpsDisplay.fps = canvas3d.fps; } onResizeGL: { GLCode.onResizeGL(canvas3d); } ControlEventSource { anchors.fill: parent focus: true id: eventSource } }
The planet related information is stored into ListModel
. The selection buttons for the planets and the information sheet are created based on the model. The 2D elements, selection buttons and sliders, are
implemented in the QML side.
The selection buttons change the focusedPlanet
property of the mainview. As the property changes the planet information is updated and the camera is animated to the new position. The camera position and the camera
look at point are updated based on values that are animated on QML side.
onFocusedPlanetChanged: { if (focusedPlanet == 100) { info.opacity = 0; updatePlanetInfo(); } else { updatePlanetInfo(); info.opacity = 0.5; } GLCode.prepareFocusedPlanetAnimation(); lookAtOffsetAnimation.restart(); cameraOffsetAnimation.restart(); }
The sliders are used to adjust the rotation speed, the planet size, and the viewing distance. When the slider value changes, JavaScript code is called to adjust the given property. For example, changing the value of the
"Viewing Distance" slider calls the setCameraDistence()
method.
onValueChanged: GLCode.setCameraDistance(value);
The JavaScript side of the implementation, planets.js, is done using a version of three.js
that is ported for Qt
Canvas 3D: three.js.
The initializeGL()
method creates the camera and the scene. It also adds the lights to the scene and creates the planet meshes. The Canvas3D renderer needs to be
created at initialization phase too.
Planet texture maps are Copyright (c) by James Hastings-Trew http://planetpixelemporium.com/planets.html used with permission. To calculate the ring geometry for the
planets with rings, the _RingGeometry()
method from three.xplanets extension is used.
The scene is rendered in paintGL()
method. That is also the place where the positions for all of the planets are calculated. The planets are rotated based on their axial tilt and their sidereal rotation period. In
the paintGL()
method the camera position and look at point are updated based on the focused planet.
For more information on how to use three.js
the documentation is available here: three.js/docs
In order to handle the mouse event in JavaScript code the Canvas3D type has to include the ControlEventSource
type.
ControlEventSource { anchors.fill: parent focus: true id: eventSource }
This type is then passed to the JavaScript code on initialization.
onInitializeGL: { GLCode.initializeGL(canvas3d, eventSource, mainview); }
On JavaScript code in the initializeGL()
method the eventSource
object is saved to a global variable. In this example mouseDown
event is connected to the
onDocumentMouseDown()
method.
eventSource.mouseDown.connect(onDocumentMouseDown);
Based on the mouse position variables passed to onDocumentMouseDown()
method, it's checked if the event takes place on top of a planet or not. The focused planet is changed according to the mouse position.
Files:
Images: