You are on page 1of 64

University of Dublin

TRINITY COLLEGE

Design of a NPR Interactive


3D Landmark Map of Dublin City

Joseph Farrell
B.A. (Mod.) Computer Science
Final Year Project May 2007
Supervisor: Dr. John Dingliana

School of Computer Science and Statistics

O’Reilly Institute, Trinity College, Dublin 2, Ireland


Declaration

I hereby declare that this thesis is, except where otherwise stated, entirely my own work and
that it has not been submitted as an exercise for a degree at any other university.

__________________________ May 8, 2007


Joseph Farrell

2
Acknowledgements

I would like to thank my supervisor, John Dingliana, for providing me with the opportunity to
pursue this project and for his support and guidance throughout the year. I would also like to
thank my family and friends for their continued support and encouragement.

3
Abstract

Non photorealistic rendering (NPR for short) has come to denote computer generated images
and animations that are not a true to life representation of a scene. These renderings represent
the scene in different methods, to convey the key information relevant to the viewer in a
reduced format that is easier to understand. NPR for the most part gives images and models
the impression as though they were completed by hand.

The main goal of this project was to produce an interactive 3D Landmark map of Dublin City.
Various different NPR techniques were used to stylise the buildings and the map creating an
aesthetically pleasing look. These techniques reduced the complexity of the building models
whilst retaining their main characteristics.

The map which was produced has overall less complexity and despite this the landmark
buildings are more recognisable and the map as a whole is more comprehendible. This project
illustrates the value of NPR for the mapping of large geographic areas by applying it to the
key landmarks of Dublin. An example of a hand painted non-photorealistic style map of the
city of St. Petersburg illustrating this, can be seen in Figure 1.

Figure 1: A hand painted NPR style map of Saint Petersburg (Russia) produced by Escape
Travel Limited [EST 07]

4
Table of Contents

Declaration....................................................................................................................2
Acknowledgements ......................................................................................................3
Abstract.........................................................................................................................4

1. Introduction..............................................................................................................9
1.1 Objectives ..........................................................................................................10
1.2 Chapter Guide ....................................................................................................11

2. Background ............................................................................................................12
2.1 Non Photorealistic Rendering ............................................................................12
2.2 A history of NPR ...............................................................................................12
2.3 NPR Techniques ................................................................................................13
2.4 Motivations ........................................................................................................16
2.5 Possible Uses .....................................................................................................19

3. Design ......................................................................................................................20
3.1 Design Choice ....................................................................................................20
3.2 Tools ..................................................................................................................21
3.3 Workflow Plan ...................................................................................................22
3.4 OpenGL..............................................................................................................23
3.5 Models................................................................................................................24

4. Implementation ......................................................................................................27
4.1 Map ....................................................................................................................27
4.2 Buildings ............................................................................................................29
4.2.1 Texture Filtering .........................................................................................30
4.2.2 Silhouetting .................................................................................................32
4.2.3 Positioning ..................................................................................................33
4.3 Graphical User Interface ....................................................................................34

5
4.4 Additional Features ............................................................................................35
4.5 Optimisation.......................................................................................................38

5. Analysis ...................................................................................................................39
5.1 Results................................................................................................................39
5.2 Evaluation ..........................................................................................................40
5.3 Problems Encountered .......................................................................................41
5.4 Lessons Learned.................................................................................................42
5.5 Future Work .......................................................................................................42

6. Summary.................................................................................................................44
6.1 Review ...............................................................................................................44
6.2 Conclusion .........................................................................................................44

Appendix A. CD Contents.........................................................................................45
Appendix B. Application Screenshots ......................................................................46
Appendix C. Code Listing .........................................................................................48
Bibliography ...............................................................................................................62

6
Table of Figures

Figure 1: A hand painted NPR style map of Saint Petersburg (Russia)


produced by Escape Travel Limited [EST 07]..................................4
Figure 2: View of a Mosque rendered used a varied screening algorithm
[TSN02]..........................................................................................14
Figure 3: Dublin City Hall rendered with solid silhouette outlines...................15
Figure 4: A map of the city of Plzen (Czech Republic) using image distortion
[TSN 02].........................................................................................16
Figure 5: Scientific Diagram illustrating the structure of Alveoli via both cross-
section and an external view [WMD 07].........................................17
Figure 6: Collins Illustrated Map of Dublin using NPR techniques .................18
Figure 7: The Workflow Plan of this project ...................................................22
Figure 8: Textured box which is the rendered output from the file ‘Cube.obj’ 26
Figure 9: Left raster base map image distorted due to zooming, Right vector
map without any distortion .............................................................28
Figure 10 Screenshot demonstrating the blended blocks of outer city...........29
Figure 11: Example of a heavily texture mapped building model rendered
normally with its texture (left), cel-shaded (centre) and pencil
shaded (right).................................................................................29
Figure 12: A photo- realistic rendering of City Hall (Filesize: 1.6mb) .............30
Figure 13: A NPR rendering of City Hall with the texture filters (Filesize:0.9mb)
.......................................................................................................32
Figure 14: City hall with both texture filter and silhouettes code applied........33
Figure 15: A screen shot of the graphical user interface................................35
Figure 16: Central Bank (left) and the Trinity Campanile (right) rendered using
silhouette outlines and without textures .........................................36
Figure 17: The selection of buildings to be highlighted or found ....................36
Figure 18: A screenshot of finding and highlight a specific building ...............37
Figure 19: Application screenshot illustrating frame rate counter display ......38

7
Figure 20: Graph illustrating the performance of NPR against photo-realism in
terms of average frame-rate ..........................................................40
Figure 21: Application Screenshot 1 ..............................................................46
Figure 22: Application Screenshot 2 ..............................................................46
Figure 23: Application Screenshot 3 ..............................................................47
Figure 24: Application Screenshot 4 ..............................................................47

8
Chapter 1

1. Introduction

This project investigates Non Photorealistic Rendering (NPR for short) techniques and their
use in mapping. Based upon these techniques an application was developed to present a map
of Dublin City. It creates images and animations which are not true to real life but still
representative of a specific scene. NPR is a broad area with many different rendering
techniques but the main objective is to convey information. In the area of maps the intent of
NPR is to omit unnecessary detail, focus attention on important characteristics, simply and
clarify the image, remove any unambiguous details and show hidden parts.

Traditionally computer graphics have been concerned with photorealism and creating
graphics and animations which look as true to life as possible. These have great applications
in film and games but when applied to mapping, these techniques create maps with excessive
detail. This in turn makes them hard to comprehend and less user-friendly. Photorealism is
also heavy on resource for example the latest ‘Shrek the Third’ movie took up to 300 hours to
render every single frame of the movie with a 3,000 processor server farm [SST 07].

A particular example of the value of NPR in the rendering of architectural buildings can be
seen in the following reference [NPA 07]. If a photo-realistic image of a proposed building is
shown as a blueprint to clients the final building may be significantly different as changes can
come from different building materials, on site building conditions, planning requirements.
These changes can cause the actual building when completed to look very different from the
initial image of the building and this can come as quite a shock and lead to angry clients. If
NPR is used to generate an image of the building the clients will accept that the design phase
of the building is not complete and accept on-site changes to the building as required.

Compared to conventional maps which are simply based on street names and text, NPR
landmark maps provide many benefits. The user of the map can recognise landmarks and key
buildings immediately and requests can be made to highlight a particular building or service.
The building can then be rendered in a different technique to make it instantly recognisable.

9
The user does not need the ability to ‘read maps’ which some people have difficulty in doing.
Conventional tourist maps are the best example of this type of approach. Examples of which
are shown in Figures 1 and 6 of this report. It can be seen in these Figures how the landmarks
are non-realistic renditions, but they still are easily noticeable. These types of maps have
naturally used NPR techniques.

NPR when applied to maps illustrates the main details while reducing its complexity, helping
to create a more comprehendible and easier to understand map. Direct images of the area such
as satellite images are too complex and provide too much detail for use. The key element is
that the NPR maps are easier to comprehend, but despite their being less detail the main
landmarks are still recognisable as they still retain their main features.

1.1 Objectives

The aim of this project is to construct a functional interactive landmark map of Dublin city (5
mile radius about O’Connell Bridge) illustrating the main landmark buildings.
The key parts to building this map include the following:
• Building a base vector map of Dublin City streets
• Adding of street labels to this map
• Adding semi-transparent city blocks to outer city
• Investigating various different NPR techniques
• Stylising the building models using NPR techniques
• Building a fully functional user interface
• Adding features to find and highlight specific buildings
• Creating a fully functional application incorporating all of the above.
• Optimise this application for best performance

A further objective of the project was to complete the above functionality while keeping the
frame rate high and keeping a high quality of experience of the map. This involves ensuring
that the image quality for all levels of zoom or angle of view is consistent and that the frame
rate is high so that the map is responsive to user commands such as pan and rotation
manoeuvres around the map.

10
1.2 Chapter Guide

Chapter 2: Background
This Chapter is a review of the background material. This includes a review of non-
photorealistic rendering techniques and discusses their applications for the modelling of large
geographic scenes such as seen in this project.

Chapter 3: Design
This Chapter describes the selection of the rendering techniques and all the various other
design decisions and selections made throughout the course of the project.

Chapter 4: Implementation
This Chapter describes in detail the applying of NPR techniques to the buildings models, the
creation of the vector map, design of the user interface and all other aspects of the
implementation phase of the project.

