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.
选择按钮改变
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()
方法。
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
类型。
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()
方法。
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.
文件:
图像: