# Lesson 3 Lists and Models

บทที่
3

รายการและแบบจ าลอง

In this lesson we take what we learned in lesson 2 and build on it. We will learn about
triangle lists and modeling.

You can use other planar polygons such as squares but when
using them you must make sure that the points are all

on the same plane. With triangles we
don't have the same worries. Any three points in space when connected form a planar
triangle. If you do use squares and accidentally use four points not in the same plane you will
get unpredictable erroneous results.

Y
ou can continue with the lesson 1 project you've already created and modified in
lesson 2. For continuity and to allow you to download the lessons as separate projects I will
be showing the new code in a new project called Lesson3.

If you didn't do lesson

2 you can get it
here
.

Up until now we have been putting all our drawing code in the display function. We
could continue to do this but you can imagine its going to get pretty
cumbersome once we
have a few hundred things on the screen; not to mention all the repetitive cut and paste code
blocks we would have. Lets start by encapsulating the code for drawing an object.

ิ่
งเหล่านี้คือส
ิ่
งที่เราต้องการ
:

1.
ล าดับช
ั้

(class)

าหรับรหัสโปรแกรมของวัตถุของเรา

2.
ฟังก์ช

นการวาด

(draw)

าหรับวัตถุ

3.
ตัวแปรสมาช

กแบบสาธารณะเพื่อที่จะใช

เก็บต าแหน่งของวัตถุในห้วงช

องอวกาศทั้ง
3

4.
ตัวแปรสมาช

กแบบสาธารณะส

าหรับเก็บการหมุนปัจจุบันของ
วัตถุในแกนทั้งสาม

5.
ตัวแปรสมาช

กส

าหรับเก็บค่าอัตราการหมุนของวัตถุในแกนทั้ง

3

Notice that we will be storing sets of 3 numbers for location, rotation and rate of
rotation.

6.
สร ้างล าดับช
ั้
นส

าหรับการเก็บค่าตัวแปรทศนิยม
3
ตัวโดยการสร ้างอินแสตนด์ส

าหรับล าดับช
ั้
นนี้เพื่อที่จะใช

เก็บ ต าแหน่ง
การหมุนและอัตราการหมุนส

าหรับวัตถุของเรา

7.
ฟังก์ช

นส

าหรับวัตถุของเราเพื่อที่จะใช

กับกรอบส

าหรับการท าแิิอนิเมช

คลิกที่แท็บ
“class”

กดเมาส

ปุ่มขวา เลือก
และ

สร ้างคลาสช
ื่

“glObject”

กดเมาส

ปุ่มขวาที่คลาส
“glObject”
เลือก
และเลือก

สร ้างฟังก์ช

นช
ื่

“draw”
โดยค่าคืนกลับเป็น
“void”
และไม่มีพารามิเตอร์

สร ้างฟังกัช

นสมาช

กแบบ
“public”

ื่

“tick”
โดยฟังก์ช

นเป็นแบบ
“void”
และ ไม่มีพารามิเตอร์
คลิกที่แท็บ
“class”
และคลิกเมาส

ปุ่มขวา
ที่
“project”
เลือก

คลิกที่แท็บ
“class”
และคลิกเมาส

ปุ่มขวาที่
“project”
และเลือก

สร ้างคลาสใหม่ช
ื่

“glPoint3D”

คลิกเมาส

ปุ่มขวาที่
“glPoint3D”
และเลือก

เพิ่มตัวแปรสมาช

กแบบ
“public” 3
ตัวช
ื่

x, y
และ
z
ชนิดข้อมูล
float

กดเมาส

ปุ่มขวาที่คลาส
“glObject”
และเลือก

เพิ่มตัวแปรสาธารณะอีก
3
ตัวให้กับค
ลาสนี้และให้เป็นชนิด
“glPoint3D”

ื่

“loc” “rotation”
และ
“rateRotate”

Expand the glObject class and double click on the def
ault constructor glObject(
void
)
you will notice that the 3

