Subversion Repositories gelsvn

Rev

Rev 633 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
405 jab 1
\documentclass[a4paper]{article}
2
\usepackage{listings}
3
\usepackage[isolatin]{inputenc}
4
\usepackage{makeidx,times}
5
\usepackage{fancyhdr}
6
\usepackage{graphicx}
7
\usepackage{float}
8
\usepackage{alltt}
9
%%\usepackage{doxygen}
10
\usepackage[pdftex,
11
            pagebackref=true,
12
            colorlinks=true,
13
            linkcolor=blue
14
           ]{hyperref}
596 jab 15
 
405 jab 16
\makeindex
17
\lstset{tabsize=1,language=C++,basicstyle=\small}
18
\author{J. Andreas B{\ae}rentzen}
465 jab 19
\title{Introduction to GEL\\\vspace{0.25cm} \normalsize
20
\textit{An informal introduction to the GEL library with many examples of usage}.}
405 jab 21
\setcounter{tocdepth}{2}
22
\begin{document}
23
\maketitle
24
\tableofcontents
465 jab 25
\newpage\section{Introduction}
596 jab 26
\sloppy
405 jab 27
 
28
GEL is an abbreviation of GEometry and Linear algebra. GEL is a C++ library with tools for manipulating digital representations of geometry such as polygonal meshes, triangle meshes, point clouds, and voxel grids. Since linear algebra tools are invariably needed for this, GEL also contains tools for linear algebra. Finally, GEL contains tools for drawing geometry using OpenGL and various utilities.
29
 
596 jab 30
This document pertains to the version of GEL which is distributed on CampusNet for 02585. This version of GEL comes with project files for Visual Studio 9 and XCode and examples relevant for the course are included in the distribution.
405 jab 31
 
