You are on page 1of 14

212CR 3D Graphic Programming:

3D Planetary system
Florin Nicusor Coada
SID:2887289

Contents
Abstract

Page 3

The Task

Page 3

1.Background Theory

Page 3

1.1 The Sun

Page 3

1.2 The planets

Page 3

1.3 Setting-up the Solar System

Page 4

1.4 Setting up the cameras

Page 4

1.4.1 Camera 1

Page 4

1.4.2 Camera 2

Page 6

1.5 Creating The Universe

Page 6

1.6 The menu

Page 7

2. Methodology and results

Page 7

2.1 Creating the classes:


a. Planet class
b. Moon class
c. Asteroid class

Page 7
Page 7
Page 9
Page 9

2.2 Cameras settings

Page 10

2.3 Sun and skybox

Page 11

2.4 Textures

Page 12

2.5 The menu

Page 13

2.6 Sounds

Page 13

2.7 Lighting

Page 14

2.8 General programming concepts

Page 14

Conclusion

Page 15

References

Page 16

Abstract
The task was implementing a 3D planetary system based on computer
graphics principles. For this assignment glut has been used to create and
animate the Solar system. The development of the system started from a
piece of code offered by Prof. Fotis Liarokapis which was further developed
and turned into a planetary system. The simulation was done using glut
special functions and basic trigonometry for creating cameras and orbits.
The finished version of the task is a 3D application with basic menus and
user interactions with the system. Another important part of the project is
that the construction allows easy customization of the planetary system and
menus. This task was a very good chance for exercising programming
techniques and acquiring basic OpenGL knowledge.

The task
Implement a 3D planetary system based on computer graphics principles.
You will need to write from scratch a complete OpenGL programme that renders a
Sun with an orbiting planet and a moon orbiting the planet simulating a planetary
system.

1. Background theory
1.1 The Sun
For the complition of this task I have decided to start my project from a
example code offered by Prof. Fotis Liarokapis during the tutorials for 212CR 3D
Graphics Programming. The code presented a torus being orbited by a a light
source represented by yellow sphere. The first step taken towards the complition of
the task was changing the light source into a static object, which will later be
transformed into the Sun.
After setting the center of the solar system the planets started to be put in
place. The first planet in the system was done by simply drawing a solid sphere
with no colour or texture to stay and positioning it at a specified distance from the
Sun.
1.2 The planets
After adding the first planet I started to add a few more, which I named at
that point Mercury,Earth and Mars. Making the planets spin on an orbit was fairly
easy since this function was set up in the example that I was offered for the
tutorial classes. The only thing required in order to make the planets move on an
orbit was changing the axis of movement to Y, which initialy was set to X. An
additional spinning function has been added for makige the planets to spin aound
their self axis like in order to make it look more realistic. Because in the real
situation planets have different speeds I decided to do the same for my planetary
system and add different speeds to the planets.
Similar to the way I added planets around the Sun, I have decided to add a
moon around the planet I named Earth. The moon had the capacity to speen
around itself and on an determined orbit around a planet. Because drawing each
planet individualy maked the code look mesy I have decide to create a planet class

