0% found this document useful (0 votes)
5 views

OpenGL Computer Graphics Project Report

The document is a project report on computer graphics created by Pierre-André Saulais and Clare Park for Heriot-Watt University. It includes sections on project design, a graphical user manual, scene graphs, and code listings. The report also contains conclusions and appendices detailing the project's implementation and features.
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)
5 views

OpenGL Computer Graphics Project Report

The document is a project report on computer graphics created by Pierre-André Saulais and Clare Park for Heriot-Watt University. It includes sections on project design, a graphical user manual, scene graphs, and code listings. The report also contains conclusions and appendices detailing the project's implementation and features.
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/ 73

Computer Graphics — Project group report

November 23, 2009

Pierre-André Saulais, Clare Park


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Contents
Executive summary 3

1 Project diary 4

2 Top-level design of the program 4


2.1 Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.1 “Frame-relative” animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.2 “Absolute-time” animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3 Graphical user manual 6


3.1 Scene control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.1 Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.2 Zoom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.3 Panning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.4 Camera mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.5 Model selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Visual indicators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2.1 Axis grids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2.2 Frame per second (FPS) counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.3 Wire-frame rendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.4 Showing normal vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Other features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.1 Reset settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.2 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.3 Mesh rendering mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3.4 Mesh level of detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4 Top-level scene graph 11

5 Scene graphs (Pierre-André) 11

6 Scene graphs (Clare) 18

7 Conclusions (Pierre-André) 21

8 Conclusions (Clare) 21

A Appendix: code listing for main.c 21

B Appendix: code listing for top-level scene graph 22

C Appendix: code listings (Pierre-André) 23


C.1 Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
C.1.1 scene.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
C.1.2 dragon.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
C.1.3 letters.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
C.1.4 primitives.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
C.1.5 mesh.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
C.1.6 images.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
C.1.7 display.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
C.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
C.2.1 scene.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
C.2.2 dragon.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
C.2.3 letters.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
C.2.4 primitives.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
C.2.5 mesh.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
C.2.6 images.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
C.2.7 display.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

Pierre-André Saulais, Clare Park 1


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

D Appendix: code listings (Clare) 59


D.1 Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
D.1.1 alphadraw.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
D.1.2 cxpinitials.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
D.1.3 scene_nest.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
D.1.4 alphavert.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
D.1.5 3Dcurve.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
D.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
D.2.1 alphadraw.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
D.2.2 cxpinitials.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
D.2.3 scene_nest.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
D.2.4 3Dcurve.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

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

Pierre-André Saulais, Clare Park 2


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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.

Pierre-André Saulais, Clare Park 3


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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 Top-level design of the program

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.

Pierre-André Saulais, Clare Park 4


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 1: Overview of the program’s design

2.2.1 “Frame-relative” animation

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).

2.2.2 “Absolute-time” animation

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).

Pierre-André Saulais, Clare Park 5


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 2: Example of functions used for animating the models

Figure 3: “Spaced in time” version of cos(t)

3 Graphical user manual

3.1 Scene control

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.

3.1.4 Camera mode

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.

Pierre-André Saulais, Clare Park 6


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Initial view (b) Rotation about axis X

(c) Rotation about axis Y (d) Rotation about axis Z

Figure 4: Rotation of the whole model

Pierre-André Saulais, Clare Park 7


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Zooming in (b) Zooming out

Figure 5: Zooming the whole model

(a) Camera following the jumping (bronze) dragon (b) Camera following the flying (black) dragon

Figure 6: Non-static camera modes

Pierre-André Saulais, Clare Park 8


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Rendering an individual model (b) Rendering only part of a model

Figure 7: Model selection

3.1.5 Model selection

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.

3.2 Visual indicators

3.2.1 Axis grids

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

Figure 8: A few visual indicators

Pierre-André Saulais, Clare Park 9


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Normal vectors shown for a letter (b) Normal vectors shown for the scene’s meshes

Figure 9: Showing meshes vertices’ normal vectors

3.2.2 Frame per second (FPS) counter

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.

3.2.3 Wire-frame rendering

Pressing the ’W’ key toggles the wire-frame rendering mode on or off. See figure 8c on the previous page.

3.2.4 Showing normal vectors

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.

3.3 Other features

This section includes other features which can’t be sorted in the two previous categories but might otherwise be useful.

3.3.1 Reset settings

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

Pierre-André Saulais, Clare Park 10


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Immediate mode (b) Vertex array mode

Figure 10: Comparison of rendering modes

on absolute time and not time relative to when animation is toggled on or off.

3.3.3 Mesh rendering mode

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.

3.3.4 Mesh level of detail

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.

4 Top-level scene graph

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.

5 Scene graphs (Pierre-André)

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:

Pierre-André Saulais, Clare Park 11


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

(a) Level of detail = 1 (b) Level of detail = 2 (c) Level of detail = 4

Figure 11: Different levels of detail

Figure 12: Top-level scene graph

Pierre-André Saulais, Clare Park 12


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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).

Pierre-André Saulais, Clare Park 13


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 13: Graph for ps188_draw_scene()

Figure 14: Graph for draw_dragon()

Pierre-André Saulais, Clare Park 14


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 15: Graph for draw_dragon_body()

Pierre-André Saulais, Clare Park 15


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 16: Graph for draw_dragon_upper()

Figure 17: Graph for draw_dragon_tail()

Pierre-André Saulais, Clare Park 16


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 18: Graph for ps188_draw_p(), ps188_draw_a() and ps188_draw_s()

Pierre-André Saulais, Clare Park 17


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

6 Scene graphs (Clare)

Figure 19: Graph for cp133_draw_scene()

Pierre-André Saulais, Clare Park 18


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 20: Graph for draw_crab()

Figure 21: Graph for draw_body_legs()

Pierre-André Saulais, Clare Park 19


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

Figure 22: Graph for draw_nest()

Figure 23: Graph for draw_nest_qtr()

Pierre-André Saulais, Clare Park 20


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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.

A Appendix: code listing for main.c


1 #include <GL/glut.h>
2 #include "ps188/display.h"
3

4 int main(int argc, char **argv)


5 {
6 glutInit(&argc, argv);
7 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_ALPHA);
8 glutInitWindowSize(1024, 768);
9 glutCreateWindow("Computer Graphics assignment");
10 init_display();
11 glutDisplayFunc(onDisplay);
12 glutReshapeFunc(onReshape);
13 glutKeyboardFunc(onKeyboard);
14 glutMouseFunc(onMouseClicked);
15 glutMotionFunc(onMouseMoved);
16 glEnable(GL_DEPTH_TEST);
17 // we do non-uniform scaling and not all normals are one-unit-length
18 glEnable(GL_NORMALIZE);

Pierre-André Saulais, Clare Park 21


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

19 start_fps();
20 glutMainLoop();
21 }

B Appendix: code listing for top-level scene graph

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

390 glPolygonMode(GL_FRONT_AND_BACK, g.wireframe_mode ? GL_LINE : GL_FILL);


391

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

411 GLfloat fps = update_fps();


412 if(g.show_fps)
413 show_fps(fps);
414 glPopMatrix();
415

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 }

Pierre-André Saulais, Clare Park 22


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

96 }

C Appendix: code listings (Pierre-André)

C.1 Headers

C.1.1 scene.h

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

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

23 void ps188_init_scene(Scene *s);


24 void ps188_reset_scene(Scene *s);
25 void ps188_draw_scene(Scene *s);
26 void draw_floor(Scene *s);
27 void draw_dragon_holding_p(Dragon *d);
28 void draw_dragon_holding_a(Dragon *d);
29 void draw_dragon_holding_s(Dragon *d);
30

31 void increase_detail_level(Scene *s);


32 void decrease_detail_level(Scene *s);
33 void set_detail_level(Scene *s, Dragon *d);
34

35 void ps188_animate_scene(Scene *s);


36 void animate_dragon(Dragon *d, GLfloat t);
37

38 // Periodic function linearly going from 0 to 1


39 GLfloat sawtooth(GLfloat t);
40

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

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */

Pierre-André Saulais, Clare Park 23


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

32 void init_dragon(Dragon *d);


33

34 void draw_dragon(Dragon *d);


35

36 void draw_dragon_upper(Dragon *d);


37 void draw_dragon_head(Dragon *d);
38 void draw_dragon_tongue(Dragon *d);
39 void draw_dragon_joint(Dragon *d);
40

41 void draw_dragon_body(Dragon *d);


42 void draw_dragon_chest(Dragon *d);
43

44 void draw_dragon_wing(Dragon *d);


45 void draw_dragon_wing_part(Dragon *d);
46 void draw_dragon_wing_outer(Dragon *d);
47 void draw_dragon_wing_membrane(Dragon *d);
48

49 void draw_dragon_paws(Dragon *d);


50 void draw_dragon_paw(Dragon *d);
51

52 void draw_dragon_tail(Dragon *d);


53 void draw_dragon_tail_end(Dragon *d);
54

55 #endif

C.1.3 letters.h

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #ifndef INITIALS_LETTERS
4 #define INITIALS_LETTERS
5

6 #include <GL/glut.h>
7

8 void ps188_init_letters();
9

Pierre-André Saulais, Clare Park 24


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

10 void ps188_draw_p();
11 void ps188_draw_a();
12 void ps188_draw_s();
13

14 #endif

C.1.4 primitives.h

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #ifndef INITIALS_PRIMITIVES
4 #define INITIALS_PRIMITIVES
5

6 #include <GL/glut.h>
7 #include "mesh.h"
8

9 #define M_PI 3.14159265358979323846 /* pi */


10 #define radians(t) (((t) / 180.0) * M_PI)
11

12 Mesh * create_curve(double theta, double width, GLuint nCurvePoints);


13 void curve_vertices(Mesh *m, double theta, double width, GLuint nCurvePoints);
14 void curve_normals(Mesh *m, double theta, double width, GLuint nCurvePoints);
15 void curve_texcoords(Mesh *m, double theta, double width, GLuint nCurvePoints);
16 void curve_meshes(Mesh *m, double theta, double width, GLuint nCurvePoints);
17

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

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

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;

Pierre-André Saulais, Clare Park 25


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

34 } Mesh;
35

36 Mesh * create_mesh(GLfloat *vertices, GLfloat *faces_normals, GLuint *faces_indices,


37 GLsizei indiceCount, GLsizei faceCount);
38

39 // Compute the normal vector of the triangle ABC


40 void normal_vector(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *n);
41

42 /* Generate texture coordinates for 4 vertices-faced meshes */


43 void mesh_quadri_textcoords(Mesh *m, GLsizei indiceCount);
44

45 void init_material(Material *material);


46 void begin_apply_material(Material material);
47 void end_apply_material();
48

49 void draw_mesh(Mesh *m);


50 // draw the mesh using glBegin/glEnd/glVertex/etc
51 void draw_mesh_immediate(Mesh *m);
52 // draw the mesh using vertex lists, which is faster than calling glBegin/glEnd
53 void draw_mesh_vertex_list(Mesh *m);
54

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

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #ifndef INITIALS_IMAGES
4 #define INITIALS_IMAGES
5

6 // Create a texture from a TIFF file using libtiff


7 GLuint textureFromTIFFImage(char *path, int mipmaps);
8

9 #endif

C.1.7 display.h

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

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

Pierre-André Saulais, Clare Park 26


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

57 #define ITEM_LAST ITEM_NEST_QUARTER


58

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

Pierre-André Saulais, Clare Park 27


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

100 void draw_axis();