596 jab 32
GEL is not documented as well as we would like, but a fair amount of Doxygen documentation is provided for those parts of GEL which are used a lot. You will find the reference manual at \href{http://www2.imm.dtu.dk/courses/02585/GELref/index.html}{http://www2.imm.dtu.dk/courses/02585/GELref/index.html}
405 jab 33
 
596 jab 34
Please use it. Autogenerated documentation is not eminently readable, but it is much better than no documentation and it should be relatively complete for the parts of GEL needed in the course. 
35
 
36
The goal of \textit{this} document is to provide more detail and to help people getting started. In particular, this document focuses on functionality in the CGLA and HMesh namespaces, but we shall also take a look at some other parts of GEL. Unfortunately, it is rather difficult to be complete: There is functionality in GEL not covered here. Consequently, if you are looking for something particular, we \textbf{entreat } you to look at the reference linked to above
405 jab 37
\subsection{Overview of GEL}
38
 
596 jab 39
GEL contains many tools for geometry processing and a number of data structures. Perhaps the most important is the \texttt{Manifold} class which resides in the \texttt{HMesh} namespace. A \texttt{Manifold} is a halfedge based representation of a polygonal mesh. There is also a simpler triangle mesh data structure, \texttt{TriMesh}, based on an indexed face set. There are several voxel grid data structures, a fairly efficient k-D tree for storing points, bounding box hierarchies etc.
405 jab 40
 
596 jab 41
A number of algorithms exist for manipulating these representations of geometric data. For instance, \texttt{Manifold} has a function for mesh simplification, several functions for smoothing (including anisotropic), mesh optimization, and mesh clean up.
42
Another strong point of GEL is the fact that it contains good support for converting between representations; especially between meshes and voxel grids. There are several tools for polygonizing isosurfaces and also converting meshes to distance fields.  The tools pertaining to the Manifold data structure are in the \texttt{HMesh} namespace. The other geometry related tools are in the \texttt{Geometry} namespace.
405 jab 43
 
596 jab 44
There are two packages for linear algebra: \texttt{CGLA} is strictly for small vectors and matrices (dimensions 2,3, and 4). \texttt{LinAlg} is a Lapack wrapper for slightly larger problems. At this point, it is fairly simple but includes a number of functions for solving linear systems, factoring matrices and finding eigensolutions for symmetric matrices.
405 jab 45
 
596 jab 46
\texttt{GLGraphics} contains facilities for drawing entities from other parts of GEL via OpenGL. Especially \texttt{TriMesh} and Manifold have good support. For instance, there is a nice wireframe drawing class. There are also two virtual trackballs for interactive programs and some tools for viewing in interactive programs and SOIL a small open source library for image loading by Jonathan Dummer.
405 jab 47
 
596 jab 48
Finally there are some utilities in \texttt{Util}: Getting command line arguments, hash table classes, a 2D grid class, a resource manager, an XML parser by Jeppe Frisvad and other tools.
405 jab 49
 
50
\section{CGLA}
51
 
596 jab 52
\texttt{CGLA} is a set of numerical C++ vector and matrix classes and class
53
templates designed with computer graphics in mind. \texttt{CGLA} stands for
465 jab 54
``Computer Graphics Linear Algebra''. Let us get right down to the obvious question: Why create another
405 jab 55
linear algebra package?
596 jab 56
Well, \texttt{CGLA} evolved from a few matrix and vector classes because I
57
didn't have anything better. Also, I created \texttt{CGLA} to experiment with
405 jab 58
some template programming techniques. This led to the most important
596 jab 59
feature of \texttt{CGLA}, namely the fact that all vector types are derived
405 jab 60
from the same template. 
61
 
62
This makes it easy to ensure identical semantics: Since all vectors
63
have inherited, say, the * operator from a common ancestor, it works
64
the same for all of them.
65
 
596 jab 66
It is important to note that \texttt{CGLA} was designed for Computer Graphics 
405 jab 67
(not numerical computations) and this had a number of
68
implications. Since, in computer graphics we mainly need small vectors
596 jab 69
of dimension 2,3, or 4 \texttt{CGLA} was designed for vectors of low
405 jab 70
dimensionality. Moreover, the amount of memory allocated for a vector
596 jab 71
is decided by its type at compile time. \texttt{CGLA} does not use dynamic
72
memory. \texttt{CGLA} also does not use virtual functions, and most functions
73
are inline. These features all help making \texttt{CGLA} relatively fast. 
405 jab 74
 
75
Of course, other libraries of vector templates for computer graphics
76
exist, but to my knowledge none where the fundamental templates are
77
parametrized w.r.t. dimension as well as type. In other words, we have
596 jab 78
a template (\texttt{ArithVec}) that gets both type
405 jab 79
(e.g. \texttt{float}) and dimension 
80
(e.g. 3) as arguments. the intended use of this template is as
81
ancestor of concrete types such as \texttt{Vec3f} - a 3D floating
82
point type. 
83
 
84
The use of just one template as basis is very important, I believe,
85
since it makes it extremely simple to add new types of
86
vectors. Another very generic template is \texttt{ArithMat} which is a
87
template for matrix classes. (and not necessarily NxN matrices). 
88
 
596 jab 89
From a users perspective \texttt{CGLA} contains a number of vector and matrix
405 jab 90
classes, a quaternion and some utility classes. In summary, the most
91
important features are
92
\begin{itemize}
93
\item A number of 2, 3 and 4 d vector classes.
94
\item A number of Matrix classes.
95
\item A Quaternion class.
96
\item Some test programs.
97
\item Works well with OpenGL.
98
\end{itemize}
99
 
100
 
101
\subsection{Naming conventions}
102
 
596 jab 103
Vectors in \texttt{CGLA} are named \texttt{VecDT} where \texttt{D} stands for
405 jab 104
dimension at  \texttt{T} 
105
for type. For instance a 3D floating point vector is named
106
\texttt{Vec3f}. Other types are d (double), s (short), i (int), uc
107
(unsigned char), and usi (unsigned shourt int).
108
 
109
Matrices are similiarly named \texttt{MatDxDT}. For instance a 4D
110
\texttt{double} matrix is called \texttt{Mat4x4d}.
111
 
112
\subsection{How to use CGLA}
113
 
596 jab 114
If you need a given \texttt{CGLA} class you can find the header file that
405 jab 115
contains it in this document. Simply include the header file and use
596 jab 116
the class. Remember also that all \texttt{CGLA} functions and classes live in
117
the \texttt{CGLA} namespace! Lastly, look at the example programs that came
405 jab 118
with the code.
119
 
120
An important point is that you should never use the Arith... classes
121
directly. Classes whose names begin with Arith are templates used for
122
deriving concrete types. It is simpler, cleaner, and the intended
123
thing to do to only use the derived types.
124
 
125
In some cases, you may find that you need a vector or matrix class
596 jab 126
that I haven't defined. If so, it is fortunate that \texttt{CGLA} is easy to
405 jab 127
extend. Just look at, say, \texttt{Vec4f} if you need a \texttt{Vec5d}
128
class.
129
 
130
For some more specific help look at the next section where some of the
131
commonly used operations are shown.
132
 
133
 
134
\subsection{CGLA: Examples of Usage}
135
 
136
The examples below are by no means complete. Many things are
137
possible but not covered below. However, most of the common usage is
138
shown, so this should be enough to get you started. Note that in the
139
following we assume that you are \texttt{using namespace CGLA} and
140
hence don't prefix with \texttt{CGLA::}.
141
 
142
In short, to compile the examples below you would need the following
143
in the top of your file
144
 
145
\begin{verbatim}
146
#include <iostream> // For input output
147
#include "CGLA/Vec3f.h"
148
#include "CGLA/Quaternion.h"
149
#include "CGLA/Mat4x4f.h"
150
 
151
using namespace std; // For input output
152
using namespace CGLA;
153
\end{verbatim}
154
 
155
To begin with let us create 3 3D vectors. This is done as follows:
156
\begin{verbatim}
157
  Vec3f p0(10,10,10);
158
  Vec3f p1(20,10,10);
159
  Vec3f p2(10,20,10);
160
\end{verbatim}
161
if we had left out the arguments the three vectors would have been
162
uninitialized, at least in release mode. If we compile in debug mode
163
they would have been initialized to ``Not a Number'' to aid
465 jab 164
debugging. However, the $[10 \;10 \;10]^T$ vector could also have been
405 jab 165
created differently, using
166
\begin{verbatim}
167
  Vec3f p0(10);
168
\end{verbatim}
169
 
596 jab 170
We often need arithmetic operators which work on vectors and matrices. This is supported by CGLA through overloaded versions of the standard arithmetic operators. Using \texttt{Vec3f} and \texttt{+} as examples, we have the following syntax:
171
\begin{verbatim}
172
  Vec3f p0(0,1,2);
173
  Vec3f p1(0,1,0);
174
 
175
  Vec3f p2 = p0 + p1;
176
  p2 += p1; // Same as p2 = p2 + p1
177
\end{verbatim}
178
Thus both the normal form of \texttt{+} and the assignment form are supported for \texttt{Vec3f}. The same is true of the other arithmetic operators \texttt{-*/} and the operators are supported for most  CGLA entities including all matrix and vector types.
179
 
635 janba 180
Multiplication is also supported for matrix vector products. Below an example with 4D double precision vector and matrix:
596 jab 181
\begin{verbatim}
635 janba 182
  Vec4d x(1,1,0,1);
596 jab 183
 
184
  Mat4x4d m = rotation_Mat4x4d(ZAXIS, 3.14);
185
 
635 janba 186
  Vec4d y = m * x;
596 jab 187
\end{verbatim}
188
 
189
but all vectors are column vectors, so only right multiplication is supported. We cannot multiply a vector on the left side of a matrix. However, there is, of course, a \texttt{dot} function which computes the dot product of two vectors. 
190
 
405 jab 191
A very common operation is to compute the normal of a triangle from
192
the position of its vertices. Assuming the three vectors represent the
193
vertices of a triangle, we can compute the normal by finding the
194
vector from the first vertex to the two other vertices, taking the
195
cross product and normalizing the result. This is a one-liner:
196
 
197
\begin{verbatim}
198
  Vec3f n = normalize(cross(p1-p0,p2-p0));
199
\end{verbatim}
200
 
201
Quite a lot goes on in the snippet above. Observe that the - operator
202
also works for vectors. In fact almost all the arithmetic operators
203
work for vectors. You can also use assignment operators (i.e
204
\texttt{+=}) which is often faster. Then there is the function
205
\texttt{cross} which simply computes the cross product of its
596 jab 206
arguments. Finally the vector is normalized using the
405 jab 207
function normalize.
208
 
209
Of course, we can print all or at least most CGLA entities. For
210
example 
211
 
212
\begin{verbatim}
213
  cout << n << endl;
214
\end{verbatim}
215
 
216
will print the normal vector just computed. We can also treat a vector
217
as an array as shown below
218
 
219
\begin{verbatim}
220
  float x = n[0];
221
\end{verbatim}
222
 
223
here, of course, we just extracted the first coordinate of the
224
vector. 
225
 
226
CGLA contains a number of features that are not used very frequently,
227
but which are used frequently enough to warrent inclusion. A good
228
example is assigning to a vector using spherical coordinates:
229
 
230
\begin{verbatim}
231
  Vec3f p;
232
  p.set_spherical(0.955317, 3.1415926f/4.0f , 1);
233
\end{verbatim}
234
 
235
CGLA also includes a quaternion class. Here it is used to construct a
236
quaternion which will rotate the x axis into the y axis.
237
 
238
\begin{verbatim}
239
  Quaternion q;
240
  q.make_rot(Vec3f(1,0,0), Vec3f(0,1,0));
241
\end{verbatim}
242
 
243
Next, we construct a $4\times 4$ matrix \texttt{m} and assign a translation
244
matrix to the newly constructed matrix. After that we ask the
245
quaternion to return a $4\times 4$ matrix corresponding to its
246
rotation. This rotation matrix is then multiplied onto \texttt{m}.
247
 
248
\begin{verbatim} 
249
  Mat4x4f m = translation_Mat4x4f(Vec3f(1,2,3));
250
  m *= q.get_mat4x4f();
251
\end{verbatim}
252
 
253
Just like for vectors, the subscript operator works on
254
matrices. However, in this case there are two indices. Just using one
255
index will return the ith row as a vector as shown on the first line
256
below. On the second line we see that using two indices will get us an
257
element in the matrix. 
258
 
259
\begin{verbatim} 
260
  Vec4f v4 = m[0];
261
  float c = m[0][3];
262
\end{verbatim}
263
 
264
There is a number of constructors for vectors. The default constructor
265
will create a null vector as we have already seen. We can also specify
266
all the coordinates. Finally, we can pass just a single number
267
$a$. This will create the $[a\:a\:a]^T$ vector. For instance, below we
268
create the $[1\: 1\: 1]^T$ vector. Subsequently, this vector is
269
multiplied onto \texttt{m}. 
270
 
271
\begin{verbatim}
272
  Vec3f p(1);
273
  Vec3f p2 = m.mul_3D_point(p);
274
\end{verbatim}
275
 
276
Note though that \texttt{m} is a $4\times
277
4$ matrix so ... how is that possible? Well, we use the function
278
\texttt{mul\_3D\_point} which, effectively, adds a $w=1$ coordinate to p
279
making it a 4D vector. This $w$ coordinate is stripped afterwards. In
280
practice, this means that the translation part of the matrix is also
281
applied. There is a similar function \texttt{mul\_3D\_vector} if we want
282
to transform vectors without having the translation. This function,
283
effectively, sets $w=0$.
284
 
285
Finally, CGLA is often used together with OpenGL although there is no
286
explicit tie to the OpenGL library. However, we can call the
287
\texttt{get} function of most CGLA entities to get a pointer to the
288
contents. E.g. \texttt{p.get()} will return a pointer to the first
289
float in the 3D vector \texttt{p}. This can be used with OpenGL's
290
``v'' functions as shown below. 
291
 
292
\begin{verbatim}
293
  glVertex3fv(p.get());
294
\end{verbatim}
295
 
296
\section{HMesh}
297
 
596 jab 298
HMesh's \texttt{Manifold} class is a halfedge based mesh data structure. To use the basic functionality you need to include the Manifold.h header and use the appropriate name space:
405 jab 299
\begin{verbatim}
596 jab 300
#include <Manifold.h>
301
using namespace HMesh;
405 jab 302
\end{verbatim}
596 jab 303
This type of data structure restricts you to manifolds, but allows for general N-gons for arbitrary N and makes manipulation somewhat simpler than other types of data structures for meshes.  Note that this particular implementation does not allow more than one loop per face. 
405 jab 304
 
596 jab 305
Since the halfedge representation can only represent polygonized manifolds, the name of the data structure is
405 jab 306
\begin{verbatim}
596 jab 307
Manifold m;
405 jab 308
\end{verbatim}
596 jab 309
The central element of the data structure is the \textit{halfedge}. A halfedge is a representation of an edge, but it is imbued with a direction: it represents the edge in the counterclockwise loop around one of the two faces that share the edge. Thus, we always have two halfedges for a given edge, and a halfedge contains an integer index that points to its opposite halfedge. Similarly, indices point to the next and the previous halfedge in a counterclockwise loop as well as the incident face and the incident vertex in the direction of the halfedge.
405 jab 310
 
596 jab 311
A vertex has an integer index referencing one of the halfedges which emanate from the vertex, and a face has the index of one of the halfedges in the loop around the face. The entities and the integer indices used to refer from one entity to another are illustrated in Figure~\ref{fig:halfedge}. Note also that the pointers from an entity to another, e.g. from a halfedge to its next edge is the mechanism that allows us to traverse the mesh.
312
\begin{figure}[h!]
313
\centering
314
\includegraphics[width=0.5\textwidth]{halfedge-entities.pdf}
315
\caption{A halfedge and related entities. The halfedge has pointers to the \texttt{next} and previous (\texttt{prev}) halfedges in the counterclockwise loop around its face. It also has a pointer to the opposite (\texttt{opp}) halfedge, which corresponds to the same geometric edge but is part of the loop around the adjacent face. Finally, the halfedge has a pointer to the next \texttt{vertex} in the direction of the halfedge and to its \texttt{face}. A face has a pointer to exactly one halfedge (\texttt{last}) and a vertex has a pointer to one outgoing halfedge (\texttt{h}). The word ``pointer'' is a bit of a misnomer. In GEL we use integer indices instead of memory pointers. }
316
\label{fig:halfedge}
317
\end{figure}
405 jab 318
 
596 jab 319
The integer indices are not only used to store references from one entity to another. In GEL, we do not directly access entities but use integer IDs to refer to them. For instance to get the position of a vertex, which is stored as a \texttt{Vec3d}, we need
405 jab 320
\begin{verbatim}
596 jab 321
VertexID vid;
322
// ... obtain a vertex ID
323
vec3d p = m.pos(vid);
405 jab 324
\end{verbatim}
633 janba 325
Note that m.pos(vid) returns a reference to the vertex identified by vid, so we can also assign the vertex position simply using 
326
\begin{verbatim}
327
m.pos(vid) = p;
328
\end{verbatim}
596 jab 329
\texttt{VertexID}, \texttt{FaceID}, and \texttt{HalfEdgeID} are simply indices which we use to refer to entities in the mesh. These types are used to communicate with the \texttt{Manifold} class. For instance to get the position of a vertex, but many other functions -- both inside and outside the \texttt{Manifold} class take one of the ID types as argument. For instance,
405 jab 330
\begin{verbatim}
596 jab 331
VertexID Manifold::split_edge(HalfEdgeID h);
405 jab 332
\end{verbatim}
596 jab 333
splits an edge and returns a \texttt{VertexID} for the introduced vertex. For functions outside the class, we need to also give the \texttt{Manifold} as an argument since an ID does not tell the function which mesh we are referring to. For example
405 jab 334
\begin{verbatim}
596 jab 335
bool boundary(const Manifold& m, HalfEdgeID h);
405 jab 336
\end{verbatim}
596 jab 337
returns true if the halfedge identified by \texttt{h} is a boundary edge in \texttt{m}.
338
 
633 janba 339
A very frequent operation is that we need to iterate over all the vertices in a mesh. This is done as follows:
405 jab 340
\begin{verbatim}
633 janba 341
for(VertexID v : m.vertices())
596 jab 342
{
633 janba 343
   Vec3d p = m.pos(v);
344
   // Do something with the position
596 jab 345
}
405 jab 346
\end{verbatim}
633 janba 347
Since we also have ID types for faces and half edges, similar code could have been used to iterate over these entities. As a note: there are also specific iterator classes (e.g. \texttt{VertexIDIterator}) which can be used to iterate with old fashioned for loops. However, the syntax is far more cumbersome, so we suggest you stick with the range based for loops as  shown above.
596 jab 348
\subsection{Walker}
633 janba 349
To loop over all vertices is one way of traversing the mesh. It ensures that we visit all vertices, but it does not relate to the connectivity of the mesh. 
350
To traverse the mesh in a way that respects connectivity, we use the \texttt{Walker} class. A \texttt{Walker} always points to a specific halfedge, but unlike a \texttt{HalfEdgeID}, it can be used to move from edge to edge. For instance, to compute the centroid for a given face, we can use the following code:
405 jab 351
\begin{verbatim}
596 jab 352
Vec3d p(0);
633 janba 353
FaceID f = *m.faces_begin();
354
for(Walker w = m.walker(f); !w.full_circle(); w = w.next())
596 jab 355
  p += m.pos(w.vertex()); 
356
p /= w.no_steps();
405 jab 357
\end{verbatim}
633 janba 358
The code above computes the centroid for the first face in the mesh. It does so by jumping from edge to edge until it has come full circle. For each jump, we add the vertex pointed to by the halfedge to \texttt{p}. The benefit of the \texttt{Walker} is that it allows us to move from a halfedge to all connected halfedges. The simple traversal functions are \texttt{next}, \texttt{prev}, and \texttt{opp}:
405 jab 359
\begin{verbatim}
596 jab 360
Walker w;
361
w = w.next(); 
362
w = w.prev();
363
w = w.opp();
405 jab 364
\end{verbatim}
596 jab 365
\texttt{prev} does the same as \texttt{circulate\_face\_cw} and \texttt{next} does the same as \\\texttt{circulate\_face\_ccw}. The longer names are indicative of the geometric operation while \texttt{prev} and \texttt{next} highlight the connection with the data structure.    It is important to note that all of the functions which operate on \texttt{Walker} instances return a new \texttt{Walker} and do not alter the state of the current walker. Thus to walk around a face, we use \texttt{w = w.next()} as opposed to just \texttt{w.next()} in the for loop above. 
366
That might seem inconvenient but it is more flexible since we can obtain, say, a nearby vertex just by concatenating some traversal functions. For instance \texttt{w.next().opp().next().vertex()} returns an ID to a vertex nearby  -- without changing \texttt{w}. The sequence \texttt{w.next().opp().next()} creates three anonymous walkers. If, on the other hand, the functions used for walking updated the state of  \texttt{w}, we would have needed to first make a named copy of \texttt{w} before updating its state, so that we could get back to the original state.
367
 
368
\texttt{Walker} can be used to circulate around both faces and vertices. Below, we use vertex circulation to compute the average of the neighbors of a vertex
405 jab 369
\begin{verbatim}
596 jab 370
Vec3d p(0);
633 janba 371
VertexID v = *m.vertices_begin();
372
for(Walker w = m.walker(v);!w.full_circle(); 
373
     w = w.circulate_vertex_ccw()){
596 jab 374
  p += m.pos(w.vertex()); 
375
p /= w.no_steps();
405 jab 376
\end{verbatim}
596 jab 377
 
633 janba 378
Again, the \texttt{full\_circle()} function tests whether the walker has returned to the original halfedge whence it was created. We can also call  \texttt{no\_steps() } which returns the number of steps taken. In this regard, a step of vertex circulation is considered atomic - even though \texttt{w.circulate\_vertex\_ccw()} is the same as  \texttt{w.prev().opp()}.
596 jab 379
 
633 janba 380
From a walker we can easily obtain any of the mesh entities that the halfedge it refers to are incident upon. For instance \texttt{vertex()} returns the \texttt{VertexID} of the vertex which the halfedge points to, \texttt{face()} gives us the \texttt{FaceID} of the incident face and \texttt{halfedge()} simply returns the \texttt{HalfEdgeID}. There is one more option for circulation. The following code does precisely the same as the code above, i.e. it computes the average of the neighboring vertices.
381
\begin{verbatim}
382
        Vec3d p(0);
383
        int n = circulate_vertex_ccw(m, v, 
384
                   [&](VertexID v){ p += m.pos(v); });
385
        return p / n;
386
\end{verbatim}
387
Here the function \texttt{circulate\_vertex\_ccw} takes three arguments. The \texttt{Manifold}, \texttt{m}, and the vertex, \texttt{v}, around which we circulate, and, finally, a function that accepts a \texttt{VertexID}. This function gets called for every vertex adjacent to \texttt{v}. In this example, the function is given as a so called \textit{lambda} function. This allows us to write things compactly and to have the body of the function where it is needed. We could also have passed a function which accepts a \texttt{FaceID} or a \texttt{HalfEdgeID} or a \texttt{Walker}. Thus, we can visit incident faces and edges during circulation if that is what we need, and if we need go get some entity other than adjacent vertices, edges, or faces, we can use the \texttt{Walker} option which is the most generic.
596 jab 388
 
635 janba 389
To sum up, there are two datatypes that we use to refer to mesh entitites.
596 jab 390
\begin{itemize}
391
\item IDs \texttt{VertexID}, \texttt{HalfEdgeID}, and \texttt{FaceID} are simply indices. These types are what we use when calling functions that take arguments which refer to mesh entities. 
392
\item \texttt{Walker} is used to walk from halfedge to halfedge on the mesh. It utilizes the references stored in halfedges to other halfedges in order to facilitate this traversal. Again, we can obtain an ID from a walker.
393
\end{itemize}
635 janba 394
It might seem tiresome that you have to deal with two different methods for referring to mesh entities, but they do very different jobs. The IDs are simply indices (wrapped in a class) referring to mesh elements. The walker contains functions that allow us to move from halfedge to halfedge and additionally keeps track of the starting point and number of steps taken. In fact there are also three iterator classes, but we do not mention them, because the user does not need them; they are only a tool which allows for loops that visit all faces, edges, or vertices.
596 jab 395
 
396
\subsection{Attributes}
397
Given a \texttt{VertexID},  \texttt{v}, and a \texttt{Manifold}, \texttt{m}, we can obtain the geometric position of the vertex with the method call \texttt{m.pos(v)}. If is fairly important to note that a reference to the position is returned. Thus, we can assign the position of a vertex:
405 jab 398
\begin{verbatim}
596 jab 399
Vec3d p;
400
VertexID v;
401
// ...
402
m.pos(v) = p;
405 jab 403
\end{verbatim}
404
 
596 jab 405
Geometric position is in fact the only attribute that is stored for a vertex. That might seem strange since we would very often like to associate any number of attributes with mesh entities. For instance, we might need to associate normals, colors, curvature tensors, counters, etc. with vertices, faces, or even edges.
405 jab 406
 
596 jab 407
Unfortunately, what precise attributes we need depends greatly on the precise application. To resolve this issue, we have introduces three attribute vector class templates which allow the user to create his own attribute vectors:
405 jab 408
\begin{verbatim}
596 jab 409
VertexAttributeVector<T> vertex_attrib_vector; 
410
FaceAttributeVector<T> face_ttrib_vector;
411
HalfEdgeAttributeVector<T> halfedge_attrib_vector;
405 jab 412
\end{verbatim}
596 jab 413
where \texttt{T} is a typename. Attribute vectors are indexed with indices. Thus, a
635 janba 414
\texttt{VertexAttributeVector} is indexed with a \texttt{VertexID} and likewise for the other types. 
405 jab 415
\begin{verbatim}
635 janba 416
VertexAttributeVector<Vec3d> my_attrib;
417
VertexID v; 
418
// assign some vertex ID to v
419
my_attrib[v] = Vec3d(1,2,3);
420
\end{verbatim}
421
To give a simple example of how this is used consider smoothing a mesh. The simplest way of smoothing is to replace the vertex with the average of its neighbors. However, if we copy the average value back before the average value for some neighbor has been computed, then we clearly use one average to compute another average and thereby introduce an unfortunate dependence on the ordering of the vertices. Consequently, we need to first compute all of the averages and then update the original vertices. What we do is to copy \textit{all} vertex positions to a new attribute vector. Then we compute a new position for each vertex storing it in the new attribute vector. Finally, we copy the positions back. Some complexity is due to the treatment of boundaries. Boundary vertices are not smoothed in this example. However, since we have copied the old vertex positions to the new attribute vector this means that boundary vertices are simply left where they are. The code looks as follows:
422
\begin{verbatim}    
423
void laplacian_smooth_example(Manifold& m)
424
{
425
    VertexAttributeVector<Vec3d> new_pos = 
426
        m.positions_attribute_vector();
427
    for(VertexID v : m.vertices())
428
        if(!boundary(m, v))
596 jab 429
        {
635 janba 430
            Vec3d L(0);
431
            int n = circulate_vertex_ccw(m,v,
432
                [&](VertexID v){
433
                    L += m.pos(v);
434
            });
435
            new_pos[v] = L/n;
596 jab 436
        }
635 janba 437
   m.positions_attribute_vector() = new_pos;
438
}
405 jab 439
\end{verbatim}
635 janba 440
What if we were to write to a position in the attribute vector which did not contain a value? For instance, what happens if we add vertices to the mesh, somehow, and then assign attribute values to the added vertices. One would hope that the attribute vector is resized automatically, and that is the case, fortunately. Thus, we never explicitly need to increase the size of an attribute vector. What if there are suddenly fewer vertices? In that case, we can clean up the attribute vector. However, we also need to clean up the manifold. The procedure looks as follows:
596 jab 441
\begin{verbatim}
442
VertexAttributeVector<T> vertex_attrib_vector; 
443
Manifold m;
444
// ....
405 jab 445
 
596 jab 446
IDRemap remap;
447
m.cleanup(remap);
448
vertex_attrib_vector.cleanup(remap);
405 jab 449
\end{verbatim}
596 jab 450
Calling \texttt{cleanup} on the \texttt{Manifold} removes unused mesh entities, resizes, and resize the vectors containing these entities. When we subsequently call cleanup on the attribute vector, the same reorganization is carried out on the attribute vector keeping it in sync. Strictly speaking cleanup is rarely needed, but it removes unused memory which can be a performance advantage.
405 jab 451
 
465 jab 452
\subsection{Extended Example: Edge Flipping}
635 janba 453
The following example demonstrates how to create a \texttt{Manifold} and add polygons (in this case triangles) and finally how to flip edges of a manifold. First, let us define some vertices. This is just a vector of 3D points:
465 jab 454
\begin{verbatim}
596 jab 455
  vector<Vec3f> vertices(3);
456
  vertices[0] = p1;
457
  vertices[1] = p2;
458
  vertices[2] = p3;
465 jab 459
\end{verbatim}
460
and then a vector of faces. The faces vector contains the number of vertices of each face in the mesh we want tor produce. Initially, we want to make a mesh with just one single triangle, so we produce a vector of one element and set that element to 3.
461
\begin{verbatim}
462
vector<int> faces(1);
463
faces[0] = 3;
464
\end{verbatim}
465
Next, we need the index vector. This vector is a long list of indices to vertices. For each face, we store the indices to its vertices in this vector. Since we just have a triangle, we store three vertices in the vector.
466
\begin{verbatim}
467
vector<int> indices(3);
468
indices[0]=0;
469
indices[1]=1;
470
indices[2]=2;
471
\end{verbatim}
596 jab 472
So, if we had had two triangles, we would have stored six indices. Finally, we call \texttt{build} with the indexed face set data, we have compiled. 
465 jab 473
\begin{verbatim}
596 jab 474
m.build(3, reinterpret_cast<float*>(&vertices[0]),1,
475
   &faces[0], &indices[0]);
465 jab 476
\end{verbatim}
596 jab 477
The result of the above is a mesh with a single triangle.
465 jab 478
Next, we try to split an edge. We grab the first halfedge and split it: Now we have two triangles. Splitting the halfedge changes the containing triangle to a quadrilateral, and we call triangulate to divide it into two triangls again.
479
\begin{verbatim}
596 jab 480
HalfEdgeIDIterator h = m.halfedges_begin();
481
m.split_edge(*h); 
482
triangulate_face_by_edge_split(m, m.walker(*h).face());
465 jab 483
\end{verbatim}
484
Now, we obtain an iterator to the first of our (two) triangles.
485
\begin{verbatim}
596 jab 486
FaceIDIterator f1 =m.faces_begin();
465 jab 487
\end{verbatim}
488
We create a vertex, \texttt{v}, at centre of \texttt{f1} and insert it in that face:
489
\begin{verbatim}
596 jab 490
m.split_face_by_vertex(*f1);
465 jab 491
\end{verbatim}
492
The code below, marks one of a pair of halfedges (with the value 1).
493
\begin{verbatim}
596 jab 494
HalfEdgeAttributeVector<int> touched;
495
 
496
// ....
497
 
498
for(HalfEdgeIDIterator h = m.halfedges_begin(); 
499
   h!=m.halfedges_end(); ++h)
500
    {
501
        if(m.walker(*h).opp().halfedge() < *h)
502
            touched[*h] =0;
503
        else
504
            touched[*h] =1;
505
    }
465 jab 506
\end{verbatim}
507
Next, we set the \texttt{flipper} variable to point to the first of these halfedges:
508
\begin{verbatim}
596 jab 509
flipper = m.halfedges_begin();
465 jab 510
\end{verbatim}
511
The long piece of code below examines a halfedge pointed to by \texttt{flipper}, and if it is not a boundary halfedge it tries to flip it. Then it increments the \texttt{flipper} variable until it lands on a halfedge marked with 1. If \texttt{flipper} reaches the end of the list of halfedges, we start over.
512
\begin{verbatim}
596 jab 513
  if(!boundary(m, *flipper)) 
514
      if(precond_flip_edge(m,*flipper))
515
                m.flip_edge(*flipper);
516
  do
517
    {
518
      ++flipper;
519
      if(flipper==m.halfedges_end())
520
        {
521
          flipper = m.halfedges_begin();
522
          break;
523
        }
524
    }
525
  while(touched[*flipper] == 0);
465 jab 526
\end{verbatim}
596 jab 527
This example may not serve much of a purpose but illustrates how we can iterate over all edges and flip them. From this example, we are fairly close to Delaunay triangulation.
465 jab 528
 
596 jab 529
\subsection{HMesh tools}
465 jab 530
 
596 jab 531
The HMesh directory contains not only the basic data structure and functionality for traversing a mesh. There are also tools for mesh optimization through energy minimization, several algorithms for mesh smoothing, a number of tools for cleaning meshes as well as tools for simplifying meshes.
465 jab 532
 
533
\section{GLGraphics}
534
 
596 jab 535
\texttt{GLGraphics} contains a set of tools needed for visualization of geometrical objects. In particular, this namespace contains mesh rendering facilities, and in the following, a very simple example is given. This section is basically a walk through of the simplest GEL program that draws a mesh. Apart from GEL, we also use OpenGL and that requires a toolkit for connecting with the window system. With GEL programs, one generally uses GLUT, and this example is not an exception.
465 jab 536
 
596 jab 537
For starters, we need to include some files mostly from \texttt{GLGraphics} but also the header file for the mesh load function of \texttt{HMesh} and the \texttt{GLEW} header. Why incude \texttt{glew.h} rather than just \texttt{gl.h}? Well, \texttt{HMesh/draw.h} contains some draw functions which rely on shaders, and since \texttt{gl.h} is normally not up to date, it makes sense to use \texttt{glew.h} instead of \texttt{gl.h} even though it inflicts a dependency. We include \texttt{GLGraphics/gel\_glut.h} rather than the normal \texttt{glut.h}. That is because the GEL version works the same on Windows, OSX, Linux and probably other platforms.
465 jab 538
 
539
We also open the namespaces we will need and declare two globals: The view controller \texttt{view\_ctrl} and the mesh \texttt{mani}. The view controller class is rather complex. It more or less insulates you from having to deal directly with the projections and transformations of OpenGL: It sets up a perspective projection and also the modelview transformation needed to view the object. From a user interface perspective, it defines a virtual trackball which allows you to rotate the object.
540
\begin{verbatim}
541
#include <GL/glew.h>
542
#include <GLGraphics/gel_glut.h>
543
#include <GLGraphics/draw.h>
544
#include <GLGraphics/GLViewController.h>
545
#include <HMesh/load.h>
546
 
547
using namespace std;
548
using namespace HMesh;
549
using namespace CGLA;
550
using namespace GLGraphics;
551
 
552
GLViewController* view_ctrl;
553
Manifold mani;
554
\end{verbatim}
555
 
556
Below is the display function which is called from the GLUT event loop whenever an event that requires redrawing is received. All drawing takes place inside this function. In this case, it is simple since all we need to do is clear the screen (and depth buffer), set up a new modelview transformation with the view controller and then call the draw function followed by a swap of buffers.
557
 
558
The draw function sends the polygons to the graphics card. It is very inefficient and uses the fixed function pipeline. At a minimum one should draw the polygons to a display list, but for a simple example, this works. The buffer swap is because we use double buffering; in other words, we draw to the back buffer.
559
\begin{verbatim}
560
void display() {
561
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
562
    view_ctrl->set_gl_modelview();
563
    draw(mani);
564
    glutSwapBuffers();
565
}
566
 
567
\end{verbatim}
568
The mouse callback below is called when a mouse event has occurred. This is where user input  for the virtual trackball is registered. We check whether a mouse is pressed or released. If it is pressed, we detect which button and then ``grab'' the virtual trackball in order to rotate, zoom, or pan depending on which button is pressed. If the button is released, we inform the view controller of this.
569
\begin{verbatim}
570
void mouse(int button, int state, int x, int y)  {
571
    Vec2i pos(x,y);
572
    if (state==GLUT_DOWN) 
573
    {
574
        if (button==GLUT_LEFT_BUTTON) 
575
            view_ctrl->grab_ball(ROTATE_ACTION,pos);
576
        else if (button==GLUT_MIDDLE_BUTTON) 
577
            view_ctrl->grab_ball(ZOOM_ACTION,pos);
578
        else if (button==GLUT_RIGHT_BUTTON) 
579
            view_ctrl->grab_ball(PAN_ACTION,pos);
580
    }
581
    else if (state==GLUT_UP)
582
        view_ctrl->release_ball();
583
}
584
\end{verbatim}
585
If the mouse moves with a button depressed, we register motion in the function below. The new mouse position is sent to the view controller
586
which then, e.g., rotates the trackball accordingly. Note that this function ends by posting a redisplay event, i.e. informs GLUT that display should be called at the earliest convenience.
587
\begin{verbatim}
588
void motion(int x, int y) {
589
    Vec2i pos(x,y);
590
    view_ctrl->roll_ball(Vec2i(x,y));
591
    glutPostRedisplay();
592
}
593
\end{verbatim}
594
 
595
Finally, in the main function, we first load the mesh and then setup glut. This mostly involves defining the callback function just described. We set up the view controller passing it window dimensions and the size and position of the bounding sphere of the object just loaded. Finally, we do some minimal OpenGL set up: Essentially clearing the depth buffer and enabling lights. Finally, we pass control to the GLUT event loop.
596
\begin{verbatim}
597
int main(int argc, char** argv) {
598
    string file = "bunny-little.x3d";
599
    load(file, mani);
600
 
601
    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
602
    glutInitWindowSize(800, 800);
603
    glutInit(&argc, argv);
604
    glutCreateWindow("GEL Example Program");
605
    glutDisplayFunc(display);
606
    glutMouseFunc(mouse);
607
    glutMotionFunc(motion);
608
 
609
    Vec3f bsphere_center(0,0,0);   
610
    float bsphere_radius = 3;
611
    mani.get_bsphere(bsphere_center,bsphere_radius);
612
    view_ctrl = new GLViewController(800,800, 
613
        bsphere_center,bsphere_radius*2);
614
 
615
    glClearColor(0.0f, 0.0f, .5f, 0.f);
616
    glEnable(GL_DEPTH_TEST);
617
    glEnable(GL_LIGHTING);
618
    glEnable(GL_LIGHT0);
619
 
620
    glutMainLoop();
621
}
622
\end{verbatim}
623
Note that the mesh can be either an X3D, OBJ, PLY, or OFF files. However, only the geometry is loaded not the textures. In the case of OBJ files, we also convert all polygons to triangles, because the TriMesh loader (see the geometry class) is in fact used.
624
 
625
Apart from the drawing functions and the viewcontroller, GLGraphics also contains  other useful pieces: A few functions which greatly simplify shader loading and SOIL. SOIL is a small library for loading images. It is designed for OpenGL and makes it easy to e.g. save screen shots or load an image for use as a texture. While the need for image loading is fairly obvious, it might be more difficult to see the need for shader loading functions. However, it \textit{is} a little tricky to make shader programs in C++ using GLSL but the problems are almost all silly little things. For instance, how do you robustly read from a text file? How do you compile a shader and check for errors? In OpenGL What is the difference between a GLSL program and a shader anyway?
626
 
627
The short answer to the last question is this: A "shader" can be either a vertex shader, a geometry shader (in OpenGL 2.0) or a fragment shader. A "program" is a linked combination of these three types of shaders. Note that you don't have to have a geometry shader.
628
 
629
These functions attempt to obviate the need for an answer to the first two questions by providing an API for loading and compiling shaders and checking for errors. However, I don't include functions for creating the program, attaching shaders and linking. Why not? Because the need for flexibility means that the API would be just as complex as just using the OpenGL functions directly! However, loading shaders and checking for errors in compiled shaders is different. It makes sense to wrap that. It also makes sense to wrap the error checking for programs that are linked, so there is a function for that too.
630
 
631
Since shader loading and error check sandwhich the two calls needed for compilation, the most important function in this API, \texttt{create\_glsl\_shader}, loads a shader, compiles it, checks for errors and returns the shader handle. There is also a version which creates a shader from a string.
632
 
596 jab 633
There is some code below to illustrate usage.  
465 jab 634
\begin{verbatim}
635
GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, 
636
  shader_path, "tri.vert");
637
GLuint gs = create_glsl_shader(GL_GEOMETRY_SHADER_EXT, 
638
  shader_path, "tri.geom");
639
GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, 
640
  shader_path, "tri.frag");
