Download as pdf or txt
Download as pdf or txt
You are on page 1of 44

VISVESVARAYA TECHNOLOGICAL UNIVERSITY

“Jnana Sangama”, Belgaum-590018, Karnataka

BANGALORE INSTITUTE OF TECHNOLOGY


K.R. Road, V.V.Puram, Bangalore-560 004

OpenGL mini project on

An Amusement Park

Submitted by

Karthik A (1BI10CS040)

For the academic year 2012-2013

Department of Computer Science & Engineering


Bangalore Institute of Technology
Bangalore-560004
VISVESVARAYA TECHNOLOGICAL UNIVERSITY
“Jnana Sangama”, Belgaum-590018, Karnataka

BANGALORE INSTITUTE OF TECHNOLOGY


Bangalore-560 004

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

Certificate
This is to certify that the Project work entitled “An Amusement Park” has been
successfully completed by the student Karthik A (1BI10CS040) of VI semester B.E. for the
partial fulfillment of the requirements for the Computer Graphics and Visualization in Computer
Science & Engineering of the VISVESVARAYA TECHNOLOGICAL UNIVERSITY during
the academic year 2012-2013.

Internal Guides:
1. Prof. Nagamani D. R, Dr. Nandagopalan S,
Assistant Professor Professor and Head,
2. Prof. Girija J, Department of CSE,
Associate Professor Bangalore Institute of Technology,
Department of CSE, K.R. Road, V.V. Puram,
Bangalore Institute of Technology, Bangalore - 560004
K.R. Road, V.V. Puram,
Bangalore – 560004

Examiners:
1.
2.
Chapter - 1
INTRODUCTION

Computer graphics is the creation and manipulation of picture with the aid of
computers. It is concerned with all aspects of producing pictures or images using a computer.
Computer graphics enables us to display the information in the form of graphical objects such
as pictures, charts, graphs and diagrams instead of simple text. The pictures or graphical objects
may vary from engineering drawings, business graphs and architectural structures to animated
movies. All the functionalities required for the development and presentation of such an
environment or interface to the user is provided by the graphics package.

1.1 Computer Graphics


Computer graphics plays a major role in the design of user interfaces. There are numerous ways
in which computer graphics has made user interaction fast, effective and easy. Graphics has
enabled the designers to introduce the concept of windows that act as virtual graphics terminals,
each of which is capable of running an independent application. The introduction of the mouse
has made the selection of objects on the interface easy by the “Point and Click” facility and a
lot more.

1.1.1 Applications of Computer Graphics


Computer Graphics finds its applications in a variety of fields. The applications of computer
graphics can be divided into four major areas:

1. Display of information

2. Design

3. Simulation and animation

4. User interface

Department of CSE, BIT 2012-2013 Page |1


Amusement Park Introduction

Display of information:
Computer graphics has enabled architects, researchers and designers to pictorially
interpret the vast quantity of data. Cartographers have developed maps to display the celestial
and geographical information. Medical imaging technologies like Computerized Tomography
(CT), Magnetic Resonance Imaging (MRI), Ultrasound, Positron Emission Tomography (PET)
and many others make use of computer graphics.

Design:
Professions such as engineering and architecture are concerned with design. They start
with a set of specification; seek cost-effective solutions that satisfy the specification. Designing
is an iterative process. Designer generates a possible design, tests it and then uses the results
as the basis for exploring other solutions. The use of interactive graphical tools in Computer
Aided Design (CAD) pervades the fields including architecture, mechanical engineering, the
design of very-large-scale integrated (VLSI) circuits and creation of characters for animation.

Simulation and animation:


Once the graphics system evolved to be capable of generating sophisticated images in
real time, engineers and researchers began to use them as simulators. Graphical flight
simulators have proved to increase the safety and to reduce the training expenses. The field of
virtual reality (VR) has opened many new horizons. A human viewer can be equipped with a
display headset that allow him/her to see the images with left eye and right eye which gives the
effect of stereoscopic vision. This has further led to motion pictures and interactive video
games.

User interfaces:
Computer graphics has led to the creation of graphical user interfaces (GUI) using which
even naive users are able to interact with a computer. Interaction with the computer has been
dominated by a visual paradigm that includes windows, icons, menus and a pointing device
such as mouse. Millions of people are internet users; they access the internet through the
graphical network browsers such as Microsoft internet explorer and Mozilla Firefox

Department of CSE, BIT 2012-2013 Page | 2


Amusement Park Introduction

1.2 OpenGL

OpenGL is a standard specification defining a cross-language API for writing applications that
produce 2D and 3D computer graphics. The interface consists of over 250 different function
calls which can be used to draw complex three-dimensional scenes from simple primitives.

1.2.1 Introduction to OpenGL


OpenGL (Open Graphics Library) is a hardware-independent, operating system independent,
vendor neutral graphics API specification. Many vendors provide implementations of this
specification for a variety of hardware platforms. Bindings exist primarily for the C
programming language, but bindings are also available for other popular languages. OpenGL
has been designed using a client/server paradigm, allowing the client application and the
graphics server controlling the display hardware to exist on the same or separate machines. The
network is transparent to the application.

OpenGL was developed by Silicon Graphics Inc. (SGI) in 1992 and is widely used in
CAD, virtual reality, scientific visualization, information visualization, and flight simulation.
It is also used in video games, where it competes with Direct3D on Microsoft Windows
platforms. OpenGL is managed by the non-profit technology consortium, the Khronos Group.

OpenGL's basic operation is to accept primitives such as points, lines and polygons,
and convert them into pixels. This is done by a graphics pipeline known as the OpenGL state
machine. Most OpenGL commands either issue primitives to the graphics pipeline, or
configure how the pipeline processes these primitives.

OpenGL serves two main purposes:

 To hide the complexities of interfacing with different 3D accelerators, by presenting the


programmer with a single, uniform API.
 To hide the differing capabilities of hardware platforms, by requiring that all
implementations support the full OpenGL feature set (using software emulation if
necessary).

Department of CSE, BIT 2012-2013 Page | 3


Amusement Park Introduction

1.2.2 Features of OpenGL


Some features of OpenGL include the following:

 Geometric and raster primitives


 RGBA or color index mode
 Display list or immediate mode
 Viewing and modeling transformations
 Lighting and Shading
 Hidden surface removal (Depth Buffer)
 Texture Mapping

OpenGL is a low-level, procedural API, requiring the programmer to dictate the exact
steps required to render a scene. These contrasts with descriptive APIs, where a programmer
only needs to describe a scene and can let the library manage the details of rendering it.
OpenGL's low-level design requires programmers to have a good knowledge of the graphics
pipeline, but also gives a certain amount of freedom to implement novel rendering algorithms.
OpenGL has historically been influential on the development of 3D accelerators, promoting a
base level of functionality that is now common in consumer-level hardware.

1.2.3 OpenGL Libraries

OpenGL can be accessed directly through functions in three libraries:

1. GL library (OpenGL in windows) – Main functions for windows.


2. GLU (OpenGL utility library) - Creating and viewing objects.
3. GLUT (OpenGL utility toolkit)- Functions that help in creating interface of windows

GL library contains the main functions for windows implementation. GLU library uses only
GL functions, but contains code for creating common objects and simplifying viewing. GLUT
is the OpenGL Utility Toolkit, a window system independent toolkit for writing OpenGL
programs. It implements a simple windowing application programming interface (API) for
OpenGL. GLUT makes it considerably easier to learn about and explore OpenGL
Programming.