that included draw, spin and other functions about which I will talk later in the
Methodology section.
1.3 Setting-up the Solar System
The system I have decided to simulate in my project is the system in which
we live so I have used online information to try and represent a scale version of it.
The scale is only appli ed to the planets radius, distance from the sun, orbital
speed and the sun radius. Other elements represented in the system are placed to
demonstrate the functionality of the system.
Because the system I decided to simulate has an asteroid belt I have
implemented a simple model constructed from ransom shaped items placed on a
circle situated between two of my planets, Mars and Jupiter.
The distances were taken from Wikipedia.org , The Free Encyclopedia, and
were scaled down to be placed inside my aplication. The coversion made was by
using 1 unit of distance in OpenGL as 1 A.U. (Astronomic Unit) in the Solar system.
To keep the scale of the system I used a table, which is presented below:
Name
Satellites Nr.
Distance(from
Radius
Revolution
sun)
time
Mercury
0
0.4 A.U
0.016 A.U.
88
Venus
0
0.7 A.U.
0.04 A.U.
225
Earth
1
1 A.U.
0.04 A.U.
365
Mars
0
1.5 A.U.
0.02 A.U.
687
Jupiter
4
5.2 A.U.
0.44 A.U.
4,331
Saturn
2
9.5 A.U.
0.37 A.U.
10,759
Uranus
3
19.6 A.U.
0.16 A.U.
30,799
Neptune
1
30 A.U.
0.15 A.U.
60,190
0.93
A.U.
Sun
Asteroids belt
2.3 and 3.3
The initial source had the radius of the planets and the sun based on the
radius of the earth, e.g. the radius of Jupiter is approximately 11times the radius
of Earth. In order to maintain the scale, the radius of Earth measuring 6,378.1 Km
is converted into 0.04 A.U. From this point on, all the other planets radiuses have
been converted to Astral Units. Because the asteroids and the moons will be too
small if the scale is kept, their radiuses have been slightly increased.
1.4 Setting up the cameras
The application created has two types of camera. The first camera is defined
as a free roam camera, capable of going wherever the user might want, while the
second camera is a mobile camera that is orbiting around the Sun with the ability
of going closer or further from the Sun, based on the users needs. The second
camera is also available to move up and down allowing the user to watch the
system directly from above or below, while the first one is used mainly for closing in
on different planets, moons and even the sun. The movement and orientation of the
cameras is based on different techniques that will be presented below.
1.4.1 Camera 1
The main idea behind the camera 1 is to orient the camera on a sphere and
move towards the point to witch the camera is looking at. The advantages of this
camera are the possibility of free roaming and getting close to any point of interest,
like the asteroids belt, a moon, a planet, or a planetary ring. The base idea for the
camera was found in a tutorial presented on www.lighthouse3d.com/ website,
where the camera implement is changing its focus point on a circle and then is

moving towards it. The rotation is done by incrementing the rotation angle and
then applying a trigonometric function to that angle. By normalizing the sphere,
making the radius equal to 1, each coordinate will be the direct result of a
trigonometric function.
For the camera, the coordinates are calculated this way:
sin(angleX) for the x coordinate, where <angleX> is the angle
between the vectors (x1,z1) and (x2,z2) in the XZ coordinates system ;
z
(x2,z2)
(x1,z1)
x

-cos(angleX) for the z coordinate, where <angleX> is the same angle


as the one above;
sin(angleY) for the y coordinate, where <angleY> is the angle between
the vectors (x1,y1) and (x2,y2) in the XY coordinates system;
y
(x2,y2)
(x1,y1)
x

Camera 1
-Orientation: x, y, z axis
-Movement : x, y, z axis
-Advantages: free roam
-Drawbacks:
-the camera is unable to look
straight down or above
- possibility to get lost

Camera 1
O represents the point where the camera is place

1.4.2 Camera 2

This camera is based on a cylinder type movement. While the Sun remains
in the centre point of the cylinder, the radius and the height are suffering changes,
allowing the user to define new viewing perspectives. In other words, the camera is
moving on the outside of a cylinder by focusing always on the sun. Because the
first camera presented is based on trigonometric functions, I have decided to make
this camera using classic geometry, meaning the equation of the circle.
Moving the camera left or right is based on incrementing or decrementing
the value of x according to the type of movement the user wants to apply. After
getting the value of x, because the centre of the circle on which the camera is
moving the equation for finding the z value is
, where r is the radius.
The camera is also capable for up and down movements on the cylinder and
this has been made possible by changing the value of y according to the needs of
the user, without altering the value of x or z.
The last feature of the camera is the Zoom In or Out function. The
technique for zooming in or out is in fact based on increasing or decreasing the
radius for the cylinder base. The equation used is x=x*(r+size)/r, where x is the
coordinate on the x axis , r is the radius for the base of the cylinder, and size the
value used to increase or decrease the radius.
Camera 2
-Movement : x, z or y axis
-Advantages: simulate the orbit of a
planet
-Drawbacks:
-focus only on the sun
-no possibility for looking behind
the camera
-reduced orientation options
Camera 2 model

1.5 Creating The Universe


