Quick help needed with 2d rotation of vertex buffer object OpenGL

Started by
10 comments, last by Jevi 11 years, 5 months ago
I have a Ship object made up of 4 lines ( looks like the asteroids game ship ). I am rendering it with the vertex buffer object method. It gets drawn to the screen fine but when i go to rotate the ship the whole ship rotates around the (x,y) coordinate and not about the (x,y) coordinate, if that makes sense.

CODE SNIPPETS - full code at: https://github.com/Jevi/Asteroids/tree/master/src/org/cstutorials


This is how i render the ship object ( which is compromised of 4 lines loaded into a FloatBuffer ( im using LWJGL btw ) that FloatBuffer is loaded in to memory and I draw from that allocated memory. The random GL_POINT is to see where (x,y) currently is.


@Override
public void render(Graphics g)
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
g.rotate(x, y, angle);
g.drawLines();
glPopMatrix();
}


This is my drawLines() implementation, the variables seen inside are handled by a gameObjectManager which is not in these snippets ( no need )


public void drawLines()
{
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, currentVertexHandle);
glVertexPointer(numCoordinates, GL_FLOAT, 0, 0L);
glDrawArrays(GL_LINES, 0, numPairVertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_VERTEX_ARRAY);
}


Finally here is my rotatation implementation, it use to work fine when I used immediate mode rendering but now that I have VBOs it does not work the same


public void rotate(float x, float y, float angle)
{
glTranslatef(x, y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-x, -y, 0);
}
Advertisement
Why are you doing the -x, -y translation? I assume the verts in the VBO are in object space already?

Why are you doing the -x, -y translation? I assume the verts in the VBO are in object space already?


Because this is the method I used when I was using intermediate mode rendering. If I remove -x, -y translation the rotation error becomes even greater ( or less accurate ).

This is what I do to create the lines and store them to memory


Line[] lines = new Line[] { new Line(x, y - height / 4, x + width / 3, y + height / 4),
new Line(x + width / 3, y + height / 4, x, y), new Line(x, y, x - width / 3, y + height / 4),
new Line(x - width / 3, y + height / 4, x, y - height / 4) };
vertexHandle = glGenBuffers();
vertexBuffer = BufferUtils.createFloatBuffer(lines.length * Line.numIndividualVertices);
numCoordinates = Line.numCoordinates;
numPairVertices = lines.length * numCoordinates;
for (Line line : lines)
{
vertexBuffer.put(new float[] { line.getX1(), line.getY1(), line.getX2(), line.getY2() });
}
vertexBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, vertexHandle);
glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
What happens if you try

glRotatef(angle, 0, 0, 1);
glTranslatef(x, y, 0);

What happens if you try

glRotatef(angle, 0, 0, 1);
glTranslatef(x, y, 0);


That doesn't work either... I feel like if someone could see what was happening they could figure it out so he is a video of what is happening.. notice the dot witch is the x,y coordinate and then notice the ship

https://www.dropbox.com/s/52mq14gj8b80mb4/Untitled.mp4
to do rotations, you have to translate the object to its rotational origin, called a PIVOT position, then rotate it there, and translate it back!
if your object is a box created at (0,0) and all the way to (1,1), you have to translate it to (-0.5, -0.5) to rotate it around itself
however, if your box was created from (-0.5, -0.5) to (0.5, 0.5) you can rotate it immediately, because its rotational origin is now (0, 0) from the start, if you wanted to rotate it around itself!

3ds max (or any other 3d CAD) is a great tool to visualize how this works

to do the same thing with your model, you need to know its dimensions, and then its half-sizes, then translate it backwards so that the object is positioned with (0, 0) at the center of the object, then rotate it there (if that's what you wanted to do)

from looking at the ship creation code from the link.. its hard for me to understand how exactly it is created, except to say i never would be doing it that way myself :S
i'm sure theres some logic to it though!

to do rotations, you have to translate the object to its rotational origin, called a PIVOT position, then rotate it there, and translate it back!
if your object is a box created at (0,0) and all the way to (1,1), you have to translate it to (-0.5, -0.5) to rotate it around itself
however, if your box was created from (-0.5, -0.5) to (0.5, 0.5) you can rotate it immediately, because its rotational origin is now (0, 0) from the start, if you wanted to rotate it around itself!

3ds max (or any other 3d CAD) is a great tool to visualize how this works

to do the same thing with your model, you need to know its dimensions, and then its half-sizes, then translate it backwards so that the object is positioned with (0, 0) at the center of the object, then rotate it there (if that's what you wanted to do)

from looking at the ship creation code from the link.. its hard for me to understand how exactly it is created, except to say i never would be doing it that way myself :S
i'm sure theres some logic to it though!


Ok so now the rotation works correctly. I translate back to the starting x,y rotate it there but how do i move the ship to where the current x,y are?

And yes my code may be a little confusing but its hard to stay true to object oriented programming when all the OGL tutorials I have found don't seem to code with that convention... sad.png

This is my modified code


@Override
public void render(Graphics g)
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
glTranslatef(startx, starty, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-startx, -starty, 0);
g.drawLines();
glPopMatrix();
}
change glTranslatef(-startx, -starty, 0);
to:
glTranslatef(new_x - startx, new_y - starty, 0);

change glTranslatef(-startx, -starty, 0);
to:
glTranslatef(new_x - startx, new_y - starty, 0);


This does not work


@Override
public void render(Graphics g)
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
glTranslatef(startx, starty, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(x - startx, y - starty, 0);
g.drawLines();
glPopMatrix();
}
I got it I forgot the all this is done slightly backwards so here is the working code if anyone wants to know

So I translate to the startx, starty then i rotate around it, I translate to -startx, -starty ( all that is done is g.rotate(..) ) then I translate to the current x,y coordinates of the object. As you can see in the following code those steps are implemented backwards in the code but are interpreted in the correct order by OGL. a little confusing but its not that bad smile.png. Thanks for all the help guys!!



@Override
public void render(Graphics g)
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
glTranslatef(x - startx, y - starty, 0);
g.rotate(startx, starty, angle);
g.drawLines();
glPopMatrix();
}

This topic is closed to new replies.

Advertisement