Department of CSE, BIT 2012-2013 Page | 4


Amusement Park Introduction

Figure 1.1: Library Organization

The OpenGL Extension to the X Window System (GLX) provides a means of creating
an OpenGL context and associating it with an X Window System window.
To be hardware independent, OpenGL provides its own data types. They all begin with
"GL". For example GLfloat, GLint and so on. All symbolic constants begin with "GL_", like
GL_POINTS, GL_POLYGON. The commands have the prefix "gl" like glBegin().

1.2.4 OpenGL as a state machine


OpenGL is a state machine. It can be put into various states (or modes) that then remain in
effect until it is changed. As it is already seen, the current color is a state variable. The user can
set the current color to white, red, or any other color, and thereafter every object is drawn with
that color until the current set color to something else. The current color is only one of many
state variables that OpenGL maintains. Others control such things as the current viewing and
projection transformations; line and polygon stipple patterns, polygon drawing modes, pixel-
packing conventions, positions and characteristics of lights, and material properties of the
objects being drawn. Many state variables refer to modes that are enabled or disabled with the
command glEnable () or glDisable (). Each state variable or mode has a default value, and at
any point the user can query the system for each variable's current value.

For temporary state changes, the user should use these commands rather than any of the
query commands, since they're likely to be more efficient.

Department of CSE, BIT 2012-2013 Page | 5


Amusement Park Introduction

1.2.5 The Graphics Pipeline Architecture

OpenGL uses graphics pipeline architecture to convert high level specifications into low level
implementations. In graphics pipeline architecture, commands enter from the left and proceed
through what can be thought of as a graphics processing pipeline. Some commands specify
geometric objects to be drawn, and others control how the objects are handled during the
various processing stages. The graphics pipeline is built in stages. Every stage is specialized in
precisely one element of the rendering process. Once we are familiar with these tasks, we will
be able to recognize them in the designs of the GPU. Figure 1.2 gives an abstract, high-level
block diagram of how OpenGL processes data.

Display Lists:
All data, whether it describes geometry or pixels, can be saved in a display list for
current or later use. (The alternative to retaining data in a display list is processing the data
immediately - also known as immediate mode.) When a display list is executed, the retained
data is sent from the display list just as if it were sent by the application in immediate mode.

Figure 1.2: The Graphics Pipeline architecture

Evaluators:
The evaluator stage of processing provides an efficient means for approximating curve
and surface geometry by evaluating polynomial commands of input values. During the next

Department of CSE, BIT 2012-2013 Page | 6


Amusement Park Introduction

stage, per-vertex operations and primitive assembly, OpenGL processes geometric primitives
like points, line segments, and polygons, all of which are described by vertices. Vertices are
transformed and lit, and primitives are clipped to the viewport in preparation for the next stage
OpenGL performs to render an image on the screen.

Per-Vertex Operations:
For vertex data, next is the "per-vertex operations" stage, which converts the vertices
into primitives. Some vertex data are transformed by 4 x 4 floating-point matrices. Spatial
coordinates are projected from a position in the 3D world to a position on the screen. If
advanced features are enabled, this stage is even busier. If texturing is used, texture coordinates
may be generated and transformed here. If lighting is enabled, the lighting calculations are
performed using the transformed vertex, surface normal, light source position, material
properties, and other lighting information to produce a colour value.

Primitive Assembly:
Clipping, a major part of primitive assembly, is the elimination of portions of
geometry which fall outside a half-space, defined by a plane. Point clipping simply passes or
rejects vertices; line or polygon clipping can add additional vertices depending upon how the
line or polygon is clipped. Depending upon the polygon mode, a polygon may be drawn as
points or lines. The results of this stage are complete geometric primitives, which are the
transformed and clipped vertices with related colour, depth, and sometimes texture-coordinate
values and guidelines for the rasterization step.

Pixel Operations:
While geometric data takes one path through the OpenGL rendering pipeline, pixel data
takes a different route. Pixels from an array in system memory are first unpacked from one of
a variety of formats into the proper number of components. Next the data is scaled, biased, and
processed by a pixel map. The results are clamped and then either written into texture memory
or sent to the rasterization step. If pixel data is read from the frame buffer, pixel-transfer
operations are performed. Then these results are packed into an appropriate format and returned
to an array in system memory. There are special pixel copy operations to copy data in the frame
buffer to other parts of the frame buffer or to the texture memory. A single pass is made through

Department of CSE, BIT 2012-2013 Page | 7


Amusement Park Introduction

the pixel transfer operations before the data is written to the texture memory or back to the
frame buffer.

Texture Assembly:
An OpenGL application may wish to apply texture images onto geometric objects
to make them look more realistic. If several texture images are used, it's wise to put them into
texture objects so that it can be easily switched among them. Some OpenGL implementations
may have special resources to accelerate texture performance. There may be specialized, high-
performance texture memory. If this memory is available, the texture objects may be prioritized
to control the use of this limited and valuable resource.

Rasterization:
Rasterization is the conversion of both geometric and pixel data into fragments. Each
fragment square corresponds to a pixel in the frame buffer. Line and polygon stipples, line
width, point size, shading model, and coverage calculations to support antialiasing are taken
into consideration as vertices are connected into lines or the interior pixels are calculated for a
filled polygon. Colour and depth values are assigned for each fragment square.

Fragment Operations:
Before values are actually stored into the frame buffer, a series of operations are
performed that may alter or even throw out fragments. All these operations can be enabled or
disabled. The first operation which may be encountered is texturing, where a Texel is generated
from texture memory for each fragment and applied to the fragment. Then fog calculations may
be applied, followed by the scissor test, the alpha test, the stencil test, and the depth-buffer test.
Failing an enabled test may end the continued processing of a fragment's square. Then,
blending, dithering, logical operation, and masking by a bitmask may be performed. Finally,
the thoroughly processed fragment is drawn into the appropriate buffer.

Department of CSE, BIT 2012-2013 Page | 8


Chapter - 2
SYSTEM REQUIREMENTS

To be used efficiently, all computer software needs certain hardware components or other
software components to be present on a computer. These prerequisites are known as software
requirements. Though our graphics software does not demand strict specifications, certain basic
hardware and software requirements must be met.

2.1 Hardware Requirements

Table 2.1 specifies the minimum hardware requirements that must be met in order to run the
graphics software.

Processor Intel Pentium IV

System Memory 1 GB

Graphics Memory 64 MB

Secondary Memory 20 GB

Processor Speed 1.7 GHz

Keyboard Standard alphanumeric keyboard

Mouse Standard mouse

Display Resolution 1366 x 768

Table 2.1: Hardware requirements

Department of CSE, BIT 2012-2013 Page |9


Amusement Park System Requirements

2.2 Software requirements

Since GLUT is a cross platform library, the graphics software can be run on any platform that
GLUT supports. In our implementation, we have used a windows distribution of GLUT and
hence we expect the target machine to have windows distribution of GLUT library installed.
Table 2.2 outlines the minimum software requirements.

Operating System Windows XP

IDE Visual Studio 6.0

OpenGL Library GLUT for Windows

Graphic driver Compatible with Graphics hardware

Table 2.2: Software requirements

Department of CSE, BIT 2012-2013 P a g e | 10


Chapter - 3

DESIGN

3.1 Flowchart

