Thursday, June 23, 2016

Stars and DSOs make their appearance in KStars Lite

As the titlte suggests the latest KStars Lite update brings Stars and DSOs into the game!

Current state of KStars Lite

Currently you can see all named and static unnamed stars (also there will be support for Tycho-2 catalog available as an add-on). Having a node for each of the star results in increased memory consumption but I have an idea which I will implement during optimization phase (maintain all nodes in LRU cache and delete nodes that don't get a lot of user attention).

As usual you will find all the changes in gsoc2016-kstarslite branch. New versions of precompiled apks are available in KStars Lite version archive.

What is next?

This week I plan to finish porting Milky Way, Constellation Art, Satellites and Supernovae and proceed to optimization of KStars Lite performance. In this phase I will try to minimize the number of nodes while still maintaining good performance and change logic behind the loading of stars.

Sunday, June 12, 2016

Planet Moons, Lines and Labels in KStars Lite

So it's been a while since my last blog post and KStars Lite has grown since that time getting more and more features from its elder brother KStars. Below you will find a list of changes I've made during this period:

1.Planet moons

This small addition required me to change the structure of PlanetNode. Because moons sometimes have to be drawn in front of the planet there is now PlanetMoonsNode that holds pointer to PlanetNode and a bunch of PointSourceNodes that represent moons. Whenever z-order changes PlanetMoonsNode reorders all nodes in node tree to follow the order.
Jupiter and its moons

 

2. Horizon and Ground

At first sight drawing horizon and ground might seem trivial (I also thought that it is) but it turned out that there is no in-built support for concave polygons neither in OpenGL nor in Qt Quick Scene. And the only way to draw a filled polygon in OpenGL is to convert it to the set of triangles. So I spent some time on finding the best algorithm or library to triangulate the polygon used for drawing ground and decided to use this library (standalone version of tessellator from OpenGL Utility Library (GLU)). It produces perfect results and performs well on both my laptop and Android tablet

 

3. Lines

This is a major part of SkyMapLite. Equator, Ecliptic, Constellation Bounds and Lines, Horizontal Coordinate Grid and Equatorial Coordinate Grid were ported to SkyMapLite. Unfortunately, lines caused significant loss in performance on Android due to a lot of calls to routines that convert equatorial and horizontal coordinates of object to QPoint. There are few ways how we can optimize it (e.g. use SkyMesh to skip checking of lines that are not visible in current sky hemisphere, optimize Projector) it but I decided first to finish porting all components to SkyMapLite and then come back to optimization.
Another trivial problem that turned out to be not so trivial caused Equatorial and Horizontal Coordinate Grids. In KStars they are drawn with dotted lines but Qt Quick Scene Graph doesn't support it. First I tried to use custom shaders but guys from Qt interest mailing list gave me an idea to use QSGVertexColorMaterial to draw different line segments with different color.

 

4. Labels

Another major member of KStars which is now available in SkyMapLite. At first I thought that each SkyNode (e.g. PlanetNode and PointSourceNode) can have its own label as a child node but this way it would be impossible to control the drawing order of labels as other planets or stars can overlap labels. So I created LabelsItem class that holds and updates all labels, which can be instantiated on request to LabelsItem.
Qt Quick Scene Graph doesn't offer tools for drawing text so I decided to store labels as textures. To do that you need to call SkyMapLite::textFromTexture() which will return QSGTexture with the text. This approach has one problem - if we want labels to have different size on different zoom levels than on each zoom change we will need to create a new texture or just resize the texture but I'm already working on this problem.

There are 2 types of labels LabelNode and GuideLabelNode where the latter can be rotated with a given angle but in most cases LabelNode is used.

Also I changed the structure of SkyMapLite and its children. Previously each of SkyComponents was represented with QQuickItem derived class that was reparented to SkyMapLite like SolarSystemSingleComponent -> PlanetsItem. Now I moved everything inside SkyMapLite e.g. PlanetsItem is now derived from QSGOpacity. This way we have only one clipping node and texture cache. The reason I haven't done that before is that rendering of QQuickItem and all another stuff are done in two separate threads that shouldn't intersect. I thought that we might have problems if I will delegate all data work to QSGNodes, but it turns out that multiple clipping nodes cause loss of performance and transition to this scheme was inevitable. Also I haven't faced any problems with this approach yet (it works better and there is much less duplicate code now).

 
 Current state of KStars Lite on desktop

And on my Nexus 7 tablet

What's next?

My next stop is stars and DSOs. If everything goes well I will finish SkyMapLite by GSoC midterm examinations and proceed to optimization of KStars Lite.

Sunday, May 22, 2016

How to build KStars Lite for Android

Intro

 If you want to test KStars Lite without building then download the pre-built .apk file here (API 14, armeabi-v7a). Please, give me the feedback about it if possible (did you manage to run it, was the performance good enough, etc.)

Required dependencies

  • Qt for Android - You can download it here. Later we will point CMake to the folder with Qt libraries compiled for Android.
  • Setup Android environment:
    • Follow the instructions provided here to setup the environment
      • Most probably you will find ant in you distros repositories.
      • I had problems with ant when using OpenJDK but no problems with the latest Oracle JDK (version 8)
  • KF5 for Android - You have to build it yourself using following instructions (you can also find instructions here):
     cd /opt/android  
     git clone git://anongit.kde.org/scratch/cordlandwehr/kdesrc-conf-android.git  
     mkdir -p extragear/kdesrc-build  
     git clone git://anongit.kde.org/kdesrc-build extragear/kdesrc-build  
     ln -s extragear/kdesrc-build/kdesrc-build kdesrc-build  
     ln -s kdesrc-conf-android/kdesrc-buildrc kdesrc-buildrc  
    
    Now open the kdesrc-buildrc file in any text editor and change the following lines:
    1. line 15: -DCMAKE_PREFIX_PATH= "path to Qt5 Android libraries. Example: /home/polaris/dev/Qt5.6.0/5.6/android_armv7"
    2. Line 42 "use-modules..." : If you want to save some time then comment it with # and add after it "use-modules kconfig ki18n kplotting". Thus only modules needed by KStars Lite will be built.

    Now set environment variables and run the script:
     export ANDROID_NDK="Your path to Android NDK folder"
     export ANDROID_SDK_ROOT="Your path to Android SDK folder"
     export Qt5_android="path to Qt5 Android libraries. Example: /home/polaris/dev/Qt5.6.0/5.6/android_armv7"
     export PATH=$ANDROID_SDK_ROOT/platform-tools/:$PATH
     export ANT="path to your ant installation (/usr/bin/ant on Ubuntu)"
     export JAVA_HOME="path to your JDK (choose from the folders at /usr/lib/jvm/ on Ubuntu)
     ./kdesrc-build libintl-lite extra-cmake-modules frameworks-android  
    

    Note: It is important to have libintl-lite as a first parameter. I spent some time on figuring out that it is not built if I don't specify it explicitly. It is a dependency of KI18n without which it won't be built!
    Note 2: All the environment variables set here will be used for compiling KStars Lite so please make sure that they are set before proceeding further.

Building instructions

  • Go to your KStars source folder and set the path to source directory:
     export kstars_DIR=`pwd`  
    
  • Create in a desired location 2 folders - build for final build and export for files that will be included in apk along with the code (textures, data, icons etc.). After that set env. variable for export
     cd export
     export kstars_PRODUCT_DIR=`pwd`
  • Now run CMake to configure make files:
    I use ccmake to see which parameters are missing
     ccmake "${kstars_DIR}" 
    /opt/android is a location where you downloaded and built KF5 for Android
     -DCMAKE_TOOLCHAIN_FILE=/opt/android/kde/install/share/ECM/toolchain/Android.cmake
     -DCMAKE_BUILD_TYPE=Release
     -DCMAKE_PREFIX_PATH="${Qt5_android}"
     -DCMAKE_INSTALL_PREFIX="${kstars_PRODUCT_DIR}" 
     -DQTANDROID_EXPORTED_TARGET=kstars
     -DANDROID_APK_DIR="${kstars_DIR}"/apk 
     -DBUILD_KSTARS_LITE=ON
     -DKF5Config_DIR=/opt/android/kde/install/lib/cmake/KF5Config/ 
     -DKF5Plotting_DIR=/opt/android/kde/install/lib/cmake/KF5Plotting/
     -DKF5I18n_DIR=/opt/android/kde/install/lib/cmake/KF5I18n
    Now this is important as you wont' be able to compile config file if you set this wrong. Use the path to KF5ConfigConfig.cmake on your system. This is needed to use host system kconfig_compiler rather than the Android version.
     -DKF5_HOST_TOOLING="Path to KF5Config cmake files e.g. /usr/lib/x86_64-linux-gnu/cmake/"
    Optional: Set Android API. By default is 14. Set if your want to compile for specific Android version (e.g. API level 9 for devices >= 2.3.1)
     -DANDROID_API_LEVEL=14
    Obviously cmake has to be executed in one line with all the parameters but without comments
  • Compile KStars Lite by executing:
     make
  • You think we are done? Not yet :) Now we have to create apk file and bundle all resources in it.

    Allow inclusion of all extra files in apk
     make install/strip
     make create-apk-kstars
  • Your apk is in "build/kstars_build_apk/bin/" with the name "QtApp-debug.apk"
  • If you want to install it to your device from your PC do the following:
    • Check that your device has USB debugging switched on and connect it via USB to your machine.
    • Make sure that adb is installed (or use one from android-sdk-linux/platform-tools/adb) and run:
       adb install -d kstars_build_apk/bin/QtApp-debug.apk
    Well, that's it! You now should have KStars Lite apk file. If you want to compile KStars Lite for desktops just pass -DBUILD_KSTARS_LITE=ON to cmake and enjoy it :)

    Saturday, May 21, 2016

    KStars Lite comes to Android

    Let's start this post by watching two videos :) I have finally got KStars Lite working on Android.


    Sorry for bad quality, but it seems to be everything my old smartphone is capable of.
    And here comes the corresponding screen video! (Don't forget to set 720p)



    As you can see there are a lot of things to do - pinch to zoom right now works as scrolling with wheel, so I need to tweak it a bit. Interface will be changed completely and right now it is just my proposal prototype. Loading of files seems to take more time than on my laptop, but I'm happy to see that with asteroids and comets it still performs well on tablet (need to try it on other devices).

    And now I will tell you a small story about what has been done since the previous my post and how did I compile Android version:

    1. All nodes that are responsible for drawing graphics are now reparented to the class RootNode (later there may be used its subclasses for the same purpose). RootNode handles QSGTexture generation for stars and also clipping. The problem with clipping was that in QtQuick Scene Graph you can't draw ellipse as OpenGL draws everything in triangles. To do it I found C++ triangulation algorithm implementation specifically tailored for QQuickItem, but it was designed to handle all kinds of polygons so it required a lot of resources and made SkyMapLite really slow. Later I found much simpler solution: choose some corner (in the case of ellipse any its point) and create a triangle from this point to the next 2 points. Simple but works perfectly.
    2. Added asteroids and comets. To do it I changed the structure of nodes a bit. So now there are 2 types of SkyNodes - PlanetNode and PointSourceNode. Both of them reflect to SkyPainter's functions drawPlanet and drawPointSource. For all objects in PlanetItem and some of the objects in AsteroidsComet PlanetNode is used, while CometsItem uses only PointSourceNode to draw comets as stars. After adding asteroids and comets performance didn't fall down. I even tried to draw all of them as bright stars without any checkings on magnitude/zoom level and everything worked well.
    3. Android build - well, that is a long story :) Initially I thought about it as something easy to do and haven't even included to my tentative timeline in proposal, but I was totally wrong. First there was a problem with KF5 dependencies because less than a half of KF5 modules are available for Android.
      My mentor, Jasem Mutlaq, made a great thing and got rid of KIO dependency, without which I was able to compile Android version. Even after that it didn't work and I got only a black screen. I spent a lot of time trying to setup debugger as you can't debug CMake project for Android from Qt Creator. The only feedback from my tablet that I am able to get now is looking at log output (which seems to be sufficient as all major errors are there).
      After spending a plenty of time on searching for a cause of black screen, I found out that "include(KDECompilerSettings NO_POLICY_SCOPE)" in top CMakeLists.txt file seems to cause the error. Without it everything worked fine, but still I had to tackle a few minor bugs before I was able to see SkyMapLite on my tablet.
      I also started to work on pinch to zoom as you can see from my video. 
    You will find instructions on how to compile KStars Lite for Android in my next post (which will be published tomorrow I hope). For now, I will run Android build in various Android emulators to see whether it works fine everywhere and then I will port PlanetMoons to KStars Lite. Stay tuned!

    Sunday, May 8, 2016

    Starting from the shore of cosmic ocean

    This week I made the first commit to KStars Lite branch (gsoc2016-kstarslite). This commit includes everything that I made during my first week of coding:
    1.   My mentor and I agreed that code for KStars Lite will be included to the main branch using #ifdef KSTARS_LITE macro condition. Though this solution is not beautiful the amount of code duplication is significantly reduced this way. However, some of the functionality still needs separate classes so I created KStarsLite(KStars), SkyMapLite(SkyMap) and a bunch of new classes for handling planets. The only modification to KStarsData was to add parameter name in signal void progressText ( const QString& text ); because in QML you can't handle unnamed signal parameter.
    2. KStarsLite - It initializes SkyMapLite and KStarsData. Apart from the code for SkyMapLite instantiation most was copied from KStars because of the same functionality.
    3. SkyMapLite - The pan and zoom functions were copied from SkyMap. Added functionality for displaying and updating SolarSystemSingleComponent on SkyMapLite. Moved cache for star images from SkyQPainter to this class. Currently, only LambertProjector is available because I wait for an answer from KStars community whether I can move Projection enum from SkyMap to Projector class so I can use it in SkyMapLite without including skymap.h
    4. Added support for displaying planets on SkyMapLite. Like in SkyMap, the planets can be drawn either as stars (using cached star images) or as planet images. Apart from storing star images in the cache, we can cache QSGTexture objects that are created from images. So with my initial approach where each planet has its own QQuickItem derived object I wouldn't be able to use cached QSGTextures for all planets. Finally I ended up with the following:
      1. PlanetNode that holds an image of star and image of planet
      2. PlanetItemNode that stores all PlanetNodes, creates QSGTexture objects from cached star images and caches it upon its creation. 
      3. PlanetItem - QQuickItem derived class that holds pointers to SolarSystemSingleComponent objects, displays all nodes and is a visual child of SkyMapLite.
      4. Every SolarSystemSingleComponent upon its creation calls SkyMapLite::addPlanetItem(SolarSystemSingleComponent* ) to add PlanetNode in PlanetItemNode. Based on zoom level PlanetNode hides and shows picture of planet or star image. It turns out that this approach won't be so complicated as I thought about it. To make some things clear to me I asked a few questions on Qt Interest mailing list.
    5. Moved Splash screen to QML. Splash screen might be later replaced by full screen version that is more suitable to different screen sizes of mobile devices.
    Only planets are currently displayed. (Click to zoom)

    Next thing to do

    Right now I struggle to make Options class available for use from QML because for some reason I get an error while compiling config files with support for QML so I wrote an e-mail to one of the developers of KConfig compiler asking how can I solve this problem.
    In the upcoming week, I plan to implement clipping polygons for all projection systems, make it possible to display planets as ellipses, introduce asteroids and comets to SkyMapLite and setup CMake project for compilation for Android. Asteroids and comets will bring interesting results as QtQuick version of KStars will show its performance on displaying a lot of objects (not that many as there are stars but still something to measure:) ).

    Friday, April 29, 2016

    Evaluation of the Qt Quick Scene Graph Performance

    To get a grasp of what I should do to achieve the best performance I played a little with Qt Quick Scene Graph.

    Difference between QPainter approach and Qt Quick Scene Graph.

    QPainter, which is the base of drawing in KStars, uses an imperative way whereas QtQuick Scene Graph utilizes declarative paradigm. In Scene Graph you add some set of "nodes" (classes with prefix QSG) to the root node that is returned by calling QQuickItem::updatePaintNode() whenever you want to render QQuickItem and manipulate them during the runtime (change position, geometry, material, etc.) This gives possibilities to perform some optimization like batching the nodes to draw them in fewer calls to OpenGL, which can be of tremendous help for us in drawing stars, for example.

    SkyMapLite

    My initial idea of SkyMapLite in KStars Lite was to create for every SkyComponent separate QQuickItem derived object and reparent it to SkyMapLite, thus making it visible. The QQuickItem derived object would contain the painting code and communicate with SkyComponent to get the actual coordinates of the object in sky and convert them using Projector to "x" and "y" coordinates. However, it seemed to me that this approach would result in making a lot of unnecessary actions like calling signals during the change of "x", "y" and "visible" properties.

    Another approach is to directly ask SkyMapLite to instantiate a QSGNode derived object, which would visually represent SkyComponent, and add it to the root node of SkyMapLite, thus bypassing the QQuickItem. However, this way the code would become more complicated as the Scene Graph on the most platforms lives in the separate thread and possibilities in communicating with the GUI thread from QSGNodes are slightly limited.

    To test both approaches I made two versions of program that just shows you 5000 .png images of blue balls with the resolution 16x16 (Use of images with the resolution of some power of 2 allows better batching). The first version - each ball is a separate QQuickItem derived object with overridden updatePaintNode() function, and the second one consists of the object of class Canvas, which instantiates objects of QSGNode derived class that paints the same texture on the screen. I also played with plain rectangles instead of textures and the results of my small test you can find here. The table shows the number of CPU counts used to create nodes and render the first frame of the program.

    Areas with similar color are drawn in batch. Visualized by setting QSG_VISUALIZE env. variable to "batches"

    As you can see from the test results - batching reduces the number of instructions executed in CPU significantly. As for the difference between two approaches - the direct creation of QSGNodes doesn't perform significantly better than instantiating QQuickItems.

    So what I noticed was that rectangles with different colors are not drawn in batch, and late very good expert in Scene Graph, Gunnar Sletta, told me that I should use QSGGeometryNode + QSGVertexColorMaterial instead of QSGSimpleRectNode. Also to draw the texture in batch the QQuickWindow::TextureCanUseAtlas flag has to be set during the creation of texture and to include a lot of texture in texture atlas you probably would have to set QSG_ATLAS_WIDTH and QSG_ATLAS_HEIGHT env. variables to the GL_MAX_TEXTURE_SIZE. You can visualize what textures are included in atlas by setting QSG_ATLAS_OVERLAY to 1. A structure of all nodes in Scene Graph can be obtained by setting QSG_RENDERER_DEBUG to "dump". You can read our full conversation here.

    Then I made textures "movable" and tried to measure how much CPU counts requires setting "x", "y" and "visible" properties when the QQuickItem is moved or gets out of screen. xChanged() and yChanged() each took about 2 500 000 counts during the few seconds of moving 5000 objects out and to the screen and visibleChanged() signal required 238.564 instructions to execute.
    https://www.blogger.com/blogger.g?blogID=6452817988747192886#editor/target=post;postID=6946697078078991651
    I tested the "moving" version with QQuickItems on my laptop and Nexus 7 (2nd gen) and got fairly smooth results, especially when part of the items was set to invisible state because they were out of the screen. I even managed to run it with 1000 objects on my old Motorola Defy with Android 2.3!

    Results

    I inserted a counter in SkyObject constructor to see that KStars creates about 14400 of them with standard set of catalogs (this count is just to get an idea about approximate amount of objects). Given that number and the fact that various objects appear only on some levels of zoom and not all of them will be inside the current user's view, although we won't be able to batch everything in SkyMapLite, as elements differ in their visual representation, I think that my initial approach with QQuickItem will be enough.
    Doing all of this was very useful to me as I've used for the first time the Valgrind profiler and now know better the internals of Scene Graph.
    From now on I will concentrate on prototyping the SkyComponentsLite derived objects and details of SkyMapLite.

    Monday, April 25, 2016

    Hello World!

    Dear readers of my blog.

    This year I'm happy to be a participant of Google Summer of Code 2016 program and work together with my mentor Jasem Mutlaq on such an exciting project like Lite version of one of the KDE's applications KStars (you can find more about KStars here).

    What is KStars Lite?

    As the title suggests it is a lite version for mobile/tablets, slow machines like budget laptops, netbooks, single-board computers like Raspberry Pi, etc. One of the main differences between desktop and lite versions is that the graphics of the latter is based on QML/QtQuick. KStars Lite is built bearing in mind the differences between mouse/touch interfaces and the graphical frontend will be designed according to touch interfaces of mobile platforms.

     

    What will be done?

    The first goal of this project is to build a QML/QtQuick version of SkyMap, the "heart" of the KStars. . This includes displaying of almost all sky objects like planets, stars, asteroids, etc (you can find a detailed list of sky objects in my proposal in the end of this post). It can be done using several approaches and my first task is to choose the best one to provide fluent and smooth experience to the end user.
    User will be able to interact with the SkyMap by panning with touch screen, using gestures like "pinch to zoom" and tap on the objects. Everything from this list will be also available for use with mouse.
    Other features include Search, Simulation Time, Location retrieval and Timekeeping, Projection Systems and Color Schemes.
    To provide the best experience the logic behind loading the sky objects from catalogs will be changed (you can read details in my proposal).

    Why KStars? 

    I become interested in Astronomy last year after reading a book about the space exploration. Right now I'm subscribed to the one of the astronomy magazines and with each its issue I'm getting a part of the telescope so my first newbie telescope is on my way :)
    KStars Lite is also a great opportunity to strength my skills in QML/QtQuick. I like the declarative way of designing the interfaces and see KStars Lite as a probable motivation to move the whole project to QML/QtQuick.

     

    About me

    My name is Artem Fedoskin and I come from Kazakhstan. I'm a first-year master student majoring in Computer Science at South Kazakhstan State University. Apart from programming I love music (different genres from rock and metal to synthpop), reading sci-fi and fantasy books and comics. Especially I like Star Wars universe :)

    You can find my proposal for KStars Lite here