Making the background for the system black has made the system feel
unrealistic and increased the difficulty to orientate.
In order to improve this aspects of the application a
Skybox has been added. The skybox was created as
a sphere on which was applied a star map like
texture. Because the light source for the planetary
system has been set inside the sphere, the texture
that was applied was visible from the inside,
creating the impression of endless space. Even
though the skybox sphere has a big radius,
limitations have been added to the camera to avoid
it from getting outside the skybox.

Outside view of the Skybox

1.6 The menu


The main ideea of the menu was to create buttons and also to enable the use
of keyboard to navigate through the menu. This plan was however abandoned
because of the dificulty of creating buttons for the menu. As a result a new menu

was designed, based upon having a moving sun in the left part of the screen and
the instructions for the user o the right side. At the press of a buton the user can
go to the planetary system and start interacting with the application. The
application also uses a right-click base menu, available during the simulation.

2. Methodology and results


2.1Creating the classes:
a. Planet class
The first created class for the project has been the planet class. This class
has ben used to draw the planets, initialize and aply the textures, and other
features that the planets have.
Class variables:
The variables _x, _y, _z are used to store the position in the XYZ coordinates
system, while the _radius store the radius of the planet to be drawn. spin and
_speed variables are used to store the current rotation angle and the value used to
increment or decrement the rotation angle. texNr and *tag are used to store the
number of the texture to be applied and the named of the planet which will be later
printed. The *planet and planetTexture are used to define a new orthogon used
for aplying the textures stored in the second variable.
Because the planets can have none or multiple moons a vector of Moon
class type has been defined and an integer nrMoons has been used to store the
number of the moons.
Class functions:
The class constructor
Planet class header - variables
uses 6 arguments: x,y,z for the
_x,_y,_z coordinates, r for the
_radius value, the _speed value
which is used to alter the rotation
angle. The last value nr is
assigned to texNr variable.
The first listed function is
called init() and it is used to
initialize the textures
Planet class header - functions 1
for the planets and
also helps initializing textures for the moons.
The second listed function, draw() is the most important function of the
class and it is used for drawing the planet base, a solid sphere, apllying textures
and calling other functions used to draw the moons, the orbit and to print the
name for each planet. One of the biggest problem while creating this functions was
how apllying the textures. Because the spheres are by default drawn by the glut
library along the Z axis a rotation of 90 degrees along the X axis was required in
order to have the textures properly set.
//Rotate planet -90 on x axis, so the emispheres are
set corectlly
glRotated((GLdouble) -90, 1.0, 0.0, 0.0);

This rotation however changed the way the planets are spinning and
rotating, so for a rotation around the Y the rotation should in fact take place
around the Z axis.
//Spin planet around self axis
glRotated((GLdouble) spin*40, 0.0, 0.0, 1.0);

After drawing the spheres and applying the textures, the rings are being
drawn if the planet that is being drawn is Saturn or Uranus. The program checks if
the planet has a ring by looking if the *tag value is one of the planets mentioned
above and then calls the ring function.
if(tag=="Saturn") ring(20,0.2);
if(tag=="Uranus") ring(5,0.1);

The last stage of the draw() function is drawing the moons. This is done by
calling the draw function for each moon located in the moons vector.
for(i=0;i<nrMoons;i++)
{
moons[i].draw();
}

The Spin() function is used to increment the rotation angle stored in the
spin variable with the value stored in _speed. The function also checks to see if the
angle is greater than 360, and if it is true, will convert the angle to the first
quadrant.
The moon function is used to initialize the moons that will later spin around
the planet. This is done by calling the constructor of the moon class inside the
function. The k integer has the purpose to set which one of the moons from the
vector, if there is any, will be initialized.
The function setTextures() is used to store the textures path in the string
path[10] defined in the header. These textures will later be applied to planets.
setTag(char *s) and printTag() functions are used to store and print the
planets name. While the first functions just stores the name inside the *tag
variable, the second function is more complex and its not only used to print out
the stored value, but also to determine the planets position in the XZ coordinates
system using trigonometric functions.
angle=spin*2*M_PI/360;
int len, i;
//Set the new position for the text
glRasterPos3f(_x*cos(angle),_radius+0.1,-_x*sin(angle));