glPoint3D variables are listed here with a constructor input of (0).
This code was automatically generated by the IDE when we used the wizard to add variables
to the class. However there is not a
constructor for the glPoint3D class that takes an int as a
parameter. To correct this just erase the 0 in each of these lines so we will be calling the
default constructor for the glPoint3D class. The glObject constructor should look like this now.

Now we are ready to put code in our the glObject draw function. Most of this code you
have seen before in the display function for les
son 2. The notable changes are that we will
use a list of triangles to draw our cube on the screen instead of using the glut pre
-
function. It takes 3 points to make each triangle and since there are 6 side to a cube we will
have 12 triangles. At
first you might think we need 36 points (3 * 12) for the triangles but a
lot of the points are shared in common with neighboring triangles so we really only have 8
unique points in a cube (the corners). We also need to set the color for each of the triangl
es.
We will pick different colors for each triangle so we can see the cube well. We will set up
some arrays holding our floats so we can iterate through them when drawing the triangle list.
Expand the glObject class and double click on the draw function. P
ut the following code in
the draw function:

glPushMatrix();
// save matrix prior to transform

glTranslatef(loc.x, loc.y, loc.z);

glRotatef( rotation.x, 1.0, 0.0, 0.0 );

glRotatef( rotation.y, 0.0, 1.0, 0.0 );
is

glRotatef( rotation.z, 0.0, 0.0, 1.0 );

// 8 unique points in a cube

float

vert_xyz = {

{
-
10.0,
-
10.0,
-
10.0 },
// point 0

{
-
10.0,
-
10.0, 10.0 },
// point 1

{
-
10.0, 10.0,
-
10.0 },
// point 2

{
-
10.0, 10.0, 10.0 },
// po
int 3

{ 10.0,
-
10.0,
-
10.0 },
// point 4

{ 10.0,
-
10.0, 10.0 },
// point 5

{ 10.0, 10.0,
-
10.0 },
// point 6

{ 10.0, 10.0, 10.0 }
// point 7

};

int

tri_abc =

{

{0,2,4}, {4,2,6},
// Back

{0,4,1}, {1,4,5},
// Bottom

{0,1,2}, {2,1,3},
// Left

{4,6,5},
{5,6,7},
// Right

{2,3,6}, {6,3,7},
// Top

{1,5,3}, {3,5,7}
// Front

};

//the colors of each of the triangles

float

colors_rgb = {

{0.5f,0.1f,0.1f }, {1.0f,0.1f,0.1f },
// Red

{0.5f,0.5f,0.1f }, {1.0f,1.0f,0.1f },
// Yellow

{0.1f,0.5f,0.1f }, {0.1f,
1.0f,0.1f },
// Green

{0.1f,0.5f,0.5f }, {0.1f,1.0f,1.0f },
// Cyan

{0.1f,0.1f,0.5f }, {0.1f,0.1f,1.0f },
// Blue

{0.5f,0.1f,0.5f }, {1.0f,0.1f,1.0f }
// Magenta

};

// heres where we iterate through the triangle list

int

iTriTotal = 12;

int

iTriIndex = 0;

glBegin(GL_TRIANGLES); // this tells OpenGL to change the state to drawing triangles

for

( iTriIndex = 0; iTriIndex < iTriTotal; iTriIndex++ ) {

glColor3fv( colors_rgb[iTriIndex] );//set the color of the vertex

glVertex3fv( vert_xyz[tri_abc[iTriIndex]]

);//set the A vertex of the triangle

glColor3fv( colors_rgb[iTriIndex] );//set the color of the vertex

glVertex3fv( vert_xyz[tri_abc[iTriIndex]] );//set the B vertex of the triangle

glColor3fv( colors_rgb[iTriIndex] );//set the color of the vertex

glVe
rtex3fv( vert_xyz[tri_abc[iTriIndex]] );//set the C vertex of the triangle

}

glEnd();// take OpenGL out of the draw list state

glPopMatrix();// restore matrix after transform

Here's a screen capture of the function with indentations::

Notice we used a
rrays in the draw function. The reason we did this is that glVertex3fv
expects arrays as inputs. Even though this can be error prone with larger models we will use
simple arrays