A flowchart is a common type of chart that represents an algorithm or process showing the steps
as boxes of various kinds, and their order by connecting these with arrows. Flowcharts are used in
analyzing, designing, documenting or managing a process or program in various fields. Figure 3.1
shows the interactions between various components of the graphics software system as a flowchart.

Idle Start Mouse/Keyboard Input

Change colour
Main
Start/Stop movement
Flag set?
Navigation
Display
Yes
Change camera
Update Angle position
or Rotation and Draw Skybox
Roller Coaster
progress
Update state variables and
Draw Giant
movement flags
Wheel,
Columbus and
Roller Coaster

Quit

Stop

Figure 3.1: Flowchart showing organization of components

Department of CSE, BIT 2012-2013 P a g e | 11


Amusement Park Design

3.2 Algorithm

The design process of each component can be explained using algorithms. An algorithm is a step-
by-step finite list of well-defined instructions. Algorithms provide only high level descriptions,
but sometimes they can also provide implementation level details. The following sections describe
algorithms for each component created in this graphics software system.

3.2.1 Algorithm to draw a spinning Giant Wheel


1. Initialize rotation_angle = 0.
2. Create two circular rings using solid torus.
3. Draw a trolley on the edge (rim) of torus. Trolley is drawn using wired cube. To draw
multiple trolleys, rotate the original trolley with respect to the center of the torus multiple
times and draw it at every point. Also spin the trolleys in opposite direction about their
center so that they always remain upright.
4. The stand for the Giant Wheel is drawn using cylinders.
5. To rotate the giant wheel, rotate the torus about its center with an angle equal to
rotation_angle and also spin each trolley about its center with an angle equal to the
rotation_angle to make them appear always upright.
6. Increment the rotation_angle and go to step 2.

Rotate trolley about


center of the torus

Spin trolley
about its center

Figure 3.2: Second trolley formed by Figure 3.3: Second trolley made
rotating original trolley. upright by spinning about its center.

Department of CSE, BIT 2012-2013 P a g e | 12


Amusement Park Design

3.2.2 Algorithm to draw a swinging Columbus Ship

1. Initialize theta=0.
2. Scale the z axis about thrice its original scale and draw a sphere. Use a clipping plane to
cut it horizontally exactly about its center to form the Columbus ship body.
3. Stand of Columbus is visualized using cylinders.
4. Rotate the Columbus ship body about the center of the stand with an offset_angle where
the offset_angle is the product of a fixed offset and sine of the angle theta, where theta
varies from 0 to 360 degrees continuously.
5. Since sine of theta varies from +1 to -1, rotation angle of Columbus ship varies from
+offset_angle to -offset_angle. This gives a swinging effect to the Columbus ship body.
6. Increase the value of theta and go to step 2.

3.2.3 Algorithm to draw moving Roller Coaster

1. Initialize Roller coaster progress variable to 0.


2. Scale the z axis twice its original scale and draw a cube to make it look like a cuboid. Cut
the cuboid horizontally at the center to make the roller coaster body.
3. Place the roller coaster on the initial curve point.
4. Calculate the next roller coaster track point using Bezier curve function.
5. Place the roller coaster on the newly calculated point.
6. Calculate the angle made by the curve with the tangent, normal and bi-normal at new curve
point and rotate the roller coaster with respect to x, y and z axes about the calculated angles
to properly orient the roller coaster along the track.
7. Increment roller coaster progress variable. If the track is not complete, go to step 2. If track
is complete, stop.
Normal
Binormal
Tangent

Figure 3.4: Tangent, Normal and Binormal of a


curve at a point p.

Department of CSE, BIT 2012-2013 P a g e | 13


Amusement Park Design

3.2.4 Algorithm to draw a SkyBox environment

1. Create a cube. Use the six skybox images to texture map them on the six faces from the
inner side of the cube.
2. If the viewer moves horizontally or vertically in the scene, translate the center of the skybox
along with him so that he does not goes beyond the face of the skybox after moving
continuously.
3. If viewer rotates, rotate the skybox in opposite direction to give appropriate effect.
4. The ground is created using textured squares repeated like tiles of a floor.

Figure 3.5: Viewer along with the scene placed


inside the Skybox

Department of CSE, BIT 2012-2013 P a g e | 14


Chapter - 4
IMPLEMENTATION

Implementation is a stage where the planned activities are put into action. It is the realization
of a technical specification or an algorithm as a program or software component.

4.1 Modules
The module implementation of the graphics software system can be described in two stages:

1. OpenGL library functions description


2. User defined functions description

4.1.1 OpenGL functions

Initializes GLUT. The arguments from main are passed in


glutInit()
and can be used by the application.

Requests a display with the properties in mode. The value of


mode is determined by the logical OR of options including
glutInitDisplayMode()
the colour model (GLUT_RGB, GLUT_INDEX) and
buffering (GLUT_SINGLE, GLUT_DOUBLE).

glutInitWindowSize() Specifies the initial height and width of the window in pixels.

Creates a window on the display. The string can be used to


label the window. The return value provides a reference to
glutCreateWindow()
the window that can be used when there are multiple
windows.

Registers the display function that is executed when the


glutDisplayFunc()
window needs to be redrawn.

Registers the display callback function that is executed


glutIdleFunc()
whenever there are no other events to be handled.

Department of CSE, BIT 2012-2013 P a g e | 15


Amusement Park Implementation

Registers the mouse callback function. The callback function


returns the button (GLUT_LEFT_BUTTON,
GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON),
glutMouseFunc()
the state of the button after the event (GLUT_UP,
GLUT_DOWN), and the position of the mouse relative to the
top-left corner of the window.

Cause the program to enter an event-processing loop. It


glutMainLoop()
should be the last statement in main.

Sets the present RGBA clear colour used when clearing the
glClearColor()
colour buffer.

Sets the reshape callback for the current window. The reshape
callback is triggered when a window is reshaped. A reshape
glutReshapeFunc() callback is also triggered immediately before a window's first
display callback after a window is created or whenever an
overlay for the window is established.

Sets the keyboard callback for the current window. When a


user types into the window, each key press generating an
glutKeyboardFunc() ASCII character will generate a keyboard callback. The x and
y callback parameters indicate the mouse location in window
relative coordinates when the key was pressed.

Creates a new pop-up menu and returns a unique small


glutCreateMenu()
integer identifier.

glLoadIdentity() Sets the current transformation matrix to an identity matrix

Registers the display callback function that is executed


glutIdleFunc()
whenever there are no other events to be handled.

gluPerspective() Sets up a perspective projection matrix

Department of CSE, BIT 2012-2013 P a g e | 16


Amusement Park Implementation

It attaches a mouse button for the current window to the


identifier of the current menu. By attaching a menu identifier
to a button, the named menu will be popped up when the user
glutAttachMenu() presses the specified button. Button should be one of
GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, and
GLUT_RIGHT_BUTTON. Note that the menu is attached to
the button by identifier, not by reference.

Specifies which matrix will be affected by subsequent


glMatrixMode() transformations. Mode can be GL_MODELVIEW,
GL_PROJECTION or GL_TEXTURE.

Sets the parameter for face (GL_FRONT, GL_BACK or


glMaterialfv()
GL_FRONT_AND_BACK).

glLightfv() Sets scalar and vector parameters for light source.

Enables an OpenGL feature. Features that can be enabled


include GL_DEPTH_TEST, GL_,
glEnable()
GL_POLYGON_STIPPLE, GL_FOG and
GL_NORMALIZE.

Post multiplies the current matrix by a matrix determined by


