Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (499)
Games in Android Showcase (118)
games submitted by our members
Games in WIP (567)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Need help with quanterion (cube rotate)  (Read 3412 times)
0 Members and 1 Guest are viewing this topic.
Offline akzyl

Senior Newbie





« Posted 2012-03-04 19:20:31 »

Hello.
I need help with quanterion. I have spent on this all saturday and couple hour today and still I don't know how to do it properly (I feel so dumb).
I want to rotate cube (around on own x,y or z axis) in fact on the beginning only  two wall front and right.
//front wall
-0.5f,  0.5f,  0.0f,  
0.5f,  0.5f,  0.0f,  
0.5f, -0.5f,  0.0f,
-0.5f, -0.5f,  0.0f,
//right wall
0.5f,  0.5f,  0.0f,  
0.5f, -0.5f,  0.0f,  
0.5f, -0.5f, -1.0f,  
0.5f,  0.5f, -1.0f

So if I want to make a rotation on Z axis (roll) I must to do something with 8 vectors and I did something like this
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
private final static float DEGTORAD = (float)(Math.PI/180);
private static float rollAngle = 4;
private static Quaternion roll = new Quaternion();
private Quaternion change;
private float[] array = new float[]{
          -0.5f,  0.5f,  0.0f,  
          0.5f,  0.5f,  0.0f,  
          0.5f, -0.5f,  0.0f,
          -0.5f, -0.5f,  0.0f,
         
          0.5f,  0.5f,  0.0f,  
          0.5f, -0.5f,  0.0f,  
          0.5f, -0.5f, -1.0f,  
          0.5f,  0.5f, -1.0f};
private FloatBuffer vertexData;

private void update(){
      roll();
      for(int i = 0;i<array.length;i+=3) {
         change = new Quaternion(array[i], array[i+1], array[i+2], 0.0f);
         Quaternion.mul(roll, change, change);
         array[i] = change.x;
         array[i+1] = change.y;
         array[i+2] = change.z;
      }
       vertexData.put(array);
        vertexData.flip();
   }

public static void roll() {
       roll.setFromAxisAngle(new Vector4f(0, 0, 1, rollAngle * DEGTORAD));
       roll.normalise();
   }

public void gameLoop(){
      ...
      while(running) {
         update();
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glLoadIdentity();//Matrix reseting.
        GL11.glTranslatef(0.0f, 0.0f, -6.0f); // Move Right And Into The Screen
        GL11.glRotatef(80, 0.5f, 0.5f, -0.5f); // Rotate The Cube On X, Y & Z
       
         glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
         
            glVertexPointer(vertexSize, 0, vertexData);
            glColorPointer(colorSize, 0, colorData);
           
            glDrawArrays(GL_QUADS, 0, amountOfVertices);
           
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);
         
         Display.sync(60);
         Display.update();
      }
      glDisableClientState(GL_COLOR_ARRAY);
      glDisableClientState(GL_VERTEX_ARRAY);
     
      Display.destroy();
   }

and I must admit that the front wall rotate properly also right but unfrtunateli something bad happening with right wall namely
is getting smaller and smaller. The same happens with front wall if I change rotation e.g.
roll.setFromAxisAngle(new Vector4f(1, 0, 0, rollAngle * DEGTORAD));

What's wrong how to do this properly?



I think i should create this topic in 'LWJGL Development' it's more appropriate place. Can someone move it.
Offline DiEvAl

Junior Newbie





« Reply #1 - Posted 2012-03-04 21:31:54 »

It looks like you are creating wrong quaternion in roll().
Offline akzyl

Senior Newbie





« Reply #2 - Posted 2012-03-04 22:19:03 »

It looks like you are creating wrong quaternion in roll().
That's why I ask. I really don't know how it should be.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Roquen
« Reply #3 - Posted 2012-03-05 04:52:36 »

A rotation about some axis 'V', where V is a normalized vector about an angle "a" in quaternion space is: sin(a/2)V + cos(a/2).

I'd assume that the Quaternion class that you're using has a method to directly set and/or create one directly from an axis angle pair.
Offline akzyl

Senior Newbie





« Reply #4 - Posted 2012-03-05 05:45:29 »

A rotation about some axis 'V', where V is a normalized vector about an angle "a" in quaternion space is: sin(a/2)V + cos(a/2).

I'd assume that the Quaternion class that you're using has a method to directly set and/or create one directly from an axis angle pair.
I'm using
org.lwjgl.util.vector.Quaternion
Offline Roquen
« Reply #5 - Posted 2012-03-05 06:01:40 »

Humm...okay, something like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
// x,y,z must be a unit vector & 'a' is the angle.
public static Quaternion setAxisAngle(Quaternion q, float x, float y, float z, float a)
{
  a *= 0.5f;

  float sinA = (float)Math.sin(a);
  float cosA = (float)Math.cos(a);

  x *= sinA;
  y *= sinA;
  z *= sinA;

  q.set(x,y,z,cosA);

  return q;
}
Offline DiEvAl

Junior Newbie





« Reply #6 - Posted 2012-03-05 06:04:44 »

Try this.
1  
2  
3  
4  
5  
         change = new Quaternion(array[i], array[i+1], array[i+2], 1.0f);
         Quaternion.mul(roll, change, change);
         array[i] = change.x / change.w;
         array[i+1] = change.y / change.w;
         array[i+2] = change.z / change.w;

