OpenGL Computer Graphics Project Report
OpenGL Computer Graphics Project Report
Contents
Executive summary 3
1 Project diary 4
7 Conclusions (Pierre-André) 21
8 Conclusions (Clare) 21
List of Figures
1 Overview of the program’s design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Example of functions used for animating the models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3 “Spaced in time” version of cos(t) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4 Rotation of the whole model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
5 Zooming the whole model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
6 Non-static camera modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
7 Model selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
8 A few visual indicators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
9 Showing meshes vertices’ normal vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
10 Comparison of rendering modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
11 Different levels of detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
12 Top-level scene graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
13 Graph for ps188_draw_scene() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
14 Graph for draw_dragon() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
15 Graph for draw_dragon_body() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
16 Graph for draw_dragon_upper() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
17 Graph for draw_dragon_tail() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
18 Graph for ps188_draw_p(), ps188_draw_a() and ps188_draw_s() . . . . . . . . . . . . . . . . . . . . . 17
19 Graph for cp133_draw_scene() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
20 Graph for draw_crab() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
21 Graph for draw_body_legs() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
22 Graph for draw_nest() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
23 Graph for draw_nest_qtr() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Executive summary
This document serves as an in-depth report on the OpenGL-based Computer Graphics final project, as presented
by Pierre-André Saulais and Clare Park. The project, which features three flying dragons above a crab and a nest,
responds to mouse clicks and selected key entries. Callback features include: zooming in and out, rotation around
axes, toggling axes, selecting different dragons to follow with the camera, viewing individual models, wire-frame
rendering, and panning. Each model is designed based on alphabetical models derived from the initial sets PAS and
CXP.
The report first lists key events in the project time-line. It is then followed by a top-level design overview of the pro-
gram, a graphical user manual, and detailed scene graphs, which show the hierarchical structures of the components.
The full code is included in the appendices.
1 Project diary
Thursday, 1st October (PA) Implemented a small prototype for the project: two roughly-shaped initials with support
for rotating, zooming and panning
Friday, 23th October Met to decide on the theme of the scene and models. Made sketches of possible models
10th November-12nd November (PA) Implemented 3D curves and cubes with normals and texture coordinates.
Recreated the initials with these primitives
12nd November–13rd November (PA) Created the dragon’s scene graph, model and textures
13rc November–14th November (PA) Added some animations for the dragon model
14th November–15th November (PA) Animation for the whole scene, instantiating the dragon model multiple times
12nd November–16th November (Clare) Created the model for the initials with colors and cartoonish look
Tuesday, 17th November (Clare) Created the model for the nest and crab using the initials
16th November–17th November Merged everyone’s code and made it work together
17th November–18th November Wrote the GUI manual
Wednesday, 18th November Demonstration of the program and its features
19th November–23rd November Wrote the group report
Monday, 23rd November Handed in the group report
Name Signature
Pierre-André Saulais
Clare Park
2.1 Communication
As can be seen in figure 1 on the following page, top-level routines and callbacks communicate through global vari-
ables. The keyboard and mouse callbacks modify parameters and settings that affect the way the scene should be
displayed (e.g. scene-wide rotation and scaling parameters, settings like drawing axes and normals). These param-
eters are then used by the display callback to render the scene. In addition the idle callbacks modify animation
parameters for each animated model, which are in turn used by the relevant xxx_draw_scene() function to render the
models with proper animation.
Each callback (excluding the display callback) calls the glutPostRedisplay() function. This causes GLUT to call the
display callback to refresh the screen with a newly rendered frame. If animation is enabled (i.e. the whole scene is
being rendered, not just one model) then the idle callback causes the program to render the scene as often as possible
(to have the highest possible FPS).
See appendices C.1.7 and D.1.3 for the declaration of global variables.
2.2 Animation
In the program animation is done in two different ways. Each has its advantages and drawbacks.
With the first way, distances and angles are incremented (or decremented) by a constant value. When the value of the
distance or angle becomes lower or greater than the limit, the initial value is restored. The advantages of this method
is that it is very simple to understand and implement. The downside is that the animation’s speed is dependent on
how fast frames are drawn (i.e. the animation speed is proportional to the scene’s FPS).
The second way uses the current time to determine the value of the distances or angles, combined with periodic
functions like cosine to ensure the animation is played repeatedly. The first advantage of this method is that it is not
dependent on the scene’s FPS. The second is that mathematical functions can be easily plotted (see figure 2 on the
next page) to make experimenting with animation easier.
The first downside is that pausing and then resuming the animation causes a very rough transition (the models seem to
instantly move to another point). The second is that it is harder to reason about. Indeed combining periodic functions
is not easy, four functions were needed to create a simple “spaced in time” version of the cosine function (see figure 3
on the following page). The source code for these functions can be found at the end of scene.c (appendix C.2.1).
Features in this section allow the user to control what is rendered and where.
3.1.1 Rotation
Pressing the ’Z’ or ’S’ keys respectively increases or decreases the rotation of the whole scene about the X axis; the ’E’
and ’A’, ’D’ and ’Q’ do the same for the Y and Z axes, respectively. The left button of the mouse can be used to rotate
the scene about the X and Y axes. Pressing the ’5’ key changes the current rotation angle for each axis to zero. See
figure 4 on the next page.
3.1.2 Zoom
Pressing the ’X’ or ’C’ keys respectively increases or decreases the zoom factor. The same can be done with the mouse
wheel if the system’s GLUT implementation supports it (e.g., on Linux). See figure 5 on page 8.
3.1.3 Panning
Pressing the mouse wheel button (or middle button) lets the user pan the whole scene in the X and Y axes. Similarly
to zooming using the mouse, this might not work depending on the GLUT implementation.
Pressing the ’1’, ’2’ or ’3’ key changes the current camera mode. The first mode is a static camera, while the second
rotates to follow the jumping dragon; the last one rotates to follow the flying dragon. See figure 6 on page 8.
(a) Camera following the jumping (bronze) dragon (b) Camera following the flying (black) dragon
Pressing the ’-’ and ’+’ keys changes the currently shown model. The default model is the whole scene, but each model
in the scene and their parts can be shown individually. See figure 7.
The ’.’ key toggles on or off grids for all three axes X, Y and Z. The origin is denoted by three unit vectors: a red vector
for the X axis, a green one for the Y axis and a blue one for the Z axis. See figure 8a.
(a) Axis grids (b) Frames Per Second counter (c) Wire-frame rendering
(a) Normal vectors shown for a letter (b) Normal vectors shown for the scene’s meshes
Pressing the ’!’ key toggles showing the FPS counter. This indicates the approximate number of frames being rendered
per second. Please note than this number is calculated with decent precision only if the animation is turned on, and
if the scene is animated (i.e. the whole scene is shown, not just individual models). See figure 8b on the preceding
page.
Pressing the ’W’ key toggles the wire-frame rendering mode on or off. See figure 8c on the previous page.
Normal vectors can be shown for some meshes in the scene (e.g. the dragons and the letters they hold), using the ’N’
key. For such meshes, every vertex’s normal vector is shown, but there is no proper scaling. Also, this noticeably slows
down the scene. See figure 9.
This section includes other features which can’t be sorted in the two previous categories but might otherwise be useful.
Pressing the ’R’ key resets all settings to their default values.
3.3.2 Animation
Pressing the space bar toggles the animation on or off. This only works if the whole scene is being shown. When
animation is toggled on again it usually doesn’t “pick up where it left off”, because animation for most meshes depends
on absolute time and not time relative to when animation is toggled on or off.
The ’V’ key toggles between using vertex arrays or immediate mode (e.g. calls to glBegin/glVertex/glEnd) for rendering
meshes. This only affects meshes whose normal vectors can be shown (e.g. dragons and the letters they hold). The
main purpose of this feature is to show the performance benefits of using vertex arrays. See figure 10.
Pressing the ’/’ or ’*’ keys respectively decreases or increases the level of detail of some meshes (e.g. dragon joints –
used for the neck, legs and tail – chest and tail end). This lets the user make a trade-off between realism of the model
and animation fluidity as more complex models take longer to render. See figure 11 on the following page.
As we have worked completely in parallel, the top-level scene graph — shown in figure 12 on the next page — is
trivially simple. Please see sections 5 and 6 for graphs detailing the ps188_draw_scene() and cp133_draw_scene()
nodes.
For readability reasons and due to the complexity of the scene and model, I have broken the scene graph down in
several sub-graphs (see figures 13, 14, 15, 16, 17 and 18). When encountering a leaf node, please refer to the
following graphs for details.
A name of an angle (e.g. theta_neck) above an image means the model represented on the image is rotated by that
angle by its parent. Note that only the angles that can be changed are shown on the graph, that is, angles that are
present in the following C structure:
8 typedef struct
9 {
10 GLfloat theta_jaw;
11 GLfloat theta_head_z;
12 GLfloat theta_head_y;
13 GLfloat theta_neck;
14 GLfloat theta_wing;
15 GLfloat theta_wing_joint;
16 GLfloat theta_front_legs;
17 GLfloat theta_back_legs;
18 GLfloat theta_paw;
19 GLfloat theta_tail;
20 GLfloat alpha; //
21 GLfloat beta; // animation-dependent variables
22 GLfloat gamma; //
23 GLuint joint_parts;
24 GLuint chest_parts;
25 GLuint tail_end_parts;
26 Material default_material;
27 Material tongue_material;
28 Material wing_material;
29 Material wing_membrane_material;
30 } Dragon;
Each draw_dragon_xxx() function (see appendix C.1.2 on page 23) receives a pointer to an instance of this structure.
This is why the rotation parameters have to be represented that way, instead of indicating for each function its param-
eters. The xxx_parts attributes indicate the number of parts that should be used to draw joints, the chest and the tail.
This is related to the ’level of detail’ setting of the program (see section 3.3.4).
7 Conclusions (Pierre-André)
I think I have learned a lot and that’s what I really liked; there were plenty of technical challenges (making things
work) as well as artistic ones (making things look nice). For example, before this project I had never used Photoshop-
like image manipulation software (to create textures) or worked on 3D graphics. Also, before taking this module
3D graphics seemed really arcane and too focused on mathematics for me. But thanks to this module’s lectures and
project, and also thanks to OpenGL’s simple API this doesn’t seem nearly as hard and a lot more fun!
However, in my opinion the project’s guidelines is something that wasn’t really clear and which I didn’t fully under-
stand. I thought we were to work completely separately to create the initials and individual models (with one set of
initials). Indeed we were told no code could be possibly shared between students because of assessment reasons. Also
I thought we had to create a complete scene — not just a single model — as was suggested by the part on instantiation
in the lectures. This is what led us to work separately on most of the project, and put everything together only at the
end. Looking at the self-assessment sheet, this doesn’t seem to be what was expected though. This is why I think this
project would have been much simpler organisation- and assessment-wise if it had been an individual project. Maybe
the restriction on not sharing code could have been loosened too, this way people could still have helped each other.
That’s why if I had to do this project again, I would have made sure I understood guidelines better, even though I
didn’t expect them to be that different from what I thought they were. In addition I would have taken a more active
role in organizing the project so we could have worked together more.
If I had twice the time for the project, I think I would have created more models from initials, thought of a more
complex scene with more instantiated models and maybe added programmable shaders to use more advanced graphic
techniques such as bump mapping or cell shading.
Overall though, I’d say that for me this project was the most interesting and challenging of this semester.
8 Conclusions (Clare)
Through this project, I have learned to design and implement elementary 3D models using OpenGL, applying the
theory as taught in class. As well, this hands-on component of the module encouraged creative thinking, as it involved
designing an animation using just a small set of alphabets.
If I could redo the project, I would have left in the motion callback actions that I had implemented in a draft version,
instead of having all of the crab’s movements set under idle callback. Also, I would have restructured and cleaned up
the code for improved readability.
If I had twice as much time to complete the project, I would also redesign the alphabet models such that each letter
would be a single 3D object, instead of objects formed as combinations of five-sided 3D shapes. In addition, I would
add texture and make use of different light angles.
19 start_fps();
20 glutMainLoop();
21 }
The display.c file contains the code for drawing the top-level scene. For code specific to each group member’s scene,
see function ps188_draw_scene() in scene.c (appendix C.2.1 on page 28) and cp133_draw_scene() in scene_nest.c (ap-
pendix D.2.3 on page 70).
385 void onDisplay()
386 {
387 glClearColor(0.6, 0.6, 1.0, 1.0);
388 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
389
392 // determine which rotation to apply from both the user and the scene
393 GLfloat theta[3];
394 for(GLuint i = 0; i < 3; i++)
395 {
396 theta[i] = g.theta[i];
397 if(g.selected_item == ITEM_SCENE)
398 theta[i] += g.scene->theta[i];
399 }
400
401 glPushMatrix();
402 glLoadIdentity();
403 glTranslatef(g.delta[0], g.delta[1], g.delta[2]);
404 glRotatef(theta[0], 1.0, 0.0, 0.0);
405 glRotatef(theta[1], 0.0, 1.0, 0.0);
406 glRotatef(theta[2], 0.0, 0.0, 1.0);
407 //printf("%f %f %f\n", g.theta[0], g.theta[1], g.theta[2]);
408 glScalef(g.sigma, g.sigma, g.sigma);
409 draw_selected();
410
416 glFlush();
417 glutSwapBuffers();
418 }
76 void draw_selected()
77 {
78 int item = g.selected_item;
79 if(item == ITEM_SCENE)
80 {
81 ps188_draw_scene(g.scene);
82 //glDisable(GL_LIGHTING);
83 //cp133_draw_scene();
84 //glEnable(GL_LIGHTING);
85 }
86 else if((item >= ITEM_LETTER_PS188_P) && (item <= ITEM_DRAGON_HOLDING_S))
87 draw_selected_ps188(item);
88 else if((item >= ITEM_LETTER_CP133_C) && (item <= ITEM_NEST_QUARTER))
89 draw_selected_cp133(item);
90
91 if(g.draw_axes)
92 {
93 draw_axes();
94 draw_axis_grids(1, 1, 1);
95 }
96 }
C.1 Headers
C.1.1 scene.h
3 #ifndef INITIALS_SCENE
4 #define INITIALS_SCENE
5
6 #include <GL/glut.h>
7 #include "mesh.h"
8 #include "dragon.h"
9
10 #define CAMERA_STATIC 0
11 #define CAMERA_JUMPING 1
12 #define CAMERA_FLYING 2
13
14 typedef struct
15 {
16 GLfloat theta[3]; // rotations for the whole scene
17 int camera;
18 int detail_level; // between 1 and 4
19 Mesh *floor;
20 Dragon *dragon[3];
21 } Scene;
22
41 // Periodic function which returns 0 for w seconds then returns 1 for a seconds
42 GLfloat spaced_rect(GLfloat t, GLfloat w, GLfloat a);
43
44 // Periodic function which returns 0 for w seconds then is the sawtooth function for a seconds
45 GLfloat spaced_sawtooth(GLfloat t, GLfloat w, GLfloat a);
46
47 // Periodic function which returns 0 for w seconds then is the cosine function for a seconds
48 GLfloat spaced_cos(GLfloat t, GLfloat w, GLfloat a);
49
50 #endif
C.1.2 dragon.h
3 #ifndef INITIALS_DRAGON
4 #define INITIALS_DRAGON
5
6 #include "mesh.h"
7
8 typedef struct
9 {
10 GLfloat theta_jaw;
11 GLfloat theta_head_z;
12 GLfloat theta_head_y;
13 GLfloat theta_neck;
14 GLfloat theta_wing;
15 GLfloat theta_wing_joint;
16 GLfloat theta_front_legs;
17 GLfloat theta_back_legs;
18 GLfloat theta_paw;
19 GLfloat theta_tail;
20 GLfloat alpha; //
21 GLfloat beta; // animation-dependent variables
22 GLfloat gamma; //
23 GLuint joint_parts;
24 GLuint chest_parts;
25 GLuint tail_end_parts;
26 Material default_material;
27 Material tongue_material;
28 Material wing_material;
29 Material wing_membrane_material;
30 } Dragon;
31
55 #endif
C.1.3 letters.h
3 #ifndef INITIALS_LETTERS
4 #define INITIALS_LETTERS
5
6 #include <GL/glut.h>
7
8 void ps188_init_letters();
9
10 void ps188_draw_p();
11 void ps188_draw_a();
12 void ps188_draw_s();
13
14 #endif
C.1.4 primitives.h
3 #ifndef INITIALS_PRIMITIVES
4 #define INITIALS_PRIMITIVES
5
6 #include <GL/glut.h>
7 #include "mesh.h"
8
18 Mesh * create_cube();
19 Mesh * create_sheared_paralpd(double baseWidth, double height, double theta);
20 double sheared_paralpd_width(double baseWidth, double height, double theta);
21
22 #endif
C.1.5 mesh.h
3 #ifndef INITIALS_MESH
4 #define INITIALS_MESH
5
6 #include <GL/glut.h>
7
8 typedef struct
9 {
10 GLfloat ambient[4];
11 GLfloat diffuse[4];
12 GLfloat specular[4];
13 GLfloat shine;
14 GLuint texture;
15 int use_mipmaps;
16 } Material;
17
18 typedef struct
19 {
20 GLenum mode;
21 GLsizei count;
22 GLint offset; // location of the face vertices in the mesh’s indices array
23 int draw;
24 } Face;
25
26 typedef struct
27 {
28 GLfloat *vertices;
29 GLfloat *normals;
30 GLfloat *texCoords;
31 GLuint *indices;
32 GLsizei faceCount;
33 Face *faces;
34 } Mesh;
35
55 /* Show the normal for every vertex in the mesh, for debugging purposes. */
56 void draw_mesh_normals(Mesh *m);
57 void free_mesh(Mesh *m);
58
59 #endif
C.1.6 images.h
3 #ifndef INITIALS_IMAGES
4 #define INITIALS_IMAGES
5
9 #endif
C.1.7 display.h
3 #ifndef INITIALS_DISPLAY
4 #define INITIALS_DISPLAY
5
6 #include <GL/glut.h>
7 #include <time.h>
8 #include "scene.h"
9 #include "../cp133/scene_nest.h"
10 #include "../cp133/cxpinitials.h"
11 #include "../cp133/alphadraw.h"
12
13 #define ITEM_SCENE 0
14
15 #define ITEM_LETTER_PS188_P 1
16 #define ITEM_LETTER_PS188_A 2
17 #define ITEM_LETTER_PS188_S 3
18
19 #define ITEM_DRAGON 4
20 #define ITEM_DRAGON_UPPER 5
21 #define ITEM_DRAGON_HEAD 6
22 #define ITEM_DRAGON_TONGUE 7
23 #define ITEM_DRAGON_JOINT 8
24 #define ITEM_DRAGON_BODY 9
25 #define ITEM_DRAGON_CHEST 10
26 #define ITEM_DRAGON_PAWS 11
27 #define ITEM_DRAGON_PAW 12
28 #define ITEM_DRAGON_WING 13
29 #define ITEM_DRAGON_WING_OUTER 14
30 #define ITEM_DRAGON_WING_PART 15
31 #define ITEM_DRAGON_WING_MEMBRANE 16
32 #define ITEM_DRAGON_TAIL 17
33 #define ITEM_DRAGON_TAIL_END 18
34
35 #define ITEM_FLOOR 19
36 #define ITEM_DRAGON_HOLDING_A 20
37 #define ITEM_DRAGON_HOLDING_P 21
38 #define ITEM_DRAGON_HOLDING_S 22
39
40 #define ITEM_LETTER_CP133_C 23
41 #define ITEM_LETTER_CP133_X 24
42 #define ITEM_LETTER_CP133_P 25
43
44 #define ITEM_LETTER_CP133_XP 26
45 #define ITEM_LETTER_CP133_CXP 27
46
47 #define ITEM_CRAB 28
48 #define ITEM_CRAB_BODY_LEGS 29
49 #define ITEM_CRAB_BODY 30
50 #define ITEM_CRAB_LEFT_LEG 31
51 #define ITEM_CRAB_RIGHT_LEG 32
52
53 #define ITEM_NEST 33
54 #define ITEM_NEST_HALF 34
55 #define ITEM_NEST_QUARTER 35
56
59 typedef struct
60 {
61 int active;
62 int x0;
63 int y0;
64 GLfloat last[3]; // value of delta/theta when the user last clicked
65 } MouseState;
66
67 typedef struct
68 {
69 // viewer settings
70 GLfloat delta[3];
71 GLfloat theta[3];
72 GLfloat sigma;
73 MouseState trans_state;
74 MouseState rot_state;
75 // on/off settings
76 int draw_axes;
77 int draw_normals;
78 int animate;
79 int wireframe_mode;
80 int use_vertex_list;
81 // FPS counter state
82 int show_fps;
83 clock_t start;
84 GLuint frames;
85 // scene state
86 int selected_item; // item in the scene to draw
87 Scene *scene;
88 } GlobalState;
89
90 extern GlobalState g;
91
92 void init_display();
93 void reset_camera();
94 void select_item(int index);
95
96 void draw_selected();
97 void draw_selected_ps188(int item);
98 void draw_selected_cp133(int item);
99
117 #endif
C.2 Implementation
C.2.1 scene.c
3 #include <math.h>
4 #include <time.h>
5 #include <malloc.h>
6 #include "scene.h"
7 #include "letters.h"
8 #include "primitives.h"
9 #include "images.h"
10 #include "mesh.h"
11
35 };
36
59 ps188_reset_scene(s);
60 }
61
101 break;
102 case 4:
103 d->joint_parts = 8;
104 d->chest_parts = 16;
105 d->tail_end_parts = 8;
106 break;
107 }
108 }
109
259 switch(s->camera)
260 {
261 default:
262 case CAMERA_STATIC:
263 s->theta[1] = 0.0; // static camera
264 break;
265 case CAMERA_JUMPING:
266 s->theta[1] = angle; // following jumping dragon
267 break;
268 case CAMERA_FLYING:
269 s->theta[1] = -angle; // following drunk dragon
270 }
271 }
272
279 // Periodic function which returns 0 for w seconds then returns 1 for a seconds
280 GLfloat spaced_rect(GLfloat t, GLfloat w, GLfloat a)
281 {
282 return (sawtooth(t / (w + a)) > w / (w + a)) ? 1.0 : 0.0;
283 }
284
285 // Periodic function which returns 0 for w seconds then is the sawtooth function for a seconds
286 GLfloat spaced_sawtooth(GLfloat x, GLfloat w, GLfloat a)
287 {
288 return spaced_rect(x, w, a) * sawtooth((x - w) / (w + a)) * ((w + a) / a);
289 }
290
291 // Periodic function which returns 0 for w seconds then is the cosine function for a seconds
292 GLfloat spaced_cos(GLfloat x, GLfloat w, GLfloat a)
293 {
294 return cos(2.0 * M_PI * spaced_sawtooth(x, w, a) + M_PI / 2.0);
295 }
296
C.2.2 dragon.c
3 #include <GL/glut.h>
4 #include <stdio.h>
5 #include <math.h>
6 #include "dragon.h"
7 #include "letters.h"
8
45 glPushMatrix();
46 glScalef(3.0, 3.0, 3.0);
47 draw_dragon_body(d);
48 glPopMatrix();
49
50 glPushMatrix();
51 glTranslatef(-1.0, 0.0, 0.0);
52 glRotatef(180.0, 0.0, 0.0, 1.0);
53 glRotatef(90.0, 1.0, 0.0, 0.0);
54 glScalef(2.0, 3.0, 3.0);
55 draw_dragon_tail(d);
56 glPopMatrix();
57 glPopMatrix();
58 end_apply_material();
59 }
60
121 glPushMatrix();
122 glTranslatef(0.47, 0.0, 0.0);
123 glScalef(1.1, 0.275, 1.1);
124 glRotatef(180.0, 1.0, 0.0, 0.0);
125 ps188_draw_s();
126 glPopMatrix();
127 }
128
152 glPushMatrix();
153 glTranslatef(0.0, -0.3, 0.0);
154 glScalef(1.3, 1.3, 1.3);
155 draw_dragon_paws(d);
156 glPopMatrix();
157
253 ps188_draw_a();
254 glPopMatrix();
255 glPushMatrix();
256 glTranslatef(0.04, 0.0, 0.0);
257 glRotatef(90.0, 1.0, 0.0, 0.0);
258 glScalef(0.16, 0.36, 0.05);
259 ps188_draw_a();
260 glPopMatrix();
261 glPushMatrix();
262 glTranslatef(0.2, 0.0, 0.12);
263 glRotatef(270.0, 1.0, 0.0, 0.0);
264 glRotatef(90.0, 0.0, 0.0, 1.0);
265 glScalef(0.28, 0.4, 0.071);
266 ps188_draw_p();
267 glPopMatrix();
268 glPushMatrix();
269 glTranslatef(0.2, 0.0, -0.12);
270 glRotatef(90.0, 1.0, 0.0, 0.0);
271 glRotatef(90.0, 0.0, 0.0, 1.0);
272 glScalef(0.28, 0.4, 0.071);
273 ps188_draw_p();
274 glPopMatrix();
275 glPopMatrix();
276 }
277
319 glPushMatrix();
320 glTranslatef(-0.5, 0.0, 0.15);
321 glRotatef(-d->theta_back_legs, 0.0, 0.0, 1.0);
322 glRotatef(-10.0, 0.0, 1.0, 0.0);
323 glScalef(1.2, 1.2, 1.2);
324 draw_dragon_paw(d);
325 glPopMatrix();
326 glPopMatrix();
327 }
328
384 glPopMatrix();
385 }
386
C.2.3 letters.c
3 #include <GL/glut.h>
4 #include "letters.h"
5 #include "mesh.h"
6 #include "primitives.h"
7
12 typedef struct
13 {
14 Mesh *arc_c;
15 Mesh *arc_s;
16 Mesh *disk;
17 Mesh *cube;
18 Mesh *sheared_a;
19 } Meshes;
20
23 void ps188_init_letters()
24 {
25 meshes.arc_c = create_curve(180.0, 0.5, 16);
26 meshes.arc_s = create_curve(ANGLE_S, 0.5, 16);
27 meshes.disk = create_curve(180.0, 1.0, 16);
28 meshes.cube = create_cube();
29 meshes.sheared_a = create_sheared_paralpd(BASE_WIDTH_A, 1.0, ANGLE_A);
30 }
31
32 void ps188_draw_p()
33 {
34 glPushMatrix();
35 glPushMatrix();
36 glTranslatef(3.5/7.0, 0.5/7.0, 0.0/7.0);
37 glScalef(3.5/7.0, 0.5/7.0, 0.5/7.0);
38 draw_mesh(meshes.cube);
39 glPopMatrix();
40 glPushMatrix();
41 glTranslatef(2.0/7.0, 1.0/7.0, 0.0/7.0);
42 glScalef(2.0/7.0, 2.0/7.0, 1.0/7.0);
43 draw_mesh(meshes.arc_c);
44 glPopMatrix();
45 glPopMatrix();
46 }
47
48 void ps188_draw_a()
49 {
79 void ps188_draw_s()
80 {
81 glPushMatrix();
82 glRotatef(180, 1.0, 0.0, 0.0);
83 glScalef(0.28, 0.28, 0.28);
84 // top curve
85 glPushMatrix();
86 glTranslatef(0.75, 0.00, 0.00);
87 glRotatef(180, 0.0, 0.0, 1.0);
88 glScalef(1.0, 1.0, 0.5);
89 draw_mesh(meshes.arc_s);
90 glPopMatrix();
91 // bottom curve
92 glPushMatrix();
93 glTranslatef(-0.75, 0.00, 0.00);
94 glScalef(1.0, 1.0, 0.5);
95 draw_mesh(meshes.arc_s);
96 glPopMatrix();
97
C.2.4 primitives.c
3 #include <GL/glut.h>
4 #include <math.h>
5 #include <malloc.h>
6 #include "primitives.h"
7
22 // specify the model using triangle strips for the different faces
23 curve_meshes(m, theta_rad, width, nCurvePoints);
24 return m;
25 }
26
51 // outer curve
52 *v0outer_up++ = *v0outer_side++ = x;
53 *v0outer_up++ = *v0outer_side++ = y;
54 *v0outer_up++ = *v0outer_side++ = -0.5;
55
56 *v1outer_up++ = *v1outer_side++ = x;
57 *v1outer_up++ = *v1outer_side++ = y;
58 *v1outer_up++ = *v1outer_side++ = 0.5;
59
60 // inner curve
61 *v0inner_up++ = *v0inner_side++ = x * r;
62 *v0inner_up++ = *v0inner_side++ = y * r;
63 *v0inner_up++ = *v0inner_side++ = -0.5;
64
65 *v1inner_up++ = *v1inner_side++ = x * r;
66 *v1inner_up++ = *v1inner_side++ = y * r;
67 *v1inner_up++ = *v1inner_side++ = 0.5;
68 }
69
70 // start face
71 *v2++ = r; *v2++ = 0.0; *v2++ = -0.5;
72 *v2++ = 1.0; *v2++ = 0.0; *v2++ = -0.5;
73 *v2++ = 1.0; *v2++ = 0.0; *v2++ = 0.5;
74 *v2++ = r; *v2++ = 0.0; *v2++ = 0.5;
75
76 // end face
77 *v3++ = r * cos(theta); *v3++ = r * sin(theta); *v3++ = -0.5;
78 *v3++ = 1.0 * cos(theta); *v3++ = 1.0 * sin(theta); *v3++ = -0.5;
79 *v3++ = 1.0 * cos(theta); *v3++ = 1.0 * sin(theta); *v3++ = 0.5;
80 *v3++ = r * cos(theta); *v3++ = r * sin(theta); *v3++ = 0.5;
81 }
82
143 void curve_texcoords(Mesh *m, double theta, double width, GLuint nCurvePoints)
144 {
145 m->texCoords = (GLfloat *)malloc(sizeof(GLfloat) * 2 * ((nCurvePoints * 8) + 8));
146
194 void curve_meshes(Mesh *m, double theta, double width, GLuint nCurvePoints)
195 {
196 m->faceCount = 6;
C.2.5 mesh.c
3 #include <malloc.h>
4 #include <math.h>
5 #include "mesh.h"
6 #include "display.h"
7 #include "scene.h"
8
16 {
17 Mesh *m = (Mesh *)malloc(sizeof(Mesh));
18 GLuint verticesPerFace = indiceCount / faceCount;
19
20 // vertices
21 m->vertices = (GLfloat *)malloc(sizeof(GLfloat) * 3 * indiceCount);
22 GLfloat *v = m->vertices;
23 for(GLuint i = 0; i < indiceCount; i++)
24 {
25 GLuint indice = faces_indices[i];
26 *v++ = vertices[(indice * 3) + 0];
27 *v++ = vertices[(indice * 3) + 1];
28 *v++ = vertices[(indice * 3) + 2];
29 }
30
31 // normals
32 m->normals = (GLfloat *)malloc(sizeof(GLfloat) * 3 * indiceCount);
33 GLfloat *n = m->normals;
34 if(faces_normals)
35 {
36 // we have normals
37 for(GLuint i = 0; i < indiceCount; i++)
38 {
39 GLuint indice = i / verticesPerFace;
40 *n++ = faces_normals[(indice * 3) + 0];
41 *n++ = faces_normals[(indice * 3) + 1];
42 *n++ = faces_normals[(indice * 3) + 2];
43 }
44 }
45 else
46 {
47 // we don’t have normals, compute them
48 GLfloat u[3], v1[3], v2[3], v3[3];
49 for(GLuint i = 0; i < faceCount; i++)
50 {
51 // use the face’s first three vertices to compute its normal vector
52 GLuint ind1 = faces_indices[(i * verticesPerFace) + 0];
53 GLuint ind2 = faces_indices[(i * verticesPerFace) + 1];
54 GLuint ind3 = faces_indices[(i * verticesPerFace) + 2];
55
80 // indices
81 m->faceCount = faceCount;
95 // texture coords
96 if(verticesPerFace == 4)
97 mesh_quadri_textcoords(m, indiceCount);
98 else
99 m->texCoords = 0;
100 return m;
101 }
102
117 // normalize it
118 GLfloat w = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
119 n[0] /= w;
120 n[1] /= w;
121 n[2] /= w;
122 }
123
148 if(g.draw_normals)
149 draw_mesh_normals(m);
150 }
151
175 // draw the mesh using vertex lists, which is faster than calling glBegin/glEnd
176 void draw_mesh_vertex_list(Mesh *m)
177 {
178 if(m->normals)
179 {
180 glEnableClientState(GL_NORMAL_ARRAY);
181 glNormalPointer(GL_FLOAT, 0, m->normals);
182 }
183 if(m->texCoords)
184 {
185 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
186 glTexCoordPointer(2, GL_FLOAT, 0, m->texCoords);
187 }
188 glEnableClientState(GL_VERTEX_ARRAY);
189 glVertexPointer(3, GL_FLOAT, 0, m->vertices);
190 for(GLsizei i = 0; i < m->faceCount; i++)
191 {
192 Face f = m->faces[i];
193 if(f.draw)
194 glDrawElements(f.mode, f.count, GL_UNSIGNED_INT, m->indices + f.offset);
195 }
196 if(m->texCoords)
197 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
198 if(m->normals)
199 glDisableClientState(GL_NORMAL_ARRAY);
200 glDisableClientState(GL_VERTEX_ARRAY);
201 }
202
214
238 /* Show the normal for every vertex in the mesh, for debugging purposes. */
239 void draw_mesh_normals(Mesh *m)
240 {
241 begin_apply_material(normals_material);
242 glBegin(GL_LINES);
243 for(GLuint f = 0; f < m->faceCount; f++)
244 {
245 Face face = m->faces[f];
246 if(!face.draw)
247 continue;
248 for(GLuint p = 0; p < face.count; p++)
249 {
250 GLuint i = m->indices[face.offset + p];
251 GLfloat *v = &m->vertices[i * 3];
252 GLfloat *n = &m->normals[i * 3];
253 glVertex3f(v[0], v[1], v[2]);
254 glVertex3f(v[0] + n[0], v[1] + n[1], v[2] + n[2]);
255 }
256 }
257 glEnd();
258 end_apply_material();
259 }
260
C.2.6 images.c
3 #include <GL/glut.h>
4 #include <stdio.h>
5 #include <tiffio.h>
6 #include "images.h"
7
34 // create a texture
35 GLuint texID;
36 glGenTextures(1, &texID);
37 glBindTexture(GL_TEXTURE_2D, texID);
38 if(mipmaps)
39 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height,
40 GL_RGBA, GL_UNSIGNED_BYTE, data);
41 else
42 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
43 GL_RGBA, GL_UNSIGNED_BYTE, data);
44 _TIFFfree(data);
45 TIFFClose(tiff);
46 return texID;
47 }
C.2.7 display.c
3 #include <GL/glut.h>
4 #include <malloc.h>
5 #include <stdio.h>
6 #include "display.h"
7 #include "letters.h"
8 #include "scene.h"
9 #include "../cp133/cxpinitials.h"
10
21 GlobalState g = {0};
22
23 void init_display()
24 {
25 glEnable(GL_LIGHTING);
26 glEnable(GL_LIGHT0);
27 glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
28 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
29 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
30 glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
31 g.scene = (Scene *)malloc(sizeof(Scene));
32 ps188_init_scene(g.scene);
33 reset_camera();
34 }
35
36 void reset_camera()
37 {
38 for(int i = 0; i < 3; i++)
39 {
40 g.trans_state.last[i] = 0.0;
41 g.rot_state.last[i] = 0.0;
42 }
43 g.delta[0] = 0.0;
44 g.delta[1] = 0.0;
45 g.delta[2] = -3.0;
46 g.theta[0] = 21.0;
47 g.theta[1] = -37.0;
48 g.theta[2] = 0.0;
49 g.trans_state.active = 0;
50 g.rot_state.active = 0;
51 g.sigma = 0.25;
52 g.animate = 1;
53 g.draw_axes = 0;
54 g.draw_normals = 0;
55 g.wireframe_mode = 0;
56 g.use_vertex_list = 1;
57 g.show_fps = 0;
58 ps188_reset_scene(g.scene);
59 select_item(ITEM_SCENE);
60 }
61
69 g.selected_item = index;
70 if(index == ITEM_SCENE)
71 glutIdleFunc(animate_selected);
72 else
73 glutIdleFunc(0);
74 }
75
76 void draw_selected()
77 {
78 int item = g.selected_item;
79 if(item == ITEM_SCENE)
80 {
81 ps188_draw_scene(g.scene);
82 //glDisable(GL_LIGHTING);
83 //cp133_draw_scene();
84 //glEnable(GL_LIGHTING);
85 }
86 else if((item >= ITEM_LETTER_PS188_P) && (item <= ITEM_DRAGON_HOLDING_S))
87 draw_selected_ps188(item);
88 else if((item >= ITEM_LETTER_CP133_C) && (item <= ITEM_NEST_QUARTER))
89 draw_selected_cp133(item);
90
91 if(g.draw_axes)
92 {
93 draw_axes();
94 draw_axis_grids(1, 1, 1);
95 }
96 }
97
129 begin_apply_material(debug_material);
130 if(item == ITEM_LETTER_PS188_P)
131 ps188_draw_p();
132 else if(item == ITEM_LETTER_PS188_A)
133 ps188_draw_a();
134 else if(item == ITEM_LETTER_PS188_S)
135 ps188_draw_s();
136 else if(item == ITEM_FLOOR)
137 draw_floor(g.scene);
138 else if(item == ITEM_DRAGON_HOLDING_A)
139 draw_dragon_holding_a(g.scene->dragon[0]);
140 else if(item == ITEM_DRAGON_HOLDING_P)
141 draw_dragon_holding_p(g.scene->dragon[1]);
142 else if(item == ITEM_DRAGON_HOLDING_S)
143 draw_dragon_holding_s(g.scene->dragon[2]);
144 else if((item >= ITEM_DRAGON) && (item <= ITEM_DRAGON_TAIL_END))
145 {
146 int i = item - ITEM_DRAGON;
147 (draw_dragon_parts[i])(&dragon);
148 }
149 end_apply_material();
150 }
151
164 glDisable(GL_LIGHTING);
165 switch(item)
166 {
167 case ITEM_LETTER_CP133_C:
168 c_all(body_color, cb_flip_angle);
169 break;
170 case ITEM_LETTER_CP133_X:
171 x_all(body_color);
172 break;
173 case ITEM_LETTER_CP133_P:
174 draw_p(star_rot_angle, body_color, star_color);
175 break;
176 case ITEM_LETTER_CP133_CXP:
177 draw_cxp(star_rot_angle, cb_flip_angle, x_ll_rot_angle,
178 x_rl_rot_angle, whole_model_angle, cx_angle, xp_angle);
179 break;
180 case ITEM_LETTER_CP133_XP:
181 draw_xp(star_rot_angle, x_ll_rot_angle, x_rl_rot_angle, xp_angle);
182 break;
183 case ITEM_CRAB:
184 draw_crab(body_color, star_color, star_rot_angle,
185 cb_flip_angle, x_ll_rot_angle, x_rl_rot_angle);
186 break;
187 case ITEM_CRAB_BODY_LEGS:
188 draw_body_legs(body_color, star_color, star_rot_angle,
189 x_ll_rot_angle, x_rl_rot_angle);
190 break;
191 case ITEM_CRAB_BODY:
192 draw_body(body_color, star_color, star_rot_angle);
193 break;
194 case ITEM_CRAB_LEFT_LEG:
195 x_left_leg(body_color);
196 break;
197 case ITEM_CRAB_RIGHT_LEG:
198 x_right_leg(body_color);
199 break;
200 case ITEM_NEST:
201 draw_nest(body_color);
202 break;
203 case ITEM_NEST_HALF:
204 draw_nest_half(body_color);
205 break;
206 case ITEM_NEST_QUARTER:
207 draw_nest_qtr(body_color);
208 break;
209 }
210 glEnable(GL_LIGHTING);
211 }
212
222 glPushMatrix();
223 glTranslatef(0.8, 0.0, 0.0);
224 glRotatef(90.0, 0.0, 1.0, 0.0);
225 glutSolidCone(0.04, 0.2, 10, 10);
226 glPopMatrix();
227 }
228
236 glPushMatrix();
237 // X axis
238 m.ambient[0] = 1.0; m.ambient[1] = 0.0; m.ambient[2] = 0.0;
239 begin_apply_material(m);
240 draw_axis();
241 end_apply_material();
242 // Y axis
243 m.ambient[0] = 0.0; m.ambient[1] = 1.0; m.ambient[2] = 0.0;
244 begin_apply_material(m);
245 glRotatef(90.0, 0.0, 0.0, 1.0);
246 draw_axis();
247 end_apply_material();
248 // Z axis
249 m.ambient[0] = 0.0; m.ambient[1] = 0.0; m.ambient[2] = 1.0;
250 begin_apply_material(m);
251 glRotatef(-90.0, 0.0, 1.0, 0.0);
252 draw_axis();
253 end_apply_material();
254 glPopMatrix();
255 }
256
264 begin_apply_material(m);
265 if(draw_x)
266 {
267 draw_axis_grid();
268 }
269
270 if(draw_y)
271 {
272 glPushMatrix();
273 glRotatef(-90.0, 1.0, 0.0, 0.0);
274 draw_axis_grid();
275 glPopMatrix();
276 }
277
278 if(draw_z)
279 {
280 glPushMatrix();
281 glRotatef(90.0, 0.0, 1.0, 0.0);
282 glRotatef(180.0, 0.0, 0.0, 1.0);
283 draw_axis_grid();
284 glPopMatrix();
285 }
286 end_apply_material();
287 }
288
307 glLineWidth(3.0);
308 glBegin(GL_LINES);
309 glVertex3f(0.0, -10.0, 0.0);
310 glVertex3f(0.0, -1.0, 0.0);
311 glVertex3f(0.0, 0.0, 0.0);
312 glVertex3f(0.0, 10.0, 0.0);
313 glVertex3f(-10.0, 0.0, 0.0);
314 glVertex3f(0.0, 0.0, 0.0);
315 glVertex3f(1.0, 0.0, 0.0);
316 glVertex3f(10.0, 0.0, 0.0);
317 glEnd();
318 glLineWidth(1.0);
319 }
320
354 glDisable(GL_LIGHTING);
355
382 glPopAttrib();
383 }
384
392 // determine which rotation to apply from both the user and the scene
393 GLfloat theta[3];
394 for(GLuint i = 0; i < 3; i++)
395 {
396 theta[i] = g.theta[i];
397 if(g.selected_item == ITEM_SCENE)
398 theta[i] += g.scene->theta[i];
399 }
400
401 glPushMatrix();
402 glLoadIdentity();
403 glTranslatef(g.delta[0], g.delta[1], g.delta[2]);
404 glRotatef(theta[0], 1.0, 0.0, 0.0);
405 glRotatef(theta[1], 0.0, 1.0, 0.0);
406 glRotatef(theta[2], 0.0, 0.0, 1.0);
407 //printf("%f %f %f\n", g.theta[0], g.theta[1], g.theta[2]);
408 glScalef(g.sigma, g.sigma, g.sigma);
409 draw_selected();
410
416 glFlush();
417 glutSwapBuffers();
418 }
419
486 decrease_detail_level(g.scene);
487 else if(key == ’5’)
488 g.theta[0] = g.theta[1] = g.theta[2] = 0.0;
489
490 glutPostRedisplay();
491 }
492
526 glutPostRedisplay();
527 }
528
540 if(g.rot_state.active)
541 {
542 int dx = g.rot_state.x0 - x;
543 int dy = g.rot_state.y0 - y;
544 g.theta[0] = g.rot_state.last[0] + (dy * 2.0);
545 g.theta[1] = g.rot_state.last[1] + (dx * 2.0);
546 glutPostRedisplay();
547 }
548 }
D.1 Headers
D.1.1 alphadraw.h
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 #include "alphavert.h"
8
9 extern void tri_stick_tri(float a[], float b[], float c[], int colorint) ;
10 extern void tri_stick_rec(float a[], float b[], float c[], float d[], int colorint);
11
12 extern void tri_stick(float a[], float b[], float c[], float d[], float e[], float f[], int
colorint) ;
13 // Draw 5 sided 3D object with given vertices
14 // a,b,c make one triangle, d,e,f make other triangle
15
D.1.2 cxpinitials.h
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 extern void draw_crab(int body_color, int star_color, int star_rot_angle, float cb_flip_angle,
float x_ll_rot_angle, float x_rl_rot_angle);
8 extern void draw_body_legs(int body_color, int star_color, int star_rot_angle, float
x_ll_rot_angle, float x_rl_rot_angle);
9 extern void draw_body(int body_color, int star_color, int star_rot_angle);
10
D.1.3 scene_nest.h
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 //Parameters
8 #define THICKNESS 0.2
9 #define CB_FLIP_LIMIT -200
10 #define CRAB_MOVE_LIMIT 2
11
12 //============================================
13 //GLOBALS FOR COMMUNICATION
14 //============================================
15
D.1.4 alphavert.h
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 //======================================================
8 // ALPHABET ROUTINES
9 //======================================================
10 // Alphabet points and colours for cxp
11
105 };
106
131 };
D.1.5 3Dcurve.h
D.2 Implementation
D.2.1 alphadraw.c
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 #include <stdlib.h>
8 #include <GL/glut.h>
9 #include <math.h>
10 #include <stdio.h>
11 #include "alphadraw.h"
12 #include "3Dcurve.h"
13
14
17 glBegin(GL_POLYGON);
18 glColor3fv(colors[colorint%8]);
19 glVertex3fv(a);
20 glVertex3fv(b);
21 glVertex3fv(c);
22 glEnd();
23
24 glEnable(GL_LINE_SMOOTH);
25
26 glBegin(GL_LINE_LOOP);
27 glColor3f(0, 0, 0);
28 glVertex3fv(a);
29 glVertex3fv(b);
30 glVertex3fv(c);
31 glEnd();
32
33 glDisable(GL_LINE_SMOOTH);
34
35 }
36
37 void tri_stick_rec(float a[], float b[], float c[], float d[], int colorint) {
38
39 glBegin(GL_POLYGON);
40 glColor3fv(colors[colorint%8]);
41 glVertex3fv(a);
42 glVertex3fv(b);
43 glVertex3fv(c);
44 glVertex3fv(d);
45 glEnd();
46
47 glEnable(GL_LINE_SMOOTH);
48
49 glBegin(GL_LINE_LOOP);
50 glColor3f(0, 0, 0);
51 glVertex3fv(a);
52 glVertex3fv(b);
53 glVertex3fv(c);
54 glVertex3fv(d);
55 glEnd();
56
57 glDisable(GL_LINE_SMOOTH);
58 }
59
60
61 void tri_stick(float a[], float b[], float c[], float d[], float e[], float f[], int
colorint) {
62 // Draw 5 sided 3D object with given vertices
63 // a,b,c make one triangle, d,e,f make other triangle
64
65 // triangle a,b,c
66 tri_stick_tri(a, b, c, colorint);
67 // triangle d,e,f
68 tri_stick_tri(d, e, f, colorint);
69
70 // rectangle a,b,e,d
71 tri_stick_rec(a, b, e, d, colorint);
72 // rectangle b,e,f,c
73 tri_stick_rec(b, e, f, c, colorint);
74 // rectangle a,b,d,f
75 tri_stick_rec(a, b, d, f, colorint);
76
77 }
78
92
95 }
96
107 glPopMatrix();
108
113 }
114
120 c_top(colorint);
121
122 glPushMatrix();
123 glTranslatef(-0.93, -0.5, 0.1);
124 glRotatef(flip_angle, 0, 0, 1.0);
125 glTranslatef(0.93, 0.5, -0.1);
126 c_bottom(colorint);
127 glPopMatrix();
128 }
129
142 }
143
144
162 glPushMatrix();
163 glRotatef(0, 0.5, 0.5, 0);
164 x_left_leg(colorint);
165 glPopMatrix();
166
167 glPushMatrix();
168 glRotatef(0, -0.5, 0.5, 0);
169 x_right_leg(colorint);
170 glPopMatrix();
171
172
173 }
174
183 }
184
196 }
D.2.2 cxpinitials.c
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 #include <stdlib.h>
8 #include <GL/glut.h>
9 #include <math.h>
10 #include <stdio.h>
11 #include "alphadraw.h"
12 #include "cxpinitials.h"
13
18 glPushMatrix();
19 glTranslatef(5.1, 1.3, 0);
20 glRotatef(180, 1, 0, 0);
21 glRotatef(180, 0, 1, 0);
22 //glRotatef(180, 0, 1, 0);
23 draw_nest_half(body_color);
24 glPopMatrix();
25 }
26
31 glPushMatrix();
32 glTranslatef(3.2, -2, 0);
33 glRotatef(95, 0, 0, 1);
34 draw_nest_qtr(body_color);
35 glPopMatrix();
36 }
37
41 glPushMatrix();
42 glScalef(0.5, 0.5, 0.5);
43 c_all(body_color, -50);
44
45 glPushMatrix();
46 glTranslatef(1.5, -2.8, 0);
47 glRotatef(-15, 0, 0, 1.0);
48 glScalef(1.4, 1.4, 1.4);
49 x_all(body_color);
50
51 glPopMatrix();
52
53 glPushMatrix();
54 glTranslatef(4.2, -4.1, 0);
55 glRotatef(170, 0, 0, 1);
56 glScalef(1.5, 1.5, 1.5);
57 //draw_p(0, body_color, 3);
58 p_out(body_color);
59
68 p_star(body_color);
69 glPopMatrix();
70
71 glPushMatrix();
72 glTranslatef(0, 0, -0.15);
73
78 p_star(body_color);
79 glPopMatrix();
80
81
82 glPopMatrix();
83
84 glPopMatrix();
85
86 glPushMatrix();
87 glTranslatef(0, -1.3, 1);
88 glRotatef(90, 0, 0, 1.0);
89 glRotatef(120, 0, 1.0, 0);
90 //glRotatef(-100, 1.0, 0, 0);
91 //c_all(body_color, -50);
92 glPopMatrix();
93
94 glPushMatrix();
95 glTranslatef(1, -1.3, 1);
96 glRotatef(90, 0, 0, 1.0);
97 glRotatef(120, 0, 1.0, 0);
98 glRotatef(-30, 1.0, 0, 0);
99 //x_all(body_color);
100 glPopMatrix();
101
102
103 glPushMatrix();
104 glTranslatef(1, -1.3, 0);
105 glRotatef(110, 0, 0, 1.0);
106 glRotatef(60, 0, 1.0, 0);
112 void draw_crab(int body_color, int star_color, int star_rot_angle, float cb_flip_angle, float
x_ll_rot_angle, float x_rl_rot_angle)
113 {
114
115 glPushMatrix();
116 glTranslatef(-1.1, -0.2, 0);
117 glRotatef(30, 0, 0, 1.0);
118 glRotatef(180, 1.0, 0, 0);
119 glScalef(0.4, 0.4, 0.4);
120
123 glPopMatrix();
124
127 glPushMatrix();
128 glTranslatef(1.1, -0.2, 0);
129 glRotatef(150, 0, 0, 1.0);
130 glScalef(0.4, 0.4, 0.4);
131
134 glPopMatrix();
135 }
136
137 void draw_body_legs(int body_color, int star_color, int star_rot_angle, float x_ll_rot_angle,
float x_rl_rot_angle)
138 {
139 draw_body(body_color, star_color, star_rot_angle);
140
150 glPushMatrix();
151 glRotatef(x_ll_rot_angle, 0.5, 0.5, 0);
152 x_left_leg(body_color);
153 glPopMatrix();
154
155 glPushMatrix();
156 glRotatef(x_rl_rot_angle, -0.5, 0.5, 0);
157 x_right_leg(body_color);
158 glPopMatrix();
159
160
161 glPopMatrix();
162
171
172
173
174 glPushMatrix();
175 glRotatef(x_ll_rot_angle, 0.5, 0.5, 0);
176 x_left_leg(body_color);
177 glPopMatrix();
178
179 glPushMatrix();
180 glRotatef(x_rl_rot_angle, -0.5, 0.5, 0);
181 x_right_leg(body_color);
182 glPopMatrix();
183
184 glPopMatrix();
185 }
186
194 glPushMatrix();
195 glRotatef(180, 0, 0, 1.0);
196 p_out(body_color);
197 glPopMatrix();
198
199 glPushMatrix();
200 glTranslatef(0, -0.65, 0.20);
201 //glRotatef(star_rot_angle%360, 0, 0, 1.0);
202
203 glTranslatef(0.11, 0.35, 0); // centre of star will be at origin, for purpose
of rotations
204 glRotatef(star_rot_angle%360, 0, 0, 1.0);
205 glTranslatef(-0.11,-0.35, 0); // restore previous star origin
206
207 p_star(star_color);
208
209 glPopMatrix();
210
211 }
212
216 glPushMatrix();
217 glRotatef(whole_model_angle, 0, 0, 1.0);
218 c_top(1);
219
220
221 glPushMatrix();
222 glTranslatef(-0.93, -0.5, 0.1);
223 glRotatef(cb_flip_angle, 0, 0, 1.0);
224 glTranslatef(0.93, 0.5, -0.1);
225 c_bottom(1);
226 glPopMatrix();
227
228
229 glPushMatrix();
230 glTranslatef(1.635, -0.07, 0);
231
232 glTranslatef(-0.9, 0.57, 0.1); // translate top left corner to origin for
rotation
233 glRotatef(45.0 + cx_angle, 0.0, 0.0, 1.0);
239 glPopMatrix();
240 }
241
242 void draw_xp(float star_rot_angle, float x_ll_rot_angle, float x_rl_rot_angle, float xp_angle)
243 {
244 x_top(1);
245
246 glPushMatrix();
247 glRotatef(x_ll_rot_angle, 0.5, 0.5, 0);
248 x_left_leg(1);
249 glPopMatrix();
250
251 glPushMatrix();
252 glRotatef(x_rl_rot_angle, -0.5, 0.5, 0);
253 x_right_leg(1);
254 glPopMatrix();
255
256 glPushMatrix();
257 glTranslatef(1.565, -0.115, 0);
258
266 }
267
276 glTranslatef(0.11, 0.35, 0); // centre of star will be at origin, for purpose
of rotations
277 glRotatef(star_rot_angle, 0, 0, 1.0);
278 glTranslatef(-0.11,-0.35, 0); // restore previous star origin
279
280 p_star(star_color_pr);
281 glPopMatrix();
282
283 glPushMatrix();
284 glTranslatef(0, 0, -0.15);
285
286 glTranslatef(0.11, 0.35, 0); // centre of star will be at origin, for purpose
of rotations
287 glRotatef(star_rot_angle, 0, 0, 1.0);
288 glTranslatef(-0.11,-0.35, 0); // restore previous star origin
289
290 p_star(star_color_pr);
291 glPopMatrix();
292 }
D.2.3 scene_nest.c
1 //============================================
2 // Clare S. Park
3 // cp133@hw.ac.uk
4 // Last updated 17/11/2009
5 //============================================
6
7 #include "scene_nest.h"
8 #include "cxpinitials.h"
9 #include <GL/glut.h>
10
21 int cb_flip_cw = 1;
22 int one_model = 0;
23 int crab_left = 1;
24
25 void cp133_animate_scene()
26 {
27 star_rot_angle += 0.5;
28
29 if (star_rot_angle == 360)
30 star_rot_angle = 0;
31
36 } else {
37 cb_flip_angle += 0.5;
38 if (cb_flip_angle == 0) cb_flip_cw = 1;
39 }
40
45 } else {
46 crab_translate += 0.01;
47 if (crab_translate >= CRAB_MOVE_LIMIT) crab_left = 1;
48 }
49
50 x_ll_rot_angle += 0.5;
51 x_rl_rot_angle += 0.5;
52 }
53
54 //===========================================================
55 // DRAW_SCENE
56 //===========================================================
57 void cp133_draw_scene()
58 {
59 glPushMatrix();
60 glColor3f(1.0, 1.0, 1.0);
61 glTranslatef(0.0, -0.7, 0.0);
62 glScalef(0.5, 0.5, 0.5);
63 glPushMatrix();
64
68
69 glPopMatrix();
70
71 glPushMatrix();
72 glTranslatef(-3.7, -1.3, 0);
73 glRotatef(-90, 1, 0, 0);
74 glScalef(1.5, 1.5, 1.5);
75 draw_nest(3);
76 glPopMatrix();
77
78 glPushMatrix();
79 glTranslatef(-2.5, -1.0, 0);
80 glRotatef(-90, 1, 0, 0);
81 glTranslatef(0, 0, -1);
82 draw_nest(3);
83 glPopMatrix();
84
85 glPushMatrix();
86 glTranslatef(-1.5, -0.6, 0);
87 glRotatef(-90, 1, 0, 0);
88 glScalef(0.6, 0.6, 0.6);
89 glTranslatef(0, 0, -2.9);
90 draw_nest(3);
91 glPopMatrix();
92
93 glPopMatrix();
94 }
D.2.4 3Dcurve.c