Because the spin angle is in degrees, a new angle variable is used to store
the same value written in radians.
In order to draw the orbit for the planet the function drawOrbit() has been
created. The function is called inside the draw function, before all the other
functions. It is mainly based on a function created to draw a circle by rotating a
vector. The idea for drawing the orbit was discussed in class during the lectures.
for(int i=0;i<360;i++)
{
angle = i*2*M_PI/360;
glVertex3f(_x*cos(angle),0,_x*sin(angle));
}

The function draws 360 points and connects them with lines giving the
impression of a circle.
Because the system was created using a scale, the speed of some planets
will be very low so a function updateSpeed() was created to increase and decrease
the value stored in the _speed variable.
The last function created was ring(float angle, double size) where angle is
used to rotate the ring around the Y axis and size sets the distance between the
inner and the outer radius of the ring.
One of the most important functions in the class is the constructor. Even
though it is only used to store values, it could also be used to add extra features to
the application, like placing the planets randomly on their orbit. This is done

assigning a random value, smaller than 360 and greater than0, to the spin value
that defines the rotation angle. By having a random value the planets will start to
spin each time from a different point.

b. Moon class
Even though the moon class is similar to the planet class, it does not
inherit it. It is defined as an independent class used to draw and animate the moon
or moons for each planet.
The variable _x, _y, _z, _spin, _speed and _radius have the same use and
purpose as the ones explained for the planet class.
As in the planet class described above the draw(),spinm() and init()
functions, have the role to draw the moons, define the rotation angle and initialize
the textures.
The textures are applied inside the draw() function, with the exception that
here all the moons have the same texture.

c. Asteroid class
This class is used to draw the asteroid belt. It is based on a random generation
of parameters like the x ,y and z coordinates and shape parameters used to define
the shape of the sphere. By using random values for the asteroids, the resulting
asteroid belt will be chaotic and will be similar to the model its trying to simulate.
The most important function for this class is the main constructor. The only
parameter sent, i, is used as an angle, to disperse the asteroids over a circle like
area.

Asteroid class constructor

Special features:
2.2 Cameras settings
The application makes use of two cameras, operating using the systems
described above. Both the cameras are keyboard controlled and have similar
controls. The function used to read the keys is a special glut function
glutKeyboardFunc(Keyboard) where Keyboards is a second function used for
reading keys and assigning action to them.
void Keyboard(unsigned char key, int A, int B) sending the ASCII code to be
read by a switch function.
if(cameraType==2) switch(key)