gluLookAt() a viewer at the eye point looking at the point with the
specified up direction.

Sets the present RGB colours. The maximum and minimum


glColor()
values of the floating point types are 1.0 and 0.0 respectively

glRasterPosition() Specifies a raster position.

Renders the character with ASCII code char at the current


raster position using the raster font given by font. Fonts
glutBitmapCharacter()
include GLUT_BITMAP_TIMES_ROMAN_10. The raster
position is incremented by the width of the character

Department of CSE, BIT 2012-2013 P a g e | 17


Amusement Park Implementation

glutSwapBuffers() Swaps the front and back buffers.

glFlush() Forces any buffered OpenGL commands to execute

Requests that the display callback be executed after the


glutPostRedisplay() current callback returns.

Alters the current matrix by a displacement specified along x


glTranslatef() y and z directions.

gluCylinder() Draw a cylinder with height in z direction.

Define a sphere using slices lines of longitude and stacks


glutSolidSphere()
lines of latitude.

glutSolidTorus() Draw a solid torus (circular ring).

4.1.2 User defined functions

1. void set_material(int): Sets the material for a particular object.


2. int LoadBMP(char*): Loads a bitmap texture and returns the index of loaded texture.
3. void initSky(): Initializes SkyBox variables and textures.
4. void initLights(): Initializes the light intensity and position configuration.
5. void Draw_Skybox(float x, float y, float z, float width, float
height, float length): Draws a skybox at a specified point of required dimensions
6. void draw_ground(): Draws ground by repeating textured tiles.
7. void draw_gwheel(): Draws the giant wheel.
8. void draw_columbus(): Draws the Columbus ship.
9. void draw_wagon(): Draws the wagon for giant wheel.
10. void idle(): Updates state variables like rotation angle and Roller Coaster progress.
11. void draw_seat(): Draws seat at a required position.

Department of CSE, BIT 2012-2013 P a g e | 18


Amusement Park Implementation

12. void draw_wheels(): Draws wheels for Roller Coaster.


13. void draw_loco(): Draws the Roller Coaster locomotive.
14. void getCurveAt(double *x, double *y, double *z, int index, double
progress): Gets the next curve point calculated from the current progress.
15. void drawText(char* str, float x, float y, float z): Displays text on
the screen.
16. void display(): Display function draws all objects.
17. void displayReshape(int h, int w): Reshape callback function to maintain
aspect ratio.
18. double bezier(double a, double b, double c, double d, double t):
Applies Bezier function and returns the curve point.
19. void moveToBezier(double progress):Moves the camera to a specified point on
curve
20. void draw_cyl(float x1, float y1, float z1, float x2, float y2,
float z2, int radius, int subdiv): Draws a cylinder between two given points
with proper orientation.
21. void draw_bezier(): Draws the roller coaster track
22. void windowSpecial(int key, int x, int y): Handles navigational keys
movement
23. void kb(unsigned char key, int x, int y): Keyboard callback function to
respond to user inputs
24. void handleMouse(int x, int y): Handles mouse drag to rotate the view
25. void passiveMouse(int x, int y): Keeps track of mouse position
26. void place_camera(int action): Places camera at a specified position
27. void addMenu(): Adds submenu, defines callback handlers and attaches it to right-
click of mouse.
28. void main(int argc, char* argv[]): Creates a window of given size at a given
position, registers the call back functions and runs an event driven loop.

Department of CSE, BIT 2012-2013 P a g e | 19


Amusement Park Implementation

4.2 Code

#include<stdlib.h>
#include<GL/glut.h>
#include<GL/gl.h>
#include<stdio.h>
#include<math.h>
#include<windows.h>
const int SKY_FRONT=0, SKY_RIGHT=1, SKY_LEFT=2, SKY_BACK=3, SKY_UP=4, SKY_DOWN=5,
COLUMBUS=1, COLUMBUS_STAND=2, GWHEEL_RING=3, GWHEEL_TROLLEY=4, GWHEEL_TOP=5,
ROLLER_BODY=6, ROLLER_FRAME=7;

int ni=0,prevx=0, rcam=1,bezno,camw=0, roll=0, background=0, cswing=0,


gw=0,columbus_color=0, columbus_stand_color=0, gwheel_ring_color=0,
gwheel_trolley_color=0, roller_body_color=0;

GLint skybox[6], grass,help=0,x_r=0, y_r=0, z_r=0;

GLfloat viewer[3] = {1.0f, 0.0f, 0.0f},camera[3] = {0.0f, 0.0, 0.0};

GLdouble curr=0, prev=0,gw_spin = 0.0,angle=0.0,c_angle=90.0,gw_width = 8.0,


gw_radius=45.0,gw_x=-180.0, gw_y=50.0, gw_z=220.0,co_x=180.0, co_y=0.0,
co_z=80.0,lx=50.0,ly=50.0,lz=50.0,bez_prog=0.0,roller_speed=0.0150,gy=0,movcord[3]
={-150,-10,200};

double bez[][3]={{30,10,-200},{30,10,-110}, {30,10,10}, {30,10,50},


{30,70,100}, {60,90,140}, {80,80,100}, {70,80,70}, {0,50,80}};

void set_material(int m)

{ if(m==0)
{
float materialGrey[]={0.8,0.8,0.8},materialWhite[]={0.2,0.2,0.2};
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,materialGrey);
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,materialWhite);
}

if(m==COLUMBUS)

{ float materialColours[][3]={{1,0.6,0.3}, {0.2,0.2,0.2},


{0.6,0.6,0.6}, {0.75,0.164,0.164},{0.601,0.19,1.0}, {1,1,0}},
materialLightBr[]={0.2,0.2,0.0};

glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,
materialColours[columbus_color]);

glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,materialLightBr);

Department of CSE, BIT 2012-2013 P a g e | 20


Amusement Park Implementation

GLuint LoadBMP(const char *fileName)

{
FILE *file;
unsigned char header[54],*data;
unsigned int dataPos,size,width, height;
file = fopen(fileName, "rb");
fread(header, 1, 54, file);
dataPos = *(int*)&(header[0x0A]);
size = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (size == NULL)
size = width * height * 3;
if (dataPos == NULL)
dataPos = 54;
data = new unsigned char[size];
fread(data, 1, size, file);
fclose(file);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT,
GL_UNSIGNED_BYTE, data);
return texture;
}
void initSky()
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
skybox[SKY_DOWN] = LoadBMP("BMP11/down.bmp");
skybox[SKY_FRONT] = LoadBMP("BMP11/front.bmp");
skybox[SKY_BACK] = LoadBMP("BMP11/back.bmp");
skybox[SKY_RIGHT] = LoadBMP("BMP11/right.bmp");
skybox[SKY_LEFT] = LoadBMP("BMP11/left.bmp");
skybox[SKY_UP] = LoadBMP("BMP11/up.bmp");
grass=LoadBMP("BMP11/grass_1.bmp");
}

Department of CSE, BIT 2012-2013 P a g e | 21


Amusement Park Implementation

void initLights()
{
GLfloat whiteSpecularMaterial[] =
{1.0,1.0,1.0},light_post0[]={0.0,0.0,10.0,1.0},whiteSpecularLight[] = {1.0,
1.0, 1.0},blackAmbientLight[] = {0.3, 0.3, 0.3},whiteDiffuseLight[] = {1.0,
1.0, 1.0},mShininess[] = {50},twoModel[]={GL_TRUE};
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_SPECULAR, whiteSpecularLight);
glLightfv(GL_LIGHT0, GL_AMBIENT, blackAmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, light_post0);
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, twoModel);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, whiteSpecularMaterial);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mShininess);
}