Chapter 5: Analysis
This chapter is an analysis of the project in terms of overall performance and effectiveness.
The application is analysed based on frame rate performance and future developments for the
application are also considered

Chapter 6: Summary
This chapter provides a summary of the project in which the key areas of the project are
reviewed and any specific conclusions are drawn.

11
Chapter 2

2. Background

2.1 Non Photorealistic Rendering

Research in computer graphics over the last number of decades has primarily been concerned
with the creation of ever increasingly realistic graphics and animation. Non-photorealistic
graphics has come to denote picture and animation in a way in which deviates from the
physical reality of a scene. In effect non photorealistic graphics are not a true to life
representation of a scene. NPR has been described in the past as comprehensible rendering,
artistic rendering and non-realistic rendering, however of late it has come to be known
predominantly under the term non-photorealistic rendering.

2.2 A history of NPR

NPR styles and techniques were probably first investigated in the mid 1980s in papers by
Strassmann 1986 [SHB 86] and Sasada in 1987 [ANS 87]. These papers discussed various
different brush stroke styles and computer generated natural sceneries. However it was not
until more recently in 1994 when this field was brought to the fore by two papers on
generality and underlying principles. These papers by Winkenbach et al [WNB 94] and by
Salisbury et al [SAL 94] were presented at SIGGRAPH (Special Interest Group on Graphics
and Interactive Techniques) 1994 and illustrated the generality of the various different NPR
techniques; bringing together previously separate research into this new field of NPR. Since
1994 research in this are has flourished and there currently exists approximately 7,000
scholarly papers on the topic [GSN 07].

12
2.3 NPR Techniques

There exists a wealth of NPR techniques that can be used to create and emulate NPR styles in
computer graphics. The majority of which simulate natural artistic techniques. However, the
results of these different techniques vary significantly from each other but all produce
graphics and animations that are un-realistic. Some techniques are focused heavy on
mimicking traditional human art like watercolour and hand sketches while others are focused
on communicating their content information more effectively as seen in scientific and biology
diagrams. Other styles place more emphasis on the creation of an aesthetically pleased look,
like cartoon shading.

There are numerous NPR techniques but the report will focus on those most relevant to the
goal of this project. Pixel manipulation also commonly referred to as image processing or
image filtering will be used in this project to manipulate the texture of the building models.
This process involves the manipulation of the pixel elements of a 2D image. It can be often
applied after a model or animation is rendered. In this particular incident it will be applied to
the texture of the model before rendering. Common NPR methods such as shading will not be
used as they would be ineffective for the heavily textured mapped models being used in this
application. Texture filters can produce numerous effects such as greyscale, blurring,
stippling, screening and colour, brightness or contrast manipulations. All of these techniques
are applied using different algorithms. An interesting example of screening algorithm can be
screen in Figure 2.

13
Figure 2: View of a Mosque rendered used a varied screening algorithm [TSN 02]

To complement the image filtering silhouette outlines are added to the buildings models to
add emphasis and add to their NPR style. Outlines are commonly used in NPR to mimic hand
drawn sketch styles. Hand drawn styles tend to have so called ‘incorrect outlines’ which vary
in straightness, length, thickness and brightness. NPR rendering algorithms which add
outlines to models vary the values of the incorrectness based on the required output style.
Other algorithms render the outline based upon brush stoke to achieve painted styles. Outline
rendering is generally combined with cel-shading to achieve most NPR styles. For this project
a combination of heavy solid outlines and image filter is textured to achieve a style which
reduces complexity but increases recognition. An example of City Hall rendered with solid
black outlines and no textures can be seen in Figure 3.

14
Figure 3: Dublin City Hall rendered with solid silhouette outlines

Image distortion is another technique used to achieve NPR look. Traditional representations
by hand tend for the most part not to be to the exact scale. These various scales in traditional
hand drawn images tended to result in the more important aspects being drawn larger. This
has developed into a way in which to communicate a scene more effectively. Scaling has a
particular relevance to landmark maps, as the larger a building is drawn the more importance
it has to the viewer. An advanced image distortion can be seen in Figure 4. Different scaling
is applied in the project to add importance to landmarks and to help communicate the map’s
information more comprehensively.

15
Figure 4: A map of the city of Plzen (Czech Republic) using image distortion [TSN 02]

2.4 Motivations

NPR came initially from a motivation to follow and emulate human artistic process which at
its roots has an incentive to convey content information more effectively. As a result of this,
the most part of NPR styles generate effects that appear as though they were completed by
hand. Examples of such renderings would include watercolour and sketch rendering which
closely mimic an artists hand painted style.

There are other non-photorealistic techniques which attempt to emphasise particular elements
of a scene, with an overall goal to increase the viewer’s knowledge and understanding of the
particular scene. These techniques are used regularly by technical, scientific and medical
illustrators. An example such a technique can be seen in Figure 5, which is a NPR rendering
of a biological organ. It is easy to see that this representation conveys more information than a
realistic interpretation would.

16
Figure 5: Scientific Diagram illustrating the structure of Alveoli via both cross-section and an
external view [WMD 07]

It has now been shown that the different NPR effects can be achieved by various rendering
techniques. Now the reasons for the use of NPR in this project can be discussed. NPR has
number of advantages which are further relevant to map representations. The sole purpose of
maps is to convey information and as NPR aids this communication it is straightforward to
see NPR’s value.

Over the centuries NPR has been used and developed upon in maps. It seems as though this
has happened purely on intuition as maps try to covey so much information in such a small
space. The details and complexity in maps has been reduced to make maps more
comprehendible and make landmarks more recognisable. It is only natural to take these
techniques and replicate them in computer generated rendering and continue to develop upon
them further. In Figure 6 we can see a Landmark map of Dublin in which NPR is used.

17
Figure 6: Collins Illustrated Map of Dublin using NPR techniques

The NPR styles not only reduce the detail and complexity of the map but in addition reduce
the amount of processing power and memory required. This is a positive situation as the
buildings are more recognisable and the map is more user-friendly whilst the performance of
the application is also increased.

18
2.5 Possible Uses

The resultant program from this project and the techniques used to achieve this have several
possible uses. The application itself with further development would be a useful tool for path
finding and to help guide tourists around Dublin City. The techniques used to achieve the
NPR stylised building models would be useful for other mapping applications such Google
Maps [GMW 07]. It should also be noted that Google Earth uses some simple NPR
techniques and some interesting features but the rendering is very basic.

The reduced processing requirements if coupled with more advanced culling would make this
application valuable for mobile devices and PDA. The application could even be ported to
OpenGL ES [OES 07] which is a tailored version of OpenGL for mobile devices.
Furthermore the building models could be valuable if used on GPS navigation systems. In all
in this project and its research have many benefits for future development.

19
Chapter 3

3. Design

Throughout the project a number of design choices needed to be made. When this occurred all
available choices were examined and evaluated and the best solution was chosen. An example
of this is the selection of which file format to use for storage of the building models. In this
case different file formats were examined and various different loaders for each of the formats
were investigated. 3ds the standard 3DS Max file format was examined, but this produced
larger model sizes and varied greatly from version to version. OBJ Alias Wavefront format
[OBJ 07] was the selected format, as it was the simplest to implement, stable (doesn’t change
structure from version to version like 3DS) and the available loaders were easily available
within Trinity College.

3.1 Design Choice

For the creation of the map, it was decided that the same file format as the buildings models
was used. This had the advantage that the means for loading this file format was already
present and a vector image could be converted to this format. The decision to use Adobe
Illustrator to create the map was made as the AI file could be easy exported to a format for
loading into OpenGL. It was easier to work in a 2D environment in AI as opposed to a 3D
environment in 3DS Max because the basic structure of a map is two dimensional.

An approach was attempted to apply the texture filters to the building models in real time,
although this proved expensive on resources. The load time for this application was 3 times
that of the previous application where the textures were pre-applied and as a result this was
considered a waste of processing power. Due to this the option to use the texture filters pre-
rendering was selected as opposed to applying them in real-time.

20
3.2 Tools

The application was programmed in C++ using OpenGL. OpenGL is the most widely used
and supported graphics API [OGL 07]. OpenGL was required for the creation of the 2D and
3D graphics components of application. OpenGL is supported on every major operating
system and is compliant with most programming languages. This provides the advantage that
the final application is platform independent. C++ was chosen to code the project as it is the
most commonly used language in conjunction with OpenGL. This language provides all the
necessary function to access the library and doesn’t limit its performance.

The application was compiled and programmed using Microsoft Visual Studio .net 2003
[MVS 03]. All coding of the application was my own work except were some minor elements
were built upon and used previous work. The OBJ model loader [OBJM 07] class was used
with permission from John Hamill (ISG group TCD). Some common graphics algorithms
have been used and adapted for this application and they are referenced when discussed in the
implementation chapter.

Adobe Illustrator was also used for the creation of the vector map. Various different
commercial applications for converting from a raster to a vector map were also tried however
theses all failed to produce a quality vector map.

The building models were mostly taken from the Virtual Dublin Project by the ISG group in
trinity. Some alterations were made to these models using 3DS Max [3DS 07] which is a
popular software package for the creation and editing of 3D models. Deep Exploration a
program for export to and from various 3D file formats was used to the building and map
models into the Alias Wavefront OBJ file format.

Adobe Photoshop was used to apply a number of filters to the building’s textures after a proof
of concept using coded algorithms. The fact that the textures were in varying file formats
made it impractical due to time constraints to code these conversions by hand.