641
 
642
prog_P0 = glCreateProgram();
643
 
644
if(vs) glAttachShader(prog_P0, vs);
645
if(gs) glAttachShader(prog_P0, gs);
646
if(fs) glAttachShader(prog_P0, fs);
647
 
648
// Specify input and output for the geometry shader.
649
// Note that this must be done before linking the program.
650
glProgramParameteriEXT(prog_P0,GL_GEOMETRY_INPUT_TYPE_EXT,
651
  GL_TRIANGLES);
652
glProgramParameteriEXT(prog_P0,GL_GEOMETRY_VERTICES_OUT_EXT,3);
653
glProgramParameteriEXT(prog_P0,GL_GEOMETRY_OUTPUT_TYPE_EXT,
654
  GL_TRIANGLE_STRIP);
655
 
656
// Link the program object and print out the info log
657
glLinkProgram(prog_P0);
658
print_glsl_program_log(prog_P0);
659
 
660
// Install program object as part of current state
661
glUseProgram(prog_P0);
662
 
663
// Set the value of a uniform
664
glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), 
665
  win_size_x/2.0, win_size_y/2.0);
666
\end{verbatim}
667
 
668
\section{LinAlg}
669
Sometimes the simple 2,3,4 dimensional vectors from CGLA just don't cut it. We often need to solve large linear systems. The LinAlg namespace contains some vector and matrix classes and an interface to Lapack. This provides fairly easy way to do many numerical computations.
670
 
671
In the example below, we  find coefficients for $a x^2 + b y^2 +cxy + dx + ey + f$ such that the surface contains six specific points. The coefficients are found by solving the linear system $\mathbf A \mathbf x = \mathbf b$ where the rows of the $\mathbf A$ matrix contains $x^2 \; y^2 \; xy \; x \; y \; 1$ computed from the $xy$ positions of each point, $\mathbf x$ contains the unknown coefficients, and $\mathbf b$ on the right hand side contains the $z$ values of the six points. Using LinAlg, we implement it as follows: 
672
\begin{verbatim}
673
    CMatrix A(6,6);
674
    CVector b(6);
675
 
676
    for(int i=0;i<6;++i)
677
    {
678
        A.set(i,0,pts[i][0]*pts[i][0]);
679
        A.set(i,1,pts[i][1]*pts[i][1]);
680
        A.set(i,2,pts[i][0]*pts[i][1]);
681
        A.set(i,3,pts[i][0]);
682
        A.set(i,4,pts[i][1]);
683
        A.set(i,5,1);
684
        b[i] = pts[i][2];
685
    }
686
    CVector x;
687
    LinearSolve(A,b,x);
688
\end{verbatim}
689
While this example shows only the function for solving a system which should have a solution, there are also functions for solving overdetermined systems in the least square sense and finding the minimum norm solution to underdetermined systems using singular value decomposition. There is also a function for finding eigenvalues and eigenvectors of symmetric matrices and more.
690
\section{Geometry}
691
The Geometry namespace contains many different classes and functions. Roughly, we can divide the contents into
692
\begin{itemize}
693
\item Spatial data structures such as kd tress, bounding box hierarchies, and BSP trees.
694
\item A Triangle mesh data structure called TriMesh. TriMesh is different from HMesh in that it only contains triangles. It is much more an API for real time rendering which also facilitates material properties and not just geometry.
695
\item Classes and functions for dealing with volume data. HGrid and RGrid are, respectively, a class for hierarchically stored voxel grids (sparse grids) and regular grids. There is a number of functions for traversing voxel grids systematically and along rays.
696
\item Surprisingly, you will also find my C++ port of Jules Bloomenthals isosurface polygonizer and an implementation of Luiz Velho's parametric surface tiler in this namespace.
697
\end{itemize}
698
One of the most frequently used tools in Geometry is the kD tree class which merits an example. In the code below, we create a kD tree which had \texttt{Vec3f}s as keys and integers as data. Note that since the kD tree is a template, we could use any other type as both key and data, however, only CGLA vectors have been tested as key types, but there are no restrictions on data types.
699
\begin{verbatim}
700
    KDTree<Vec3f,int> tree;
701
    for(int i=0;i<N;++i)
702
        {
703
            Vec3f p0;
704
            make_ran_point(p0);
705
            tree.insert(p0, i);
706
        }
707
    tree.build();
708
\end{verbatim}
709
Note also, that before we use the tree it needs to be built. This is because the internal representation is a balanced binary heap which it is easier to build at the end rather than maintain during insertion of new points. To look for the points near a given point, we can call
710
\begin{verbatim}
711
    Vec3f p0;
712
    // ...
713
    std::vector<Vec3f> keys;
714
    std::vector<int> vals;
715
    float radius = 1.95f;
716
    int N = tree.in_sphere(p0, radius , keys, vals);
717
\end{verbatim}
718
This will find all points in a radius of 1.95 units from \texttt{p0}. The keys and values are stored in \texttt{keys} and \texttt{vals} when the functions returns. The return value of the function is the number of points found within the radius. 
719
 
720
Sometimes, we simply want the point closest to a given point \texttt{p0} which is done using \texttt{tree.closest\_point(p0, d, pos, x)} where the two first arguments indicate the point and the maximum search radius. The two last arguments are set to the key and data of the point found to be closest to \texttt{p0}. The function returns true if a closest point was found.
721
 
722
 
723
 
724
 
725
\section{Util}
726
The Util namespace contains a rather mixed bag of utilities many of which are quite useful and very diverse. 
727
\begin{trivlist}
728
\item The XML parser for instance is written from scratch and the basis for our X3D loader although it will load any XML file. 
729
\item \texttt{Grid2D} is often useful when we want to deal with e.g. simulation on a 2D grid. 
730
\item The \texttt{Timer} class is nearly indispensable when we need to time something, and it is very easy to use. 
731
\item \texttt{ArgExtracter} is a class for getting the command line arguments to a program. 
732
\item There is more - for instance a resource manager template, some string utility templates and a hash table implementation.
733
\end{trivlist}
734
Arguably, it would be more pretty if these pieces had been more thematically linked, but many are used a lot, and it seemed reasonable to have somewhere to stick various functions and classes that did not naturally belong elsewhere.
735
 