void Draw_Skybox(float x, float y, float z, float width, float height, float


length){
glMatrixMode(GL_PROJECTION);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
x = x - width / 2;
y = y - height / 2;
z = z - length / 2;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,skybox[SKY_UP]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+width, y+height, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+width, y+height, z+length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y+height, z+length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y+height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D,skybox[SKY_FRONT]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+width, y, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+width, y, z+length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x+width, y+height, z+length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x+width, y+height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D,skybox[SKY_BACK]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y+height, z);

Department of CSE, BIT 2012-2013 P a g e | 22


Amusement Park Implementation

glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y+height, z+length);


glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z+length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D,skybox[SKY_RIGHT]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x+width, y+height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y+height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D,skybox[SKY_LEFT]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z+length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y+height, z+length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x+width, y+height, z+length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+width, y, z+length);
glEnd();
glBindTexture(GL_TEXTURE_2D,skybox[SKY_DOWN]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+width, y, z+length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y, z+length);
glEnd();
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
}

void draw_ground()
{ glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,grass);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(5000,-10,5000);
glTexCoord2f(800.0f, 0.0f); glVertex3f(5000,-10,-5000);
glTexCoord2f(800.0f, 800.0f); glVertex3f(-5000,-10,-5000);
glTexCoord2f(0.0f, 800.0f); glVertex3f(-5000,-10,5000);
glEnd();
glDisable(GL_TEXTURE_2D);
glLineWidth(5.0);
glTranslatef(0.0, -2, 0.0);
draw_bezier();
glTranslatef(0.0, 2, 0.0);
}

Department of CSE, BIT 2012-2013 P a g e | 23


Amusement Park Implementation

void draw_gwheel()
{
int num=12;
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
glPushMatrix();
initLightsforGW();
GLfloat twoModel[]={GL_FALSE};
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, twoModel);
set_material(GWHEEL_RING);
glTranslatef(0.0,0.0, gw_width);
glRotatef(-gw_spin,0,0,1);
draw_cyl(0,0,0,0,-55,20,1.5,8);
glTranslatef(0.0,0.0, -gw_width*2);
draw_cyl(0,0,0,0,-55,-20,1.5,8);
glTranslatef(0.0,0.0, gw_width*2);
glRotatef(gw_spin,0,0,1);
glutSolidTorus(1.0, 35.0, 16, 64);
gluDisk(quadric,0.0, 10.0, 10.0, 1);
glTranslatef(0.0,0.0, -gw_width*2);
glutSolidTorus(1.0, 35.0, 16, 64);
gluDisk(quadric,0.0, 10.0, 10.0, 1);
glTranslatef(0.0,0.0, gw_width);
for(int i=0; i<num; i++)
{ glEnable(GL_LIGHTING);
glPushMatrix();
glRotatef(360*i/num, 0.0, 0.0, 1.0);
glEnable(GL_DEPTH_TEST);
glTranslatef(0.0,0.0, gw_width);
draw_cyl(0.0, 45.0, 0.0, 0.0, 45.0, -5.0, 1.0, 12);
draw_cyl(0.0, 45.0, 0.0, 0.0, 2.0, 0.0, 1.0, 12);
glTranslatef(0.0,0.0, -gw_width*2);
draw_cyl(0.0, 45.0, 0.0, 0.0, 2.0, 0.0, 1.0, 12);
draw_cyl(0.0, 45.0, 0.0, 0.0, 45.0, 5.0, 1.0, 12);
glTranslatef(0.0,0.0, gw_width);
glDisable(GL_LIGHTING);
glTranslatef(0.0, -45.0, 0.0);
glRotatef(-gw_spin-(360*i/num)-sin(gw_spin/10)*10, 0, 0, 1.0);
set_material(GWHEEL_TROLLEY);
draw_wagon();
set_material(GWHEEL_RING);
glTranslatef(0.0, 45.0, 0.0);
glPopMatrix();
}
set_material(0);
twoModel[0]=GL_TRUE;
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, twoModel);
glPopMatrix();
glDisable(GL_LIGHT1);
}

Department of CSE, BIT 2012-2013 P a g e | 24


Amusement Park Implementation

void draw_columbus()
{
double eqn[]={0.0, -1.0, 0.0, 0.5};
glPushMatrix();
glEnable(GL_LIGHTING);
GLfloat twoModel[]={GL_FALSE};
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, twoModel);
set_material(COLUMBUS_STAND);
draw_cyl(0.0, 105.0,30.0,0.0,105.0,-30.0 ,1.0,10);
draw_cyl(0.0, 105.0,30.0,30.0,-10.0,30.0 ,1.0,10);
draw_cyl(0.0, 105.0,30.0,-30.0,-10.0,30.0 ,1.0,10);
draw_cyl(0.0, 105.0,-30.0,30.0,-10.0,-30.0 ,1.0,10);
draw_cyl(0.0, 105.0,-30.0,-30.0,-10.0,-30.0 ,1.0,10);
glTranslatef(0.0, 105.0, 0.0);
glRotatef(cos(c_angle*3.14/180.0)*50.0, 0.0, 0.0, 1.0);
draw_cyl(0.0, -70.0,-15.0,0.0,-2.0,-1.0 ,0.3,10);
draw_cyl(0.0, -70.0,15.0,0.0,-2.0,1.0 ,0.3,10);
glutSolidTorus(1.0, 3.0, 5, 8);
twoModel[0]=GL_TRUE;
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, twoModel);
glTranslatef(0.0, -70.0, 0.0);
glEnable(GL_DEPTH_TEST);
glClipPlane(GL_CLIP_PLANE0, eqn);
glEnable(GL_CLIP_PLANE0);
glScalef(3.0,1.0, 1.0);
set_material(COLUMBUS);
glutSolidSphere(15.0, 64.0, 64.0);
set_material(0);
glScalef( 1/3.0,1.0, 1.0);
glDisable(GL_CLIP_PLANE0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glScalef(3.0, 5.0, 3.0);
glTranslatef(11.5,0.0,0.0);
for(int c=0;c<6;c++)
{
glTranslatef(-3.2, 0.0, 0.0);
draw_seat();
}
glPopMatrix();

Department of CSE, BIT 2012-2013 P a g e | 25


Amusement Park Implementation

void draw_wagon()
{
GLdouble wagon_size=5.0;
double eqn[]={0.0, -1.0, 0.0, -3.5};
glPushMatrix();
glTranslatef(0.0, -5.0, 0.0);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE0, eqn);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glDisable(GL_CLIP_PLANE0);
for(int c=0;c<4;c++)
{
glRotatef((90/4.0), 0.0, 1.0, 0.0);
glNormal3f(1.0,0.0,0.0);
glutWireCube(wagon_size*2.0);
}
glPopMatrix();
}