for these simple examples.

You may to use this array method of defining
trian
gle lists in your larger projects if you like, but we will show you a more robust method
later so you can choose how you would like to implement your models.

Now that our glObject has some display code lets add an instance of it to our project
so we can se
e it in the scene.

Click on the class tab and right click on the MFCopenGL class and choose add and add
variable. Create a private class variable of type glObject named cube to the MFCopenGL class.

In the MFCopenGL class display function add "cube.draw();" just before the
"glutPostRedisplay();"
call.

Compile and run and press play. You should see:

The spinning cube from lesson
2 is in our upper left but now we have a triangle list
cube in the default location in the center of the scene.

In order to animate our new glObject we will need to put code in the glObject tick()
function and call that function from our main program.

Clic
k on the class tab and expand the glObject class. Double click on the tick(void)
member function. Put the following code in the tick() fucntion:

rotation.x = rotation.x + rateRotate.x;
//Increment the rotation about the X
-
axis

rotation.y = rotation.y + rat
eRotate.y;
//Increment the rotation about the Y
-
axis

rotation.z = rotation.z + rateRotate.z;
//Increment the rotation about the Z
-
axis

if
(rotation.x >= 360)

rotation.x = 0;
// this keeps out rotation in the range of 0 to 360 degrees

if
(rotation.y >= 360)

rotation.y = 0;
// this keeps out rotation in the range of 0 to 360 degrees

if
(rotation.z >= 360)

rotation.z = 0;
// this keeps out rotation in the range of 0 to 360 degrees

if
(rotation.x < 0)

rotation.x = 359;
// this keeps out rotation in the range of 0 t
o 360 degrees

if
(rotation.y < 0)

rotation.y = 359;
// this keeps out rotation in the range of 0 to 360 degrees

if
(rotation.z < 0)

rotation.z = 359;
// this keeps out rotation in the range of 0 to 360 degrees

I bet this code looks remarkably familiar doesn'
t it. That's a modified version of our
animation code we used in lesson 2. What we are doing is adding the rate of rotation value to
the rotation storage variable on each animation tick. Your tick function should look like this:

We will need to set the rate of rotation for our cube. In the default constructor for the

cube.rateRotate.x = 1;

cube.rateRotate.y =
2;

cube.rateRotate.z = 4;

The constructor should look like this:

In order to make the animation happen we will need to call it
in our loop. In our
display function put "cube.tick();" just before "cube.draw();"

Compile and run and press play. You should s
ee the frame cube from lesson 2 and the
spinning multicolored cube in the center.

Remember how we moved and shrank the frame
cube? See if you can move the new
cube to the lower right and shrink it to half size so it looks like this:

In order to move
our cube you may have realized you could set the loc variable for
cube in the MFCopenGL constructor just like we set the rotation.

You may be wondering where we set the scale for our cube. Some of you may have
just hard coded a "glScalef(0.5,0.5,0.5);" in the glObjects draw function while others may
have been more clever and added another variable to our glObject class. We will go

with the
latter method. Add a public member variable of type glPoint3D to the glObject class.

Fix the default constructor by r
emoving the 0 in (0).

Set the cube scale in the MFCopenGL default constructor.

Add a call to glScalef to the glObject draw function.

Remove the code left over from lesson 2 that draws the frame cube and replace it with
another instance of our glObject.

Did you get you scene to look like this?

If not here's the code:

The MFCopenGL with another glObject added.

The MFCopenGL default constructor.

The display function.

The display function is much easier to read now. Lets add two more cubes in the other
corners, but put all 4 cubes in an arra
y instead of instancing them separately. Use for loops
to iterate through your object array and vary the speed of rotation based on the position in
the array. This will give you visual feed back to indicate which cube is which on the screen.

The array declaration.

The constructor.

The display function.

That's it for this lesson. On your own try making models for other common shapes like
pyramid or sphere. Modeling software maybe needed for more complex shapes but you
should be able to do some simp
le ones by using graph paper and hand coding them.