0% found this document useful (0 votes)
144 views6 pages

Computer Graphic Final Project

This document summarizes a computer graphics final project that simulates a dragon firework. It loads a 3D dragon model, animates the dragon's movement along a designed path using matrix transformations, and implements a particle system to simulate the explosion of fireworks. It discusses using retained and immediate OpenGL modes and transitions between the two. SDL is used to sequence the dragon flight and subsequent firework explosions.

Uploaded by

api-303634380
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
144 views6 pages

Computer Graphic Final Project

This document summarizes a computer graphics final project that simulates a dragon firework. It loads a 3D dragon model, animates the dragon's movement along a designed path using matrix transformations, and implements a particle system to simulate the explosion of fireworks. It discusses using retained and immediate OpenGL modes and transitions between the two. SDL is used to sequence the dragon flight and subsequent firework explosions.

Uploaded by

api-303634380
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Summary on Computer Graphic Final

Project
Li Yicheng
Leiden Institution of Computer Science
[email protected]
Abstract
This document illustrates several interested topics in computer graphic, including the movement of
an object using matrix transformation with the demonstration of a flying dragon, two different modes in
developing openGL programs: retained mode and immediate mode and the designing of particle system
with the demonstration of firework in which some fuzzy operations was introduced. SDL was used so that
the two different scenes - the dragon as the firework rocket and the explosion of firework can be arranged
in good time sequence.

I. Introduction

II. Dragon Rocket


I.

First we ask for the 3-D model from those 3-D


model designers, such 3-D models can be created with softwares like 3Ds-Max, AutoCAD,
Maya etc. There are several ways to store the
data of the model, and one of the file type is
the Wavefront .obj file. This file can be easily
open with the common text editor. The most
common elements in the file are geometric vertices, texture coordinates, vertex normals and
polygonal faces. In this projects, since there
is no light sources in the environment and no
texture is used to modify the dragon, and the
dragon should looks like particles forming together, therefore, only the vertices data are
used. A vertex can be specified in a line starting with the letter "v". That is followed by
(x,y,z[,w]) coordinates. W is optional and defaults to 1.0. Some applications support vertex
colors,by putting red,green,and blue values after x,y and z.The following show a snippet of
a Wavefront .obj file.

The initial goal of this final project is to simulate the dragon fireworks from Gandalf in the
movie, The Fellowship of the Ring(2001). The
basic idea is using the dragon as the rocket and
when the dragon flew far away and disappear
within our sight, a firework exploded at where
the dragon disappeared. The first problem to
solve is how to load a dragon model into our
program. The main problem I solve is that the
dragons self motion should correspond to the
path it follows. A simple path was designed
that the dragon flew towards the screen then
it turned around and flew far away from us.
Four different kinds of firework was designed,
there is the basic sphere mode, curtain shape
mode, which is from one point several particles
pouring down, laser mode, which is from one
point particles pop out in a fast speed like the
laser. All the modes are just transformation
of a basic particle system class. The difference
are just how to define the moving path, the
kinematics of each particle system. These will
be further illustrated in later section.

Object Loader

# List of geometric vertices , with (x,y,z [, w


]) coordinates, w is optional and
defaults to 1.0.
v 0.123 0.234 0.345 1.0

special thank to Mark Hoekveen for his help in having taught me how to use SDL in the program

v ...
...
# List of texture coordinates, in (u, v [,
w]) coordinates, these will vary
between 0 and 1, w is optional and
defaults to 0.
vt 0.500 1 [0]
vt ...
...
# List of vertex normals in (x,y,z) form;
normals might not be unit vectors.
vn 0.707 0.000 0.707
vn ...
...
# Parameter space vertices in ( u [, v] [, w
] ) form; free form geometry
statement ( see below )
vp 0.310000 3.210000 2.100000
vp ...
...
# Polygonal face element (see below)
f 123
f 3/1 4/2 5/3
f 6/4/1 3/5/3 7/6/5
f ...
...

11 bool LoadObj :: loadOBJ(const char path){


12
FILE file = fopen(path, "r") ;
13
if ( file == NULL ){
14
printf ("Impossible to open the file !\n") ;
15
getchar() ;
16
return false ;
17
}
18
int count =0;
19
while( 1 ) {
20
count ++;
21
char lineHeader[128];
22
// read the first word of the line
23
int res = fscanf ( file , "%s", lineHeader);
24
if (res == EOF)
25
break;
26
// EOF = End Of File. Quit the loop .
27
// else : parse lineHeader
28
if ( strcmp( lineHeader, "v" ) == 0 ){
29
glm::vec3 vertex;
30
fscanf ( file , "%f %f %f\n", &vertex.x, &vertex.y, &
vertex.z );
31
vertices . push_back(vertex);
32
}else{
33
break;
34
}
35
}
36 }

Then later when create Vertex Buffer, we use


this class to read the vertices data and create
our buffer.

In this project, a class called Loadobj is created and since only the vertices are needed
the implementation is very simple and informal. The only thing we need to do is to judge
whether the beginning of a new line is actually a single letter v, if it is, then the following
three float numbers would be stored in a vector
with 3 element, such data struct a vector with
3 elements is defined in the glm library. Then
we push the single vertex to the whole vertices
structure and here the structure is defined in
the <vector> library. The whole vertices is the
member of the class LoadObj.
1
2
3
4
5
6
7
8
9
10

II.

Dragon Movement

The basic problem to solve in this part is to


make the self transformation corresponding to
the path which the object is following, as the
following figure shown:

/
originally created by Yicheng in Leiden
/
#include <vector>
#include <stdio.h>
#include <string>
#include <cstring>
#include "glm/glm.hpp"
#include "loadobj.hpp"

Figure 1: Movement Example: 2D

The velocity direction marked as blue dotted line should provide two information. First,
it is the tangent line of every point on the path.
Second, it reflects how much degree should
the object be rotated. Here the example is
only given in a 2-Dimensional case. And the
1
equations are obvious:
2
3
4
5

dy

tan() = dx
dx = v x dt
dy = vy dt
y = f (x)

6
7
8
9

I first design the path as a sin path. The


amplitude and the frequency can be adjusted
by user. The following is a code block showing how can the dragon rotate itself with the
path.
systime +=dt;
y_new=amplitudesin(frequencysystime);
mrotate = atan((y_newy_old)/(vzdt));
mat4 Rotating;
Rotating[0]= vec4(cos(mrotate),sin(mrotate),0.0f
,0.0f);
Rotating[1]= vec4(sin(mrotate),cos(mrotate),0.0f
,0.0f) ;
Rotating[2]= vec4(0.0f ,0.0 f ,1.0 f ,0.0 f ) ;
Rotating[3]= vec4(0.0f ,0.0 f ,0.0 f ,1.0 f ) ;
glUniformMatrix4fv(gRotate,1,GL_FALSE,&Rotating
[0][0]);
y_old=y_new;

f(x) is the estimate function of the path.


Generally, becasue we are building the sim- 10
ulatin of our nature, the dimension will not
go much higher than three dimensions.One
the code block is in a loop thus everytime the
angle can express the movement of an object
systime will be accumulated with dt, since
in 2D dimension, 2 angles will be sufficient in
the CPU is fast, we can expect a continous
3 Dimensions. Thus here if y is the function of
moving. The time tells us what is the exactly
x and z. and it shows what the path is, what
y position of the dragon now, and since we
we can get is the following equations:
remember the last time when the dragon is (I
use the yold to store the old data), it is eazy to
f ( x,z)
tan(1 ) = x
get the dy . In the project, the dragon is moving
f ( x,z)
tan(2 ) = z
towards us, therefore, the other velocity is vz ,
0
and clearly vz dt is the dz we want here. then
vertex = vertex matrix (1 , 2 )
the rotate angle is easily to be calculated by
d

arctan( dyz ). Then it is just applying the angle


into the rotating matrix.

then we apply the two angles in our rotation


matrix to tell how musch degree and in what
direction should the object rotate. However, in
the project, the 2-D movement is implemented.

Figure 2: Dragon Example

More complex path and movement can be


implemented using such method. But it does
not make sence if we would like to build further more intelligent simulation. Because what
I want is the path is formed by the dragons
own movement. Then all the equations may be
solved in the different direction. Such part will
not be talked about in this project.

III.

4
5
6
7
8 }

glDetachShader ( ShaderProgram , ShaderObj


);
g l D e l e t e S h a d e r ( ShaderObj ) ;
glUseProgram ( 0 ) ;
glDeleteProgram ( ShaderProgram ) ;

Then if you would like to go back to the retained mode, just create your objects again.
However, the problem here is if you have programmed in the immediate mode, it is not possible to keep on declaring the shader program
because the shader program also have effect
on the vertices you created in the immediate
mode. I tried and the program could run but
some ugly cube and shadow appears flashing
in the window you created, it is a bit scary!!
To conclude, it is still better to build all the
project on the retained mode.

OpenGL Retain Mode

At the beginning of the semester and in the


first several workshops, the immediate mode
is used. But the dragon rendering part is implemented with OpenGL Retain Mode. What
we should do in the retained mode is: we
do not call some function to actually render
something, instead we uodate an internal
model(typically a list of objects) which is maintained within the librarys data space. So
clearly from code we can see vertex buffer
objects, shader objects. And operations like
link the shader file to the shader program, compile the program, define the vertex attributes,
bind the object to the buffer etc. Compared to
Immediate Mode, the Retained Mode is more
efficient and can be shared among OpenGL
graphics contexts.

II.

Particle System

III. Firework
I.

Retained Mode -> Immediate Mode

Because I am more familiar to construct the


particle system with the Immediate Mode, now
there comes to the problem, how do we realize
having two modes together in one program.
In fact, it is not so hard , you only have to
1:unbind all the buffers, delete all the buffers,2:
detach the shader program from the shader obj,
delete the shader object and delete the shader
program. I implement such behavior with a
function, which looks like this:
1
2
3

void changeProgramState ( ) {
g l B i n d B u f f e r (GL_ARRAY_BUFFER, 0 ) ;
g l D e l e t e B u f f e r s (1 ,&VBO) ;

Figure 3: Firework Example

I create different classes for different kind of


particles, basicly all the particle system are the
same, the only differences are how the particles
behave in different systems.
First is the structure of a basic particle. What
attributes does it have? Here, I defined the
following structure for one single particle:
1 typedef s t r u c t
2 {

in the last frame were all kept on the screen.


Second, in each frame, I create a rectangle with
alpha equals to 0.1, so it is like wearing a vague
glass. The following shows what it looks like.

3
/ data /
4
vec3 p o s i t i o n ;
5
vec3 v e l o c i t y ;
6
vec3 a c c e l e r a t i o n ;
7
Color c o l o r ;
8
f l o a t age ;
9
float l i f e ;
10
float size ;
11 } P a r t i c l e ;

To make the firework more realistic, you have


to use the real physics model to generate the
relations between these attributes.
For instance, in color, there is one attribute
called alpha which tells how transparent a particle is. And a firework particle has its life
since it will not be shiny all the time. The relationship between these two is defined in the
following:
1
2

Figure 4: Movement Example: 2D

/ / i t e r i s j u s t one p a r t i c l e
f l o a t alpha = 1 ( i t e r > age ) /( i t e r >
life ) ;

IV.

When the particles age reach its life, it becomes transparent. Of course, the variables
velocity,position and acceleration are used to
modify how the particles would move and the
inner function between these variables is what
makes every particle system different.
The following is just a simple example of show- 1
ing how a round firework is created.
2
1
2
3
4
5
6
7
8
9

10

f l o a t posX , posY = 0 . 0 f ;
f l o a t dangle = 2 3 . 1 4 1 5 / ptlCount ;
f l o a t angle = 0 . 0 ;
for ( vector < P a r t i c l e > : : i t e r a t o r i t e r =
p a r t i c l e s . begin ( ) ;
i t e r ! = p a r t i c l e s . end ( ) ;
i t e r ++) {
i t e r > age += dt ;
/ / add t h e p a s s i n g
time ( d i f f e r i a n t i a l time )
angle += dangle ;
i t e r > v e l o c i t y = vec3 ( 2 0 cos ( angle ) ,
20 s i n ( angle ) , rand ( ) %30 1 5 . 0 f )
;
}

III.

Fuzzy Operation

How can we create the vague trail left by the


flying particle? As for me, two steps are taken
to build such visual effect. First,I do not clear
the screen every frame, so what were rendered

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Using SDL

It is lucky that I finally choose SDL instead of


glut to routine my program. The sequencial feature of SDL make it really easy to arrange different scenes like I am making a movie. Look
at the main loop:
while ( running )
{
handleEvent ( ) ;
newtime = SDL_GetTicks ( ) ;
i f ( newtime < 6 0 0 0 ) {
/ / m t r a n s l a t e += 3 . 5 f ;
t r a n s l a t e _ d i r e c t i o n =1;
handleEvent ( ) ;
RenderScene ( ) ;
SDL_GL_SwapBuffers ( ) ;
} e l s e i f ( newtime < 6 9 0 0 ) {
w rota te += 0 . 0 5 f ;
handleEvent ( ) ;
RenderScene ( ) ;
SDL_GL_SwapBuffers ( ) ;
} e l s e i f ( newtime <13100) {
/ / x p o s i t i o n = 47.0 f ;
/ / m t r a n s l a t e = 3 . 5 f ;
t r a n s l a t e _ d i r e c t i o n = 1;
handleEvent ( ) ;
RenderScene ( ) ;
SDL_GL_SwapBuffers ( ) ;
} else {
break ;
}

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

13.1 seconds, the dragon kept moving away


from the screen. then we change the state, to
render the firework.
Moreover, the SDL provides us with various
events to handle, and what I used those keyboard events to test how much degree should
the dragon rotate, how should the dragon scale,
since the model we loaded may provide a large
data, and we can easily control the camera.

}
changeProgramState ( ) ;
while ( running )
{
handleEvent ( ) ;
ps . s i m u l a t e ( 0 . 0 1 ) ;
ps_n . s i m u l a t e ( 0 . 0 1 ) ;
ps_n1 . s i m u l a t e ( 0 . 0 1 ) ;
ps_s . s i m u l a t e ( 0 . 0 1 ) ;
ps_d . s i m u l a t e ( 0 . 0 1 ) ;
renderGL_dragon ( ) ;
renderGL_lazer ( ) ;
renderGL_normal ( ) ;
renderGL_normal1 ( ) ;
renderGL_scatter ( ) ;
}

V.

Conclusion

Conducting the project provides me with another way to build and simulate models, while
I ususlly use Matlab to build simulations. And
computer graphic now started to intrigue me,
there is huge possibility that I would move on
to more study in Computer Graphics.

The code block shows that, very easy to read,


in the first 6 seconds, the dragon moves towards the screen, then between 6 sec and 6.9
sec, the dragon turned around, and then until

You might also like