GLUI which is an extension built upon OpenGL was used to produce a graphical user
interface. The program was tested on a laptop with a 1.6 GHz Pentium M processor and 2GB
of RAM and all frame times mentioned in this report relate to tests on this machine.

21
3.3 Workflow Plan

Figure 7: The Workflow Plan of this project

The main work of this project was broken into a number of stages as illustrated in Figure 3
above.
1. Firstly various different NPR techniques were investigated and then these were
applied to the building models.
2. A vector base map was created using a number of tools.
3. Both the vector map and the NPR styled buildings were then brought together into
one functional application.
4. A user interface was designed and built on top of this.
5. A number of functional features were then added.
6. The application was then debugged and analyzed for optimal performance.

The project was initially broken into these stages to help organise and plan the project.
Evidently the creation of the NPR buildings was the largest and most time consuming of all
the stages. However this was closely followed by the stages involving the creation of the map
and the design of the user interface. The optimisation and the additional features stages were
the smallest, but helped to polish off the finished application.

22
3.4 OpenGL

OpenGL is an event driven multi-platform graphics API [OGL07]. OpenGL is supported on


every major operating system and is compliant with most programming languages. It is a
software interface to a graphics system implemented in hardware or software. This interface
consists of in excess of 120 distinct commands, which can be used to specify the objects and
operations needed to produce interactive three-dimensional graphics applications.

The interface consists of the following three libraries [OGG 07].


• The GL library is the core OpenGL system and is primarily concerned with
modelling, viewing, lighting, clipping aspects.
• The GLU library (GL Utility) simplifies common tasks and is used for the creation of
common objects (spheres, quadrics) and the specification of standard views (e.g.
perspective, orthographic).
• The GLUT library (GL Utility Toolkit) provides an interface with the windowing
system to allow window management, menus and other mouse interaction.

OpenGL is interactive and works in an event driven fashion continuously waiting for and
handling interactions from the user. Interactions are handled by what is known as the glut
event loop. An application must register handlers (or call-back functions) which are called
upon, the occurrence of a particular event. Such events include a mouse button press, mouse
motion, timer, window resize or redraw.

To add handlers for events we register a call-back function as follows:

// Function to deal with key press


glutKeyboardFunc( GlutKeyboard );

The function GlutKeyboard is a called when a key press event occurs and this function must
handle the following parameters:

// Key press function handler


void GlutKeyboard(unsigned char Key, int x, int y)

23
For the glutKeyboardFunc the value of the key variable is the ASCII code of the key hit and
the value of x and y are the coordinates of the mouse position within the window at the
moment when the key was hit.

3.5 Models

The building models used in the application were for the most part taken from Virtual Dublin
which is a real-time urban simulation of Dublin city developed by the Interaction, Simulation
and Graphics Lab (ISG) with in Trinity [VDUB07]. Some building models from the Google
SketchUp 3D Warehouse were tested, but proved to be of too low quality for inclusion in the
final application.

These models are in Alias Wavefront OBJ file format [OBJ 07] which is a commonly used
format for the storing of polygonal 3D models. The file format is text based consisting of
lines of data. Each line of data started with a keyword such as v for vertex or vn for the vertex
normals which defined the data which followed. The following is an example of a simple OBJ
file which defines a cube and maps a texture to its faces.

#
# Wavefront OBJ file
# Cube.obj
#
mtllib ./Cube.mtl
g

# object Box01

v -8.091908 0.000000 8.556394


v 11.908092 0.000000 8.556394
v -8.091908 0.000000 -11.443606
v 11.908092 0.000000 -11.443606
v -8.091908 20.000000 8.556394
v 11.908092 20.000000 8.556394
v -8.091908 20.000000 -11.443606
v 11.908092 20.000000 -11.443606
# 8 vertices

vt 0.000000 0.000000 0.000000


vt 20.000000 0.000000 0.000000
vt 0.000000 20.000000 0.000000
vt 20.000000 20.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 20.000000 0.000000 0.000000
vt 0.000000 20.000000 0.000000
vt 20.000000 20.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 20.000000 0.000000 0.000000
vt 0.000000 20.000000 0.000000
vt 20.000000 20.000000 0.000000
# 12 texture vertices

24
vn 0.000000 -1.570796 0.000000
vn 0.000000 -1.570796 0.000000
vn 0.000000 -1.570796 0.000000
vn 0.000000 -1.570796 0.000000
vn 0.000000 1.570796 0.000000
vn 0.000000 1.570796 0.000000
vn 0.000000 1.570796 0.000000
vn 0.000000 1.570796 0.000000
# 8 vertex normals

g Box01
usemtl Map_Material

s 2
f 4/11/4 2/9/2 1/10/1 3/12/3
s 4
f 8/12/8 7/11/7 5/9/5 6/10/6
s 8
f 6/8/6 5/7/5 1/5/1 2/6/2
s 16
f 8/4/8 6/3/6 2/1/2 4/2/4
s 32
f 7/8/7 8/7/8 4/5/4 3/6/3
s 64
f 5/4/5 7/3/7 3/1/3 1/2/1
# 6 faces

The structure of the OBJ file format can be seen above listed file Cube.obj. It can be seen that
any line preceded by ‘#’ is a comment. Similarly the file lists the cubes vertices (v), texture
vertices (vt) and vertex normal (vn). The shapes box01 sides (s) and faces (f) are then
declared using the Map_Material as declared in the material library (mtllib) called ‘Cube.mtl’
which can be seen below.

#
# Wavefront material file
# Cube.mtl
#
newmtl Map_Material
Ka 0.5882 0.5882 0.5882
Kd 0.5882 0.5882 0.5882
Ks 0.9 0.9 0.9
illum 2
Ns 4
map_Kd map_quad.bmp

25
The above two files when rendered in OpenGL resulted in the textured cube in Figure 8. It is
relatively easy to see how this file format could be used to define the more complex building
models as seen later in the report.

Figure 8: Textured box which is the rendered output from the file ‘Cube.obj’

26
Chapter 4

4. Implementation
This chapter examines in detail the execution and the workings of the design as it was
outlined previously in the previous chapter. The completion of the map, the buildings and the
user interface are discussed. Also the adding of some further features and the optimisation of
the code is examined in detail.

4.1 Map

Initially it was attempted to use a matrix of raster images to represent the base map. It
immediately became apparent that this approach would not be successful as the raster images
lost their quality when zooming in or out. Another approach was tested where the raster
images were swapped with high resolution images when zooming in. This proved difficult to
smoothly implement and was wasteful of resources as the high resolution image dramatically
increased in size.

To avoid the quality loss of the raster images a vector map was required. To produce this
vector map various applications for conversion from a raster to a vector file format were tried,
nevertheless every one produced substandard maps. The only effective approach to achieve a
quality vector map was to manually trace the map.

This was completed in Adobe Illustrator as the AI file (Adobe Illustrators standard file
format) could be easily exported to an OBJ file through 3DS Max. Adobe Illustrator was used
as opposed to 3DS Max for this as it was easier to work in 2D rather than a 3D environment.
Moreover, it was relatively straightforward to export to the OBJ file format which could then
be used in OpenGL. The finished product can be seen in Figure 9 which compares the
resultant vector map to the initial raster map image when zoomed in close. This show the
dramatic improvement in the quality of the image that the selected approach enabled. From a
user point of view this enables zooming to be used to any magnification with the deterioration
of image quality.

27
Figure 9: Left raster base map image distorted due to zooming, Right vector map without any
distortion

Street labels were added to the map using Glut stroke characters. The text for the label and
details of the translations and rotations were stored in a text based file. These details were
then loaded into local memory of the program and the labels were then positioned based on
these. The positioning variables in this text file can be updated and additional labels added
through the positioning application which is discussed further in the positioning section.

After placing the main landmarks on the map some of the other regions appeared to lack
details due to being two dimensional. As a result certain elements of the maps OBJ file were
edited in 3DS Max to create raised blocks to represent irrelevant buildings on the outer edges
of the map. Blending code was a then applied to the map in the application to make these
blocks appear semi-transparent, so as not to take from the maps important landmarks. In
Figure 10 the result of this can be seen more clearly.

28
Figure 10 Screenshot demonstrating the blended blocks of outer city

4.2 Buildings

It was apparent from early research that the classic NPR rendering styles would not achieve
an effective style. As you can seen in figure 11 where some classic NPR shader’s have been
applied to a building model from the Virtual Dublin project [VDUB 05]. These results proved
unsatisfactory as the models are heavily reliant on the detail contained in the textures and this
detail was lost with these NPR techniques. It was made clear from this that this project would
have to focus on a different approach. A decision was made to use a combination of texture
filtering and outlining, this kept the necessary detail from the textures whilst still achieving an
effective NPR style. The following sections delve more deeply into how exactly this was
accomplished.

Figure 11: Example of a heavily texture mapped building model rendered normally with its
texture (left), cel-shaded (centre) and pencil shaded (right)

29
Prior to proceeding with the texture filtering some additional alterations were also made to the
models. The first of these was polygon reduction. This involved the manipulation of the
models using 3DS Max. As these models were intended to be photorealistic some contained
excessive detail. Reducing the polygon count of the models reduced this detail sufficiently.
This alteration both aided the NPR style and the reduction of the size of the model. Also
texture sizes were reduced by 50% using the batch conversion tool of Adobe Photoshop. This
was also needed as these models were initially intended to be photorealistic and the high
resolution of these textures was not necessary for this application.