{
// Start rotation
case '1': glutIdleFunc(spinScene2); // Sets the global idle callback
break;
// Stop rotation
case '2': glutIdleFunc(spinScene1); // Sets the global idle callback
break;
//Camera 2
case 'a':
moveLeft();break;
case 'd':
moveRight();break;

The cameraType variable is used to decide which one of the cameras is


working and will be modified. If the value is 1 the keyboard will work with the
Camera 1 while the value of 2 will enable the use of Camera 2. A special function
has been assigned for the # key, which will switch from one camera type to the
other. The switch between cameras is also enabled by right click mouse menu.
Camera 2
case '#':
cameraType=1;
break;

Camera 1
case '#':
cameraType=2;
break;

The functions for each camera have been defined using a special function file
camera.cpp and a header, camera.h, used for declaring the functions and the
variables altered during the simulation.
Because the cameras are based on different principles, different variables
have been constructed for each camera, and also each camera has its own call for
the gluLookAt() function that defines the viewing point.
Variables
//Camera 1
static float angleY=-0.630000,
angleX=0.180000, ratio;
static float x=-0.062538, y=23.972706,
z=43.393322;
static float lx=0.179030, ly=-0.589145,
lz=-1.0;

//Camera 2
static float speedL=-0.1,speedR=0.1;
static float xp=8.0, yp=2.0, zp=6.0,
side=1, radius=10;

Functions
//Camera 1
void moveMeFlat(int direction);
void orientMeX(float angx,float angy);
void orientMeY(float angx,float angy);
void setCamera1();

//Camera 2
void zoom(float size);
void moveUp(float speed);
void moveRight();
void moveLeft();
void setCamera2();

gluLookAt()
void setCamera1()
{
gluLookAt(x,y,z,
x+lx,y+ly,z+lz,
0.0, 1.0, 0.0);
}

void setCamera2()
{
gluLookAt(xp,yp,zp,
0,0,0,
0.0,1.0,0.0);
}

The variables are initialized with values that are used to set initial position of
the camera and the viewpoint. For Camera 1, the angles were initialized in order to
allow the user to continue the rotation of the viewpoint from the current angle. If
not initialized, the camera would jump from the current viewing point to the one
defined by the angleX=0 and angleY=0. The values used to initialize the cameras
were taken by reading them after manually setting the camera in the desired
position.

2.3 Sun and skybox


The Sun and the skybox will be explained in the same section of the report
because they have been done using similar methods and are both textured and
drawn using the same
The inner part of the sun
functions.
// Draw a sphere
The Sun is composed
gluSphere(sun, sunRad-0.02, 100, 100);
from two spheres spinning on
The outer part of the sun
different axes. This technique
//Enable blend mode, this will make textures
is used to create the sun of
Transparent
an active sun surface. Even
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
though both spheres have the
//set color and transparency below texture
same texture, a special
glColor4f(1.0,0.8,0.0,0.6);
function offered by the glut
//Spin sun along self-axis
library allowed the change in
glRotated((GLdouble) spin*2, 0.0, 0.5, -0.5);
the colour tone for the outer
//draw sphere
sphere. The same functions
gluSphere(sun, sunRad, 100, 100);
enabled the use of alpha channel that made the whole sphere transparent. In order
to achieve transparency only for the outer sphere the inner part of the sun has
been drawn before the outer part. The sunRad variable used to define the radius
for the inner and outer part of the sun is a global define constant with the value of
0.93(A.U.).
The skybox has been constructed using a similar technique as the one used
for the planets, moons and the Sun. A big sphere with a texture has been drawn
right after drawing the Sun. However, this solution is slowing down the program
because the time required applying the texture to a big item. The texture is light
from the inside and creates for the viewer the effect of endless space. This is though
a false assumption, because the cameras are set to stop the movement when they
get to close to the edges, allowing the user only to move only inside the sphere
where the system is placed. Because of the way it has been constructed, Camera2
in some special cases can go out from the sphere; however, this has been designed
to be big enough for the user to see the system without problems. The way the
texture is applied creates two black hole areas on the top and the bottom of the
skybox. For this reason, in those places, the application is displaying a Black
hole tag.

2.4 Textures
The textures for this project have been done using tutorials from the
internet. One of the most useful tutorial was found at
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Nu
mber=267363 . The users not only explained how the textures work, they also
published a piece of code that was used to load the textures for the application. As
stated inside the textures.cpp file, I do not present this piece of code as being
developed by myself. I do however understand the code that was presented and I
have decided to use it to texture items present in the planetary system. The code is

based upon loading .bmp files that are then read pixel by pixel and then applied to
an orthogonal. The same orthogonal is later used to represent the face of a sphere,
representing a moon, a planet, the Sun or the skybox.
The paths for the textures are stored in a string called path, which is
initialized each time a new planet class type object is created. For the moon, the
Sun and the skybox, a single path is directly defined.
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -2.0, 2.0);
planet = gluNewQuadric();
gluQuadricTexture( planet, GL_TRUE);
planetTexture = LoadBitmap(path[texNr].c_str());
//Initialize textures for the moons
Assigning textures path for the planet type items

2.5 The menu


The menu has been created by defining a still camera. In the left side of the
screen, the animated image of the Sun has been placed, in order to make the menu
feel more interactive. For printing the text in the menu, a simple text class has
been defined. The class stores the text to be printed, and the coordinates used to
define the text position. The class incorporates only one function, void print(),
void print()
{
int i,len;
glRasterPos3f(_x,_y,_z);
len = strlen(s);
//draw 1 item at a time
for (i = 0; i < len; i++)
{ if(_type==1) glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, s[i]);
if(_type==2) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i]);
}
}