101 void draw_axes();
102 void draw_axis_grids(int draw_x, int draw_y, int draw_z);
103 void draw_axis_grid();
104

105 void animate_selected();


106

107 void start_fps();


108 GLfloat update_fps();
109 void show_fps(GLfloat fps);
110

111 void onDisplay();


112 void onReshape(int w, int h);
113 void onKeyboard(unsigned char key, int x, int y);
114 void onMouseClicked(int button, int state, int x, int y);
115 void onMouseMoved(int x, int y);
116

117 #endif

C.2 Implementation

C.2.1 scene.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

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

12 static Material floor_material =


13 { // ambient, diffuse, specular, shine, texture, use_mipmap
14 {0.5, 0.5, 0.5, 1.0}, {1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}, 00.0, 0, 1
15 };
16

17 static Material tongue_material =


18 { // ambient, diffuse, specular, shine, texture, use_mipmap
19 {0.1, 0.0, 0.0, 1.0}, {0.6, 0.0, 0.0, 1.0}, {1.0, 1.0, 1.0, 1.0}, 50.0, 0, 0
20 };
21

22 static Material scales_material =


23 { // ambient, diffuse, specular, shine, texture, use_mipmap
24 {0.2, 0.2, 0.2, 1.0}, {0.8, 0.8, 0.8, 1.0}, {1.0, 1.0, 1.0, 1.0}, 20.0, 0, 0
25 };
26

27 static Material wing_material =


28 { // ambient, diffuse, specular, shine, texture, use_mipmap
29 {0.2, 0.2, 0.2, 1.0}, {1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}, 20.0, 0, 0
30 };
31

32 static Material wing_membrane_material =


33 { // ambient, diffuse, specular, shine, texture, use_mipmap
34 {0.1, 0.0, 0.0, 1.0}, {0.6, 0.0, 0.0, 1.0}, {0.2, 0.2, 0.2, 1.0}, 20.0, 0, 0

Pierre-André Saulais, Clare Park 28


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

35 };
36

37 void ps188_init_scene(Scene *s)


38 {
39 ps188_init_letters();
40 s->floor = create_cube();
41 floor_material.texture = textureFromTIFFImage("lava_green.tiff", 1);
42

43 for(GLuint i = 0; i < 3; i++)


44 {
45 s->dragon[i] = (Dragon *)malloc(sizeof(Dragon));
46 init_dragon(s->dragon[i]);
47 s->dragon[i]->default_material = scales_material;
48 s->dragon[i]->tongue_material = tongue_material;
49 s->dragon[i]->wing_material = wing_material;
50 s->dragon[i]->wing_membrane_material = wing_membrane_material;
51 }
52 s->dragon[0]->default_material.texture = textureFromTIFFImage("scale_green.tiff", 0);
53 s->dragon[0]->wing_material.texture = textureFromTIFFImage("wing_green.tiff", 0);
54 s->dragon[1]->default_material.texture = textureFromTIFFImage("scale_black.tiff", 0);
55 s->dragon[1]->wing_material.texture = textureFromTIFFImage("wing_black.tiff", 0);
56 s->dragon[2]->default_material.texture = textureFromTIFFImage("scale_bronze.tiff", 0);
57 s->dragon[2]->wing_material.texture = textureFromTIFFImage("wing_bronze.tiff", 0);
58

59 ps188_reset_scene(s);
60 }
61

62 void ps188_reset_scene(Scene *s)


63 {
64 for(GLuint i = 0; i < 3; i++)
65 s->theta[i] = 0.0;
66 s->detail_level = 4;
67 s->camera = CAMERA_STATIC;
68 }
69

70 void increase_detail_level(Scene *s)


71 {
72 if(s->detail_level < 4)
73 s->detail_level++;
74 }
75

76 void decrease_detail_level(Scene *s)


77 {
78 if(s->detail_level > 1)
79 s->detail_level--;
80 }
81

82 void set_detail_level(Scene *s, Dragon *d)