736
 
596 jab 737
\section{Authors}  
738
\begin{trivlist}
739
\item Andreas B{\ae}rentzen created the library and has written most of the code not contributed by the people below.
740
\item Jeppe Revall Frisvad has contributed greatly to the CGLA part of GEL and elsewhere.
741
\item Christian Thode Larsen rewrote the classes in HMesh. They are much nicer for it.
742
\item Anders Wang Kristensen has been a great help in the process of reworking HMesh and also contributed some code for an OpenGL console.
743
\item Henrik Aan{\ae}s provided the original LinAlg package, which is a set of simple but very useful Lapack bindings.
744
\item Rasmus Paulsen, Bjarke Jakobsen, Marek Misztal helped with structure and compilation on various platforms with testing and ideas.
745
\end{trivlist}
405 jab 746
 
596 jab 747
\section{License}  
748
\begin{trivlist}
749
\item
750
You are allowed to use GEL for academic or commercial purposes. In particular, you are welcome to give GEL to students as a basis for academic work or to use it in your own applications.
751
\item
752
Regarding the use of GEL in other libraries. GEL does exist in slightly different versions, since we have created pared down packages for various courses. We would like to retain the prerogative of repackaging. If you would like to use GEL in its entirety in another library  that is fine, but we do not allow you not to take bits and pieces and put them into a different library.
753
\item
754
If you use GEL, we would be grateful for due credit.
755
\item
756
Finally, we follow the MIT license as regards warranty:
757
\item
758
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
759
\item
760
If anything is unclear, please send an email to jab@imm.dtu.dk. 
761
\end{trivlist}
762
\section{Open Source Code used in GEL}  
405 jab 763
 
596 jab 764
Source code from other projects have been incorporated in GEL.
765
\begin{trivlist}
766
\item From Graphics Gems, two functions for inverting matrices and Jules Bloomenthal's polygonizer which I reworked from C to C++. This is allowed according to the license.
767
\item rply by Diego Nehab, Princeton University, and the Simple OpenGL Image Loader by Jonathan Dummer.  These are MIT licensed and our use is congruent with that license.
768
\item The OpenGL Extension Wrangler Library is also included and appears to have a license identical to the MIT license.	 As mentioned, our use is congruent with that license.
769
\end{trivlist}
770
The incorporated code amounts to only a small fraction of the GEL source code.
405 jab 771
\end{document}