Jump to content
  • Advertisement
Sign in to follow this  
Gamer_N_Developer

Quaternion rotation of polygon vertices (SLERP)

This topic is 2101 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I tried using a quaternion SLERP to update the vertices of a polygon and the problem I ran into is that as the polygon tries to rotate a full 360 it stretches along an axis, I think its the y-axis actually.

 

This is the polygon initially.

 

[attachment=19541:image2.png]

 

and this is what happens at about 45 degrees into the rotation (notice the polygon stretches towards the edge and actually escapes to the

corner).

 

[attachment=19540:image1.png]

 

I can post the code on pastebin if needed.

 

Here's an excerpt from the program, its the main call that updates the vertices which calls the SLERP function to interpolate 2 quaternions.

CVec3 RotatePoint( float t, CVec3 P1,
                  float angle_i, float angle_f,
                  int x1, int y1, int z1
                  , int x2, int y2, int z2)
{
    CQuat QRot;
    CQuat Q1( angle_i, CVec3( x1, y1, z1)); // Set by axis-angle
    CQuat Q2( angle_f, CVec3( x2, y2, z2));
    //QRot.Slerp( Q1, Q2, t, false);
    QRot.QuaternionSlerp( Q1, Q2, t);

    CMatrix M;
    QRot.ToMatrix( M.mf);
    return M*P1;
}
void calc_quaternion_verts( verts *c_verts, verts *s_verts,
                                    int vertices_count, float t,
                                    float angle_i, float angle_f,
                                    int x1, int y1, int z1,
                                    int x2, int y2, int z2)
{
        CVec3 P1;
        float new_x = 0.0f;
        float new_y = 0.0f;
        float new_z = 0.0f;
        float x_center = (float)SCREEN_X / 2.0f;
        float y_center = (float)SCREEN_Y / 2.0f;

        for( int i = 0; i < vertices_count; i++)
        {
            P1.x = c_verts[i].vx;
            P1.y = c_verts[i].vy;
            P1.z = c_verts[i].vz;

            //P1 = RotatePoint( t, P1, angle_i, angle_f, x1, 0.0f, 0.0f, x2, 0.0f, 0.0f);
            //P1 = RotatePoint( t, P1, angle_i, angle_f, 0.0f, y1, 0.0f, 0.0f, y2, 0.0f);
            //P1 = RotatePoint( t, P1, angle_i, angle_f, 0.0f, 0.0f, z1, 0.0f, 0.0f, z2);
            P1 = RotatePoint( t, P1, angle_i, angle_f, x1, y1, z1, x2, y2, z2);

            new_x = P1.x;
            new_y = P1.y;
            new_z = P1.z;

            s_verts[i].vx = new_x + x_center;
            s_verts[i].vy = new_y + y_center;
            s_verts[i].vz = new_z;
        }
}

Share this post


Link to post
Share on other sites
Advertisement
I don't see anything wrong with the code at a first glance. But why are you using `int' for axis coordinates? And why are you using three different representations of rotations?

Share this post


Link to post
Share on other sites

I don't see anything wrong with the code at a first glance. But why are you using `int' for axis coordinates? And why are you using three different representations of rotations?

I use 1 or -1 for all the axes coordinates. I'm not sure if I'm supposed to use 3 different representations for rotations, what line are you looking at?

 

 

Here's the whole code, compile and link with Allegro 5.

 

quaternion_rotation.cpp http://pastebin.com/rtjWb5hf

quat.h                            http://pastebin.com/34xeJ229

matrix.h                           http://pastebin.com/k8F47rup

vec3.h                             http://pastebin.com/VXjxStL8

Edited by Gamer_N_Developer

Share this post


Link to post
Share on other sites

I use 1 or -1 for all the axes coordinates.

Why limit yourself to coordinate axes? The same code works for arbitrary rotation axes.
 

I'm not sure if I'm supposed to use 3 different representations for rotations, what line are you looking at?

I was looking at the function `RotatePoint', which takes as input two rotations expressed in angle-axis form, it converts them to quaternions, interpolates between them, then converts them to a matrix, then finally applies the rotation to a point. I would use quaternions for everything, for simplicity.

Also, there is no point in using degrees for angles: Use radians everywhere. It's much too easy to make mistakes when there are too many representations available for the same thing. Edited by Álvaro

Share this post


Link to post
Share on other sites

 

I use 1 or -1 for all the axes coordinates.

Why limit yourself to coordinate axes? The same code works for arbitrary rotation axes.
 

I'm not sure if I'm supposed to use 3 different representations for rotations, what line are you looking at?

I was looking at the function `RotatePoint', which takes as input two rotations expressed in angle-axis form, it converts them to quaternions, interpolates between them, then converts them to a matrix, then finally applies the rotation to a point. I would use quaternions for everything, for simplicity.

Also, there is no point in using degrees for angles: Use radians everywhere. It's much too easy to make mistakes when there are too many representations available for the same thing.

 

 

I would use quaternions for everything although I'm not sure how I would do that. Right now I'm converting angles to quaternions (as you said) in:

CQuat Q1( angle_i, CVec3( x1, y1, z1)); // Set by axis-angle
    CQuat Q2( angle_f, CVec3( x2, y2, z2));

I suppose I could create a quaternion initially without this although I would have trouble understanding the quaternion orientation to begin with. Using degrees is easier to understand. I would like to maybe try radians but I'm not sure if the code has that, that would also be nothing more than converting from degrees to radians. How would I setup quaternions without radians or degrees by the way?

 

 

 

I use 1 or -1 for all the axes coordinates.

Why limit yourself to coordinate axes? The same code works for arbitrary rotation axes.
 
 

You're right, I was using 1's because those are unit vectors and they make the most sense when rotating along an axis, or at least that's what I thought.

 

Did you find anything wrong with the code though, like whether the polygon should stretch.

Share this post


Link to post
Share on other sites
It took a while to install Allegro 5, cmake and figure out how to compile your program on Mac OS X, but I finally got it to work (or not work ;) ).

The problem is that your axes (x1, y1, z1) and (x2, y2, z2) are not normalized. By the way, since you have a type for vectors, why don't you use it, instead of passing three individual values? Similarly, a lot of your code that manipulates coordinates one by one could be written using vectors, and the code would be easier to read as a result.

Share this post


Link to post
Share on other sites
Continuing on the theme of representing the same thing in too many ways, why do you need `verts' if you have `CVec3'? And why is `verts' plural? Why do you need the typedef `matrix' if you have `CMatrix'?

Share this post


Link to post
Share on other sites

It took a while to install Allegro 5, cmake and figure out how to compile your program on Mac OS X, but I finally got it to work (or not work ;) ).

The problem is that your axes (x1, y1, z1) and (x2, y2, z2) are not normalized. By the way, since you have a type for vectors, why don't you use it, instead of passing three individual values? Similarly, a lot of your code that manipulates coordinates one by one could be written using vectors, and the code would be easier to read as a result.

Congrats on running it. Anyways normalizing (x1,y1,z1) and (x2,y2,z2) for 1 or -1 would still be 1 or -1 no? To normalize I would need to make it a unit vector by dividing using the norm, I guess that would be root 3 then?

 

You're right about passing values, and about cvec and verts, this code was essentially pieced together from two different sources on the internet and I tried to make it work using the "least programming work needed as possible" theorem, sorry!  Thanks for helping so far though, how do I normalize though?

Share this post


Link to post
Share on other sites

You can pass the rotation axes as one CVec3 each, instead of three ints each. You can then normalize them using the method CVec3::Normalize that is already in your code.

Share this post


Link to post
Share on other sites

You can pass the rotation axes as one CVec3 each, instead of three ints each. You can then normalize them using the method CVec3::Normalize that is already in your code.

 

I'm guessing I would normalize a CVec3 type before doing this then right?

CQuat Q1( angle_i, CVec3( x1, y1, z1)); // Set by axis-angle
    CQuat Q2( angle_f, CVec3( x2, y2, z2));

Thanks for your help so far!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!