(http://en.wikipedia.org/wiki/Homogeneous_coordinates)
Offline akzyl

Senior Newbie





« Reply #7 - Posted 2012-03-05 07:30:24 »

Humm...okay, something like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
// x,y,z must be a unit vector & 'a' is the angle.
public static Quaternion setAxisAngle(Quaternion q, float x, float y, float z, float a)
{
  a *= 0.5f;

  float sinA = (float)Math.sin(a);
  float cosA = (float)Math.cos(a);

  x *= sinA;
  y *= sinA;
  z *= sinA;

  q.set(x,y,z,cosA);

  return q;
}

This method doing the same what
roll.setFromAxisAngle(new Vector4f(0, 0, 1, rollAngle * DEGTORAD));
and result is the same.
Try this.
1  
2  
3  
4  
5  
         change = new Quaternion(array[i], array[i+1], array[i+2], 1.0f);
         Quaternion.mul(roll, change, change);
         array[i] = change.x / change.w;
         array[i+1] = change.y / change.w;
         array[i+2] = change.z / change.w;

(http://en.wikipedia.org/wiki/Homogeneous_coordinates)
and this in general does terrible things which I will not describe Wink
Offline Stranger

Senior Member


Medals: 6



« Reply #8 - Posted 2012-03-05 08:56:20 »

If you want to use quaternion Q to rotate point (vertex) P with respect to translated origin G use this formula:

 P' = Q(P-G)Q' + G

where P' is the transformed point, and Q' is the quaternion inverse.

Anton
Offline Roquen
« Reply #9 - Posted 2012-03-05 09:04:01 »

That's nice algebraically, but it significantly reduces.  But you hit on a good point, a rotation isn't being performed.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Stranger

Senior Member


Medals: 6



« Reply #10 - Posted 2012-03-05 12:29:05 »

Here is some code. Hope it will work with minor changes.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
...

   private void update(){
      roll();
      for(int i = 0;i<array.length;i+=3) {
         change = new Vector3f(array[i], array[i+1], array[i+2]);
         MathUtils.transform(roll, change, change);
         array[i] = change.x;
         array[i+1] = change.y;
         array[i+2] = change.z;
      }
       vertexData.put(array);
       vertexData.flip();
   }

...

public class MathUtils {
   public static Vector3f transform( Quaternion q, Vector3f vector, Vector3f result )
    {
        Quaternion inv = new Quaternion(-q.getX(), -q.getY(), -q.getZ(), q.getW() );
        inv.normalize();
       
        Quaternion tmp = new Quaternion();
       
        mul(q, vector, tmp );
        tmp.mul( inv );
       
        result.set( tmp.getX(), tmp.getY(), tmp.getZ() );
       
        return ( result );
    }

    public static Quaternion mul(Quaternion q, Vector3f t, Quaternion out )
    {
        out.set( ( q.getW() * t.getX() ) + ( q.getY() * t.getZ() ) - ( q.getZ() * t.getY() ),
                    ( q.getW() * t.getY() ) + ( q.getZ() * t.getX() ) - ( q.getX() * t.getZ() ),
                    ( q.getW() * t.getZ() ) + ( q.getX() * t.getY() ) - ( q.getY() * t.getX() ),
                   -( q.getX() * t.getX() ) - ( q.getY() * t.getY() ) - ( q.getZ() * t.getZ() )
               );
       
        return ( out );
    }
  }

Anton
Offline akzyl

Senior Newbie





« Reply #11 - Posted 2012-03-05 17:37:41 »

Oh gosh!!! Stranger and Roquen your code works the same I mean PROPERLY  Grin.
The mistake was in this part of code
1  
2  
3  
array[i] = change.x;
array[i+1] = change.y;
array[i+2] = change.z;

during rotation around axis Z I shouldn't do this
1  
array[i+2] = change.z;

around axis Y I shouldn't do this
1  
array[i+1] = change.y;

and
1  
array[i] = change.x;

during rotation around axis X.

I really appreciate your help.
Thanks all of you!
Offline Roquen
« Reply #12 - Posted 2012-03-07 09:04:03 »

That great.  Now some comments.  First you're modifing your source data by incrementally rotating it.  You don't want to do this as float point operations introduce errors.  You want to make a modified copy, always using the 'source' data as input.  So you need two quaternions, one for the current rotation and a second (what you already have) to update the first (by a multiply).  The second thing is that directly rotating a vector by quaternion should only be used when the number of vectors is very small (like a couple), otherwise convert to a matrix and rotate with it.  And since the target data is to be used solely by the graphics card, you don't need to rotate the vectors yourself.  Feed the matrix to OpenGL and let it do the work.  If your library doesn't have a conversion, see this thread: http://www.java-gaming.org/topics/skeletal-animation/25483/view.html


@Stranger: You don't want to directly transcribe the algebraic equation into code.  The formula contains a fair amount of cancellation (by design), multiplies by zero & unneeded normalization which is a pretty undesirable thing in float point computation.  See here for these operations removed: http://www.java-gaming.org/topics/quaternion-vector-multiplication/25517/view.html
Offline Stranger

Senior Member


Medals: 6



« Reply #13 - Posted 2012-03-07 09:55:08 »

@Roquen: I had in mind general case, just to get it working. Of course, the code can be optimized (if any).

Anton
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Pippogeek (37 views)
2014-09-24 16:13:29

Pippogeek (29 views)
2014-09-24 16:12:22

Pippogeek (18 views)
2014-09-24 16:12:06

Grunnt (42 views)
2014-09-23 14:38:19

radar3301 (24 views)
2014-09-21 23:33:17

BurntPizza (60 views)
2014-09-21 02:42:18

BurntPizza (30 views)
2014-09-21 01:30:30

moogie (36 views)
2014-09-21 00:26:15

UprightPath (49 views)
2014-09-20 20:14:06

BurntPizza (52 views)
2014-09-19 03:14:18
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!