used to display the required text. The class


Main menu
makes use of the inline that allows the
declaration of functions inside the header
file, without requiring an additional .cpp file.
Depending on the type of text that is displayed, title or subtitle, the
function glutBitmapCharacter will print one letter at a time, from a predefined
string s. The application will close the menu and begin the planetary system
simulation when the key Space is pressed, defined by the ASCII code of 32, the
pressing of these key will also produce some changes to the camera in order to
correctly display the system.

2.6 Sounds
The background sound for the planet system has been created with the use
of windows.h library. This library offers a simple audio rendering function
PlaySound("soundtrack.wav",NULL,SND_FILENAME|SND_LOOP|SND_ASYNC); . The function
loads a wave file which is looped for an infinite number of times or until the
application is closed. The sound is only available during the simulation. The initial
idea was to create a 3D sound coming from the Sun, but because the alut library
was not working properly, an easier method has been used instead. The

soundtrack has been kindly offered by Prof. Peter Every from Coventry University
and it is a track entitled no invisible thing from the album Recovery.

2.7 Lighting
To better simulate the solar system only one light source has been used.
This light source has been placed inside the sphere representing the Sun and it is
spreading a constant light over all the objects in the system including the skybox.
No other lighting parameter has been modified except the ambient light, which was
used to darken the hidden parts of the planets and the moons.
GLfloat ambient[] = {0.1,0.1,0.1,1.0};
//increase the darkness level for the hidden part of the planets and the moon
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);

There was no need for a light equation because glut does all these
calculations by itself.

2.8 General programming concepts


While programming one of the main reasons for creating classes was having
a clear and well laid out code. Special functions have been added for things like
calling the draw() function for the planet, asteroids, the sun and the skybox. By
adding these extra functions, those that are located in the main.cpp file are clearer
and easier to understand.

Conclusion
The project described above, represents the coursework for the 212CR 3D
Graphic Programming and was intended to demonstrate the ability to develop a 3D
graphics environment.
The system described above represents an approximate simulation of our Solar
System, by displaying planets, their approximate orbits, a sun, and other features.
A more exact approach would have been put into practice if more time had awarded
for this particular task. These changes would have included a new type of defining
the asteroid belt, a new style for the planets ring and even a possible particle
engine for the Sun.

References
1. Lighthouse 3D, (n/a) OpenGL Tutorials [online] available from
<http://www.lighthouse3d.com/opengl/> [20 November 2010]
2. Gold Standard Group,(2010) The OpenGL Programming Guide The Redbook[online]
available from < http://www.opengl.org/documentation/red_book/> [15 November 2010]
3. Gold Standard Group, (2010) Transparency, Translucency and Blending [online] available
from < http://www.opengl.org/resources/faq/technical/transparency.htm> [25 November
2010]

4. Gold Standard Group,(2010) Texture on a sphere [online] available from


< http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=267363> [23

November 2010
5. Gold Standard Group, (2010) OpenGL Documentation [online] available from
< http://www.opengl.org/sdk/docs/man/xhtml/ > [17 November 2010]
6. Liarokapis, F. (2010) Introduction to 3D Graphics Programming [online] available from <
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=12191> [ 10 November
2010]
7. Liarokapis, F. (2010) Introduction to OpenGL-GLUT [online] available from <
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=12940> [ 15 November
2010]
8. Liarokapis, F. (2010 Interaction and Callbacks [online] available from <
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=13424> [ 17 November
2010]
9. Liarokapis, F. (2010) Color [online] available from
<http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=12940> [ 25 November
2010]
10. Liarokapis, F. (2010) Introduction to OpenGL - Part I [online] available from
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=12945> [ 20 November
2010]
11. Liarokapis, F. (2010) Introduction to OpenGL - Part II [online] available from
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=12946> [ 25 November
2010]
12. Liarokapis, F. (2010) Introduction to OpenGL - Part III [online] available from
< http://moodle.coventry.ac.uk/ec/mod/resource/view.php?id=14305> [ 25 November
2010]

You might also like