void idle()
{
double bez_offset=0.000;
if(cswing)
{ c_angle++;
if(camw==2)
{ movcord[0]=-co_x-cos(c_angle*3.14/180.0)*50.0;
movcord[1]=-co_y-35-fabs(cos(c_angle*3.14/180.0))*35;
movcord[2]=co_z;
}
}

if(roll)
{ if(ni==bezno-2)
{ roll=0;
bez_prog=0.0;
ni=0.0;
viewer[0]=1.0;
viewer[1]=viewer[2]=camera[0]=camera[1]=camera[2]=x_r=0.0;
return;
}
if(bez_prog>=1.0)
{ ni++;

Department of CSE, BIT 2012-2013 P a g e | 26


Amusement Park Implementation

bez_prog=0.0;
}
bez_prog+=roller_speed;
moveToBezier(bez_prog+bez_offset);
}

if(gw)
{ gw_spin+=0.25;
if(camw==1)
{
movcord[0]=-gw_x+(gw_radius*sin(gw_spin*3.14/180))+ sin(gw_spin/10);
movcord[2]=gw_z;
movcord[1]=-gw_y-(gw_radius*cos(gw_spin*3.14/180.0))+6;
}
}
glutPostRedisplay();
}

void draw_seat()
{ glPushMatrix();
glEnable(GL_LIGHTING);
glTranslatef(1.0, 0.0, -1.0);
glRotatef(90.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.5, 0.0);
draw_cyl(-2.5,0.0,0.0,2.5,0.0,0.0,0.05,6);
glTranslatef(0.0,-0.5,0.0);
glNormal3f(0.0,1.0,0.0);
glScalef(4.0, 0.1, 1.0);
glutSolidCube(1.0);
glScalef(1/4.0, 1/0.1, 1.0);
glTranslatef(0.0, 0.5, -1.0);
glRotatef(80.0, 1.0, 0.0, 0.0);
glScalef(4.0, 0.1, 1.0);
glNormal3f(0.0,1.0,0.0);
glutSolidCube(1.0);
glScalef(1/4.0, 1/0.1, 1.0);
glPopMatrix();
}

