Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Qt 6
  4. [Rotation of an object using a QList of QQuaternion doesn't work]
Forum Updated to NodeBB v4.3 + New Features

[Rotation of an object using a QList of QQuaternion doesn't work]

Scheduled Pinned Locked Moved Solved Qt 6
34 Posts 5 Posters 5.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A appdev

    I'm sorry, I didn't understand.

    Why should I change quaternion_w ?

    quaternioncsv is the QList that contains values of QQuaternion and that I will be using to rotate my object.

    Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    Christian Ehrlicher
    Lifetime Qt Champion
    wrote on last edited by
    #16

    @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

    quaternioncsv is the QList that contains values of QQuaternion and that I will be using to rotate my object.

    But where? I only see you iterate over a list and modify a variable, nothing more...

    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
    Visit the Qt Academy at https://academy.qt.io/catalog

    1 Reply Last reply
    0
    • A Offline
      A Offline
      appdev
      wrote on last edited by appdev
      #17

      Okay, here is the code:

      for (int i=0; i<quaternion_w.size();++i)
           {
      
          quaternioncsv.append(QQuaternion(quaternion_w[i],quaternion_x[i], 
          quaternion_y[i], quaternion_z[i]));
       
          matrix.rotate(quaternioncsv[i]); // the object should rotate
      
           }
      

      So first thing first I fill the QList "quaternioncsv" with values from other QLists then I use the rotate function that multiplies the modelview matrix by the rotation matrix that corresponds to every quaternion of the QList " quaternioncsv".

      The rotate function executes the rotation.

      Christian EhrlicherC 1 Reply Last reply
      0
      • A appdev

        Okay, here is the code:

        for (int i=0; i<quaternion_w.size();++i)
             {
        
            quaternioncsv.append(QQuaternion(quaternion_w[i],quaternion_x[i], 
            quaternion_y[i], quaternion_z[i]));
         
            matrix.rotate(quaternioncsv[i]); // the object should rotate
        
             }
        

        So first thing first I fill the QList "quaternioncsv" with values from other QLists then I use the rotate function that multiplies the modelview matrix by the rotation matrix that corresponds to every quaternion of the QList " quaternioncsv".

        The rotate function executes the rotation.

        Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #18

        @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

        matrix.rotate(quaternioncsv[i]); // the object should rotate

        there is no object, just a matrix and you don't paint anything after you set the matrix to a new value...

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        1 Reply Last reply
        0
        • A Offline
          A Offline
          appdev
          wrote on last edited by
          #19

          The object is represented by that matrix which is the modelview matrix.

          this works perfectly:

          quaternion = QQuaternion(0.8536, 0.3536, -0.1464, 0.3536);
          matrix.rotate(quaternion)
          

          I tried this with different quaternion values and the object does change its orientation.

          If I'm not painting anything after setting the matrix to a new value, how come the code lines I wrote above, make the object rotate. I'm confused.

          Christian EhrlicherC 1 Reply Last reply
          0
          • A appdev

            The object is represented by that matrix which is the modelview matrix.

            this works perfectly:

            quaternion = QQuaternion(0.8536, 0.3536, -0.1464, 0.3536);
            matrix.rotate(quaternion)
            

            I tried this with different quaternion values and the object does change its orientation.

            If I'm not painting anything after setting the matrix to a new value, how come the code lines I wrote above, make the object rotate. I'm confused.

            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #20

            @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

            make the object rotate. I'm confused.

            Because then you enter the event loop again, a paintEvent is triggered and your stuff is painted...

            Use a QTimer, set the desired timeout and advance your rotation to the next state in the connected slot.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            4
            • A Offline
              A Offline
              appdev
              wrote on last edited by
              #21

              Using QTimer and setting the desired timeout is fine but advancing the rotation to the next state isn't really clear ? shouldn't I use something like a loop to make it advance ?

              Christian EhrlicherC jsulmJ 2 Replies Last reply
              0
              • A appdev

                Using QTimer and setting the desired timeout is fine but advancing the rotation to the next state isn't really clear ? shouldn't I use something like a loop to make it advance ?

                Christian EhrlicherC Offline
                Christian EhrlicherC Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on last edited by
                #22

                @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

                shouldn't I use something like a loop to make it advance ?

                Remember the current value, add one to get to the next and use this during the next execution of your slot. How else should it work?

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                1 Reply Last reply
                0
                • A appdev

                  Using QTimer and setting the desired timeout is fine but advancing the rotation to the next state isn't really clear ? shouldn't I use something like a loop to make it advance ?

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #23

                  @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

                  but advancing the rotation to the next state isn't really clear ?

                  In each timeout slot call you take next quaternion from your list and do the rotation.

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    appdev
                    wrote on last edited by
                    #24

                    Okay but don't I need to iterate throught the QList ?

                    jsulmJ 1 Reply Last reply
                    0
                    • A appdev

                      Okay but don't I need to iterate throught the QList ?

                      jsulmJ Offline
                      jsulmJ Offline
                      jsulm
                      Lifetime Qt Champion
                      wrote on last edited by
                      #25

                      @appdev As already explained: on each timeout slot call you take next element from the list. Isn't this "iteration"?

                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      3
                      • A Offline
                        A Offline
                        appdev
                        wrote on last edited by
                        #26

                        But an iteration needs a loop to iterate through the whole QList so I need to use a for loop right ?

                        JonBJ 1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          appdev
                          wrote on last edited by appdev
                          #27

                          I tried something but it didn't work:
                          I added a new function to my code: it's actually a SLOT

                          void MainWidget::rotate_csv(QMatrix4x4 m)
                          {
                              for (int i=0; i<quaternioncsv.size();++i)
                              {
                                  m.rotate(quaternioncsv[i]);
                              }
                          }
                          
                          

                          It iterates through the QList of quaternions and multiplies the matrix "m" with the rotation matrix of quaternioncsv[i].

                          Then in my paintGL() function I did this:

                              this->m_timer=new QTimer(this);
                              m_timer->setInterval(10000);
                              QTimer::connect(m_timer,SIGNAL(timeout()),this,SLOT(rotate_csv(matrix)));
                              m_timer->start();
                          

                          So according to Qt documentation, the rotate_csv will be called every 10 seconds.
                          When I run my application, the object remains at its initial orientation. It doesn't start rotating.

                          1 Reply Last reply
                          0
                          • A appdev

                            But an iteration needs a loop to iterate through the whole QList so I need to use a for loop right ?

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #28

                            @appdev
                            First, SLOT(rotate_csv(matrix)) isn't even legal. Why you cannot do yourself a favor and change over to New Signal Slot Syntax (unless you are on Qt4, which you do not say), which would catch this, is beyond me.... If you really won't change over, why don't you test the result returned from connect()?

                            When I run my application, the object remains at its initial orientation. It doesn't start rotating.

                            Did you put a qDebug() statement inside MainWidget::rotate_csv() to see how many times it was called? I have advised you to do this....

                            @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

                            But an iteration needs a loop to iterate through the whole QList so I need to use a for loop right ?

                            No, this is not what the others are asking you to do. They are asking you to perform one quaternion in the list per each timeout. No for loop!

                            They are asking you to write something like:

                            connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv);
                            
                            m_iterations = 0;
                            m_timer->start();
                            
                            void MainWidget::rotate_csv()
                            {
                                if (m_iterations >= quaternioncsv.count())
                                    return;
                                matrix.rotate(quaternioncsv[m_iterations]);
                                m_iterations++;
                            }
                            
                            1 Reply Last reply
                            3
                            • S Offline
                              S Offline
                              SimonSchroeder
                              wrote on last edited by
                              #29

                              You have several wrong expectations. Let's take a step back and look why your original code does not work.

                              1. The main thing (and most likely also why it still does not work) is that you assume that changing the model view matrix will also change what you see on the screen. However, you never instruct the computer to redraw what you see on the screen. You should call update() on the widget that draws the rotated object.

                              2. While you are inside the loop nothing can be drawn (at least as long as you are inside the same thread). This is why others have suggested to use a timer instead. You should create one timer that is started in the constructor already. You wrote that you create a new timer in paintGL(). This would mean that whenever you repaint your widget a new timer is added. The timers are set to repeat every 10 seconds (that is what setInterval() is for). You will end up with too many timers. Just create one repeating timer in the constructor.

                              3. Let's suppose your original code magically also updated what you see on screen. Computers are fast! Really fast! The loop will take only a bunch of milliseconds to run. At 60 Hz one single frame will take about 16 ms. Your loop would have finished once the next frame can be displayed. Anyway your brain would only be fast enough to perceive a single rotation even if the hardware would run much much faster than at 60 fps.

                              4. Successively applying rotations: Your code snippet is too short to see the declaration of your model view matrix. The easiest way would be to have it as a member variable. This would mean that the next time you paint you already know the last rotation. Then, you only need to apply the next rotation, i.e. a single rotation from your list. This goes along with @JonB's suggestion.

                              1 Reply Last reply
                              1
                              • A Offline
                                A Offline
                                appdev
                                wrote on last edited by appdev
                                #30

                                Okay, that's clear.
                                But I only have one question.

                                In the documentation it's written that the signal and slots parameters must not contain any variable names, only the type and I guess that's why @JonB told me that what I wrote was illegal.

                                I tried what you guys suggested; I added the function that rotates the object (which is the SLOT):

                                void MainWidget::rotate_csv()
                                {
                                    if (i >= quaternioncsv.size())
                                        return;
                                    matrix.rotate(quaternioncsv[i]);
                                    i++;
                                }
                                

                                then I connected the signal and the slot in my paintGL() function where I defined my modelview matrix.

                                However when I do this:

                                connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv())
                                

                                the rotate_csv won't do anything because it doesn't know that it should multiply the rotation matrix of each quaternion with the modelview matrix named matrix in my program, unless I pass it as an argument in the SLOT and which is illegal.
                                I mean like this:

                                connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv(matrix))
                                

                                I know that this is SO wrong.

                                I tried to declare the modelview matrix as global variable to solve the problem but that made the object totally disappear and I know that it doesn't make any sense.
                                I'm not sure how I can make the SLOT know that the matrix it has to work with is THE modelview matrix.
                                But I know that sometimes you can pass the variable to the SIGNAL so it can be used in the SLOT. The problem is that in my case the signal is a timeout(). I'm so confused.
                                I'm not really sure if my problem is clear or I should be more accurate.

                                JonBJ 1 Reply Last reply
                                0
                                • A appdev

                                  Okay, that's clear.
                                  But I only have one question.

                                  In the documentation it's written that the signal and slots parameters must not contain any variable names, only the type and I guess that's why @JonB told me that what I wrote was illegal.

                                  I tried what you guys suggested; I added the function that rotates the object (which is the SLOT):

                                  void MainWidget::rotate_csv()
                                  {
                                      if (i >= quaternioncsv.size())
                                          return;
                                      matrix.rotate(quaternioncsv[i]);
                                      i++;
                                  }
                                  

                                  then I connected the signal and the slot in my paintGL() function where I defined my modelview matrix.

                                  However when I do this:

                                  connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv())
                                  

                                  the rotate_csv won't do anything because it doesn't know that it should multiply the rotation matrix of each quaternion with the modelview matrix named matrix in my program, unless I pass it as an argument in the SLOT and which is illegal.
                                  I mean like this:

                                  connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv(matrix))
                                  

                                  I know that this is SO wrong.

                                  I tried to declare the modelview matrix as global variable to solve the problem but that made the object totally disappear and I know that it doesn't make any sense.
                                  I'm not sure how I can make the SLOT know that the matrix it has to work with is THE modelview matrix.
                                  But I know that sometimes you can pass the variable to the SIGNAL so it can be used in the SLOT. The problem is that in my case the signal is a timeout(). I'm so confused.
                                  I'm not really sure if my problem is clear or I should be more accurate.

                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by
                                  #31

                                  @appdev said in [Rotation of an object using a QList of QQuaternion doesn't work]:

                                  connect(m_timer, &QTimer::timeout, this, &MainWidget::rotate_csv(matrix))

                                  If matrix is a member variable of MainWidget I cannot see any difference between passing it as a parameter versus accessing it directly as matrix in MainWidget::rotate_csv().

                                  Anyway, if you do need to call a slot with parameters which do not come from the signal, you need to use a C++ lambda for the slot in the connection, like so:

                                  QMatrix4x4 matrix;
                                  connect(m_timer, &QTimer::timeout, this, [this, matrix]() { this->rotate_csv(matrix); };
                                  
                                  void MainWidget::rotate_csv(QMatrix4x4 m)
                                  { ... }
                                  

                                  But then you must make sure matrix, which was in scope at the connect() line, remains in scope so long as the timer ticks and calls rotate_csv(matrix); on it. Else very nasty things will happen. Which is why I would have thought it needs to be some variable from somewhere which remains in scope, not a local variable....

                                  I tried to declare the modelview matrix as global variable to solve the problem but that made the object totally disappear and I know that it doesn't make any sense.

                                  I'm not sure how I can make the SLOT know that the matrix it has to work with is THE modelview matrix.

                                  I don't know what to make of this. I don't know what you pass as the QMatrix4x4 m to rotate_csv(QMatrix4x4 m) or what you problem is or what "but that made the object totally disappear" means.

                                  1 Reply Last reply
                                  1
                                  • S Offline
                                    S Offline
                                    SimonSchroeder
                                    wrote on last edited by
                                    #32

                                    With your current approach you got the order all wrong. The QTimer is used to trigger a redraw. It looks like currently matrix is a local variable in your case. You should not use a signal/slot connection as this could be executed asynchronously. It would make most sense to make matrix a member variable of your class. Then you don't have to recreate the whole model view matrix every time you paint. Isn't there a initGL() function where you can initialize the model view matrix once? Then you only need to apply a single rotation in a specific interval as has been suggested before.

                                    However, your approach in itself is also not entirely wrong. Here is a slightly different suggestion: Create a timer in your constructor. Instead of connecting the timeout to your rotate_csv() slot connect it to update(). update() will in turn trigger the call to paintGL(). Now, in paintGL() you can compute the rotated model view matrix for the current timeout. Just make sure that with every call of paintGL you apply a different amount of rotation. However, other things could also trigger a call to paintGL. This again means that you need a slot to QTimer::timeout that manages a member variable describing how much rotation should be applied with the next paint event. To understand what I mean you can start out with a timer of 10 seconds and then also start moving your widget around or resizing it which will also trigger an update of the widget. This way you can make sure that a rotation is only applied every 10 seconds and not when you are changing the widget size.

                                    1 Reply Last reply
                                    1
                                    • A Offline
                                      A Offline
                                      appdev
                                      wrote on last edited by appdev
                                      #33
                                      This post is deleted!
                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        appdev
                                        wrote on last edited by
                                        #34

                                        Hello again guys, I hope you're all doing well.

                                        So I tried what you all suggested and it finally worked.
                                        Thank you so much for your precious time, advices and patience.

                                        1 Reply Last reply
                                        0

                                        • Login

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • Users
                                        • Groups
                                        • Search
                                        • Get Qt Extensions
                                        • Unsolved