4.2.1 Texture Filtering

Various different algorithms were applied to the textures of the models to achieve an effective
NPR style. These algorithms were adapted from previous work [IMP 07] and were used for
increasing contrast, increasing brightness and greyscale conversion. An example of the photo-
realistic buildings from which work began can be seen in Figure 12 below.

Figure 12: A photo- realistic rendering of City Hall (File-size: 1.6mb)

Firstly the textures were converted to greyscale and this was achieved by use of the following
algorithm. This code scans through all the picture elements (pixels). Each pixel has a red,
green and blue value and to convert the image to greyscale each pixel value is updated with
an average of the three.

30
// Manipulate the image data converting to greyscale
for(int pixel=0; pixel < numPixels*bytesInPixel;
pixel+=bytesInPixel){
imageData[pixel]=(imageData[pixel]+imageData[pixel+1]
+imageData[pixel+2])/3;
imageData[pixel+1]=(imageData[pixel]+imageData[pixel+1]
+imageData[pixel+2])/3;
imageData[pixel+2]=imageData[pixel]+imageData[pixel+1]
+imageData[pixel+2])/3;
}

Secondly this algorithm manipulates all the pixels increasing the value of all elements by a set
value. Testing of different values for this variable shown £% giving the optimal output. This
resulted in an increase in brightness of the image from its previous state.

// setup variables for brightness manipulation


int light = 35;
int Light_transform[256];

for(i=0;i<256;i++){
Light_transform[i]=i+light;
if(Light_transform[i]>255)
Light_transform[i]=255;
if(Light_transform[i]<0)
Light_transform[i]=0;
}

// Manipulate the image data increasing brightness


for(int pixel=0; pixel < numPixels*bytesInPixel; pixel+=bytesInPixel){
imageData[pixel] = Light_transform[imageData[pixel]];
imageData[pixel+1] = Light_transform[imageData[pixel+1]];
imageData[pixel+2] = Light_transform[imageData[pixel+2]];
}

This third algorithm below manipulates the contrast of the texture. The code first sets up a
contrast transformation array based on a contrast variable. The code then scans through all the
pixels updating each element based upon this transform array.

// set up variables for contrast manipulation


float contrast = 0.8;
int Contrast_transform[256];

for(int i=0;i<256;i++){
if(i<(int)(128.0f+128.0f*tan(contrast))&&
i>(int)(128.0f-128.0f*tan(contrast)))
Contrast_transform[i]=(i-128)/tan(contrast)+128;
else if(i>=(int)(128.0f+128.0f*tan(contrast)))
Contrast_transform[i]=255;
else
Contrast_transform[i]=0;
}

// Manipulate the image data increasing contrast


for(int pixel=0; pixel < numPixels*bytesInPixel; pixel+=bytesInPixel){
imageData[pixel] = Contrast_transform[imageData[pixel]];

31
imageData[pixel+1] = Contrast_transform[imageData[pixel+1]];
imageData[pixel+2] = Contrast_transform[imageData[pixel+2]];
}

These texture filters were applied to models with TGA file formats; however as the texture
file formats varied so much for all the building models Adobe Photoshop was used to apply
texture filters to the other file formats. This was decided upon as it would have been
impractical and wasteful of time to code for all the different image file formats. As a result of
these texture filters the building models were produced as seen in Figure 13:

Figure 13: A NPR rendering of City Hall with the texture filters (File-size: 0.9mb)

4.2.2 Silhouetting

To complement the texture filtering style achieved in the previous section it is beneficial to
apply solid outlines ideally like those in the classic cell animation as in Chapter 2. The
extraction of outline from 3D models is generally an expensive procedure in terms of
processing requirements. However the same effect can be achieved in an indirect fashion
using some of the features of OpenGL. The code to achieve this technique follows:

// Set up required setting


glPushAttrib( GL_ENABLE_BIT );
glEnable (GL_LINE_SMOOTH);
glEnable (GL_POLYGON_SMOOTH);

glEnable(GL_CULL_FACE); // Enable Culling


glCullFace (GL_FRONT); //Cull front polygon faces

glPushAttrib( GL_POLYGON_BIT | GL_CURRENT_BIT );


//Draw Outline

32
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2); // Set the line width to 2
glColor3f(0, 0, 0); // Set Colour to black

**Draw Buildings**

glPopAttrib();

glDisable(GL_CULL_FACE); // Disable Culling


glColor3f(1, 1, 1);

**Draw Buildings**

glPopAttrib();

The above code actually draws the building twice. Firstly the building model is drawn with
the front facing polygons culled which draws all the outline edges of the model. The second
time the building is drawn using our filtered textures. Through the combination of this
silhouetting code and the texture filters which were already applied we achieve a NPR style as
seen in the below Figure 14.

Figure 14: City hall with both texture filter and silhouettes code applied.

4.2.3 Positioning

After all the NPR styles had been applied to the building the next step was positioning these
on the map. The buildings are positioned on the map using basic GL translations. Each
building has its own specific translation values to identify its position on the map. In order to
position the buildings correctly on the map a side application was coded, in which the position
of these elements could be manipulated and saved via key strokes. When the buildings are
positioned correctly the translation variable can then be updated in a text file containing all
the building translations.

33
The development of this side application proved vital and necessary in achieving a complete
application, as trying to manually work out these translation variables would have been
immensely time consuming and extremely difficult. This side application was also used for
the manipulation and updating of the translation variables for the street labels.

4.3 Graphical User Interface

The graphical user interface (GUI) was built using GLUI, a user interface library built on top
of the OpenGL API. Initially there were a number of compatibility issues while trying to get
the GLUI library working with the latest release of OpenGL. GLUI was initially written by
Paul Rademacher [GLUI 2.1] in 1999 and it is presently being updated and maintained by
Nigel Stewart and Bill Baxter [GLUI 07]. However, the latest releases of version 2.35 and
version 2.2 were fraught with compatibility issues and bugs. This resulted in having to drop
back to the earlier version of 2.1, which still needed some fine-tuning to run without errors.

The application has the capability to zoom (in, out), pan (up, down, left, right) rotate and tilt
the map. All of these interactions have been integrated into the user interface and can also be
made through both the keyboard and the mouse. Interactions are intuitive through these three
input devices and allow for maximum usability of the application

In Figure 15 a screenshot of the GUI can be seen which illustrates the simple and intuitive
controls. The following GUI appears on the right hand-side of the application with the map to
the left. To use any of the controls, the user simply clicks on the control icon and drags in the
appropriate direction. For example when the user clicks on the pan icon and drags either up
down left or right, this interaction is then reflected in the view-port of the map on the left
hand-side.

34
Figure 15: A screen shot of the graphical user interface

4.4 Additional Features

A number of additional features were added to the application to increase usability and
include additional functions. These include the options to turn on and off the display of
various elements (such as the map street names and buildings) of the application. Also there is
an option to draw the building models without textures producing a rendering of the buildings
as can be seen in the figure 16:

35
Figure 16: Central Bank (left) and the Trinity Campanile (right) rendered using silhouette
outlines and without textures

Furthermore, a feature providing the functionality to find and highlight specific buildings was
added. I firstly chose the top 20 most recognised landmarks and these can now be selected
from two drop down boxes in the User Interface as illustrated in the figure 17.

Figure 17: The selection of buildings to be highlighted or found

36
When a buildings is selected from the find drop down box the main view port jumps to a
position where the selected buildings is in focus in the centre of the screen. Similarly selecting
a building from the highlight drop down box causes the outline of the selected building to turn
red. This helps make the selected building stand out even further from the surrounding
buildings. This is shown in the screenshot of the application in Figure 18.

Figure 18: A screenshot of finding and highlight a specific building

Scaling was also applied to the buildings models in the final build of the application. This can
be manipulated in the User Interface and the scaling variable is applied to all buildings on the
map. Different scaling factors could be applied to each building producing another NPR effect
similar to that seen in Figure 4. This could be used to make a selected landmark more
noticeable by scaling it larger than the surroundings. The full implementation of this feature
was not completed due to the time constraints of this project, however the concept of how this
would work was proven.

37
Another important feature which was added was a frame-rate counter which continuously
moderated the applications frame. This was adapted from previous work [OFC 07] to print the
frames per second in the top left had corner of the program as seen in Figure19 below. This
was a vital component for the optimisation and analysis of this application.

Figure 19: Application screenshot illustrating frame rate counter display

4.5 Optimisation

After getting the application to a stable running state the code was optimised in order to keep
the frame rate counter to a minimum. In effect this meant trying to keep the application as
responsive as possible, despite the large number of buildings that were being displayed. There
were some changes made to the way in which the buildings models were stored in memory.

Initially each building was stored as an object with an array. This however generated
problems as the array would overload due to the size of the models. The building models were
as a result stored as an array of pointers. However this also generated errors as some of the
methods of the OBJ loader class lost access to some of its variables. In the end the building
models were stored in a series of small arrays avoiding the memory overload issue.

Some changes were made to the application (e.g. setting of limits on the interaction
variables). Other minor errors were debugged and resolved at this stage. The resulting
application was capable of loading approximately 60 buildings while still maintaining an
interactive frame rate of above 10 frames per second.

38
Chapter 5

5. Analysis
In this section the original goals as at the outset of the project are compared to the completed
application. Also this chapter evaluates how the final application weighs up and discusses any
problems encountered on the journey to achieving this. Further future developments for the
application are also considered.

5.1 Results