void draw_wheels()
{
int i=0;
glPushMatrix();
glRotatef(90.0,1.0,0.0,0.0);

Department of CSE, BIT 2012-2013 P a g e | 27


Amusement Park Implementation

for(i=0;i<4;i++)
{ glutSolidTorus(0.2,0.3,4,16);
glTranslatef(0.0,2.0,0.0);
}
glPopMatrix();

void draw_loco()
{
int i;
double eqn[]={1.0, 0.0, 0.0, -0.5};
double eqnt[]={-1.0, 0.0, 0.0, 1.6};
glPushMatrix();
set_material(ROLLER_BODY);
glEnable (GL_LIGHTING);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE0, eqn);
glScalef(1.3, 2.0, 1.5);
glutSolidCube(3.0);
glScalef(1/1.3, 1/2.0, 1/1.5);
glDisable(GL_CLIP_PLANE0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glEnable(GL_CLIP_PLANE1);
glClipPlane(GL_CLIP_PLANE1, eqnt);
glTranslatef(0.0, 0.0, 3.0);
glutSolidTorus(0.2, 3.0, 10, 10);
draw_seat();
glTranslatef(0.0, 0.0, -1.5);
glutSolidTorus(0.2, 3.0, 10, 10);
glTranslatef(0.0, 0.0, -1.5);
glutSolidTorus(0.2, 3.0, 10, 10);
draw_seat();
glTranslatef(0.0, 0.0, -1.5);
glutSolidTorus(0.2, 3.0, 10, 10);
glTranslatef(0.0, 0.0, -1.5);
glutSolidTorus(0.2, 3.0, 10, 10);
glDisable(GL_CLIP_PLANE1);
set_material(0);
glTranslatef(2.5,1.0,0);
draw_wheels();
glTranslatef(-2.5,-1.0,0);
glTranslatef(2.5,-1.0,0);
draw_wheels();

Department of CSE, BIT 2012-2013 P a g e | 28


Amusement Park Implementation

for(i=0;i<4;i++)
{
draw_cyl(0,2.1,0,0,-0.1,0,0.1,12);
glTranslatef(0.0,0.0,2.0);
}
glPopMatrix();
}

void getCurveAt(GLdouble *ax,GLdouble *ay,GLdouble *az,int index,GLdouble atpoint)


{
if(ax) *ax=-
bezier(bez[0+index][0],bez[1+index][0],bez[2+index][0],bez[3+index][0],atpoint);
if(ay) *ay=-
bezier(bez[0+index][1],bez[1+index][1],bez[2+index][1],bez[3+index][1],atpoint);
if(az) *az=-
bezier(bez[0+index][2],bez[1+index][2],bez[2+index][2],bez[3+index][2],atpoint);
}

void display()
{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0,1.0,1.0,1.0);
glLoadIdentity();
gluLookAt(viewer[0], viewer[1], viewer[2],camera[0], camera[1],
camera[2],0, 1, 0);

getCurveAt(&tx,&ty,&tz,ni,bez_prog+0.058);
getCurveAt(&nx,&ny,&nz,ni,bez_prog+0.070);
gy=ny;
float
bz1=bezier(bez[0+ni][2],bez[1+ni][2],bez[2+ni][2],bez[3+ni][2],bez_prog+0.02)-
1*fabs(cos(angle*3.14/180.0));
float
bx1=bezier(bez[0+ni][0],bez[1+ni][0],bez[2+ni][0],bez[3+ni][0],bez_prog+0.02)-
1*fabs(sin(angle*3.14/180.0));
float
bz2=bezier(bez[0+ni][2],bez[1+ni][2],bez[2+ni][2],bez[3+ni][2],bez_prog+0.02)+1*fa
bs(cos(angle*3.14/180.0));
float
bx2=bezier(bez[0+ni][0],bez[1+ni][0],bez[2+ni][0],bez[3+ni][0],bez_prog+0.02)+1*fa
bs(sin(angle*3.14/180.0));
double degreer = atan2(1,bx2-bx1)*fabs(sin(angle*3.14/180.0))* 180 /
3.14+fabs(cos(angle*3.14/180.0))*atan2(1,bz2-bz1)* 180 / 3.14;
double angler = degreer ;
double degree= atan2(nz-tz, nx-tx);
angle = degree * 180 / 3.14;
double degreey= atan2(ny-ty,1);
double angley = degreey * 180 / 3.14;

Department of CSE, BIT 2012-2013 P a g e | 29


Amusement Park Implementation

glPushMatrix();
glTranslatef(-nx,-ny,-nz);
glRotatef(-angle, 0.0, 1.0, 0.0);
glRotatef(angley-90, 0, 0, 1.0);
glRotatef(angler-45, 0.0, 1.0, 0.0);
if(camw==0) angle=90.0;
glTranslatef(-2.5, 3.0, 0.0);
draw_loco();
glPopMatrix();
glPushMatrix();
glTranslatef(co_x, co_y, -co_z);
draw_columbus();
glPopMatrix();
glPushMatrix();
glTranslatef(gw_x, gw_y, -gw_z);
glRotatef(gw_spin, 0.0, 0.0, 1.0);
draw_gwheel();
glPopMatrix();
glutSwapBuffers();
}
void displayReshape(int width,int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65,(GLfloat)width/(GLfloat)height,0.01f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

double bezier(double x0, double x1, double x2, double x3, double t)
{
return 0.5f*((2.0f*x1)+(-x0+x2)*t+(2.0f*x0-5.0f*x1+4*x2-x3)*t*t+(-
x0+3.0f*x1-3.0f*x2+x3)*t*t*t);
}
void moveToBezier( double t)
{ int n=0.0;
viewer[0]=1.0;
viewer[1]= viewer[2]=0.0;
if(camw==3)
{ getCurveAt(&movcord[0],&movcord[1], &movcord[2], ni, t);
movcord[0]+=1.0;
movcord[1]-=3.5;

Department of CSE, BIT 2012-2013 P a g e | 30


Amusement Park Implementation

camera[0]=bezier(bez[0+ni][0],bez[1+ni][0],bez[2+ni][0],bez[3+ni][0],t+0.1)
-bezier(bez[0+ni][0],bez[1+ni][0],bez[2+ni][0],bez[3+ni][0],t);

camera[1]=bezier(bez[0+ni][1],bez[1+ni][1],bez[2+ni][1],bez[3+ni][1],t+0.1)-
bezier(bez[0+ni][1],bez[1+ni][1],bez[2+ni][1],bez[3+ni][1],t);

camera[2]=bezier(bez[0+ni][2],bez[1+ni][2],bez[2+ni][2],bez[3+ni][2],t+0.1)-
bezier(bez[0+ni][2],bez[1+ni][2],bez[2+ni][2],bez[3+ni][2],t);

if(gy<movcord[1]+2.5)
movcord[1]=gy-2.5;
glutPostRedisplay();
}
}

void renderCylinder(float x1, float y1, float z1, float x2,float y2, float z2,
float radius,int subdivisions,GLUquadricObj *quadric)
{ float vx = x2-x1,vy = y2-y1,vz = z2-z1;
if(vz == 0) vz = .0001;
float v = sqrt( vx*vx + vy*vy + vz*vz );
float ax = 57.2957795*acos( vz/v );
if ( vz < 0.0 )
ax = -ax;
float rx = -vy*vz;
float ry = vx*vz;
glPushMatrix();
glTranslatef( x1,y1,z1 );
glRotatef(ax, rx, ry, 0.0);
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluCylinder(quadric, radius, radius, v, subdivisions, 1);
gluQuadricOrientation(quadric,GLU_INSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glTranslatef( 0,0,v );
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glPopMatrix();
}
void draw_cyl(float x1, float y1, float z1, float x2,float y2, float z2, float
radius,int subdivisions)
{
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
renderCylinder(x1,y1,z1,x2,y2,z2,radius,subdivisions,quadric);
gluDeleteQuadric(quadric);
}

Department of CSE, BIT 2012-2013 P a g e | 31


Amusement Park Implementation

void draw_bezier()
{ GLfloat bx,by,bz,bx1,by1,bz1,bx2,by2,bz2,i=0.0;
int n=0;
glColor3f(1.0,1.0,0.0);
glDisable(GL_LIGHTING);
glPushMatrix();
for(n=0; n<bezno-2; n++)
{

for(i=0.0;i<=1.0;i+=0.015)
{
glBegin(GL_LINES);
bx1=bezier(bez[0+n][0],bez[1+n][0],bez[2+n][0],bez[3+n][0],i)-
1.3*fabs(sin(angle*3.14/180.0));
by1=bezier(bez[0+n][1],bez[1+n][1],bez[2+n][1],bez[3+n][1],i);
bz1=bezier(bez[0+n][2],bez[1+n][2],bez[2+n][2],bez[3+n][2],i)-
1.3*fabs(cos(angle*3.14/180.0));
glVertex3f(bx1,by1,bz1);
bx2=bezier(bez[0+n][0],bez[1+n][0],bez[2+n][0],bez[3+n][0],i)+1.3*fabs(sin(
angle*3.14/180.0));
by2=bezier(bez[0+n][1],bez[1+n][1],bez[2+n][1],bez[3+n][1],i);
bz2=bezier(bez[0+n][2],bez[1+n][2],bez[2+n][2],bez[3+n][2],i)+1.3*fabs(cos(
angle*3.14/180.0));
glVertex3f(bx2,by2,bz2);
glEnd();
}
glBegin(GL_LINE_STRIP);
for(i=0.0;i<=1.00;i+=0.02)
{
bz1=bezier(bez[0+n][2],bez[1+n][2],bez[2+n][2],bez[3+n][2],i+0.02)-
1.0*fabs(cos(angle*3.14/180.0));
bx1=bezier(bez[0+n][0],bez[1+n][0],bez[2+n][0],bez[3+n][0],i+0.02)-
1.0*fabs(sin(angle*3.14/180.0));
by1=bezier(bez[0+n][1],bez[1+n][1],bez[2+n][1],bez[3+n][1],i+0.02);
glVertex3f(bx1,by1,bz1);
}
glEnd();
glBegin(GL_LINE_STRIP);
for(i=0.0;i<=1.0;i+=0.02)
{

bz1=bezier(bez[0+n][2],bez[1+n][2],bez[2+n][2],bez[3+n][2],i+0.02)+1.0*fabs
(cos(angle*3.14/180.0));
bx1=bezier(bez[0+n][0],bez[1+n][0],bez[2+n][0],bez[3+n][0],i+0.02)+1.0*fabs
(sin(angle*3.14/180.0));
by1=bezier(bez[0+n][1],bez[1+n][1],bez[2+n][1],bez[3+n][1],i+0.02);

Department of CSE, BIT 2012-2013 P a g e | 32


Amusement Park Implementation

glVertex3f(bx1,by1,bz1);
}
glEnd();
glLineWidth(2.0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
for(i=0.0;i<=1.0;i+=1.00)
{
bx=bezier(bez[0+n][0],bez[1+n][0],bez[2+n][0],bez[3+n][0],i);
by=bezier(bez[0+n][1],bez[1+n][1],bez[2+n][1],bez[3+n][1],i);
bz=bezier(bez[0+n][2],bez[1+n][2],bez[2+n][2],bez[3+n][2],i);
draw_cyl(bx,by-0.5,bz,bx,-10.0,bz,0.5,12);
}
glDisable(GL_LIGHTING);
glLineWidth(2.0);
}
glFlush();
glPopMatrix();
}
void windowSpecial(int key,int x,int y)
{
if(key==GLUT_KEY_UP)
{ movcord[0]+=5*cos(-2.0*x_r*3.14/180.0);
movcord[2]+=5*sin(2.0*x_r*3.14/180.0);
}
if(key== GLUT_KEY_DOWN)
{ movcord[0]-=5*cos(-2.0*x_r*3.14/180.0);
movcord[2]-=5*sin(2.0*x_r*3.14/180.0);
}
if(key==GLUT_KEY_RIGHT) x_r+=3;
if(key==GLUT_KEY_LEFT) x_r-=3;
display();

}
void kb(unsigned char key, int x, int y)
{ if(key=='+') movcord[1]--;
if(key=='-') movcord[1]++;
glutPostRedisplay();
}
void handleMouse(int x,int y)
{ if((x-prevx)>=0) x_r+=1;
else x_r-=1;
prevx=x;
}

Department of CSE, BIT 2012-2013 P a g e | 33


Amusement Park Implementation

void passiveMouse(int x, int y)


{
prevx=x;
}
void place_camera(int action)
{
if(camw==3)
x_r=0;
camw=action;
if(camw==2)
{ movcord[0]=-co_x+cos(c_angle*3.14/180.0)*50.0;
movcord[1]=-co_y-38;
movcord[2]=co_z;
}
if(camw==3)
{ moveToBezier(bez_prog);
viewer[0]=1.0;
viewer[1]=viewer[2]=camera[0]=camera[1]=camera[2]=0.0;
x_r=-45;
}
if(camw==1)
{ movcord[0]=-gw_x +(gw_radius*sin(gw_spin*3.14/180.0)) +
sin(gw_spin/10.0);
movcord[2]=gw_z;
movcord[1]=-gw_y-(gw_radius*cos(gw_spin*3.14/180.0))+6;
}
if(camw==0)
viewer[1]=viewer[2]=camera[0]=camera[1]=camera[2]=0.0;
}

void handle_gwheel(int action)


{
if(action==0) gw==0?(gw=1):(gw=0);
}

void handle_columbus(int action)


{
if(action==0) cswing==0?(cswing=1):(cswing=0);
}
void handle_roller(int action)
{
if(action==0) {
roll==0?(roll=1):(roll=0);
viewer[0]=1.0;

Department of CSE, BIT 2012-2013 P a g e | 34


Amusement Park Implementation

viewer[1]=viewer[2]=camera[0]=camera[1]=camera[2]=x_r=0.0;
}
}

void menu(int action)


{
if(action==0) {
background=(background+1)%3;
initSky();
}
if(action==1) exit(0);
}

void handle_columbus_body(int action)


{ columbus_color=action;
}

void handle_columbus_stand(int action)


{ columbus_stand_color=action;
}

void handle_gwheel_ring(int action)


{ gwheel_ring_color=action;
}

void handle_gwheel_trolley(int action)


{ gwheel_trolley_color=action;
}
void handle_roller_color(int action)
{ roller_body_color=action;
}
void addMenu()
{
int submenu1,submenu2,submenu21, submenu22,submenu3, submenu31, submenu32,
submenu4, submenu41;
submenu1 = glutCreateMenu(place_camera);
glutAddMenuEntry("Free Movement",0);
glutAddMenuEntry("Inside Giant Wheel",1);
glutAddMenuEntry("On Columbus ship",2);
glutAddMenuEntry("On Roller Coaster",3);
submenu21 = glutCreateMenu(handle_gwheel_ring);
glutAddMenuEntry("Yellow",0);
glutAddMenuEntry("Silver",1);

Department of CSE, BIT 2012-2013 P a g e | 35


Amusement Park Implementation

glutAddMenuEntry("Pale red",2);
glutAddMenuEntry("Brown",3);
glutAddMenuEntry("Grey",4);
submenu22 = glutCreateMenu(handle_gwheel_trolley);
glutAddMenuEntry("Blue",0);
glutAddMenuEntry("Yellow",1);
glutAddMenuEntry("Grey",2);
glutAddMenuEntry("Pale red",3);
glutAddMenuEntry("Brown",4);
submenu2 = glutCreateMenu(handle_gwheel);
glutAddMenuEntry("Stop/Start Giant Wheel",0);
glutAddSubMenu("Giant Wheel frame colour",submenu21);
glutAddSubMenu("Giant Wheel trolley colour",submenu22);
submenu31 = glutCreateMenu(handle_columbus_body);
glutAddMenuEntry("Light Brown",0);
glutAddMenuEntry("Black",1);
glutAddMenuEntry("Grey",2);
glutAddMenuEntry("Dark Brown",3);
glutAddMenuEntry("Purple",4);
submenu32 = glutCreateMenu(handle_columbus_stand);
glutAddMenuEntry("Light Grey",0);
glutAddMenuEntry("White",1);
glutAddMenuEntry("Dark Grey",2);
glutAddMenuEntry("Brown",3);
glutAddMenuEntry("Dark Blue",4);
submenu3 = glutCreateMenu(handle_columbus);
glutAddMenuEntry("Stop/Start Columbus ship",0);
glutAddSubMenu("Columbus body colour",submenu31);
glutAddSubMenu("Columbus stand colour",submenu32);
submenu41 = glutCreateMenu(handle_roller_color);
glutAddMenuEntry("Silver",0);
glutAddMenuEntry("Gold",1);
glutAddMenuEntry("Dark Grey",2);
glutAddMenuEntry("Brown",3);
glutAddMenuEntry("Purple",4);
submenu4 = glutCreateMenu(handle_roller);
glutAddMenuEntry("Stop/Start Roller Coaster",0);
glutAddSubMenu("Roller Coaster colour",submenu41);
glutCreateMenu(menu);
glutAddSubMenu("Camera Position",submenu1);
glutAddSubMenu("Giant Wheel",submenu2);
glutAddSubMenu("Columbus ship",submenu3);
glutAddSubMenu("Roller Coaster",submenu4);
glutAddMenuEntry("Change Background",0);

Department of CSE, BIT 2012-2013 P a g e | 36


Amusement Park Implementation

glutAddMenuEntry("Quit",1);
glutAttachMenu(GLUT_RIGHT_BUTTON);

}
int main(int argc, char** argv)
{
bezno=(sizeof(bez)/24)-2;
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(800,600);
glutCreateWindow("Amusement Park");
initLights();
initSky();
glutDisplayFunc(display);
glutReshapeFunc(displayReshape);
glutKeyboardFunc(kb);
glutMotionFunc(handleMouse);
glutPassiveMotionFunc(passiveMouse);
glutIdleFunc(idle);
glutSpecialFunc(windowSpecial);
addMenu();
glutMainLoop();
return 0;
}

Department of CSE, BIT 2012-2013 P a g e | 37


Chapter - 5
SNAPSHOTS

Figure 5.1: Giant Wheel viewed from free movement camera.

Figure 5.2: Camera placed inside Giant Wheel trolley.

Department of CSE, BIT 2012-2013 P a g e | 38


Amusement Park Snapshots

Figure 5.3: Camera placed on the Columbus ship.

Figure 5.4: Columbus ship viewed from free movement camera.

Department of CSE, BIT 2012-2013 P a g e | 39


Amusement Park Snapshots

Figure 5.5: Camera placed on the moving Roller Coaster.

Figure 5.6: Roller Coaster viewed from free movement camera.

Department of CSE, BIT 2012-2013 P a g e | 40


Chapter - 6
CONCLUSION AND FURTHER ENHANCEMENTS

Conclusion

An Amusement Park simulator is developed in OpenGL using the library functions defined in
it. The graphics software system not only draws objects like Giant Wheel, Columbus and Roller
Coaster, but also adds rotation and motion effects to them. The Entire scene is placed in a
SkyBox for a realistic sky effect. The system also features first person movement, where the
viewer can move around anywhere in the scene.

The curves of Roller Coaster track is drawn using Bezier functions. Lighting effect is
also employed for a better 3D appearance. The graphics software system is found to be
successful in displaying an Amusement Park.

This graphics system can be used in:

 The graphics software system can be used as a Roller Coaster simulator.


 This system can be used as a virtual Amusement Park.
 This system can be used to study the motion of a trajectory along a curved path.

Further enhancements

 This system can also be modified as a game.


 The SkyBox can be modified to an Aircraft Simulator to train pilots.
 Other amusement park games can be added.

Department of CSE, BIT 2012-2013 P a g e | 41


BIBLIOGRAPHY

References:
[1] Edward Angel, “Interactive Computer Graphics A Top-Down Approach with
OpenGL”, 5th Edition, Pearson Education, 2004.
[2] F.S. Hill Junior, “Computer Graphics using OpenGL”, 2nd Edition, Pearson Education,
2001.
[3] http://www.opengl.org/resources/code/samples/redbook/
[4] http://stackoverflow.com/questions/4288367/how-to-rotate-and-then-move-on-that-
direction/
[5] http://stackoverflow.com/questions/6243693/move-object-along-a-bezier-path-in-3d-
rotation-problem
[6] http://nehe.gamedev.net/

You might also like