2004. április 18., vasárnap

OpenGL III: Moving and rotating 3D shapes

Problem/Question/Abstract:

In this article I'll show you how to create 3D shapes, which is just an extension of the last article, also you'll see how to rotate around the same shape axis or rotate around other object (like the solar system)

Answer:

Ok, this is the 3rd of a series of articles on OpenGL, so far we have seen:

OpenGL I: Hello World, Setup a Delphi OpenGL Application
OpenGL II: Moving and rotating 2D shapes

Now we're gonna expand on the last article to create 3D shapes, rotate them around their own axis and rotating objects around some other object (like a solar system)

To accomplish such thing we're still going to use the same basic OpenGL instructions but because this is graphics, one line in the wrong place makes a huge difference As I stated in my last article, OpenGL just follows instructions like "move forward", "turn left X degrees", etc, so just with that you know is not the same:

"move forward 10 units", "turn left 90 degrees"
than:
"turn left 90 degrees", "move forward 10 units"

simple, right??
well, just those simple rules will make a difference when you want to rotate an object around it's own axis or around other object axis

Rotating in the object own axis would be something like:

"move to 0, 0, 0", "move forward 10 units", "turn left X degrees", "draw a shape", "inc(X, 1.0)"

very simple, we move to a fixed position (10 units forward) turn X degrees, X gets incremented later, so that makes the shape rotate around its own axis and then we draw the shape, and increment the angle

In Delphi would be something like:

glTranslatef(-0.5, 0.0, -15.0); // Move 0.5 Units Left And 15.0 units Into The Screen
glRotatef(rquad, 0.0, 1.0, 1.0); // Rotate The Quad On The Y and Z axis ( NEW )
glBegin(GL_QUADS); // We are going to draw a cube, so let's use QUADS
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.5, 0.5, -0.5); // Top Left
glVertex3f(-0.5, 0.5, -0.5); // Top Right
{.
.
.}
glEnd();

rquad := rquad + 1.0;

Now to rotate around that object we just drew, we would have to do the following:

"cancel previous rotation", "turn left X degrees", "move 3 units into screen",  "turn right Y degrees", "draw shape"
The first important thing to notice here is that we didn't use "move 0, 0, 0", which means we're going to keep drawing from the position where we drew the last shape
The second thing is cancelling the previous rotation, why is that? Because if you don't, when you move forward X units, is going to move into whatever direction the last angle was, that might be what you want, but if you want your shape to rotate in a different axis, then you have to cancel the rotation, and then rotate to where you want and then move... confusing? luckily you'll get to play with the source code and see what happens when you cancel and when you don't.
The third thing is rotating to the angle that you want (this actually makes the rotation around the first object posible)
Move 3 units into screen, This to separate the new shape from the last, if we don't move to any direction, we will draw this shape in the same place!, maybe rotated to a different angle but in the same coordinates
Finally we do a last rotation around a new variable angle and draw the shape. This last rotation will make the new object rotate around it's own axis just like the solar system, the earth rotates around the sun, and then also rotates around it's own axis, makes sense? I hope so

let's look at the Delphi code:

//Notice we don't use glLoadIdentity here, which means we are at whatever position we drew the quad
glRotatef(-rquad, 0.0, 1.0, 1.0); // Cancel the previous rotation!!!
glRotatef(rtri, 0.0, 1.0, 0.0); // Rotate The Triangle On The Y axis (around the quad)
glTranslatef(0.0, 0.0, 3.0); // Move 3.0 Units Into The screen
glRotatef(rtri, 0.0, 0.0, 1.0);
// Let's rotate the pyramid, while we rotate around the quad
glBegin(GL_TRIANGLES); // We're gonna draw a pyramid, so let's use TRIANGLES
glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(0.0, 0.5, 0.0); // Top Of Triangle (Front)
{.
.
.}
glEnd();

rtri := rtri + 2.0;

ok, that's it on explanations, here's the source code for the drawing procedure I added a polygon to the scene just to show you how to create them Also check the coloring mix on the pyramid

function DrawGLScene(): Bool; { All Rendering Done Here }
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //Clear Screen and Depth Buffer
glLoadIdentity(); //Reset The View

glTranslatef(-0.5, 0.0, -15.0); // Move 0.5 Units Left And 15.0 units Into The Screen
glRotatef(rquad, 0.0, 1.0, 1.0); // Rotate The Quad On The Y and Z axis ( NEW )
glBegin(GL_QUADS); // We are going to draw a cube, so let's use QUADS
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.5, 0.5, -0.5); // Top Left
glVertex3f(-0.5, 0.5, -0.5); // Top Right
glVertex3f(-0.5, 0.5, 0.5); // Bottom Right
glVertex3f(0.5, 0.5, 0.5); // Bottom Left