The initial project outline laid down numerous tasks to be completed throughout the project.
Firstly, a detailed research was undertaken into the areas of computer graphics, NPR, NPR
techniques, OpenGL, and GLUI. This early background was essential to proceeding with the
project and furthermore for the project to be aware of the current state of the art in these
fields. This was completed and a great deal was learned about the current research in this area
which helped to guide the project to it final state.

The project workflow plan set out the three main goals as follows:
1. The creation of the map
2. Stylising of the building models
3. Design of Graphical User interface

All of the goals have been reached and have been discussed in detail in the preceding
Implementation chapter. All this leads to the conclusion that this project was an overall
success. This can be further seen in the attached fully functional application which illustrates
the hard work and effort which leaves a platform for future further development.

39
5.2 Evaluation

The frame rate counter code of which implementation as previously been discussed was
continuously monitored throughout the applications development. This was used as a gauge to
insure the program remained responsive (i.e. frame rate above 10 frame/second). The
application was run using both the realistic rendering of the buildings and the NPR.
Comparing the frame rate data of both these produced the following interesting graph:

120
Average Framerate

100
80
NPR
60
Realistic
40
20
0
0 20 40 60
Number of Buildings

Figure 20: Graph illustrating the performance of NPR against photo-realism in terms of
average frame-rate

This graph clearly illustrates the advantages of NPR on processing and memory requirements.
The reduced complexity and detail of the NPR model resulted in less memory and processing
requirements and effectively higher frame rates than realistic renderings. The above illustrated
positives, coupled with more recognisable buildings and a more comprehendible map, really
demonstrates the value of NPR for such an application.

40
5.3 Problems Encountered

While the project resulted in a complete and functional application, along the way there were
of course a number of problems. Firstly prior to the coding stage the project a detailed
understanding of OpenGL had to be acquired. This was achieved via the completion of
numerous tutorials [NEHE 07] [MLT 07] and coding of some basic programs. After gaining
an in depth knowledge of OpenGL a vast deal of research had to be undertaken into the field
of NPR and the various techniques for achieving this.

Throughout the implementation phase further problems did arise. The first of which was the
creation of the base map upon which the buildings were to be placed. Early on it became
apparent that a raster image as a map simply wouldn’t work. Raster images as they are pixel
based lose their quality when viewed close up. With the map needing the ability to zoom in
and out another method had to be investigated. Firstly it was attempted to produce a map
using a matrix of small raster images and flick between different images of different detail as
one zoomed in on the map. This was implemented and proved unproductive as there were a
large number of images required for this implementation and in addition large memory
requirements.

A vector map had to be created and this did prove difficult. There exist a large number of
commercial applications [AIS 07] [APS 07] for converting from raster to vector images. A
large number of these were trailed and they all produced vector images which lost the
majority of the detail of the map. Also the majority of vector formats are closed sources and
would be difficult to load within the OpenGL framework. It was considered to try and code a
program to filter through the pixels of the raster map to try creating a vector file. However, as
a number of commercial applications struggled to achieve this, it was decided against this so
as not to take time from the core research area of NPR.

A decision had to be made upon this map and in the end one was created by hand using
Adobe Illustrator which then could be imported into 3DS Max and then exported in to an OBJ
file which could be displayed in OpenGL. This part of the project was time consuming but
provided significantly increased performance for the completed application.

41
Positioning of the buildings and street labels was another part which proved somewhat
problematic and required the creation of a side application which was used to manipulate the
translation values of these items and then store the updated values. This application proved a
useful and efficient tool for solving the positioning problem as by any other means this would
have proved exceptional difficult. This program can be seen on the attached CD see appendix
A for exact location on the CD.

5.4 Lessons Learned

If this project were completed again from scratch it would be difficult to say as to whether
any of its elements would be completed differently. The project involved at the outset, a steep
learning curve into the field of computer graphics. This added significantly to the production
time of the project but was necessary for its completion. There were a lot of elements of
investigation in this project where different ideas and techniques were explored which have
now become acquired knowledge.

Such specific areas are familiarisation with various 3D and graphic file formats and how they
operate, and how to apply filters to image files and an in-depth understanding of OpenGL and
GLUI. There is nothing really that should be changed upon repeating the project as all the
research and investigation was vital to gain a knowledge of the background field of computer
graphics. However things would probably now be completed faster as a result of all that has
been learned throughout the duration of the project.

5.5 Future Work

This project has developed an application which could easily be expanded upon in the future.
The base map could be expanded to incorporate a larger geographical area or similar
techniques could be used to build a similar map for other cities. The application lacks any
advanced culling it is simply relying upon the basic culling implemented by OpenGL.

42
However this could be improved upon as seen in the Virtual Dublin application from the ISG.
Improved culling would be need if this application was to be commercialised but this was not
focused upon, as Non Photorealistic Rendering was the main area of focus for this project.
This advanced culling would be need for increasing the map geographical area as it would
result in the frame rate dropping below responsiveness levels for the application to continue to
be interactive.

The building models could be improved upon with more time and resources. The building
models used are primarily texture mapped. This means that the models are reliant on the
texture to add detail. This limited the NPR techniques that could be applied in the project and
with improved base models the representation of the buildings could be further enhanced.

43
Chapter 6

6. Summary

6.1 Review

The project was an interesting and educational experience which has given me a passion for
the area of computer graphics and a sense of the value of a number of NPR techniques.
Initially the project was set out to create an interactive 3D landmark map of Dublin City
stylized using NPR techniques. This was achieved through the investigation of various NPR
techniques and then applying these to a set of building models and a map. The resultant
application runs smoothly which illustrates the value of NPR in mapping. This application
provides a platform for future development and the project was certainly a success. The
project was interesting and has given me a passion that will see me continue to work in this
area into the future.

6.2 Conclusion

It has been proven that NPR is a beneficial and effective rendering technique for large
geographical areas. Throughout the report the results of NPR on the building models has been
evident. The reduced complexity and increased recognisablity of the building has been
witnessed as various NPR techniques were applied to the building models. Furthermore, the
reduction in memory requirements and processing power has been illustrated. All this
evidence concludes that NPR is an invaluable tool especially for the rendering of maps and
buildings.

44
Appendix A. CD Contents

The attached CD contains a fully functional and working version of the completed
application. It also contains the source code for the program, the OBJ models of the base map,
the building models used in the application and all the associated translation data. The exact
structure of the CD is described below in detail.

The root folder of the CD contains the following:


Thesis.pdf
• A PDF version of this thesis, viewable in Adobe Reader.
Application folder
• This folder contains all the necessary files for the project executable to be run
and the complete Visual Studio project files. The following is a list of this
folders contents in more detail:

Dublin_City_Map.exe
• This is a compiled executable of the application. The application folder must
be copied to the local hard drive to run the application efficiently.

main.cpp
• This is the main file of the program which contains the majority of the coding
completed for this project.

OBJModel.cpp, OBJModel.h, ImageLaoder.lib, glext.h


• These files are used for the loading of the OBJ buildings models. Thanks to
John Hamill (ISG group TCD) for use of this piece of code.

Buildings.txt and labels.txt


• These two text files store the data and translation details for both the street
labels and the building models.

The remaining folders contain all the building and map models which are stored
in different grouped folders.

45
Appendix B. Application Screenshots

The following is a selection of screenshots of the application in operation:

Figure 21: Application Screenshot 1

Figure 22: Application Screenshot 2

46
Figure 23: Application Screenshot 3

Figure 24: Application Screenshot 4

47
Appendix C. Code Listing

The full source code for this project is included on the enclosed CD. Below is the code listing
for the file ‘main.cpp’, which contains the core of the coding for this application.

An Interactive Computer Generated Landmark Map of Dublin

#include <string.h> // String class to hold Label data


#include <GL/glut.h> // GlUT and OpenGL
#include <GL/glui.h> // GLUI
#include <windows.h> // for timeGetTime() for framerate
#include <mmsystem.h>
#include <stdio.h> // input, output

#pragma comment(lib, "ImageLoader.lib") // ImageLoader Library

#include "OBJModel.h" // OBJModel class


#include "ImageLoader.h" // ImageLoader class

// Variables to hold frame-start and


// frame-end times for frame-rate calculations...
DWORD frameStartTime, frameEndTime;

// Variables required for the mouse interactions


float xy_aspect;
int last_x, last_y;
float rotationX = 0.0, rotationY = 0.0;

/** These are the live variables passed into GLUI ***/
int obj_type = 1;
int main_window;
float scaleX=1.0,scaleY=1.0,scaleZ=1.0;

// Variable to store the display state of specific items


int show_build = 1;
int show_map = 1;
int show_text = 1;
int show_bare = 0;

// Variable function stares


int curr_highlight = 0;
int curr_find = 0;
int last_find;

// Top 20 landmarks for find and highlight functions


char *string_list[] = {" ", "Art Gallery",
"Bank Of Ireland","Berkley Hall",
"Busaras","Central Bank",
"Christ Church","City Hall",
"Civic Offices","Dublin Castle",
"Dublin Spire","Hapenny Bridge",
"IFSC","Liberty Hall",
"Stephens Green","The Custom's House",

48
"The Four Courts","Trinity Campanile",
"Trinty Chapel","Trinity Museum"};

// Scaling and other interaction variables are declared


