One application, two different results

I made a speedometer app, which runs quite nicely on my Sony Xperia 10II. The same app (running on SDK) shows something quite different. See images.

I wanted to see/develop my app in a larger format, so I decided to use the Emulator, but my app does not display correctly and runs like poop, dropping frames, stalling and the applied effect for the trailing colour glow is displayed in the wrong direction and also is showing at 0 kmh, the trail should NOT be visible when at 0 kmh, let alone displaying it upside down. Why?

Image from Emulator;

Colour trail showing and upside down when at 0 kmh, it should not be visible at all.

Image from phone;

The phone (Sony Xperia 10II) screenshot is how it should look when at 0 kmh.

2 Likes

Kind of off topic but before you release it can you also make it log speed and present a chart? Ie. tap a button to start logging > tap it again to stop logging.

No, I don’t know how to do that and as such, it won’t get released, at least not yet.

Can you post the QML file contents here, or post a link to the source code? Without it there’s little to do…

Better yet, can you make a simple example app that exposes the same behavior?

1 Like

A stripped example of my speedometer as requested, it’s very basic and is missing many components but the sample serves to demo the problem. It will look different from the original screenshots previously shown.

The trail should follow the needle and gradually build up as the needle rotates. As it rotates, it should dissolve the trail from before the needle…does that make sense?

Moreover, I have tried tweaking the app to work on Emulator, but no dice no matter what I come up with.

For clarity on how the demo should behave, here’s an RPM for aarch64 only;

Once installed and app is running, just tap on the ZERO to start the animation!

FirstPage.qml

import QtQuick 2.6
import QtPositioning 5.4
import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0

Page {
    id: page

    allowedOrientations: Orientation.All

    CircularSlider {
        id: speedometer

        property real factor: 3.6
        property int valid: 0

        width: 760
        height: width
        minValue: 0
        maxValue: 130
        startAngle: -130
        endAngle: 0
        anchors {
            top: parent.top
            topMargin: isPortrait ? 840 : 270
            horizontalCenter: parent.horizontalCenter
        }
        value: src.position.speedValid === false ? 0 : src.position.speed*factor

        // color progress bar
        CircularProgress {
            id: progress
            size: 1075
            anchors.centerIn: parent
            minValue: 0
            maxValue: 260
            value: speedometer.value / 360
            rotation: speedometer.startAngle

            // shader effect for progress bar
            ShaderEffect {
                id: bluegauge
                anchors.fill: parent
                rotation: speedometer.value/3.2

                property real pi: -3.141593/360
                property real angleBase: -pi*0.99
                property real angle: speedometer.value/83

                // readable shader effect components, not the usual garbled mess!!
                vertexShader: {'
                    uniform lowp mat4 qt_Matrix;
                    attribute lowp vec4 qt_Vertex;
                    attribute lowp vec2 qt_MultiTexCoord0;
                    varying lowp vec2 coord;
                    void main() {
                        coord = qt_MultiTexCoord0;
                        gl_Position = qt_Matrix * qt_Vertex;
                    }'
                }
                fragmentShader: {'
                    uniform lowp float qt_Opacity;
                    uniform lowp float angleBase;
                    uniform lowp float angle;
                    varying lowp vec2 coord;
                    void main() {
                        lowp vec2 d=2.0*coord-vec2(1.0,1.0);
                        lowp float r=length(d);
                        if (0.55<=r && r<=0.93) {
                            lowp float a=atan(d.x,-d.y);
                            if (angleBase<=a && a<=angle) {
                                lowp float p=(a-angleBase)/(angle-angleBase);
                                gl_FragColor = vec4(0,p,p,p) * qt_Opacity;
                            }
                        }
                    }'
                }
            }
        }
        // positioning source
        PositionSource {
            id: src
            updateInterval: 1000
            active: pageStack.depth === 1 ? !seqani.running : true
            onPositionChanged: {
                var coord = src.position.coordinate
            }
        }
        // speedometer animation control based on Tesla Plaid = experimental
        SequentialAnimation on value {
            id: seqani
            running: false
            loops: 1
            PropertyAnimation { from:   0; to:  60; duration: 3000 }
            PropertyAnimation { from:  60; to: 100; duration: 3050 }
            PropertyAnimation { from: 100; to: 160; duration: 3100 }
            PropertyAnimation { from: 160; to: 200; duration: 3150 }
            PropertyAnimation { from: 200; to: 260; duration: 3200 }
            PropertyAnimation { from: 260; to:   0; duration: 4999 }
        }
        MouseArea {
            anchors.fill: speedtext
            propagateComposedEvents: true
            onClicked: {
                if  (seqani.running == true)
                     seqani.running =  false
                else seqani.running =  true
            }
        }

        // speed text
        Text {
            id: speedtext
            color: "white"
            anchors.centerIn: parent
            text: Math.round(speedometer.value)
            font {
                letterSpacing: 15
                family: "sans-serif"
                bold: true; pixelSize: 202
            }
        }

        // needle movement
        Repeater {
            model: 1
            Rectangle {
                z: 1
                id: needle
                width: 10
                height: 200
                radius: 444
                color: "orange"
                smooth: true
                antialiasing: true
                transform: [ Translate { x: speedometer.width / 2 - width / 2; y: -110 },
                    Rotation {
                        origin.x: speedometer.width / 2
                        origin.y: speedometer.height / 2
                        angle: speedometer.angle
                    }
                ]
            }
        }
    }
}

CircularProgress.qml

import QtQuick 2.6
import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0

Item {
    id: root
    width: size
    height: width

    property int size: 150
    property real value: 0
    property real minValue: 0
    property real maxValue: 360
}

CircularSlider.qml

import QtQuick 2.6
import Sailfish.Silica 1.0

Item {
    id: control

    property real value: 0.0
    property real startAngle: 0
    property real endAngle: 360
    property real minValue: 0.0
    property real maxValue: 1.0
    readonly property alias angle: internal.angle

    QtObject {
        id: internal
        readonly property real angle: internal.mapFromValue(control.minValue, control.maxValue, control.startAngle, control.endAngle, control.value)
        function mapFromValue(inMin, inMax, outMin, outMax, inValue) { return (inValue - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
    }
}

Happy bug hunting, any questions?

1 Like

Okay, I finally worked it out and now it works on SDK and my device.

I realised from my notes, I had removed a line of text in the fragment shader code, it didn’t seem to be necessary for running on my device.

After adding the removed code, the sample now displays correctly in the emulator, see “<— ADD THIS”

                fragmentShader: {'
                    uniform highp float qt_Opacity;
                    uniform highp float angleBase;
                    uniform highp float angle;
                    varying highp vec2 coord;
                    void main() {
                        gl_FragColor = vec4(0.0,0.0,0.0,0.0); <-------ADD THIS
                        lowp vec2 d=2.0*coord-vec2(1.0,1.0);
                        lowp float r=length(d);
                        if (0.55<=r && r<=0.93) {
                            lowp float a=atan(d.x,-d.y);
                            if (angleBase<=a && a<=angle) {
                                lowp float p=(a-angleBase)/(angle-angleBase);
                                gl_FragColor = vec4(0,0,p,p) * qt_Opacity;
                            }
                        }
                    }'
                }
1 Like