glColor3f(1.0, 0.5, 0.0);
glVertex3f(0.5, -0.5, -0.5); // Top Left
glVertex3f(-0.5, -0.5, -0.5); // Top Right
glVertex3f(-0.5, -0.5, 0.5); // Bottom Right
glVertex3f(0.5, -0.5, 0.5); // Bottom Left

glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.5, 0.5, 0.5); // Top Left
glVertex3f(-0.5, 0.5, 0.5); // Top Right
glVertex3f(-0.5, -0.5, 0.5); // Bottom Right
glVertex3f(0.5, -0.5, 0.5); // Bottom Left

glColor3f(1.0, 1.0, 0.0);
glVertex3f(0.5, -0.5, -0.5); // Top Left
glVertex3f(-0.5, -0.5, -0.5); // Top Right
glVertex3f(-0.5, 0.5, -0.5); // Bottom Right
glVertex3f(0.5, 0.5, -0.5); // Bottom Left

glColor3f(0.0, 0.0, 1.0);
glVertex3f(-0.5, 0.5, 0.5); // Top Left
glVertex3f(-0.5, 0.5, -0.5); // Top Right
glVertex3f(-0.5, -0.5, -0.5); // Bottom Right
glVertex3f(-0.5, -0.5, 0.5); // Bottom Left

glColor3f(1.0, 0.0, 1.0);
glVertex3f(0.5, 0.5, -0.5); // Top Left
glVertex3f(0.5, 0.5, 0.5); // Top Right
glVertex3f(0.5, -0.5, 0.5); // Bottom Right
glVertex3f(0.5, -0.5, -0.5); // Bottom Left
glEnd();

//Notice we don't use glLoadIdentity here, which means we are at whatever position we drew the quad
glRotatef(-rquad, 0.0, 1.0, 1.0); // Cancel the previous rotation!!!
glRotatef(rtri, 0.0, 1.0, 0.0);
// Rotate The Triangle On The Y axis (around the quad)
glTranslatef(0.0, 0.0, 3.0); // Move 3.0 Units Into The screen
glRotatef(rtri, 0.0, 0.0, 1.0);
// Let's rotate the pyramid, while we rotate around the quad
glBegin(GL_TRIANGLES); // We're gonna draw a pyramid, so let's use TRIANGLES
glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(0.0, 0.5, 0.0); // Top Of Triangle (Front)
glColor3f(0.0, 1.0, 0.0); // Green
glVertex3f(-0.5, -0.5, 0.5); // Left Of Triangle (Front)
glColor3f(0.0, 0.0, 1.0); // Blue
glVertex3f(0.5, -0.5, 0.5); // Right Of Triangle (Front)

glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(0.0, 0.5, 0.0); // Top Of Triangle (Right)
glColor3f(0.0, 0.0, 1.0); // Blue
glVertex3f(0.5, -0.5, 0.5); // Left Of Triangle (Right)
glColor3f(0.0, 1.0, 0.0); // Green
glVertex3f(0.5, -0.5, -0.5); // Right Of Triangle (Right)

glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(0.0, 0.5, 0.0); // Top Of Triangle (Back)
glColor3f(0.0, 1.0, 0.0); // Green
glVertex3f(0.5, -0.5, -0.5); // Left Of Triangle (Back)
glColor3f(0.0, 0.0, 1.0); // Blue
glVertex3f(-0.5, -0.5, -0.5); // Right Of Triangle (Back)

glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(0.0, 0.5, 0.0); // Top Of Triangle (Left)
glColor3f(0.0, 0.0, 1.0); // Blue
glVertex3f(-0.5, -0.5, -0.5); // Left Of Triangle (Left)
glColor3f(0.0, 1.0, 0.0); // Green
glVertex3f(-0.5, -0.5, 0.5); // Right Of Triangle (Left)
glEnd();

glLoadIdentity(); // Move to (0, 0, 0)
glTranslatef(1.5, 0.0, -6.0); // Move 1.5 Right and -6.0 intro screen
glRotatef(rpol, 0.0, 0.0, 1.0); // rotate on Z axis
glColor3f(0.0, 0.0, 1.0); // Add some color
glBegin(GL_POLYGON); // Draw A Polygon (I can put many points in here)
glVertex3f(-0.5, 0.5, 0.0); // Top Left
glVertex3f(0.0, 0.75, 0.0); // Upper point
glVertex3f(0.5, 0.5, 0.0); // Top Right
glVertex3f(0.5, -0.5, 0.0); // Bottom Right
glVertex3f(0.0, -0.75, 0.0); // Lower point
glVertex3f(-0.5, -0.5, 0.0); // Bottom Left
glEnd();

rtri := rtri + 2.0;
rquad := rquad + 1.0;
rpol := rpol + 1.0;

Result := True
end;

That's it, I hope it wasn't too confusing, play with the code, see what happens when you comment this or that line.


Nincsenek megjegyzések:

Megjegyzés küldése