float scale = 3.0;
float view_rotate[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
float obj_pos[] = { 0.0, 0.0, 0.0 };
float RotateAngle = 0.0;
float TiltAngle = -50.0;

// Number of buildings
int NumBuilds;

// variable for label details


const int NumLabels=40;

char LabelsName[NumLabels][30];
char llabel[40];
float lrot[NumLabels];
float lx[NumLabels],ly[NumLabels],lz[NumLabels];

// Variables for mouse camera manipualtion


int mouseX,mouseY,prevMouseX,prevMouseY;
float mouseSensitivity = 0.05;
bool cameraMove = false;
bool cameraZoom = false;

// Translation for Find functionality


float find_pos[20][2]={{0.,0.0},{-0.151,-3.0},
{-8.35,1.85},{-4.15,0.05},
{0.1,9.4},{-11.0,0.95},
{-18.5,-0.35},{-14.5,-1.7},
{-18.2,0.349},{-14.75,-1.5},
{-8.4,9.89},{-11.0,3.2},
{1.2,7.95},{-3.65,7.65},
{-6.4,-10.0},{-1.5,7.5},
{-19.95,3.15},{-4.2,0.7},
{-5.9,1.25},{-3.35,0.25}};

// OBJ OBJECTS Arrays


COBJModel Buildings1[20];
COBJModel Buildings2[20];
COBJModel Buildings3[20];
COBJModel Buildings4[20];
COBJModel Buildings5[20];
COBJModel Buildings6[20];
COBJModel Buildings7[20];

// OBJ model for general map


COBJModel map01;

// OBJ model for rivers..


COBJModel map_rivers;

/** Pointers to the windows and some of the controls we'll create **/

GLUI *glui;
GLUI_Checkbox *checkbox;
GLUI_Spinner *spinner;
GLUI_RadioGroup *radio;
GLUI_Panel *obj_panel;

#define RESET_ID 303

/*********** control_cb() ******/


/* GLUI control callback */

void control_cb( int control )

49
{
// Rest the interaction values when
if ( control == RESET_ID ) {
scale = 3.0;
obj_pos[0] = 0.0;
obj_pos[1] = 0.0;
RotateAngle = 0.0;
TiltAngle = -50.0;
show_build = 1;
show_map = 1;
show_text = 1;
curr_highlight = 0;
curr_find = 0;
}
}

/*********************** FrameStart() *******************/


void FrameStart(void) {
// Record frame start time
frameStartTime = timeGetTime();
}

/********************* FrameEnd() *******************/


void FrameEnd(void *font, GLclampf r, GLclampf g, GLclampf b,
GLfloat x, GLfloat y) {

float elapsedTime;
char str[30];
char *ch;
GLint matrixMode;
// Record frame end time
frameEndTime = timeGetTime();

// Calculate the frames per second


elapsedTime = (frameEndTime-frameStartTime);
elapsedTime = elapsedTime/1000;
sprintf(str, "Frames per second: %2.0f", 1.0/elapsedTime);

glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
// Display the calculated FPS value
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glPushAttrib(GL_COLOR_BUFFER_BIT); /* save current colour */
glColor3f(r, g, b);
glRasterPos3f(x, y, 0.0);
for(ch= str; *ch; ch++) {
glutBitmapCharacter(font, (int)*ch);
}
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(matrixMode);

/*************** GlutKeyboard() **********/

void GlutKeyboard(unsigned char Key, int x, int y)


{
// Update variable based upon key inputs
switch(Key)

50
{
case 27 :
case 'q':
case 'Q':
exit(0);
break;

case 'a':
case 'A':
TiltAngle+=1;
break;

case 'z':
case 'Z':
TiltAngle-=1;
break;

case 's':
case 'S':
RotateAngle+=1;
break;

case 'd':
case 'D':
RotateAngle-=1;
break;

case 'f':
case 'F':
scale+=0.1;
break;

case 'v':
case 'V':
scale-=0.1;
break;

};

glutPostRedisplay();
}

/************** SpecialKeys() **********/

void SpecialKeys(int key, int x, int y)


{
switch(key)
{
case GLUT_KEY_UP: // to pan up
obj_pos[1]+=1.0f;
break;

case GLUT_KEY_DOWN: // to pan down


obj_pos[1]-=1.0f;
break;

case GLUT_KEY_LEFT: // to pan left


obj_pos[0]-=1.0f;
break;

case GLUT_KEY_RIGHT: // to pan right


obj_pos[0]+=1.0f;
break;
};

glutPostRedisplay();
}

51
/***************************************** GlutIdle() ***********/

void GlutIdle( void )


{
/* According to the GLUT specification, the current window is
// Undefined during an idle call-back
// So we need to explicitly change it if necessary */
if ( glutGetWindow() != main_window )
glutSetWindow(main_window);

glutPostRedisplay();
}

/************************* MouseClick() **********/

void MouseClick(int button, int state, int x, int y){


// Set camera move to true when left click down
if(button == GLUT_LEFT_BUTTON){
switch(state){
case GLUT_DOWN:cameraMove=true;
break;
case GLUT_UP:cameraMove=false;
break;
}
}
// Set camera zoom to true on right click down
if(button == GLUT_RIGHT_BUTTON){
switch(state){
case GLUT_DOWN:cameraZoom=true;
break;
case GLUT_UP:cameraZoom=false;
break;
}
}
}

/********************* GlutMotion() **********/

void MouseMotion(int x, int y){


// If camerMove true edit translation variables
// as determined by the previous mouse position
if(cameraMove){
obj_pos[0] += (x - prevMouseX) * mouseSensitivity;
obj_pos[1] -= (y - prevMouseY) * mouseSensitivity;
}
// If camerZoom true edit map scaling variable
// as determined by the previous mouse position
if(cameraZoom){
if(!cameraMove){
scale -= (y - prevMouseY) * mouseSensitivity;
}
}
// Record the previous mouse positions
prevMouseX=x;
prevMouseY=y;
}

/******************* MouseMove() **********/


void MouseMove(int x, int y){
// Record the previous mouse positions
prevMouseX=x;
prevMouseY=y;
}

/***************** GlutReshape() *************/

void GlutReshape( int x, int y )

52
{
int tx, ty, tw, th;
GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
glViewport( tx, ty, tw, th );

xy_aspect = (float)tw / (float)th;

glutPostRedisplay();
}

/************************* DrawMap() **********/


// Draw map using previous loaded OBJ files

void DrawMap()
{
glPushMatrix();

// Apply negative height scale to the obj map


glScalef(1,1,-1);
// Scale the block height
glScalef(1,1,0.1);
// Setup blending
glDepthMask(GL_FALSE);
glEnable(GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
glColor4f(0.9051, 0.9051, 0.8051,0.3);

map01.DrawModel(); // Draw the map obj

glDisable(GL_BLEND); // Turn Blending On

glDepthMask(GL_TRUE);
//glEnable(GL_DEPTH_TEST); // Turn Depth Testing Off

glRotatef( 90.0f, 1.0, 0.0, 0.0 ); // Rotate onto map


glTranslatef( 1.3, 0.0, 1.3f );
// Translate to position rivers correctly
glColor3f(0.801, 0.801, 0.901); // Set Colour

map_rivers.DrawModel(); // Draw the rivers obj

glPopMatrix();

/********************* DrawLabels() **********/

// Draw Labels as per the previous loaded data from file

void DrawLabels()
{
glPushMatrix();

glColor3f(0, 0, 0); // Set the colour to black


glScalef( 0.001, 0.001, 0.001 ); // Scale to set the size of the font

for (int num =0; num<NumLabels ;num++){


glPushMatrix();
// Translate and Rotate to the required position
glTranslatef( lx[num], ly[num], lz[num] );
glRotatef( lrot[num], 0.0, 0.0, 1.0 );

for (int c=0; LabelsName[num][c]!= '\0'; c++) {


glLineWidth(2);
if(LabelsName[num][c]== '_'){
glutStrokeCharacter(GLUT_STROKE_ROMAN ,' ');
}else{

53
glutStrokeCharacter(GLUT_STROKE_ROMAN ,LabelsName[num][c]);
}
}
glPopMatrix();
}
glPopMatrix();

/************************ LoadBuildings() **********/

// Load the buildings based on data from files

void LoadBuildings()
{

// Attributes for temporary storage of building data


FILE *buildfp; // File used to obtain data
char *BuildName[30]; // Temp store for specific buildings name
char dirname[60]; // Temp store for buildings directory data
char BuildFilename[60]; // Temp store for the buildings filenames
char LISTTYPE[20]; // Temp store for specific buildings type

float bx=0.0,by=0.0,bz=0.0; // Temp store for buildings translations

// Open the file containing the Building Data


buildfp=fopen("Buildings.txt","r");

// Buffer used to scan through the data in the file


char buildingBuffer[256];

fgets(&buildingBuffer[0],250,buildfp); // Read the first line of data

// While this line is a comment ( denoted by '#' symbol)


while(buildingBuffer[0] == '#'){
fgets(&buildingBuffer[0],250,buildfp); // Skip the comments
}

// Read the number of builds to load from the file


sscanf(&buildingBuffer[0],"Number Of Buildings: %d",&NumBuilds);

// While the number of buildings loaded is


// less than number requiring loading loop through following code
for(int bload=0;bload<NumBuilds;bload++){
// Read the next line of data
fgets(&buildingBuffer[0],250,buildfp);

// While this line is a comment( denoted by '#' symbol)


while(buildingBuffer[0] == '#'){
fgets(&buildingBuffer[0],250,buildfp); // Skip the comments
}
sscanf(&buildingBuffer[0],"%s %s %s x%f y%f z%f %s\n",&BuildName[0],
&dirname[0],&BuildFilename[0],&bx,&by,&bz,&LISTTYPE[0]);

if(bload<20){
std::cout<<std::endl<<"
Loading Building1 array at positon "<<bload<<std::endl;
Buildings1[bload].LoadCOBJModel2(dirname,BuildFilename);

Buildings1[bload].SetOBJPos(bx,by,bz);
Buildings1[bload].ModelNumber=bload;
Buildings1[bload].LockPosition();
Buildings1[bload].ReadMTL(TEX_S3TC|TEX_PALETTED);

54
if((bload>19)&&(bload<40)){
std::cout<<std::endl<<"
Loading Building2 array at positon "<<bload-20<<std::endl;
Buildings2[bload-20].LoadCOBJModel2(dirname,BuildFilename);
Buildings2[bload-20].SetOBJPos(bx,by,bz);
Buildings2[bload-20].ModelNumber=bload;
Buildings2[bload-20].LockPosition();
Buildings2[bload-20].ReadMTL(TEX_S3TC|TEX_PALETTED);

if((bload>39)&&(bload<60)){
std::cout<<std::endl<<"
Loading Building3 array at positon "<<bload-40<<std::endl;
Buildings3[bload-40].LoadCOBJModel2(dirname,BuildFilename);
Buildings3[bload-40].SetOBJPos(bx,by,bz);
Buildings3[bload-40].ModelNumber=bload;
Buildings3[bload-40].LockPosition();
Buildings3[bload-40].ReadMTL(TEX_S3TC|TEX_PALETTED);

if((bload>59)&&(bload<80)){
std::cout<<std::endl<<"
Loading Building4 array at positon "<<bload-60<<std::endl;
Buildings4[bload-60].LoadCOBJModel2(dirname,BuildFilename);
Buildings4[bload-60].SetOBJPos(bx,by,bz);
Buildings4[bload-60].ModelNumber=bload;
Buildings4[bload-60].LockPosition();
Buildings4[bload-60].ReadMTL(TEX_S3TC|TEX_PALETTED);

if((bload>79)&&(bload<100)){
std::cout<<std::endl<<"
Loading Building5 array at positon "<<bload-80<<std::endl;
Buildings5[bload-80].LoadCOBJModel2(dirname,BuildFilename);
Buildings5[bload-80].SetOBJPos(bx,by,bz);
Buildings5[bload-80].ModelNumber=bload;
Buildings5[bload-80].LockPosition();
Buildings5[bload-80].ReadMTL(TEX_S3TC|TEX_PALETTED);

if((bload>99)&&(bload<120)){
std::cout<<std::endl<<"
Loading Building6 array at positon "<<bload-100<<std::endl;
Buildings6[bload-100].LoadCOBJModel2(dirname,BuildFilename);
Buildings6[bload-100].SetOBJPos(bx,by,bz);
Buildings6[bload-100].ModelNumber=bload;
Buildings6[bload-100].LockPosition();
Buildings6[bload-100].ReadMTL(TEX_S3TC|TEX_PALETTED);

if((bload>119)&&(bload<140)){
std::cout<<std::endl<<"
Loading Building7 array at positon "<<bload-120<<std::endl;
Buildings7[bload-120].LoadCOBJModel2(dirname,BuildFilename);
Buildings7[bload-120].SetOBJPos(bx,by,bz);
Buildings7[bload-120].ModelNumber=bload;
Buildings7[bload-120].LockPosition();
Buildings7[bload-120].ReadMTL(TEX_S3TC|TEX_PALETTED);

}
}
// close the buildings file
fclose(buildfp);

55
}

/******************************* LoadLabels() **********/

// Load the Labels based on data from files

void LoadLabels()
{
// load labels for the map

FILE *labelfp;

labelfp=fopen("Labels.txt","r");

char labelBuffer[256];
fgets(&labelBuffer[0],250,labelfp);
while(labelBuffer[0] == '#'){ // Skip Comments
fgets(&labelBuffer[0],250,labelfp);
}
//int NumLabel;
//sscanf(&labelBuffer[0],"Number Of Labels: %d",&NumLabel);

for(int lload=0;lload<NumLabels;lload++){
fgets(&labelBuffer[0],250,labelfp);
while(labelBuffer[0] == '#'){ // Skip Comments
fgets(&labelBuffer[0],250,labelfp);
}
sscanf(&labelBuffer[0],"%s x%f y%f z%f
r%f\n",&LabelsName[lload][0],&lx[lload],&ly[lload],&lz[lload],&lrot[lload]);
}
// close the Labels file
fclose(labelfp);
}

/******************************* LoadMap() **********/

void LoadMap()
{
// Load map OBJ
map01.LoadCOBJModel2("Map","map04.obj");
map01.ReadMTL();

// Load river OBJ


map_rivers.LoadCOBJModel2("Map","rivers.obj");
map_rivers.ReadMTL();

/**********************DrawBuildings() **********/

void DrawBuildings()
{

glRotatef( 90.0f, 1.0, 0.0, 0.0 ); // rotate onto map


glScalef( 0.015f, 0.015f, 0.015f); // Scaling of buildings
glTranslatef(-435.0f, 10.0f, 102.0f);
// translate to so as building positions are correct

glPushMatrix();

glScalef( scaleX, scaleY, scaleZ); // Scaling of buildings

glPushAttrib( GL_ENABLE_BIT );

glEnable (GL_LINE_SMOOTH);
glEnable (GL_POLYGON_SMOOTH);

56
glEnable(GL_CULL_FACE);
glCullFace (GL_FRONT); //Enable front face Culling

glPushAttrib( GL_POLYGON_BIT | GL_CURRENT_BIT );

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2);

for(int cc=0;cc<NumBuilds;cc++){

if(cc==(curr_highlight-1)){
glColor3f(1, 0, 0);
// Draw highlighted red silhouette
}else{
glColor3f(0, 0, 0);
// Assume all other silhouettes black
}

if(cc<20){
Buildings1[cc].DrawModel();
}
if((cc>19)&&(cc<40)){
Buildings2[cc-20].DrawModel();
}
if((cc>39)&&(cc<60)){
Buildings3[cc-40].DrawModel();
}
if((cc>59)&&(cc<80)){
Buildings4[cc-60].DrawModel();
}
if((cc>79)&&(cc<100)){
Buildings5[cc-80].DrawModel();
}
if((cc>99)&&(cc<120)){
Buildings6[cc-100].DrawModel();
}
if((cc>119)&&(cc<140)){
Buildings7[cc-120].DrawModel();
}
}

glPopAttrib();

glDisable(GL_CULL_FACE);
glColor3f(1, 1, 1);

for( cc=0;cc<NumBuilds;cc++){

if(show_bare==0){
if(cc<20){
Buildings1[cc].DrawModel();
}
if((cc>19)&&(cc<40)){
Buildings2[cc-20].DrawModel();
}
if((cc>39)&&(cc<60)){
Buildings3[cc-40].DrawModel();
}
if((cc>59)&&(cc<80)){
Buildings4[cc-6000].DrawModel();
}
if((cc>79)&&(cc<100)){
Buildings5[cc-80].DrawModel();
}
if((cc>99)&&(cc<120)){
Buildings6[cc-100].DrawModel();

57
}
if((cc>119)&&(cc<140)){
Buildings7[cc-120].DrawModel();
}
}

if(show_bare==1){
if(cc<20){
Buildings1[cc].DrawModelBare();
}
if((cc>19)&&(cc<40)){
Buildings2[cc-20].DrawModelBare();
}
if((cc>39)&&(cc<60)){
Buildings3[cc-40].DrawModelBare();
}
if((cc>59)&&(cc<80)){
Buildings4[cc-6000].DrawModelBare();
}
if((cc>79)&&(cc<100)){
Buildings5[cc-80].DrawModelBare();
}
if((cc>99)&&(cc<120)){
Buildings6[cc-100].DrawModelBare();
}
if((cc>119)&&(cc<140)){
Buildings7[cc-120].DrawModelBare();
}
}

glPopAttrib();

glPopMatrix();

/********************** GlutDisplay() *****************/

void GlutDisplay( void )


{
glClearDepth( 1.0 );
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

// Start the Frames per second counter ...


FrameStart();

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 1500.0 );

glMatrixMode( GL_MODELVIEW );

glLoadIdentity();

// Apply Restrictions To trans,rotates..


if(scale>18.0){scale=18.0;}
if(scale<0.7){scale=0.7;}
if(TiltAngle<-140.0){TiltAngle=-140.0;}
if(RotateAngle>70.0){RotateAngle=4.0;}
if(RotateAngle<-70.0){RotateAngle=-70.0;}
if(obj_pos[0]<-24.0){obj_pos[0]=-24.0;}
if(obj_pos[0]>33.0){obj_pos[0]=33.0;}
if(obj_pos[1]<-26.0){obj_pos[1]=-26.0;}
if(obj_pos[1]>36.0){obj_pos[1]=36.0;}

58
// Apply translations for finding buildings
if(curr_find!=last_find){
obj_pos[0]=find_pos[curr_find][0];
obj_pos[1]=find_pos[curr_find][1];
}
last_find=curr_find;

glTranslatef( 0.0, 0.0, -30.0f );

// Apply the tilt angle to the map


glRotatef(TiltAngle,1,0,0);

// Rotations via the Glui rotation ball


glMultMatrixf( view_rotate );

// Scaling for zooming in and out


glScalef( scale, scale, scale );

// Translation for pan up, down, left, right...


glTranslatef( -obj_pos[0], -obj_pos[1], obj_pos[2] );

// Apply the rotation angle to the map


glRotatef(RotateAngle,0,0,1);

// If show_map is true draw map..


if ( show_map ){
DrawMap();
}

// show text
if ( show_text ) {
DrawLabels();
}

if ( show_build ) {
DrawBuildings();
// DrawGenericBuild();

// Frame counter display code


FrameEnd(GLUT_BITMAP_HELVETICA_12, 0.0, 0.0, 0.0, 0.05, 0.95);

glFlush();
glutSwapBuffers();
}

/*********************** main() ********************/

void main(int argc, char* argv[])


{

/****************************************/
/* Initialize GLUT and create window */
/****************************************

//glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);


glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
glutInitWindowPosition( 20, 20 );
glutInitWindowSize( 900, 700 );

main_window = glutCreateWindow( "Dublin City Map" );

// Set OpenGL parameters


glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);

LoadMap(); // Load OBJ map files

59
LoadBuildings(); // Load buildings from obj files
LoadLabels(); // Load Labels for street names etc..

glutDisplayFunc( GlutDisplay ); // Main display function


GLUI_Master.set_glutReshapeFunc( GlutReshape );
// Function to deal with window resizing
GLUI_Master.set_glutKeyboardFunc( GlutKeyboard );
// Function to deal with key press
GLUI_Master.set_glutSpecialFunc( SpecialKeys );
// Special key function set to NULL
GLUI_Master.set_glutMouseFunc(MouseClick);
// Function to deal with mouse click
glutMotionFunc(MouseMotion);
// Function to deal with mouse motion
glutPassiveMotionFunc(MouseMove);
// Function to deal with mouse move

/****************************************/
/* Here's the GLUI code */
/****************************************/

// Print the Glui Version


printf( "GLUI version: %3.2f\n", GLUI_Master.get_version() );

/*** Create the side sub window ***/


glui = GLUI_Master.create_glui_subwindow( main_window,
GLUI_SUBWINDOW_RIGHT );

// Spacer
glui->add_statictext( " " );

// Static Text
glui->add_statictext( " CONTROLS" );

// Seperator bar
glui->add_separator();

// Pan Up, Down, Left, Right


GLUI_Translation *trans_xy =
glui->add_translation( "Pan [ML]", GLUI_TRANSLATION_XY, obj_pos );
trans_xy->set_speed( .01 );

// Seperator bar
glui->add_separator();

// Zoom in, out


GLUI_Translation *trans_z =
glui->add_translation( "Zoom [f,v,MR]", GLUI_TRANSLATION_Z, &obj_pos[2] );
trans_z->set_speed( .1 );

// Seperator bar
glui->add_separator();

// Rotate Left or Right


GLUI_Translation *trans_x =
glui->add_translation( "Rotate [s,d]", GLUI_TRANSLATION_X, &RotateAngle );
trans_x->set_speed( .1 );

// Seperator bar
glui->add_separator();

// Increase or decrease the tilt angle


GLUI_Translation *tansy =
glui->add_translation( "Tilt Angle [a,z]", GLUI_TRANSLATION_Y, &TiltAngle
);
trans_y->set_speed( .1 );

60
// Seperator bar
glui->add_separator();

// Rotation Ball
GLUI_Rotation *view_rot = glui->add_rotation( "Rotation", view_rotate );
view_rot->set_spin( 0.0005 );

// Seperator bar
glui->add_separator();

// Spacer
glui->add_statictext( "" );

/*** Add Rollout for Options ***/


GLUI_Rollout *options = glui->add_rollout( "Options", true);
glui->add_checkbox_to_panel( options, "Display Map", &show_map );
glui->add_checkbox_to_panel( options, "Display Text", &show_text );
glui->add_checkbox_to_panel( options, "Display Buildings", &show_build );
glui->add_checkbox_to_panel( options, "Draw Bare Models", &show_bare );
// Spacer
glui->add_statictext( "" );

GLUI_Spinner *segment_spinner2 =
glui->add_spinner( "Scale Buildings Height:", GLUI_SPINNER_FLOAT,
&scaleY );
segment_spinner2->set_float_limits( .2f, 4.0 );

// Spacer
glui->add_statictext( "" );

/**** Add listbox ****/


GLUI_Listbox *list2 = glui->add_listbox( "Find:", &curr_find );
int j;
for( j=0; j<20; j++ )
list2->add_item( j, string_list[j] );

/**** Add listbox ****/


GLUI_Listbox *list = glui->add_listbox( "Highlight:", &curr_highlight );
int i;
for( i=0; i<20; i++ )
list->add_item( i, string_list[i] );

// Spacer
glui->add_statictext( "" );

// A 'quit' button to terminate program


glui->add_button( "Reset", RESET_ID, control_cb);

// A 'quit' button to terminate program


glui->add_button( "Quit", 0,(GLUI_Update_CB)exit );

/** Link windows to GLUI, and register idle callback ****/


glui->set_main_gfx_window( main_window );

/**** We register the idle callback with GLUI, *not* with GLUT **/
GLUI_Master.set_glutIdleFunc( GlutIdle );

/**** Regular GLUT main loop ****/


glutMainLoop();
}

61
Bibliography

[EST 07] “Escape Travel Ltd - NPR map of St. Petersburg”


http://www.escapetravel.spb.ru/images/map.jpg
Last checked 7 May 02007

[SST 07] “Shrek Sequel - a picture that's worth 20 terabytes”


http://www.sfgate.com/cgi-
bin/article.cgi?file=/chronicle/archive/2004/06/21/BUGME78HCO1.DTL
Last checked 7 May 2007

[SHB86] “Hairy Brushes”


Proceedings of an annual conference on Computer Graphics
Steve Strassman
August 1986

[ANS87] “Drawing natural scenery by computer graphics”


T. T. Sasada
May 1987

[NPA 07] “NPR architectural example”


http://www.cs.northwestern.edu/academics/courses/special_topics/39
5-npr/npr/resource.html
Last checked 7 may 2007

[WNB 94] “Computer–Generated Pen–And–Ink Illustration”


In Proceedings of SIGGRAPH ’94
Georges Winkenbach and David H. Salesin
July 1994.

[SAL 94] “Orientable textures for image-based pen-and-ink illustration“


In Proceedings of SIGGRAPH ’94
Salisbury, M. P., Wong, M. T., Hughes, J. F., and Salesin,
1994

[GSN 07] “Google Scholar search for Non Photorealistic Rendering”


http://scholar.google.com/scholar?hl=en&lr=&q=non+photorealistic+re
ndering
Last checked 7 May 2007

[TSN 02] “Non- Photorealistic Computer Graphics”


Modelling, Rendering and Animation
Thomas Strothotte, Stefan Schlechtweg
2002

[WMD 07] “Wikipedia Medical Diagram of Alveoli”


http://en.wikipedia.org/wiki/Image:Alveoli_diagram.png
Last checked 7 May 2007

62
[GMW 07] “Google Maps Web Application”
http://maps.google.com/
Last checked 7 May 2007

[MVS 03] “Microsoft Visual Studio .net 2003”


http://msdn2.microsoft.com/en-us/vstudio/aa700867.aspx
Last checked 7 May 2007

[AIS 07] “Adobe Illustrator”


http://www.adobe.com/products/illustrator/
Last checked 7 May 2007

[APS 07] “Adobe Photoshop”


http://www.adobe.com/products/photoshop/index.html
Last checked 7 May 2007

[IMP 07] “Image Processing Algorithms”


http://www.codeproject.com/cs/media/csharpgraphicfilters11.asp
Last Checked 7 May 2007

[3DS 07] “Autodesk 3DS Max 8”


http://usa.autodesk.com/adsk/servlet/index?id=5659302&siteID=123112
Last checked 7 May 2007

[OBJ 07] “Alias Wavefront OBJ Format”


http://www.eg-models.de/formats/Format_Obj.html
Last checked 7 May 2007

[NEHE 07] “NeHe Productions”


http://nehe.gamedev.net
Last checked 7 May 2007

[MLT 07] “Morrowland Tutorials”


http://www.morrowland.com/apron/tut_gl.php
Last checked 7 May 2007

[OGL 07] “OpenGL”


http://www.opengl.org
Last checked 7 May 2007

[OGG 07] “OpenGL Programming Guide”


http://fly.cc.fer.hr/~unreal/theredbook/
Last checked 7 May 2007

[OES 07] “OpenGL ES”


http://www.khronos.org/opengles/
Last checked 7 May 2007

[VDUB 07] “Virtual Dublin Project”


http://isg.cs.tcd.ie/hamilljp/TCDModel/index.html
Last checked 7 May 2007

63
[GLUI 2.1] “GL User Interface Library 2.1”
http://www.cs.unc.edu/~rademach/glui
Paul Rademacher
Last checked 7 May 2007

[GLUI 07] “GL User Interface Library”


http://glui.sourceforge.net/
Last checked 7 May 2007

[OBJM 07] “OBJ Model Loader Class”


http://isg.cs.tcd.ie/hamilljp/
John Hamill
Last checked 7 May 2007

[OFC 07] “OpenGL frame-rate counter code”


http://www.cs.manchester.ac.uk/software/OpenGL/frames.txt
Toby Howard
March 1999

64

You might also like