83 {
84 switch(s->detail_level)
85 {
86 case 1:
87 d->joint_parts = 1;
88 d->chest_parts = 2;
89 d->tail_end_parts = 1;
90 break;
91 case 2:
92 d->joint_parts = 2;
93 d->chest_parts = 4;
94 d->tail_end_parts = 2;
95 break;
96 default:
97 case 3:
98 d->joint_parts = 4;
99 d->chest_parts = 8;
100 d->tail_end_parts = 4;

Pierre-André Saulais, Clare Park 29


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

110 void ps188_draw_scene(Scene *s)


111 {
112 // tile the texture 16 times in both directions
113 glMatrixMode(GL_TEXTURE);
114 glPushMatrix();
115 glScalef(16.0, 16.0, 1.0);
116 glMatrixMode(GL_MODELVIEW);
117 glPushMatrix();
118 glTranslatef(0.0, -2.0, 0.0);
119 glScalef(100.0, 1.0, 100.0);
120 draw_floor(s);
121 glPopMatrix();
122 glMatrixMode(GL_TEXTURE);
123 glPopMatrix();
124 glMatrixMode(GL_MODELVIEW);
125

126 Dragon *da = s->dragon[0];


127 glPushMatrix();
128 glTranslatef(0.0, 2.0 + 0.6 * da->alpha, 0.0);
129 glScalef(3.0, 3.0, 3.0);
130 set_detail_level(s, da);
131 draw_dragon_holding_a(da);
132 glPopMatrix();
133

134 Dragon *dp = s->dragon[1];


135 glPushMatrix();
136 glTranslatef(-dp->beta, dp->beta, dp->beta);
137 glRotatef(dp->alpha, 0.0, 1.0, 0.0);
138 glTranslatef(4.0, 0.0, 4.0);
139 glRotatef(60.0, 0.0, 1.0, 0.0);
140 glScalef(1.5, 1.5, 1.5);
141 set_detail_level(s, dp);
142 draw_dragon_holding_p(dp);
143 glPopMatrix();
144

145 Dragon *ds = s->dragon[2];


146 glPushMatrix();
147 glTranslatef(0.0, ds->beta, 0.0);
148 glRotatef(-ds->alpha, 0.0, 1.0, 0.0);
149 glTranslatef(3.0, 0.0, 3.0);
150 glRotatef(-120.0, 0.0, 1.0, 0.0);
151 glScalef(1.5, 1.5, 1.5);
152 set_detail_level(s, ds);
153 draw_dragon_holding_s(ds);
154 glPopMatrix();
155 }
156

157 void draw_floor(Scene *s)


158 {
159 begin_apply_material(floor_material);
160 glPushMatrix();
161 glScalef(1.0, 0.001, 1.0);
162 draw_mesh(s->floor);
163 glPopMatrix();
164 end_apply_material();
165 }
166

Pierre-André Saulais, Clare Park 30


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

167 void draw_dragon_holding_a(Dragon *d)


168 {
169 glPushMatrix();
170 glPushMatrix();
171 glRotatef(45.0, 0.0, 0.0, 1.0);
172 draw_dragon(d);
173 glPopMatrix();
174 glPushMatrix();
175 glTranslatef(1.0/3.0, 0.2/3.0, 0.0);
176 glRotatef(15.0, 0.0, 1.0, 0.0);
177 glRotatef(-d->theta_front_legs, 0.0, 0.0, 1.0);
178 glScalef(2.0/3.0, 2.0/3.0, 1.0/3.0);
179 begin_apply_material(tongue_material);
180 ps188_draw_a();
181 end_apply_material();
182 glPopMatrix();
183 glPopMatrix();
184 }
185

186 void draw_dragon_holding_p(Dragon *d)


187 {
188 glPushMatrix();
189 draw_dragon(d);
190 glPushMatrix();
191 glTranslatef(0.08, -0.13, 0.0);
192 glRotatef(-d->theta_front_legs + 90.0, 0.0, 0.0, 1.0);
193 glTranslatef(0.2, -0.1, 0.0);
194 glRotatef(-170, 0.0, 0.0, 1.0);
195 glScalef(1.0, 1.0, 0.5);
196 begin_apply_material(tongue_material);
197 ps188_draw_p();
198 end_apply_material();
199 glPopMatrix();
200 glPopMatrix();
201 }
202

203 void draw_dragon_holding_s(Dragon *d)


204 {
205 glPushMatrix();
206 draw_dragon(d);
207 glPushMatrix();
208 glTranslatef(0.26, -0.25, 0.0);
209 glRotatef(180.0 - d->theta_front_legs, 0.0, 0.0, 1.0);
210 // need to change the center of the rotation
211 glTranslatef(-0.4, 0.1, 0.0);
212 glScalef(1.0, 1.0, 0.5);
213 begin_apply_material(tongue_material);
214 ps188_draw_s();
215 end_apply_material();
216 glPopMatrix();
217 glPopMatrix();
218 }
219

220 GLfloat sawtooth(GLfloat t);


221 GLfloat spaced_rect(GLfloat t, GLfloat w, GLfloat a);
222 GLfloat spaced_sawtooth(GLfloat t, GLfloat w, GLfloat a);
223 GLfloat spaced_cos(GLfloat t, GLfloat w, GLfloat a);
224

225 void ps188_animate_scene(Scene *s)


226 {
227 clock_t ticks = clock();
228 GLfloat t = (GLfloat)ticks / (GLfloat)CLOCKS_PER_SEC;
229 double angle = fmod(t * 45.0, 360.0);
230

231 // hovering dragon


232 animate_dragon(s->dragon[0], t);

Pierre-André Saulais, Clare Park 31


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

233 s->dragon[0]->alpha = cos(t * 3.5 + M_PI);


234 s->dragon[0]->theta_head_z = -45.0;
235 s->dragon[0]->theta_paw = 60.0;
236

237 // drunk dragon trying to fly clockwise


238 animate_dragon(s->dragon[1], t);
239 s->dragon[1]->alpha = angle;
240 s->dragon[1]->beta = cos(t * 3.5) * cos(t) * cos(t);
241 s->dragon[1]->theta_head_z = -30.0;
242 s->dragon[1]->theta_neck = 30.0;
243 s->dragon[1]->theta_paw = 60.0;
244

245 // dragon jumping anticlockwise


246 animate_dragon(s->dragon[2], t);
247 s->dragon[2]->alpha = angle;
248 s->dragon[2]->beta = 1.20 * sqrt(fabs(cos(5.0 * t) - cos(6.0 * t) + cos(7.0 * t)));
249 s->dragon[2]->theta_wing = 0.0;
250 s->dragon[2]->theta_wing_joint = 20.0;
251 s->dragon[2]->theta_neck = 30.0;
252 s->dragon[2]->theta_paw = 60.0;
253 s->dragon[2]->theta_neck = 30.0;
254 s->dragon[2]->theta_paw = 60.0;
255 // this one is definitely having the time of its life
256 s->dragon[2]->theta_head_z = 60.0 * spaced_cos(t, 1.0, 2.0) - 30.0;
257 s->dragon[2]->theta_jaw = 10.0 * spaced_cos(t, 1.0, 2.0) + 10.0;
258

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

273 // Periodic function linearly going from 0 to 1


274 GLfloat sawtooth(GLfloat t)
275 {
276 return t - (GLfloat)floor(t);
277 }
278

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

297 void animate_dragon(Dragon *d, GLfloat t)


298 {

Pierre-André Saulais, Clare Park 32


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

299 d->theta_jaw = 10.0 * spaced_cos(t, 5.0, 2.0) + 10.0;


300 d->theta_head_y = 45.0 * spaced_cos(t, 5.0, 2.0);
301 d->theta_neck = 5.0 * cos(t * 3.0);
302 d->theta_wing = 45.0 * cos(t * 3.5);
303 d->theta_wing_joint = 60.0 - 30.0 * fabs(cos(t * 3.5) * cos(t));
304 d->theta_front_legs = 10.0 * cos(t * 3.0) + 40.0 + 45.0;
305 d->theta_back_legs = 10.0 * cos(t * 3.0) + 80.0 + 45.0;
306 d->theta_tail = 15.0 * cos(pow(t * 0.3, 2.0)) * cos(6.0 * t * 0.3);
307 }

C.2.2 dragon.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #include <GL/glut.h>
4 #include <stdio.h>
5 #include <math.h>
6 #include "dragon.h"
7 #include "letters.h"
8

9 void init_dragon(Dragon *d)


10 {
11 d->theta_jaw = 0.0;
12 d->theta_head_z = 0.0;
13 d->theta_head_y = 0.0;
14 d->theta_neck = 0.0;
15 d->theta_wing = 0.0;
16 d->theta_wing_joint = 0.0;
17 d->theta_front_legs = 0.0;
18 d->theta_back_legs = 0.0;
19 d->theta_paw = 0.0;
20 d->theta_tail = 0.0;
21 d->alpha = 0.0;
22 d->beta = 0.0;
23 d->gamma = 0.0;
24 d->joint_parts = 4;
25 d->chest_parts = 8;
26 d->tail_end_parts = 2;
27 init_material(&d->tongue_material);
28 init_material(&d->default_material);
29 init_material(&d->wing_material);
30 init_material(&d->wing_membrane_material);
31 }
32

33 void draw_dragon(Dragon *d)


34 {
35 begin_apply_material(d->default_material);
36 glPushMatrix();
37 glScalef(1.0/3.0, 1.0/3.0, 1.0/3.0);
38 glPushMatrix();
39 glTranslatef(1.0, 0.0, 0.0);
40 glRotatef(d->theta_neck, 0.0, 0.0, 1.0);
41 glScalef(2.0, 2.0, 2.0);
42 draw_dragon_upper(d);
43 glPopMatrix();
44

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);

Pierre-André Saulais, Clare Park 33


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

55 draw_dragon_tail(d);
56 glPopMatrix();
57 glPopMatrix();
58 end_apply_material();
59 }
60

61 void draw_dragon_upper(Dragon *d)


62 {
63 glPushMatrix();
64 glPushMatrix();
65 glTranslatef(0.4, -0.04, 0.0);
66 glRotatef(d->theta_head_y, 0.0, 1.0, 0.0);
67 glRotatef(d->theta_head_z, 0.0, 0.0, 1.0);
68 glScalef(0.6, 0.6, 0.6);
69 draw_dragon_head(d);
70 glPopMatrix();
71 glPushMatrix();
72 glScalef(0.5, 0.75, 0.75);
73 draw_dragon_joint(d);
74 glPopMatrix();
75 glPopMatrix();
76 }
77

78 void draw_dragon_head(Dragon *d)


79 {
80 glPushMatrix();
81 // top of the head
82 glPushMatrix();
83 glScalef(1.0, 1.0, 3.0);
84 ps188_draw_p();
85 glPopMatrix();
86 // left nostril
87 glPushMatrix();
88 glTranslatef(1.0, 0.49/7.0, -0.10);
89 glScalef(0.33, 0.4, 1.2);
90 glRotatef(180.0, 0.0, 1.0, 0.0);
91 ps188_draw_p();
92 glPopMatrix();
93 // right nostril
94 glPushMatrix();
95 glTranslatef(1.0, 0.49/7.0, 0.10);
96 glScalef(0.33, 0.4, 1.2);
97 glRotatef(180.0, 0.0, 1.0, 0.0);
98 ps188_draw_p();
99 glPopMatrix();
100 // tongue
101 glPushMatrix();
102 begin_apply_material(d->tongue_material);
103 glTranslatef(0.1, 0.0, 0.0);
104 glRotatef(-d->theta_jaw, 0.0, 0.0, 1.0);
105 glScalef(0.9, 0.9, 0.9);
106 draw_dragon_tongue(d);
107 end_apply_material();
108 glPopMatrix();
109 // jaw
110 glPushMatrix();
111 glRotatef(-d->theta_jaw, 0.0, 0.0, 1.0);
112 glRotatef(90.0, 1.0, 0.0, 0.0);
113 glScalef(1.0, 0.75, 0.5);
114 ps188_draw_a();
115 glPopMatrix();
116 glPopMatrix();
117 }
118

119 void draw_dragon_tongue(Dragon *d)


120 {

Pierre-André Saulais, Clare Park 34


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

129 void draw_dragon_joint(Dragon *d)


130 {
131 GLfloat step = 360.0 / d->joint_parts;
132 for(GLfloat theta = 0.0; theta < 360.0; theta += step)
133 {
134 glPushMatrix();
135 glTranslatef(0.40, 0.0, 0.0);
136 glRotatef(theta, 1.0, 0.0, 0.0);
137 glScalef(1.0, 0.5, 1.0);
138 ps188_draw_s();
139 glPopMatrix();
140 }
141 }
142

143 void draw_dragon_body(Dragon *d)


144 {
145 glPushMatrix();
146 glScalef(1.0/3.0, 1.0/3.0, 1.0/3.0);
147 glPushMatrix();
148 glScalef(1.0, 0.5, 0.5);
149 draw_dragon_chest(d);
150 glPopMatrix();
151

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

158 // left wing


159 begin_apply_material(d->wing_material);
160 glPushMatrix();
161 glRotatef(d->theta_wing, 1.0, 0.0, 0.0);
162 glRotatef(90.0, 0.0, 1.0, 0.0);
163 glScalef(3.0, 3.0, 3.0);
164 draw_dragon_wing(d);
165 glPopMatrix();
166

167 // right wing


168 glPushMatrix();
169 glRotatef(180.0, 0.0, 1.0, 0.0);
170 glRotatef(d->theta_wing, 1.0, 0.0, 0.0);
171 glRotatef(90.0, 0.0, 1.0, 0.0);
172 glScalef(3.0, 3.0, 3.0);
173 draw_dragon_wing(d);
174 glPopMatrix();
175 end_apply_material();
176 glPopMatrix();
177 }
178

179 void draw_dragon_chest(Dragon *d)


180 {
181 GLfloat step = 360.0 / d->chest_parts;
182 for(GLfloat theta = 0.0; theta < 359.0; theta += step)
183 {
184 glPushMatrix();
185 glTranslatef(-1.0, 0.0, 0.0);
186 glRotatef(theta, 1.0, 0.0, 0.0);

Pierre-André Saulais, Clare Park 35


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

187 glScalef(2.0, 2.0, 2.0);


188 ps188_draw_p();
189 glPopMatrix();
190 glPushMatrix();
191 glTranslatef(1.0, 0.0, 0.0);
192 glRotatef(theta, 1.0, 0.0, 0.0);
193 glRotatef(180.0, 0.0, 1.0, 0.0);
194 glScalef(2.0, 2.0, 2.0);
195 ps188_draw_p();
196 glPopMatrix();
197 }
198 }
199

200 void draw_dragon_wing(Dragon *d)


201 {
202 glPushMatrix();
203 // scale both parts of the wing equally
204 glScalef(0.5, 0.5, 0.5);
205 draw_dragon_wing_part(d);
206 glPushMatrix();
207 glTranslatef(1.0, 0.0, 0.0);
208 glRotatef(-d->theta_wing_joint, 0.0, 0.0, 1.0);
209 draw_dragon_wing_outer(d);
210 glPopMatrix();
211 glPopMatrix();
212 }
213

214 void draw_dragon_wing_part(Dragon *d)


215 {
216 glPushMatrix();
217 glRotatef(90.0, 1.0, 0.0, 0.0);
218 glScalef(1.0, 2.6, 0.20);
219 ps188_draw_a();
220 glPopMatrix();
221 begin_apply_material(d->wing_membrane_material);
222 glPushMatrix();
223 glTranslatef(0.25, 0.0, 0.0);
224 glScalef(0.26, 0.2, 0.2);
225 draw_dragon_wing_membrane(d);
226 glPopMatrix();
227 glPushMatrix();
228 glTranslatef(0.70, 0.0, 0.3);
229 glScalef(0.3, 0.2, 0.27);
230 draw_dragon_wing_membrane(d);
231 glPopMatrix();
232 glPushMatrix();
233 glTranslatef(0.70, 0.0, -0.3);
234 glScalef(0.3, 0.2, 0.27);
235 draw_dragon_wing_membrane(d);
236 glPopMatrix();
237 glPushMatrix();
238 glTranslatef(1.00, 0.0, 0.0);
239 glRotatef(180.0, 0.0, 1.0, 0.0);
240 glScalef(0.3, 0.2, 0.27);
241 draw_dragon_wing_membrane(d);
242 glPopMatrix();
243 end_apply_material();
244 }
245

246 void draw_dragon_wing_membrane(Dragon *d)


247 {
248 glPushMatrix();
249 glScalef(5.0, 5.0, 5.0);
250 glPushMatrix();
251 glRotatef(90.0, 1.0, 0.0, 0.0);
252 glScalef(0.2, 0.6, 0.05);

Pierre-André Saulais, Clare Park 36


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

278 void draw_dragon_wing_outer(Dragon *d)


279 {
280 glPushMatrix();
281 glTranslatef(1.0, 0.0, 0.0);
282 glRotatef(180.0, 0.0, 0.0, 1.0);
283 draw_dragon_wing_part(d);
284 glPopMatrix();
285 }
286

287 void draw_dragon_paws(Dragon *d)


288 {
289 glPushMatrix();
290 glScalef(0.76, 0.76, 0.76);
291 // front left paw
292 glPushMatrix();
293 glTranslatef(0.5, 0.0, -0.15);
294 glRotatef(-d->theta_front_legs, 0.0, 0.0, 1.0);
295 glRotatef(10.0, 0.0, 1.0, 0.0);
296 glScalef(0.8, 0.8, 0.8);
297 draw_dragon_paw(d);
298 glPopMatrix();
299

300 // front right paw


301 glPushMatrix();
302 glTranslatef(0.5, 0.0, 0.15);
303 glRotatef(-d->theta_front_legs, 0.0, 0.0, 1.0);
304 glRotatef(-10.0, 0.0, 1.0, 0.0);
305 glScalef(0.8, 0.8, 0.8);
306 draw_dragon_paw(d);
307 glPopMatrix();
308

309 // hind left paw


310 glPushMatrix();
311 glTranslatef(-0.5, 0.0, -0.15);
312 glRotatef(-d->theta_back_legs, 0.0, 0.0, 1.0);
313 glRotatef(10.0, 0.0, 1.0, 0.0);
314 glScalef(1.2, 1.2, 1.2);
315 draw_dragon_paw(d);
316 glPopMatrix();
317

318 // hind right paw

Pierre-André Saulais, Clare Park 37


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

329 void draw_dragon_paw(Dragon *d)


330 {
331 glPushMatrix();
332 glTranslatef(0.5, 0.0, 0.0);
333 glRotatef(d->theta_paw, 0.0, 0.0, 1.0);
334 glRotatef(90.0, 1.0, 0.0, 0.0);
335 glScalef(0.5, 0.5, 0.5);
336 ps188_draw_a();
337 glPopMatrix();
338 glPushMatrix();
339 glScalef(0.6, 0.5, 0.5);
340 draw_dragon_joint(d);
341 glPopMatrix();
342 }
343

344 void draw_dragon_tail(Dragon *d)


345 {
346 GLuint n = 10;
347 GLfloat k = d->theta_tail / 20.0;
348 static GLfloat sizes[10] =
349 {
350 // make the tail smaller and smaller as we get near the end
351 1.0, 0.80, 0.75, 0.75, 0.77, 0.86, 0.9, 0.89, 0.88, 0.86
352 };
353 GLfloat angles[10] =
354 {
355 // rotate more and more each joint to make the tail curl
356 -d->theta_tail, 0.0, 0.0, 45.0 * k, 45.0 * k, 60.0 * k, 45.0 * k, 60.0 * k, 120.0 *
k, 60.0 * k
357 };
358 GLfloat mod[10] =
359 {
360 // slow down some joints by a factor inversely proportional to their size
361 // 1.0, 0.80, 0.6, 0.45, 0.35, 0.30, 0.27, 0.24, 0.21, 0.18
362 1.0, 1.0, 1.0, 0.6 * 0.45, 0.6 * 0.35, 0.6 * 0.30, 0.6 * 0.27, 0.6 * 0.24, 1.0, 1.0
363 };
364 glPushMatrix();
365 glScalef(0.5, 0.5, 0.5);
366 // keep the transformation matrix for each joint,
367 // so the transformations are applied on top of the previous ones
368 glPushMatrix();
369 glTranslatef(-0.40, 0.0, 0.0);
370 glScalef(0.52, 1.0, 1.0);
371 for(GLuint i = 0; i < n; i++)
372 {
373 GLfloat f = sizes[i];
374 glTranslatef(0.80, 0.0, 0.0);
375 glRotatef(angles[i] * mod[i], 0.0, 0.0, 1.0);
376 glScalef(f, f, f);
377 draw_dragon_joint(d);
378 }
379 glTranslatef(2.4, 0.0, 0.0);
380 glRotatef(180.0, 0.0, 1.0, 0.0);
381 glScalef(2.4, 1.8, 1.8);
382 draw_dragon_tail_end(d);
383 glPopMatrix();

Pierre-André Saulais, Clare Park 38


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

384 glPopMatrix();
385 }
386

387 void draw_dragon_tail_end(Dragon *d)


388 {
389 GLfloat step = 360.0 / (d->tail_end_parts * 2.0);
390 for(GLfloat theta = 0.0; theta < 359.0; theta += step)
391 {
392 glPushMatrix();
393 glRotatef(theta, 1.0, 0.0, 0.0);
394 ps188_draw_a();
395 glPopMatrix();
396 }
397 }

C.2.3 letters.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #include <GL/glut.h>
4 #include "letters.h"
5 #include "mesh.h"
6 #include "primitives.h"
7

8 #define ANGLE_A (73)


9 #define ANGLE_S (180 * 1.15)
10 #define BASE_WIDTH_A (0.15)
11

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

21 static Meshes meshes = {0, 0, 0, 0, 0};


22

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 {

Pierre-André Saulais, Clare Park 39


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

50 double bw = BASE_WIDTH_A; // base width for the legs


51 double y = 0.40; // y position of the second bar, relative to the letter
52 double m1w = sheared_paralpd_width(bw, 1.0, ANGLE_A);
53 glPushMatrix();
54 glTranslatef(1.0, -m1w, -0.1);
55 glRotatef(90, 0.0, 0.0, 1.0);
56 // left leg
57 glPushMatrix();
58 glTranslatef((bw / 2.0), 0.0, 0.0);
59 glScalef(1.0, 1.0, 0.2);
60 draw_mesh(meshes.sheared_a);
61 glPopMatrix();
62 // right leg
63 glPushMatrix();
64 glTranslatef(m1w * 2.0 - (bw / 2.0), 0.0, 0.2);
65 glRotatef(180, 0.0, 1.0, 0.0);
66 glScalef(1.0, 1.0, 0.2);
67 draw_mesh(meshes.sheared_a);
68 glPopMatrix();
69 // lower bar
70 glPushMatrix();
71 glTranslatef(m1w, y, 0.1);
72 // make it slightly smaller to avoid texture problems
73 glScalef(m1w / 2.0 * 0.99, 0.1 * 0.99, 0.1 * 0.99);
74 draw_mesh(meshes.cube);
75 glPopMatrix();
76 glPopMatrix();
77 }
78

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

98 // round end of the top curve


99 glPushMatrix();
100 glTranslatef(0.75, 0.00, 0.00);
101 glRotatef(ANGLE_S - 180, 0.0, 0.0, 1.0);
102 glTranslatef(0.75, 0.00, 0.00);
103 glScalef(0.25, 0.25, 0.5);
104 draw_mesh(meshes.disk);
105 glPopMatrix();
106 // round end of the bottom curve
107 glPushMatrix();
108 glTranslatef(-0.75, 0.00, 0.00);
109 glRotatef(ANGLE_S, 0.0, 0.0, 1.0);
110 glTranslatef(0.75, 0.00, 0.00);
111 glScalef(0.25, 0.25, 0.5);
112 draw_mesh(meshes.disk);
113 glPopMatrix();
114 glPopMatrix();
115 }

Pierre-André Saulais, Clare Park 40


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

C.2.4 primitives.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #include <GL/glut.h>
4 #include <math.h>
5 #include <malloc.h>
6 #include "primitives.h"
7

8 Mesh * create_curve(double theta, double width, GLuint nCurvePoints)


9 {
10 double theta_rad = radians(theta);
11 Mesh *m = (Mesh *)malloc(sizeof(Mesh));
12

13 // compute the vertices of the curve


14 curve_vertices(m, theta_rad, width, nCurvePoints);
15

16 // compute the normals of the curve


17 curve_normals(m, theta_rad, width, nCurvePoints);
18

19 // compute the texture coords of the curve


20 curve_texcoords(m, theta_rad, width, nCurvePoints);
21

22 // specify the model using triangle strips for the different faces
23 curve_meshes(m, theta_rad, width, nCurvePoints);
24 return m;
25 }
26

27 void curve_vertices(Mesh *m, double theta, double width, GLuint nCurvePoints)


28 {
29 m->vertices = (GLfloat *)malloc(sizeof(GLfloat) * 3 * ((nCurvePoints * 8) + 8));
30

31 // face 0 is front, face 1 is back, 2 is start leg, 3 is end leg


32 GLfloat *v0outer_up = m->vertices;
33 GLfloat *v0inner_up = v0outer_up + (nCurvePoints * 3);
34 GLfloat *v1outer_up = v0inner_up + (nCurvePoints * 3);
35 GLfloat *v1inner_up = v1outer_up + (nCurvePoints * 3);
36 GLfloat *v0outer_side = v1inner_up + (nCurvePoints * 3);
37 GLfloat *v0inner_side = v0outer_side + (nCurvePoints * 3);
38 GLfloat *v1outer_side = v0inner_side + (nCurvePoints * 3);
39 GLfloat *v1inner_side = v1outer_side + (nCurvePoints * 3);
40 GLfloat *v2 = v1inner_side + (nCurvePoints * 3);
41 GLfloat *v3 = v2 + (4 * 3);
42

43 double angle = 0.0;


44 double step = theta / ((double)nCurvePoints - 1.0);
45 double r = (1.0 - width);
46 for(GLuint i = 0; i < nCurvePoints; i++, angle += step)
47 {
48 double x = cos(angle);
49 double y = sin(angle);
50

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

Pierre-André Saulais, Clare Park 41


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

83 void curve_normals(Mesh *m, double theta, double width, GLuint nCurvePoints)


84 {
85 m->normals = (GLfloat *)malloc(sizeof(GLfloat) * 3 * ((nCurvePoints * 8) + 8));
86

87 // face 0 is front, face 1 is back, 2 is start leg, 3 is end leg


88 GLfloat *n0outer_up = m->normals;
89 GLfloat *n0inner_up = n0outer_up + (nCurvePoints * 3);
90 GLfloat *n1outer_up = n0inner_up + (nCurvePoints * 3);
91 GLfloat *n1inner_up = n1outer_up + (nCurvePoints * 3);
92 GLfloat *n0outer_side = n1inner_up + (nCurvePoints * 3);
93 GLfloat *n0inner_side = n0outer_side + (nCurvePoints * 3);
94 GLfloat *n1outer_side = n0inner_side + (nCurvePoints * 3);
95 GLfloat *n1inner_side = n1outer_side + (nCurvePoints * 3);
96 GLfloat *n2 = n1inner_side + (nCurvePoints * 3);
97 GLfloat *n3 = n2 + (4 * 3);
98

99 double angle = 0.0;


100 double step = theta / ((double)nCurvePoints - 1.0);
101 double r = (1.0 - width);
102 for(GLuint i = 0; i < nCurvePoints; i++, angle += step)
103 {
104 double x = cos(angle);
105 double y = sin(angle);
106

107 // outer curve


108 *n0outer_up++ = x; *n0outer_side++ = 0.0;
109 *n0outer_up++ = y; *n0outer_side++ = 0.0;
110 *n0outer_up++ = 0.0; *n0outer_side++ = -1.0;
111

112 *n1outer_up++ = x; *n1outer_side++ = 0.0;


113 *n1outer_up++ = y; *n1outer_side++ = 0.0;
114 *n1outer_up++ = 0.0; *n1outer_side++ = 1.0;
115

116 // inner curve


117 *n0inner_up++ = -x; *n0inner_side++ = 0.0;
118 *n0inner_up++ = -y; *n0inner_side++ = 0.0;
119 *n0inner_up++ = 0.0; *n0inner_side++ = -1.0;
120

121 *n1inner_up++ = -x; *n1inner_side++ = 0.0;


122 *n1inner_up++ = -y; *n1inner_side++ = 0.0;
123 *n1inner_up++ = 0.0; *n1inner_side++ = 1.0;
124 }
125

126 // start face


127 GLfloat dxs = (1.0 - r) * cos(0.0);
128 GLfloat dys = (1.0 - r) * sin(0.0);
129 *n2++ = dys; *n2++ = -dxs; *n2++ = 0.0;
130 *n2++ = dys; *n2++ = -dxs; *n2++ = 0.0;

Pierre-André Saulais, Clare Park 42


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

131 *n2++ = dys; *n2++ = -dxs; *n2++ = 0.0;


132 *n2++ = dys; *n2++ = -dxs; *n2++ = 0.0;
133

134 // end face


135 GLfloat dxe = (1.0 - r) * cos(theta);
136 GLfloat dye = (1.0 - r) * sin(theta);
137 *n3++ = -dye; *n3++ = dxe; *n3++ = 0.0;
138 *n3++ = -dye; *n3++ = dxe; *n3++ = 0.0;
139 *n3++ = -dye; *n3++ = dxe; *n3++ = 0.0;
140 *n3++ = -dye; *n3++ = dxe; *n3++ = 0.0;
141 }
142

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

147 // face 0 is front, face 1 is back, 2 is start leg, 3 is end leg


148 GLfloat *t0outer_up = m->texCoords;
149 GLfloat *t0inner_up = t0outer_up + (nCurvePoints * 2);
150 GLfloat *t1outer_up = t0inner_up + (nCurvePoints * 2);
151 GLfloat *t1inner_up = t1outer_up + (nCurvePoints * 2);
152 GLfloat *t0outer_side = t1inner_up + (nCurvePoints * 2);
153 GLfloat *t0inner_side = t0outer_side + (nCurvePoints * 2);
154 GLfloat *t1outer_side = t0inner_side + (nCurvePoints * 2);
155 GLfloat *t1inner_side = t1outer_side + (nCurvePoints * 2);
156 GLfloat *t2 = t1inner_side + (nCurvePoints * 2);
157 GLfloat *t3 = t2 + (4 * 2);
158

159 double angle = 0.0;


160 double step = theta / ((double)nCurvePoints - 1.0);
161 double r = (1.0 - width);
162 for(GLuint i = 0; i < nCurvePoints; i++, angle += step)
163 {
164 double tc = (double)i / (double)nCurvePoints; // normalized texture coord
165

166 // outer curve


167 *t0outer_up++ = tc; *t0outer_side++ = 1.0;
168 *t0outer_up++ = 1.0; *t0outer_side++ = tc;
169

170 *t1outer_up++ = tc; *t1outer_side++ = 0.0;


171 *t1outer_up++ = 0.0; *t1outer_side++ = tc;
172

173 // inner curve


174 *t0inner_up++ = tc; *t0inner_side++ = 0.0;
175 *t0inner_up++ = 0.0; *t0inner_side++ = tc;
176

177 *t1inner_up++ = tc; *t1inner_side++ = 1.0;


178 *t1inner_up++ = 1.0; *t1inner_side++ = tc;
179 }
180

181 // start face


182 *t2++ = 1.0; *t2++ = 1.0;
183 *t2++ = 1.0; *t2++ = 0.0;
184 *t2++ = 0.0; *t2++ = 0.0;
185 *t2++ = 0.0; *t2++ = 1.0;
186

187 // end face


188 *t3++ = 1.0; *t3++ = 1.0;
189 *t3++ = 1.0; *t3++ = 0.0;
190 *t3++ = 0.0; *t3++ = 0.0;
191 *t3++ = 0.0; *t3++ = 1.0;
192 }
193

194 void curve_meshes(Mesh *m, double theta, double width, GLuint nCurvePoints)
195 {
196 m->faceCount = 6;

Pierre-André Saulais, Clare Park 43


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

197 m->faces = (Face *)malloc(sizeof(Face) * m->faceCount);


198 for(GLuint i = 0; i < 4; i++)
199 {
200 m->faces[i].mode = GL_TRIANGLE_STRIP;
201 m->faces[i].count = nCurvePoints * 2;
202 m->faces[i].offset = i * nCurvePoints * 2;
203 m->faces[i].draw = 1;
204 }
205

206 m->indices = (GLuint *)malloc(((nCurvePoints * 2 * 4) + 8) * sizeof(GLuint));


207 GLuint *i0 = m->indices + m->faces[0].offset;
208 GLuint *i1 = m->indices + m->faces[1].offset;
209 GLuint *i2 = m->indices + m->faces[2].offset;
210 GLuint *i3 = m->indices + m->faces[3].offset;
211 for(GLuint i = 0; i < nCurvePoints; i++)
212 {
213 *i0++ = i + (nCurvePoints * 5);
214 *i0++ = i + (nCurvePoints * 4);
215 *i1++ = i + (nCurvePoints * 7);
216 *i1++ = i + (nCurvePoints * 6);
217 *i2++ = i + (nCurvePoints * 0);
218 *i2++ = i + (nCurvePoints * 2);
219 *i3++ = i + (nCurvePoints * 1);
220 *i3++ = i + (nCurvePoints * 3);
221 }
222

223 m->faces[4].mode = GL_QUADS;


224 m->faces[4].count = 4;
225 m->faces[4].offset = (nCurvePoints * 2 * 4);
226 m->faces[4].draw = 1;
227 m->faces[5].mode = GL_QUADS;
228 m->faces[5].count = 4;
229 m->faces[5].offset = (nCurvePoints * 2 * 4) + 4;
230 m->faces[5].draw = 1;
231

232 GLuint *i4 = m->indices + m->faces[4].offset;


233 GLuint *i5 = m->indices + m->faces[5].offset;
234 for(GLuint i = 0; i < 4; i++)
235 {
236 i4[i] = m->faces[4].offset + i;
237 i5[i] = m->faces[5].offset + i;
238 }
239 }
240

241 Mesh * create_cube()


242 {
243 static GLfloat vertices[][3] =
244 {
245 {-1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0},
246 { 1.0, 1.0, 1.0}, { 1.0, -1.0, 1.0},
247 {-1.0, -1.0, -1.0}, {-1.0, 1.0, -1.0},
248 { 1.0, 1.0, -1.0}, { 1.0, -1.0, -1.0}
249 };
250 #ifdef EXACT_NORMALS
251 static GLfloat faces_normals[][3] =
252 {
253 { 0.0, 0.0, 1.0}, { 1.0, 0.0, 0.0},
254 { 0.0, -1.0, 0.0}, { 0.0, 1.0, 0.0},
255 { 0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0},
256 };
257 #else
258 // let create_mesh() compute face normals
259 GLfloat *faces_normals = 0;
260 #endif
261 static GLuint faces_indices[][4] =
262 {

Pierre-André Saulais, Clare Park 44


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

263 {0, 3, 2, 1}, {2, 3, 7, 6},


264 {0, 4, 7, 3}, {1, 2, 6, 5},
265 {4, 5, 6, 7}, {0, 1, 5, 4}
266 };
267 return create_mesh((GLfloat *)vertices,
268 (GLfloat *)faces_normals,
269 (GLuint *)faces_indices, 24, 6);
270 }
271

272 Mesh * create_sheared_paralpd(double width, double height, double theta)


273 {
274 GLfloat d = height / tan(radians(theta));
275 GLfloat vertices[8][3] =
276 {
277 {0.0, 0.0, 0.0}, {d, height, 0.0},
278 {width + d, height, 0.0}, {width, 0.0, 0.0},
279 {0.0, 0.0, 1.0}, {d, height, 1.0},
280 {width + d, height, 1.0}, {width, 0.0, 1.0},
281 };
282 #ifdef EXACT_NORMALS
283 GLfloat a = sqrt(height * height + d * d);
284 GLfloat faces_normals[6][3] =
285 {
286 { 0.0, 0.0, -1.0}, { 0.0, 0.0, 1.0},
287 {-height/a, d/a, 0.0}, {height/a, -d/a, 0.0},
288 { 0.0, 1.0, 0.0}, { 0.0, -1.0, 0.0},
289 };
290 #else
291 // let create_mesh() compute face normals
292 GLfloat *faces_normals = 0;
293 #endif
294 static GLuint faces_indices[][4] =
295 {
296 {0, 1, 2, 3}, {4, 7, 6, 5},
297 {0, 4, 5, 1}, {3, 2, 6, 7},
298 {1, 5, 6, 2}, {0, 3, 7, 4}
299 };
300 return create_mesh((GLfloat *)vertices,
301 (GLfloat *)faces_normals,
302 (GLuint *)faces_indices, 24, 6);
303 }
304

305 double sheared_paralpd_width(double baseWidth, double height, double theta)


306 {
307 GLfloat theta_rad = (theta / 180.0) * M_PI;
308 GLfloat d = height / tan(theta_rad);
309 return d + baseWidth;
310 }

C.2.5 mesh.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #include <malloc.h>
4 #include <math.h>
5 #include "mesh.h"
6 #include "display.h"
7 #include "scene.h"
8

9 static Material normals_material =


10 { // ambient, diffuse, specular, shine, texture
11 {1.0, 1.0, 1.0, 1.0}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 1.0}, 0.0, 0
12 };
13

14 Mesh * create_mesh(GLfloat *vertices, GLfloat *faces_normals, GLuint *faces_indices,


15 GLsizei indiceCount, GLsizei faceCount)

Pierre-André Saulais, Clare Park 45


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

56 v1[0] = vertices[(ind1 * 3) + 0];


57 v2[0] = vertices[(ind2 * 3) + 0];
58 v3[0] = vertices[(ind3 * 3) + 0];
59

60 v1[1] = vertices[(ind1 * 3) + 1];


61 v2[1] = vertices[(ind2 * 3) + 1];
62 v3[1] = vertices[(ind3 * 3) + 1];
63

64 v1[2] = vertices[(ind1 * 3) + 2];


65 v2[2] = vertices[(ind2 * 3) + 2];
66 v3[2] = vertices[(ind3 * 3) + 2];
67

68 normal_vector(v1, v2, v3, u);


69

70 // assign it to every vertex in the face


71 for(GLuint j = 0; j < verticesPerFace; j++)
72 {
73 *n++ = u[0];
74 *n++ = u[1];
75 *n++ = u[2];
76 }
77 }
78 }
79

80 // indices
81 m->faceCount = faceCount;

Pierre-André Saulais, Clare Park 46


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

82 m->faces = (Face *)malloc(sizeof(Face) * faceCount);


83 for(GLuint i = 0; i < faceCount; i++)
84 {
85 Face *f = &m->faces[i];
86 f->mode = GL_QUADS;
87 f->count = verticesPerFace;
88 f->draw = 1;
89 f->offset = i * verticesPerFace;
90 }
91 m->indices = (GLuint *)malloc(sizeof(GLuint) * indiceCount);
92 for(GLuint i = 0; i < indiceCount; i++)
93 m->indices[i] = i;
94

95 // texture coords
96 if(verticesPerFace == 4)
97 mesh_quadri_textcoords(m, indiceCount);
98 else
99 m->texCoords = 0;
100 return m;
101 }
102

103 // Compute the normal vector of the triangle ABC


104 void normal_vector(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *n)
105 {
106 // calculate the cross-product of AB and AC
107 GLfloat u[3], v[3];
108 for(int i = 0; i < 3; i++)
109 {
110 u[i] = b[i] - a[i];
111 v[i] = c[i] - a[i];
112 }
113 n[0] = u[1] * v[2] - u[2] * v[1];
114 n[1] = u[2] * v[0] - u[0] * v[2];
115 n[2] = u[0] * v[1] - u[1] * v[0];
116

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

124 /* Generate texture coordinates for 4 vertices-faced meshes */


125 void mesh_quadri_textcoords(Mesh *m, GLsizei indiceCount)
126 {
127 m->texCoords = (GLfloat *)malloc(sizeof(GLfloat) * 2 * indiceCount);
128 for(GLsizei i = 0; i < m->faceCount; i++)
129 {
130 Face *f = &m->faces[i];
131 for(GLuint j = 0; j < 4; j++)
132 {
133 GLuint ind = m->indices[f->offset + j];
134 GLfloat *tc = &m->texCoords[(ind * 2)];
135 tc[0] = ((j == 0) || (j == 3)) ? 0.0 : 1.0;
136 tc[1] = ((j == 0) || (j == 1)) ? 0.0 : 1.0;
137 }
138 }
139 }
140

141 void draw_mesh(Mesh *m)


142 {
143 if(g.use_vertex_list)
144 draw_mesh_vertex_list(m);
145 else
146 draw_mesh_immediate(m);
147

Pierre-André Saulais, Clare Park 47


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

148 if(g.draw_normals)
149 draw_mesh_normals(m);
150 }
151

152 // draw the mesh using glBegin/glEnd/glVertex/etc


153 void draw_mesh_immediate(Mesh *m)
154 {
155 for(GLsizei i = 0; i < m->faceCount; i++)
156 {
157 Face f = m->faces[i];
158 if(f.draw)
159 {
160 glBegin(f.mode);
161 for(GLsizei j = 0; j < f.count; j++)
162 {
163 GLuint ind = m->indices[f.offset + j];
164 if(m->normals)
165 glNormal3fv(m->normals + (ind * 3));
166 if(m->texCoords);
167 glTexCoord2fv(m->texCoords + (ind * 2));
168 glVertex3fv(m->vertices + (ind * 3));
169 }
170 glEnd();
171 }
172 }
173 }
174

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

203 void init_material(Material *material)


204 {
205 for(int i = 0; i < 4; i++)
206 {
207 material->ambient[i] = 1.0;
208 material->diffuse[i] = 1.0;
209 material->specular[i] = 1.0;
210 }
211 material->shine = 0.0;
212 material->texture = 0;
213 }

Pierre-André Saulais, Clare Park 48


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

214

215 void begin_apply_material(Material material)


216 {
217 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT);
218 glMaterialfv(GL_FRONT, GL_AMBIENT, material.ambient);
219 glMaterialfv(GL_FRONT, GL_DIFFUSE, material.diffuse);
220 glMaterialfv(GL_FRONT, GL_SPECULAR, material.specular);
221 glMaterialf(GL_FRONT, GL_SHININESS, material.shine);
222 glEnable(GL_TEXTURE_2D);
223 glBindTexture(GL_TEXTURE_2D, material.texture);
224 if(material.use_mipmaps)
225 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
226 else
227 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
228 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
229 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
230 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
231 }
232

233 void end_apply_material()


234 {
235 glPopAttrib();
236 }
237

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

261 void free_mesh(Mesh *m)


262 {
263 free(m->vertices);
264 free(m->normals);
265 free(m->texCoords);
266 free(m->indices);
267 free(m->faces);
268 free(m);
269 }

C.2.6 images.c

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

3 #include <GL/glut.h>
4 #include <stdio.h>
5 #include <tiffio.h>
6 #include "images.h"
7

Pierre-André Saulais, Clare Park 49


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

8 // Create a texture from a TIFF file using libtiff


9 GLuint textureFromTIFFImage(char *path, int mipmaps)
10 {
11 // load the image
12 TIFF *tiff = TIFFOpen(path, "r");
13 if(!tiff)
14 return 0;
15

16 GLuint width, height;


17 TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
18 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
19

20 GLuint *data = (GLuint *) _TIFFmalloc(width * height * sizeof(GLuint));


21 if(!data)
22 {
23 TIFFClose(tiff);
24 return 0;
25 }
26

27 if(!TIFFReadRGBAImage(tiff, width, height, data, 1))


28 {
29 _TIFFfree(data);
30 TIFFClose(tiff);
31 return 0;
32 }
33

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

1 /* Pierre-Andre Saulais <ps188@macs.hw.ac.uk> */


2

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

11 GLfloat ambient0[] = {1.0, 1.0, 1.0, 1.0};


12 GLfloat diffuse0[] = {1.0, 1.0, 1.0, 1.0};
13 GLfloat specular0[] = {1.0, 1.0, 1.0, 1.0};
14 GLfloat light0_pos[] = {0.0, 1.0, 1.0, 0.0};
15

16 static Material debug_material =


17 { // ambient, diffuse, specular, shine, texture, use_mipmap
18 {0.2, 0.2, 0.2, 1.0}, {1.0, 4.0/6.0, 0.0, 1.0}, {0.2, 0.2, 0.2, 1.0}, 20.0, 0, 0
19 };
20

21 GlobalState g = {0};
22

23 void init_display()

Pierre-André Saulais, Clare Park 50


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

62 void select_item(int index)


63 {
64 if(index < ITEM_SCENE)
65 index = ITEM_LAST;
66 else if(index > ITEM_LAST)
67 index = ITEM_SCENE;
68

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);

Pierre-André Saulais, Clare Park 51


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

90

91 if(g.draw_axes)
92 {
93 draw_axes();
94 draw_axis_grids(1, 1, 1);
95 }
96 }
97

98 // array of function pointers to ’void func(Dragon *)’


99 typedef void (*draw_dragon_func)(Dragon *d);
100 static draw_dragon_func draw_dragon_parts[] =
101 {
102 &draw_dragon,
103 &draw_dragon_upper,
104 &draw_dragon_head,
105 &draw_dragon_tongue,
106 &draw_dragon_joint,
107 &draw_dragon_body,
108 &draw_dragon_chest,
109 &draw_dragon_paws,
110 &draw_dragon_paw,
111 &draw_dragon_wing,
112 &draw_dragon_wing_outer,
113 &draw_dragon_wing_part,
114 &draw_dragon_wing_membrane,
115 &draw_dragon_tail,
116 &draw_dragon_tail_end
117 };
118

119 void draw_selected_ps188(int item)


120 {
121 Dragon dragon;
122 init_dragon(&dragon);
123 set_detail_level(g.scene, &dragon);
124 dragon.default_material = debug_material;
125 dragon.tongue_material = debug_material;
126 dragon.wing_material = debug_material;
127 dragon.wing_membrane_material = debug_material;
128

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

152 void draw_selected_cp133(int item)


153 {
154 float star_rot_angle = 0.0;
155 float cb_flip_angle = 0.0;

Pierre-André Saulais, Clare Park 52


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

156 float x_ll_rot_angle = 0.0;


157 float x_rl_rot_angle = 0.0;
158 float whole_model_angle = 0.0;
159 float cx_angle = 0.0;
160 float xp_angle = 0.0;
161 int body_color = 1;
162 int star_color = 2;
163

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

213 void draw_axis()


214 {
215 glLineWidth(3.0);
216 glBegin(GL_LINES);
217 glVertex3f(0.0, 0.0, 0.0);
218 glVertex3f(0.8, 0.0, 0.0);
219 glEnd();
220 glLineWidth(1.0);
221

Pierre-André Saulais, Clare Park 53


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

229 void draw_axes()


230 {
231 Material m =
232 { // ambient, diffuse, specular, shine, texture, mipmap
233 {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 0.0}, 0.0, 0, 0
234 };
235

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

257 void draw_axis_grids(int draw_x, int draw_y, int draw_z)


258 {
259 static Material m =
260 { // ambient, diffuse, specular, shine, texture, mipmap
261 {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 0.0}, 0.0, 0, 0
262 };
263

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 }

Pierre-André Saulais, Clare Park 54


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

288

289 void draw_axis_grid()


290 {
291 glLineStipple(1, 0xAAAA); //line style = fine dots
292 glEnable(GL_LINE_STIPPLE);
293 glBegin(GL_LINES);
294 for(GLint i = -10; i <= 10; i++)
295 {
296 if(i != 0)
297 {
298 glVertex3f(-1.0 * i, -10.0, 0.0);
299 glVertex3f(-1.0 * i, 10.0, 0.0);
300 glVertex3f(-10.0, -1.0 * i, 0.0);
301 glVertex3f(10.0, -1.0 * i, 0.0);
302 }
303 }
304 glEnd();
305 glDisable(GL_LINE_STIPPLE);
306

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

321 void animate_selected()


322 {
323 if(g.animate)
324 {
325 ps188_animate_scene(g.scene);
326 cp133_animate_scene();
327 glutPostRedisplay();
328 }
329 }
330

331 void start_fps()


332 {
333 g.start = clock();
334 }
335

336 GLfloat update_fps()


337 {
338 g.frames++;
339 clock_t elapsed = clock() - g.start;
340 GLfloat fps = g.frames / ((GLfloat)elapsed / CLOCKS_PER_SEC);
341 if(g.frames > 100)
342 {
343 g.frames = 0;
344 g.start = clock();
345 }
346 return fps;
347 }
348

349 void show_fps(GLfloat fps)


350 {
351 // the text shouldn’t be shaded
352 glPushAttrib(GL_ENABLE_BIT);
353 glColor3f(1.0, 1.0, 1.0);

Pierre-André Saulais, Clare Park 55


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

354 glDisable(GL_LIGHTING);
355

356 // set up the view to use screen coordinates (in pixels)


357 glMatrixMode(GL_MODELVIEW);
358 glPushMatrix();
359 glLoadIdentity();
360 glMatrixMode(GL_PROJECTION);
361 glPushMatrix();
362 glLoadIdentity();
363 GLuint width = glutGet(GLUT_WINDOW_WIDTH);
364 GLuint height = glutGet(GLUT_WINDOW_HEIGHT);
365 gluOrtho2D(0.0, width, 0.0, height);
366 glRasterPos2f(10, height - 20);
367

368 // draw the text on the screen


369 char *text = (char *)malloc(20);
370 sprintf(text, "%.1f fps", fps);
371 char *p = text;
372 while(*p)
373 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p++);
374 free(text);
375

376 // restore the previous view


377 glMatrixMode(GL_PROJECTION);
378 glPopMatrix();
379 glMatrixMode(GL_MODELVIEW);
380 glPopMatrix();
381

382 glPopAttrib();
383 }
384

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

390 glPolygonMode(GL_FRONT_AND_BACK, g.wireframe_mode ? GL_LINE : GL_FILL);


391

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

411 GLfloat fps = update_fps();


412 if(g.show_fps)
413 show_fps(fps);
414 glPopMatrix();
415

416 glFlush();
417 glutSwapBuffers();
418 }
419

Pierre-André Saulais, Clare Park 56


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

420 void onReshape(int w, int h)


421 {
422 glViewport(0, 0, w, h);
423 glMatrixMode(GL_PROJECTION);
424 glLoadIdentity();
425 if(g.selected_item == ITEM_SCENE)
426 {
427 gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 100.0f);
428 }
429 else
430 {
431 if (w <= h)
432 glOrtho(-1.0, 1.0, -1.0 * (GLfloat) h / (GLfloat) w,
433 1.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
434 else
435 glOrtho(-1.0 * (GLfloat) w / (GLfloat) h,
436 1.0 * (GLfloat) w / (GLfloat) h, -1.0, 1.0, -10.0, 10.0);
437 }
438 glMatrixMode(GL_MODELVIEW);
439 }
440

441 void onKeyboard(unsigned char key, int x, int y)


442 {
443 if(key == ’q’ || key == ’Q’)
444 g.theta[1] += 5.0;
445 else if(key == ’d’ || key == ’D’)
446 g.theta[1] -= 5.0;
447 else if(key == ’z’ || key == ’Z’)
448 g.theta[0] -= 5.0;
449 else if(key == ’s’ || key == ’S’)
450 g.theta[0] += 5.0;
451 else if(key == ’a’ || key == ’A’)
452 g.theta[2] += 5.0;
453 else if(key == ’e’ || key == ’E’)
454 g.theta[2] -= 5.0;
455 else if(key == ’x’ || key == ’X’)
456 g.sigma /= 1.10;
457 else if(key == ’c’ || key == ’C’)
458 g.sigma *= 1.10;
459 else if(key == ’r’ || key == ’R’)
460 reset_camera();
461 else if(key == ’.’)
462 g.draw_axes = ~g.draw_axes & 1;
463 else if(key == ’n’)
464 g.draw_normals = ~g.draw_normals & 1;
465 else if(key == ’w’)
466 g.wireframe_mode = ~g.wireframe_mode & 1;
467 else if(key == ’v’)
468 g.use_vertex_list = ~g.use_vertex_list & 1;
469 else if(key == ’ ’)
470 g.animate = ~g.animate & 1;
471 else if(key == ’!’)
472 g.show_fps = ~g.show_fps & 1;
473 else if(key == ’1’)
474 g.scene->camera = CAMERA_STATIC;
475 else if(key == ’2’)
476 g.scene->camera = CAMERA_JUMPING;
477 else if(key == ’3’)
478 g.scene->camera = CAMERA_FLYING;
479 else if(key == ’+’)
480 select_item(g.selected_item + 1);
481 else if(key == ’-’)
482 select_item(g.selected_item - 1);
483 else if(key == ’*’)
484 increase_detail_level(g.scene);
485 else if(key == ’/’)

Pierre-André Saulais, Clare Park 57


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

493 void onMouseClicked(int button, int state, int x, int y)


494 {
495 if(state == GLUT_DOWN)
496 {
497 if(button == GLUT_MIDDLE_BUTTON) // middle button pans the scene
498 {
499 g.trans_state.active = 1;
500 g.trans_state.x0 = x;
501 g.trans_state.y0 = y;
502 for(int i = 0; i < 3; i++)
503 g.trans_state.last[i] = g.delta[i];
504 }
505 else if(button == GLUT_LEFT_BUTTON) // left button rotates the scene
506 {
507 g.rot_state.active = 1;
508 g.rot_state.x0 = x;
509 g.rot_state.y0 = y;
510 for(int i = 0; i < 3; i++)
511 g.rot_state.last[i] = g.theta[i];
512 }
513 }
514 else if(state == GLUT_UP)
515 {
516 if(button == GLUT_MIDDLE_BUTTON)
517 g.trans_state.active = 0;
518 else if(button == GLUT_LEFT_BUTTON)
519 g.rot_state.active = 0;
520 else if(button == 3) // mouse wheel up zooms towards the scene
521 g.sigma *= 1.10;
522 else if(button == 4) // mouse wheel down zooms away from scene
523 g.sigma /= 1.10;
524 }
525

526 glutPostRedisplay();
527 }
528

529 void onMouseMoved(int x, int y)


530 {
531 if(g.trans_state.active)
532 {
533 int dx = g.trans_state.x0 - x;
534 int dy = g.trans_state.y0 - y;
535 g.delta[0] = g.trans_state.last[0] - (dx / 100.0);
536 g.delta[1] = g.trans_state.last[1] + (dy / 100.0);
537 glutPostRedisplay();
538 }
539

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 }

Pierre-André Saulais, Clare Park 58


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

D Appendix: code listings (Clare)

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

16 extern void c_top(int colorint);


17

18 extern void c_bottom(int colorint);


19

20 extern void c_all(int colorint, float flip_angle);


21

22 extern void x_top(int colorint);


23

24 extern void x_left_leg(int colorint);


25

26 extern void x_right_leg(int colorint);


27

28 extern void x_all(int colorint);


29

30 extern void p_out(int colorint);


31

32 extern void p_star(int colorint);

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

11 extern void draw_nest(int body_color);


12 extern void draw_nest_half(int body_color);
13 extern void draw_nest_qtr(int body_color);
14

15 extern void draw_cxp(float star_rot_angle, float cb_flip_angle, float x_ll_rot_angle, float


x_rl_rot_angle, float whole_model_angle, float cx_angle, float xp_angle);
16 extern void draw_xp(float star_rot_angle, float x_ll_rot_angle, float x_rl_rot_angle, float
xp_angle);
17 extern void draw_p(float star_rot_angle, float body_color, float star_color);

Pierre-André Saulais, Clare Park 59


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

16 //rotation angles for transformations


17 extern float star_rot_angle;
18 extern float cb_flip_angle;
19 extern float x_ll_rot_angle;
20 extern float x_rl_rot_angle;
21 extern float whole_model_angle;
22 extern float cx_angle;
23 extern float xp_angle;
24 extern float crab_translate;
25

26 extern int cb_flip_cw;


27 extern int one_model;
28 extern int crab_left;
29

30 extern void cp133_animate_scene();


31 extern void cp133_draw_scene();

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

12 static float colors[][3] = {


13 {0.0, 0.5, 0.5}, {1.0, 0.0, 0.3}, {1.0, 0.9, 1.0},
14 {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 1.0},
15 {1.0, 1.0, 1.0}, {0.0, 1.0, 1.0}
16 };
17

18 static float c_vertices[][3] = {


19

20 {0.73, 0.4, 0.1}, //1


21 {0.73, 0.5, 0.1}, //2
22 {0.53, 0.67, 0.1}, //3
23 {-0.67, 0.4, 0.1}, //4
24 {-0.73, 0.67, 0.1}, //5
25 {-0.93, 0.5, 0.1}, //6
26 {-0.93, -0.5, 0.1}, //7
27 {-0.67, -0.4, 0.1}, //8
28 {-0.6, -0.67, 0.1}, //9
29 {0.47, -0.67, 0.1}, //10
30 {0.57, -0.4, 0.1}, //11

Pierre-André Saulais, Clare Park 60


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

31 {0.97, -0.2, 0.1}, //12


32

33 {0.73, 0.4, -0.1}, //13


34 {0.73, 0.5, -0.1}, //14
35 {0.53, 0.67, -0.1}, //15
36 {-0.67, 0.4, -0.1}, //16
37 {-0.73, 0.67, -0.1}, //17
38 {-0.93, 0.5, -0.1}, //18
39 {-0.93, -0.5, -0.1}, //19
40 {-0.67, -0.4, -0.1}, //20
41 {-0.6, -0.67, -0.1}, //21
42 {0.47, -0.67, -0.1}, //22
43 {0.57, -0.4, -0.1}, //23
44 {0.97, -0.2, -0.1}, //24
45 };
46

47 static float x_vertices[][3] = {


48

49 {0.8, 0.67, 0.1}, //1


50 {0.9, 0.57, 0.1}, //2
51 {0.67, 0.67, 0.1}, //3
52 {0.17, 0, 0.1}, //4
53 {0, 0.17, 0.1}, //5
54 {-0.17, 0, 0.1}, //6
55 {-0.67, 0.67, 0.1}, //7
56 {-0.9, 0.57, 0.1}, //8
57 {-0.8, 0.67, 0.1}, //9
58 {0, -0.17, 0.1}, //10
59 {1.17, -0.53, 0.1}, //11
60 {0.9, -0.67, 0.1}, //12
61 {0.57, -0.37, 0.1}, //13
62 {0.43, -0.53, 0.1}, //14
63 {-0.43, -0.53, 0.1}, //15
64 {-0.57, -0.37, 0.1}, //16
65 {-0.9, -0.67, 0.1}, //17
66 {-1.17, -0.53, 0.1}, //18
67

68 {0.8, 0.67, -0.1}, //19


69 {0.9, 0.57, -0.1}, //20
70 {0.67, 0.67, -0.1}, //21
71 {0.17, 0, -0.1}, //22
72 {0, 0.17, -0.1}, //23
73 {-0.17, 0, -0.1}, //24
74 {-0.67, 0.67, -0.1}, //0.17
75 {-0.9, 0.57, -0.1}, //26
76 {-0.8, 0.67, -0.1}, //27
77 {0, -0.17, -0.1}, //28
78 {1.17, -0.53, -0.1}, //29
79 {0.9, -0.67, -0.1}, //30
80 {0.57, -0.37, -0.1}, //31
81 {0.43, -0.53, -0.1}, //32
82 {-0.43, -0.53, -0.1}, //33
83 {-0.57, -0.37, -0.1}, //34
84 {-0.9, -0.67, -0.1}, //35
85 {-1.17, -0.53, -0.1} //36
86 };
87

88 static float p_out_vertices[][3] = {


89 {0.9, 0.07, 0.1}, //1
90 {0.7, 0.53, 0.1}, //2
91 {0.47, 0.67, 0.1}, //3
92 {-0.43, 0, 0.1}, //4
93 {-0.67, 0.67, 0.1}, //5
94 {-0.9, -0.53, 0.1}, //6
95 {-0.57, -0.67, 0.1}, //7
96

Pierre-André Saulais, Clare Park 61


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

97 {0.9, 0.07, -0.1}, //8


98 {0.7, 0.53, -0.1}, //9
99 {0.47, 0.67, -0.1}, //10
100 {-0.43, 0, -0.1}, //11
101 {-0.67, 0.67, -0.1}, //12
102 {-0.9, -0.53, -0.1}, //13
103 {-0.57, -0.67, -0.1} //14
104

105 };
106

107 static float p_star_vertices[][3] = {


108

109 {0.33, 0.43, 0.1}, //1


110 {0.15, 0.43, 0.1}, //2
111 {0.07, 0.63, 0.1}, //3
112 {-0.02, 0.43, 0.1}, //4
113 {-0.2, 0.43, 0.1}, //5
114 {-0.07, 0.3, 0.1}, //6
115 {-0.13, 0.1, 0.1}, //7
116 {0.07, 0.23, 0.1}, //8
117 {0.27, 0.1, 0.1}, //9
118 {0.2, 0.3, 0.1}, //10
119

120 {0.33, 0.43, -0.1}, //11


121 {0.15, 0.43, -0.1}, //12
122 {0.07, 0.63, -0.1}, //13
123 {-0.02, 0.43, -0.1}, //14
124 {-0.2, 0.43, -0.1}, //0.1
125 {-0.07, 0.3, -0.1}, //16
126 {-0.13, 0.1, -0.1}, //17
127 {0.07, 0.23, -0.1}, //18
128 {0.27, 0.1, -0.1}, //19
129 {0.2, 0.3, -0.1} //20
130

131 };

D.1.5 3Dcurve.h

From the lecture notes

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

15 void tri_stick_tri(float a[], float b[], float c[], int colorint) {


16

17 glBegin(GL_POLYGON);
18 glColor3fv(colors[colorint%8]);
19 glVertex3fv(a);
20 glVertex3fv(b);

Pierre-André Saulais, Clare Park 62


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

79 void c_top(int colorint)


80 {
81 tri_stick(c_vertices[0], c_vertices[1], c_vertices[3], c_vertices[12], c_vertices[13],
c_vertices[15], colorint%8);
82 tri stick(c_vertices[1], c_vertices[2], c_vertices[3], c_vertices[13], c_vertices[14],
_
c_vertices[15], colorint%8);

Pierre-André Saulais, Clare Park 63


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

83 tri_stick(c_vertices[2], c_vertices[3], c_vertices[4], c_vertices[14], c_vertices[15],


c_vertices[16], colorint%8);
84

85 //tri_stick(c_vertices[3], c_vertices[4], c_vertices[5], c_vertices[15], c_vertices[16],


c_vertices[17], colorint%8);
86 glPushMatrix();
87 glTranslatef(-0.68, 0.405, 0);
88 //draw3Dcurve(0.20, 0, 0.27, 102, 161, 5, 1.0, 0.0, 0.3);
89 draw3Dcurve(0.20, 0, 0.27, 102, 161, 5, colors[colorint%8][0], colors[colorint%8][1],
colors[colorint%8][2]);
90 glPopMatrix();
91

92

93 tri_stick(c_vertices[3], c_vertices[5], c_vertices[6], c_vertices[15], c_vertices[17],


c_vertices[18], colorint%8);
94

95 }
96

97 void c_bottom(int colorint)


98 {
99 tri_stick(c_vertices[3], c_vertices[6], c_vertices[7], c_vertices[15], c_vertices[18],
c_vertices[19], colorint%8);
100

101 //tri_stick(c_vertices[6], c_vertices[7], c_vertices[8], c_vertices[18], c_vertices[19],


c_vertices[20], 2);
102 glPushMatrix();
103 glTranslatef(-0.67, -0.4, 0);
104 //draw3Dcurve(0.20, 0, 0.28, 200, 285, 5, 1.0, 0.0, 0.3);
105 draw3Dcurve(0.20, 0, 0.28, 200, 285, 5, colors[colorint%8][0], colors[colorint%8][1],
colors[colorint%8][2]);
106

107 glPopMatrix();
108

109 tri_stick(c_vertices[7], c_vertices[8], c_vertices[9], c_vertices[19], c_vertices[20],


c_vertices[21], colorint%8);
110 tri_stick(c_vertices[7], c_vertices[9], c_vertices[10], c_vertices[19], c_vertices[21],
c_vertices[22], colorint%8);
111 tri stick(c_vertices[9], c_vertices[10], c_vertices[11], c_vertices[21], c_vertices[22],
_
c_vertices[23], colorint%8);
112

113 }
114

115 void c_all(int colorint, float flip_angle)


116 {
117 //c_top(colorint);
118 //c_bottom(colorint);
119

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

130 void x_top(int colorint)


131 {
132

133 tri_stick(x_vertices[0], x_vertices[1], x_vertices[3], x_vertices[18], x_vertices[19],


x_vertices[21], colorint%8);
134 tri_stick(x_vertices[0], x_vertices[2], x_vertices[3], x_vertices[18], x_vertices[20],
x_vertices[21], colorint%8);
135 tri stick(x_vertices[2], x_vertices[3], x_vertices[4], x_vertices[20], x_vertices[21],
_
x_vertices[22], colorint%8);

Pierre-André Saulais, Clare Park 64


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

136 tri_stick(x_vertices[3], x_vertices[4], x_vertices[5], x_vertices[21], x_vertices[22],


x_vertices[23], colorint%8);
137 tri stick(x_vertices[3], x_vertices[5],
_ x_vertices[9], x_vertices[21], x_vertices[23],
x_vertices[27], colorint%8);
138 tri_stick(x_vertices[4], x_vertices[5], x_vertices[6], x_vertices[22], x_vertices[23],
x_vertices[24], colorint%8);
139 tri stick(x_vertices[6], x_vertices[5],
_ x_vertices[8], x_vertices[24], x_vertices[23],
x_vertices[26], colorint%8);
140 tri_stick(x_vertices[8], x_vertices[5], x_vertices[7], x_vertices[26], x_vertices[23],
x_vertices[25], colorint%8);
141

142 }
143

144

145 void x_left_leg(int colorint) {


146 tri_stick(x_vertices[5], x_vertices[9], x_vertices[14], x_vertices[23], x_vertices[27],
x_vertices[32], colorint%8);
147 tri stick(x_vertices[5], x_vertices[14], x_vertices[15], x_vertices[23], x_vertices[32],
_
x_vertices[33], colorint%8);
148 tri_stick(x_vertices[14], x_vertices[15], x_vertices[16], x_vertices[32], x_vertices[33],
x_vertices[34], colorint%8);
149 tri stick(x_vertices[15], x_vertices[16], x_vertices[17], x_vertices[33], x_vertices[34],
_
x_vertices[35], colorint%8);
150 }
151

152 void x_right_leg(int colorint) {


153 tri_stick(x_vertices[3], x_vertices[9], x_vertices[13], x_vertices[21], x_vertices[27],
x_vertices[31], colorint%8);
154 tri_stick(x_vertices[3], x_vertices[12], x_vertices[13], x_vertices[21], x_vertices[30],
x_vertices[31], colorint%8);
155 tri_stick(x_vertices[10], x_vertices[11], x_vertices[12], x_vertices[28], x_vertices[29],
x_vertices[30], colorint%8);
156 tri_stick(x_vertices[11], x_vertices[12], x_vertices[13], x_vertices[29], x_vertices[30],
x_vertices[31], colorint%8);
157 }
158

159 void x_all(int colorint) {


160 x_top(colorint);
161

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

175 void p_out(int colorint)


176 {
177 tri_stick(p_out_vertices[0], p_out_vertices[1], p_out_vertices[2], p_out_vertices[7],
p_out_vertices[8], p_out_vertices[9], colorint%8);
178 tri stick(p_out_vertices[0], p_out_vertices[2], p_out_vertices[3],
_ p_out_vertices[7],
p_out_vertices[9], p_out_vertices[10], colorint%8);
179 tri_stick(p_out_vertices[2], p_out_vertices[3], p_out_vertices[4], p_out_vertices[9],
p_out_vertices[10], p_out_vertices[11], colorint%8);
180 tri stick(p_out_vertices[3], p_out_vertices[4], p_out_vertices[5],
_ p_out_vertices[10],
p_out_vertices[11], p_out_vertices[12], colorint%8);
181 tri_stick(p_out_vertices[3], p_out_vertices[5], p_out_vertices[6], p_out_vertices[10],
p_out_vertices[12], p_out_vertices[13], colorint%8);
182

183 }

Pierre-André Saulais, Clare Park 65


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

184

185 void p_star(int colorint)


186 {
187 tri_stick(p_star_vertices[0], p_star_vertices[1], p_star_vertices[9], p_star_vertices[10],
p_star_vertices[11], p_star_vertices[19], colorint%8);
188 tri_stick(p_star_vertices[1], p_star_vertices[2], p_star_vertices[3], p_star_vertices[11],
p_star_vertices[12], p_star_vertices[13], colorint%8);
189 tri_stick(p_star_vertices[3], p_star_vertices[4], p_star_vertices[5], p_star_vertices[13],
p_star_vertices[14], p_star_vertices[15], colorint%8);
190 tri_stick(p_star_vertices[5], p_star_vertices[6], p_star_vertices[7], p_star_vertices[15],
p_star_vertices[16], p_star_vertices[17], colorint%8);
191 tri_stick(p_star_vertices[7], p_star_vertices[8], p_star_vertices[9], p_star_vertices[17],
p_star_vertices[18], p_star_vertices[19], colorint%8);
192 tri_stick(p_star_vertices[3], p_star_vertices[5], p_star_vertices[7], p_star_vertices[13],
p_star_vertices[15], p_star_vertices[17], colorint%8);
193 tri_stick(p_star_vertices[1], p_star_vertices[3], p_star_vertices[7], p_star_vertices[11],
p_star_vertices[13], p_star_vertices[17], colorint%8);
194 tri stick(p_star_vertices[1], p_star_vertices[7], p_star_vertices[9],
_ p_star_vertices[11],
p_star_vertices[17], p_star_vertices[19], colorint%8);
195

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

14 void draw_nest(int body_color)


15 {
16 draw_nest_half(body_color);
17

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

27 void draw_nest_half(int body_color)


28 {
29 draw_nest_qtr(body_color);
30

31 glPushMatrix();
32 glTranslatef(3.2, -2, 0);
33 glRotatef(95, 0, 0, 1);
34 draw_nest_qtr(body_color);
35 glPopMatrix();
36 }
37

38 void draw_nest_qtr(int body_color)


39 {
40

41 glPushMatrix();
42 glScalef(0.5, 0.5, 0.5);

Pierre-André Saulais, Clare Park 66


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

60 // stars on both sides of p


61 glPushMatrix();
62 glTranslatef(0, 0, 0.15);
63

64 glTranslatef(0.11, 0.35, 0); // centre of star will be at origin, for


rotations
65 glRotatef(0, 0, 0, 1.0);
66 glTranslatef(-0.11,-0.35, 0); // restore previous star origin
67

68 p_star(body_color);
69 glPopMatrix();
70

71 glPushMatrix();
72 glTranslatef(0, 0, -0.15);
73

74 glTranslatef(0.11, 0.35, 0); // centre of star will be at origin, for


rotations
75 glRotatef(0, 0, 0, 1.0);
76 glTranslatef(-0.11,-0.35, 0); // restore previous star origin
77

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);

Pierre-André Saulais, Clare Park 67


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

107 //c_all(body_color, -50);


108 //draw_p(0, body_color, 2);
109 glPopMatrix();
110 }
111

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

121 c_all(body_color, cb_flip_angle);


122

123 glPopMatrix();
124

125 draw_body_legs(body_color, star_color, star_rot_angle, x_ll_rot_angle, x_rl_rot_angle);


126

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

132 c_all(body_color, cb_flip_angle);


133

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

141 // left set


142 glPushMatrix();
143 glTranslatef(-0.5, -0.6, 0);
144 glRotatef(-15, 0, 0, 1.0);
145 glScalef(0.4, 0.4, 0.4);
146 x_top(body_color);
147

148 glScalef(1.3, 1.3, 1.3);


149

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

163 // right set


164 glPushMatrix();
165 glTranslatef(0.5, -0.6, 0);
166 glRotatef(15, 0, 0, 1.0);
167 glScalef(0.4, 0.4, 0.4);
168 x_top(body_color);
169

170 glScalef(1.3, 1.3, 1.3);

Pierre-André Saulais, Clare Park 68


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

187 void draw_body(int body_color, int star_color, int star_rot_angle)


188 {
189 glPushMatrix();
190 glRotatef(180, 1.0, 0, 0);
191 p_out(body_color);
192 glPopMatrix();
193

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

213 void draw_cxp(float star_rot_angle, float cb_flip_angle, float x_ll_rot_angle, float


x_rl_rot_angle, float whole_model_angle, float cx_angle, float xp_angle)
214 {
215

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);

Pierre-André Saulais, Clare Park 69


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

234 glTranslatef(0.9, -0.57, -0.1); // translate back


235

236 draw_xp(star_rot_angle, x_ll_rot_angle, x_rl_rot_angle, xp_angle);


237 glPopMatrix();
238

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

259 glTranslatef(-0.67, 0.67, 1); // translate top left corner to origin


260 glRotatef(30.0 + xp_angle, 0, 0, 1.0);
261 glTranslatef(0.67,-0.67, -1); // translate back to original position
262

263 draw_p(star_rot_angle, 3, 2);


264 glPopMatrix();
265

266 }
267

268 void draw_p(float star_rot_angle, float body_color_pr, float star_color_pr)


269 {
270 p_out(body_color_pr);
271

272 // stars on both sides of p


273 glPushMatrix();
274 glTranslatef(0, 0, 0.15);
275

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

Pierre-André Saulais, Clare Park 70


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

11 //rotation angles for transformations


12 float star_rot_angle = 0.0;
13 float cb_flip_angle = 0.0;
14 float x_ll_rot_angle = 0.0;
15 float x_rl_rot_angle = 0.0;
16 float whole_model_angle = 0.0;
17 float cx_angle = 0.0;
18 float xp_angle = 0.0;
19 float crab_translate = 0.0;
20

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

32 if (cb_flip_angle > CB_FLIP_LIMIT && cb_flip_cw == 1) {


33 cb_flip_angle -= 0.5;
34 if (cb_flip_angle == CB_FLIP_LIMIT) cb_flip_cw = 0;
35

36 } else {
37 cb_flip_angle += 0.5;
38 if (cb_flip_angle == 0) cb_flip_cw = 1;
39 }
40

41 if (crab_translate > -CRAB_MOVE_LIMIT && crab_left == 1) {


42 crab_translate -= 0.01;
43 if (crab_translate <= -CRAB_MOVE_LIMIT) crab_left = 0;
44

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

65 glTranslatef(-1.0 + crab_translate, 0, 0);


66 //draw_cxp(star_rot_angle, cb_flip_angle, x_ll_rot_angle, x_rl_rot_angle,
whole_model_angle, cx_angle, xp_angle);
67 draw_crab(1, 2, star_rot_angle, cb_flip_angle, x_ll_rot_angle, x_rl_rot_angle);

Pierre-André Saulais, Clare Park 71


F29GR1 Computer Graphics — Project group report Heriot-Watt University 2009–2010

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

From the lecture notes

Pierre-André Saulais, Clare Park 72

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy