zumbs.files. · pdf fileintroduction to computer graphics: visualization of parametric...

138
Introduction to Computer Graphics: Visualization of Parametric Surfaces 010582 Dirk Hasselbalch 250963 Michael Neidhardt 300679 Morten Poulsen October 12, 2006

Upload: dominh

Post on 29-Mar-2018

215 views

Category:

Documents


2 download

TRANSCRIPT

Introduction to Computer Graphics:

Visualization of Parametric Surfaces

010582 Dirk Hasselbalch 250963 Michael Neidhardt 300679 Morten Poulsen

October 12, 2006

Introduction to Computer Graphics:

Visualization of Parametric Surfaces

010582 Dirk Hasselbalch 250963 Michael Neidhardt 300679 Morten Poulsen

October 12, 2006

Abstract

Computer graphics is widely used, and seems to grow in importance. The presentreport attempts to analyse the central aspects of 3D visualisation, to find good designsolutions and to create code that might possibly be of use to us later, but as such itcontains nothing new. The main areas of interest have been scan conversion of triangles,how to handle surfaces in 3D, the projection of 3D objects onto 2D planes and how to applylight and shading to objects. We have been able to create all the required visualisations:The general parametric surface and the 2 objects defined by Bezier patches. We thinkthat illumination and shading has been done with a certain success, at least based onvisual inspection. There are minor errors in the final images that we would have preferredto remove, but time has not allowed us to do that.

Contents

Introduction iii

1 Analysis 11.1 Polygons and triangles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Filling polygons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Curves and surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.4 Projection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.5 Illumination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231.6 Shading and Coloring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261.7 Visible surface determination . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

i

CONTENTS ii

2 Design 312.1 Doing the projection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.2 Design of illumination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322.3 Visible surface determination . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.4 Polygons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.5 Surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3 Implementation 383.1 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.2 The pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4 Test and Visualizations 404.1 Building the test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404.2 Results of the test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

5 Conclusion 48

A Test Runs 49A.1 Output from testMath.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

B Source files 50B.1 graphic tools.hpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50B.2 graphic tools.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55B.3 graphic world.hpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68B.4 graphic world.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73B.5 graphic draw.hpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97B.6 graphic draw.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99B.7 readdata.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110B.8 showObligatory.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114B.9 testPolygons.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117B.10 testZbuffer.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120B.11 testPolyDrawing.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122B.12 testMath.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

Bibliography 134

Introduction

This report details our solution to the assignment in the course ”Introduktion til grafik”, atDepartment of Computer Science, Copenhagen University. The task in [Hen06] is to analyse,construct, present and implement a 3D visualisation system in C++. This is reflected in thereport, in that we have analysed the particular topics in detail and chosen an appropriatesolution in each case. We describe design considerations and an actual implementation. Thefield of computer graphics is vast, so this is by no means an exhaustive analysis, but we havetried to include as much as we could find the time for. We assume the reader knows nothingabout 3D visualisation, but is familiar with programming, linear algebra and geometry. Itis our intention that the analysis and design parts should in themselves be enough to givethe reader an understanding of the problems and solutions we have encountered. Most of thetheory is well documented in [FvDFH97].

iii

1 Analysis

1.1 Polygons and triangles

A polygon, in the general case, is a series of points and edges, where the edges interconnectthe points and thereby enclose some region. A polygon can be convex or concave. A convexpolygon is a polygon, where lines between all pairs of points are all inside the polygon. Aconcave polygon is a polygon where at least one line between a pair of points is outside thepolygon.

Figure 1.1: Left: A concave polygon. Middle: A convex polygon. Right: The convex polygondivided into triangles.

All polygons can be converted into a number of triangles. In the case where the polygonis convex this is a trivial task. In the field of computer graphics this means that the termpolygon is often synonymous with triangle. From this point forward we will also considerthe two terms equal since the polygons in this project are so simple that they in fact aretriangles. We could have chosen not to do this, but that would make our polygon fillingalgorithm more complex since we would have to take the number of edges into account alongwith the possibility of concave polygons.

1.1.1 Types of edges and polygons

Polygons can be divided into different types depending on their edges. We will define thefollowing types of edges:

Top edges are horizontal edges, where the inside of the polygon is below the edge.

Bottom edges are horizontal edges, where the inside of the polygon is above the edge.

Left edges are edges, that are neither top nor bottom edges, and where the inside of thepolygon is to the right of the edge.

1

CHAPTER 1. ANALYSIS 2

Right edges are edges, that are neither top nor bottom edges, and where the inside of thepolygon is to the left of the edge.

With this handy, we will define the following types of polygons:

Bottom edge polygon is a polygon with one bottom edge.

Top edge polygon is a polygon with one top edge.

Left edge dominated polygon is a polygon with two left edges and one right edge.

Right edge dominated polygon is a polygon with two right edges and one left edge.

Note that these types are mutually exclusive when we limit our polygons to have non-paralleledges.

1.1.2 Inside or outside

Since polygons are now all considered triangles, all polygons are convex. Thus the distinctionbetween inside and outside becomes easy: The inside of a polygon is a point where anotherpoint, traveling around the perimeter of the polygon, wraps around the point in questionexactly one time.

What if the point in question is on an edge? In that case we will have to make a consistentdecision, since eventually we will have to define whether a point is inside or outside a polygonin order to color the corresponding pixel on the screen accordingly. Using the definitions ofsection 1.1.1 we define the following:

• Points located exactly on a left or bottom edge of a polygon is considered to be insidethe polygon.

• Points located exactly on a right or top edge of a polygon is considered to be outsidethe polygon.

• When a clash of the two definitions above occur, for instance a point located exactlyon the intersection between a top edge and a left edge, the point is considered to beoutside the polygon.

1.2 Filling polygons

Filling polygons is the process of coloring the pixels that are inside a polygon. The mainchallenge is to design an efficient and simple algorithm that covers the most general case.Efficient in this case means the use of integer operations only since floating point operationsare too expensive, and not really necessary.

When working with points and lines in a two dimensional coordinate system, it seemsinevitable not to use discrete numbers such as integers. We realize, however, that we do notnecessarily need a real point field such as R2 to model these things, but can do just fine witha rational point field such as Q2. Since any rational number consists of an integral numeratorand an integral denominator we might have a way to avoid floating point arithmetics!

CHAPTER 1. ANALYSIS 3

x

y0

05 10 15

5

10

20

Figure 1.2: Points which are inside the polygons as per the definitions in section 1.1.2 arecolored.

1.2.1 The Scan Line Algorithm

We will use the following scheme to fill polygons:

1. We make a horizontal scan-line traverse the polygon from bottom to top.

2. At each step we will determine where the scan-line intersects the left and right edge ofthe polygon.

3. We will then color the points between the right and left intersection along the scan-lineaccording to some shading model, which we will describe in detail in section 1.6.

This is basically the scheme as presented in [FvDFH97, pp. 92 ff], except that in our casepolygons are all triangles as mentioned earlier.

1.2.1.1 Finding edge points

When calculating intersections between the scan-line and the left and right edges of ourpolygon, we wish to exploit the fact that the intersection points are near the intersectionpoints of the scan-line immediately below. By keeping track of x’s, y’s and the numeratorand denominator of the slopes’ coefficients of the left and right edges of our polygon this ispossible.

Keeping this in mind, the idea is to find the points on or to the immediate right of anedge. We will pinpoint one point per edge for each y-value. Thus, if the line’s slope is lessthan one and greater than minus one, there will be gaps in the line. This does not concern us,however, since the identified points are solely used as end points in drawing purely horizontallines between left and right edges.

CHAPTER 1. ANALYSIS 4

A

B

C

LR

x

y0

05 10 15

5

10

s

Figure 1.3: Finding edge points. Crosses are points on or to the immediate right of thepolygon’s left edge. Circles are points on or to the immediate right of the polygon’s right edges.The grey discs is the result when we color pixels between crosses and circles and include thecrosses but omit the circles.

Figure 1.3 shows the idea: The crosses are points on or to the immediate right of edge ACand the circles are points on or to the immediate right of edges AB and BC. The currentscan line s is at y = 4. When drawing horizontal lines from left to right, we include the leftpoint but exclude the right point. If the two points are the same we do not include it.

This is consistent with our choices of when points are considered inside or outside apolygon, cf. section 1.1.2.

Generally, we define the beginning point A of an edge to be the point with the lowesty-value. Thus, we define the beginning point A = (xbegin, ybegin) and the end point B =(xend, yend), where ybegin < yend. Both points are presumed to have integral x and y values.For now, we consider the case where also xbegin < xend. The edge AB in figure 1.3 satisfythese conditions and can be used as a case study.

The slope of the edge is m = (yend−ybegin)/(xend−xbegin) > 0. We start by pinpointing thepoint (x0, y0) = (xbegin, ybegin), which in figure 1.3 corresponds to point A = (3, 2). In order tofind the next point, we first increment our y-value by one: y1 = ybegin +1. The correspondingx-value following the edge is x′1 = xbegin + 1/m. Generally, for all n, x′n = x′n−1 + 1/m, wherex′n is the x-coordinate of the intersection between the edge and the scan-line at position yn.It is clear that the x′ns are not necessarily integers.

The xn we need to find, equals x′n rounded up to the nearest integer. When following theright edge AB in figure 1.3, for example, we have x′2 = 101

3 (which is the intersection betweenthe depicted scan-line at y2 = 4 and the edge AB), while x2 = 11 (which is the circle to theright of the line).

If the slope of the edge is steep such that 1/m < 1, yn might be incremented two or moretimes without xn changing value. If 1/m > 1 we will need to increment xn several times

CHAPTER 1. ANALYSIS 5

without yn changing value. So when yn gets incremented, xn can be incremented basicallyany number of times. How do we know when to increment xn?

The answer is that we increment xn the moment the fractional part of x′n overruns. Atthe same time, we subtract one from the fraction.

The fraction we are adding to x′n at each step can be split into a numerator n and adenominator d:

n/d = 1/m ⇒ n = xend − xbegin, d = yend − ybegin. (1.1)

The numerator of x′n’s fractional part can be used to check whether the fractional partexceeds one by comparing it to the fraction’s denominator. We name this the incrementor iand initialize it with the value of d. At all times x′n = x′n,int + x′n,frac = x′n,int + i/d. I.e., ifi/d > 1 which is the same as asking if i > d, then we will need to increment xn and subtractd from i. We repeat these steps until i is once again less than d. Then we increment yn andstart over.

In the case where the slope is negative, i.e. xbegin > xend, we need to change some things:

1. Since x′n will be less than x′n−1 we will be decrementing xn instead of incrementing it.

2. The fractional part signified by the variable i will for the same reason get smaller witheach iteration (since n < 0). We will therefore not be checking for overruns, but forunderruns. Therefore the check on i will consist of checking whether it is less than orequal to zero.

3. After i has underrun, we add d to i until i is once again greater than 0.

All this sums up to the following algorithm:

1: /∗ Initializing variables ∗/2: x← xbegin3: n← xend − xbegin4: δx← sign(n) /∗ δx determines if we increment or decrement x and i. ∗/5: d← yend − ybegin6: i← d7: /∗ Scan line traversing ∗/8: for y ← ybegin, y ≤ yend, y ← y + 1 do9: Mark (x, y) as edge point

10: i← i+ n11: while i > d ∨ i ≤ 0 do12: x← x+ δx13: i← i− δx× d14: end while15: end for

1.2.1.2 Right and left edges

One scan line intersects both a left and a right edge of a polygon as it is seen in figure 1.3.Merging two edge point algorithms as the one just outlined into a single algorithm simplyrequires that all variables except y (which will be the same for the whole line) be duplicated.

CHAPTER 1. ANALYSIS 6

So instead of keeping track of only xn, n, d, and i, we keep track of xn,right and xn,left, nrightand nleft, dright and dleft, and iright and ileft.

1.2.1.3 Changing edges

When scanning the polygon from bottom to the top we notice that the polygon usually haseither two left edges or two right edges. This means that somewhere along the way we willneed to change edges. For instance, in figure 1.3 when the scan line reaches y = 5 we need tomake sure that the edge BC is followed at the right side the rest of the way.

One way to do this is to make the scan line traverse the polygon in two phases. In thefirst phase, we make the scan line run from the bottom point to the middle point (from A toB in figure 1.3). In the second phase we let it run from there to the top point (from B to Cin the figure). Before we begin, we determine whether it is the right or the left edge whichends at the middle point. If the right edge ends there, we know that the variables associatedwith the right edge need to be changed between the phases. If the left edge ends there wechange the variables associated with the left edge.

The variables we need to update are those we use to determine the next edge point fromthe current edge point. In figure 1.3 for instance, we start with x0,right = xbegin = 3 and whenthe first phase is done, x5,right = 14. When we continue with phase two, we do not need anew x5,right – it is still 14. We only need to know how to get from x5,right to x6,right and so onfollowing the new edge BC. Thus the variables we need to update are nright, dright and irightbut not xn,right.

We determine the new updated values the same way as we initialized them in equation1.1, with i = n, except that now the begin and end coordinates equals the beginning and endpoint of the new edge.

1.2.1.4 Sorting points and edges

It is clear that we need to distinguish correctly between which edges are left edges and whichare right edges. Also, we will need to determine which point is the bottom, middle and toppoint respectively. Beginning with the latter, we need to sort the points by y-value. Wedecide that if two points have the same y-value, we sort them by x-value. This will obviouslyonly become relevant if a polygon has a top or bottom edge. In those cases, the middle pointwill have the same y-value as one of the two other points.

We name the points Pbottom, Pmiddle and Ptop. With these known, the task is to determinewhich edge is the left edge and which is the right – in other words to figure out if the angle fromthe vector from Pbottom to Pmiddle to the vector from Pbottom to Ptop is positive or negative.This can be done by determining the sign of the determinant d = (xmiddle − xbottom)(ytop −ybottom)−(ymiddle−ybottom)(xtop−xbottom). If d < 0 then the angle is positive, and the vectorfrom Pbottom to Pmiddle is left edge. If d > 0 then the angle is negative, and the vector fromPbottom to Ptop is left edge. If d = 0 the two edges coincide.

With the edges sorted out, the last thing to resolve is if the polygon is left edge dominatedor right edge dominated. This is simple: if the top point of the left edge is higher (e.g. ifits y value is greater) than the top point of the right edge, then the polygon is right edgedominated, and we will need to change right edge variables between the phases in the scanline algorithm. Otherwise we can consider the polygon left edge dominated.

CHAPTER 1. ANALYSIS 7

1.2.1.5 Summary

To sum up: drawing a polygon is done like this:

1. Sort points and edges

• Sort points

• Determine left and right edges

• Determine if the polygon is right edge or left edge dominated

2. Phase 1: Scan line left and right edge points simultaneously up to the middle point.

• At each y step interpolate colors or points and normals depending on the shadingmodel according to an interpolation difference function.

• Draw pixels from the left edge point to the right edge point at the given y positionwith a shading scheme. An interpolation differencing function will need to becalculated at each y position.

3. When reaching the middle point, update the variables associated with the left or rightside depending on left edge or right edge domination.

4. Phase 2: Scan line edge points from the middle point to the top point.

For the sake of example, figure 1.4 depicts how figure 1.3 has been colored when the scan linealgorithm is done.

A

B

C

x

y0

05 10 15

5

10 s

Figure 1.4: The result of the scan line algorithm.

CHAPTER 1. ANALYSIS 8

1.3 Curves and surfaces

In most graphics software, some form of primitives are needed for modeling objects. In ourcase these primitives are curves and surfaces. With these we can model all necessary objects.

1.3.1 Curves

Drawing a curve is particularly easy if it goes straight from one point to another. If severalsuch line segments are connected, they form a polyline. This can be modelled by a sequence

P1

P2

P3

P4

Figure 1.5: A polyline

of ordinary functions (e.g. y = ax + b) or by a sequence of pairs of points. There are prob-lems with this approach, however. Firstly, vertical lines cannot be modelled by this type offunction and secondly, the number of points to store can become large. An alternative wayof expressing the line L from P1 to P2 is this:

L(t) = P1 + t(P2 −P1), 0 ≤ t ≤ 1

More explicitly for a line in three dimensions, this is:

L(t) =

x(t) = x1 + t(x2 − x1)y(t) = y1 + t(y2 − y1)z(t) = z1 + t(z2 − z1)

, 0 ≤ t ≤ 1

This is called a parametric curve and it gets around the problem with vertical lines. How-ever, we would still need one such parametric curve per line segment. If we want to draw,say, a sine curve, and impress more than just the most impressionable, we will need a lotof line segments, which could easily complicate things. It is better to use a more powerfulcurve, a parametric cubic curve. This type of curve is defined by 3 cubic polynomials. Cubicsare attractive because they are the lowest degree polynomials that allow us to interpolate 2end points, that each have a specified derivative. Further, they are also the lowest degreepolynomials that are non-planar in 3D. In the following, unless otherwise stated, the parame-ter t is restricted to the interval [0, 1]. Formally, a parametric cubic curve, Q(t), has the form:

Q(t) =

x(t) = axt

3 + bxt2 + cxt+ d

y(t) = ayt3 + byt

2 + cyt+ dz(t) = azt

3 + bzt2 + czt+ d

CHAPTER 1. ANALYSIS 9

We can split this into coefficients and parameters:

Q(t) =

ax bx cx day by cy daz bz cz d

t3

t2

t1

t0

If we call the coefficient matrix C and the parameter matrix T, we get Q(t) = CT. If wealso split C into G and M, we get Q(t) = GMT. G is called the geometry matrix and Mis called the basis matrix. This is a piecewise polynomial curve, which implies that we canjoin curves together. When doing that, it is useful to know the kind of continuity that isobtainable:

• Two curves have G0 geometric continuity in a join point if the end point of the first isidentical to the start point of the second.

• To have G1 geometric continuity, the tangents in the join point must have the samedirection.

• To have C1 continuity, the tangents in the join point must have the same direction andthe same magnitude.

P1 P2 P3

Q1 Q2

P1 P3

P2Q1 Q2

P2

P1 P3

Q2Q1

a)

b)

c)

Figure 1.6: From above: G0, G1 and C1 continuity.

These kinds of continuities are depicted in figure 1.6.Below we describe 2 examples of parametric cubic curves, Hermite and Bezier curves.

CHAPTER 1. ANALYSIS 10

1.3.1.1 Hermite curves

A Hermite curve is described by its start point, its end point and the tangents for the curvein each of these.

P1 P4

R1 R4

Figure 1.7: A Hermite curve.

Reusing the terminology from the general case, the Hermite curve is defined by this ex-pression:

QH(t) = GHMHT = GHMH(t3 t2 t1 t0)T .

We know what the geometry matrix, GH , contains, namely the geometric elements of thecurve:

GH = (P1 P4 R1 R4)

Differentiating QH(t) with respect to t, we get:

Q′H(t) = GHMH(3t2 2t 1 0)T

This gives us tangents in the start and end points, i.e. for t = 0 and t = 1:

R1 = Q′H(0) = GHMH(0 0 1 0)T

R4 = Q′H(1) = GHMH(3 2 1 0)T

We also know the start and end points themselves:

P1 = QH(0) = GHMH(0 0 0 1)T

P4 = QH(1) = GHMH(1 1 1 1)T

Now we have:

(P1 P4 R1 R4) = GH = GHMH

0 1 0 30 1 0 20 1 1 11 1 0 0

CHAPTER 1. ANALYSIS 11

It is clear that MH must be the inverse of the last matrix. Therefore the final expression is:

QH(t) = GH

2 −3 0 1−2 3 0 0

1 −2 1 01 1 0 0

t3

t2

t1

t0

1.3.1.2 Bezier curves.

A Bezier curve is described by a start point, 2 control points and an end point. The vector

P1 P4

P2 P3

Figure 1.8: A Bezier curve.

formed by subtracting P1 from P2 is tangent to the curve in point P1, and P4−P3 is tangentto the curve in point P4. The 4 points make up the Bezier geometry matrix:

GB = (P1 P2 P3 P4)

From this, it is easy to calculate the Hermite curve: Simply form the vector from P1 to P2

and the vector from P3 to P4:

GH =

P1

P4

R1

R4

=

P1

P4

3(P2 −P1)3(P4 −P3)

Getting the Bezier basis matrix is also straightforward:

GH = GBMHB = GB

1 0 −3 00 0 3 00 0 0 −30 1 0 3

QH(t) = GHMHT = GBMHBMHT⇒MB = MHBMH

And finally:

QB(t) = GBMBT

CHAPTER 1. ANALYSIS 12

Apart from being very intuitive, a Bezier curve is also distinguished by the fact that it isalways contained within the convex hull defined by the start, end and 2 control points.

1.3.1.3 Drawing curves

We know of 3 methods, to draw a parametric cubic curve: sampling, forward differences andsubdivision. Sampling is simple but quite expensive, whereas forward differences is faster, butmore complicated. Subdivision is elegant and simple, which is why we focus on it. It worksby recursively halving the curve, and when it reaches a level where the curve is short enough,we simply draw a line from start to end point. For Bezier curves, we can decide when thatlevel is reached by checking the flatness, i.e. the distance from the line P1P4 to the highestpoint on the curve. A second method is to always let the recursion run a fixed number oftimes.

P1 P4

P2 P3

d

Figure 1.9: Checking the flatness by the distance d.

Subdivision is visualised below:

� �

� � � �

� �

� �

� �

� �

��

��

�� �

� �� �

Figure 1.10: Subdividing a Bezier curve. c©Knud Henriksen, DIKU.

The new points are easily obtained:L2 = (G1 + G2)/2, H = (G2 + G3)/2, L3 = (L2 + H)/2,R3 = (G3 + G4)/2, R2 = (H + R3)/2, L4 = R1 = (L3 + R2)/2.

1.3.2 Surfaces

When modeling a surface, it is tempting to simply form a grid and represent it with a collectionof points and edges. For anything but very simple figures, however, this will quickly grow

CHAPTER 1. ANALYSIS 13

complicated. If, say, we were modeling a teapot and wanted a slightly taller and more slenderform, there would be lots of individual points that needed to be changed. Fortunately, thereare alternatives, and one of these is the Bezier surface. It is an extension of Bezier curves, insuch a way that we form a grid with the curves. More precisely, we model our surface witha collection of 16 points, called a patch. Where a curve was parameterized on a single value,the surface is parameterized on two, s and t. These correspond to the two dimensions of thegrid seen in figure 1.11. Each row and each column is in fact a Bezier curve.

Figure 1.11: A Bezier surface.

Like curves, surfaces can be joined with different levels of continuity, occurring acrossedges. G0 and C0 continuity occurs across edges when the four common control points are(pairwise) identical. C1 continuity occurs when control points are identical and the directionand magnitude of the tangents are also identical.

1.3.2.1 Drawing a surface

As for curves, we mention 3 ways of drawing a surface: Sampling, forward differences andsubdivision. For the same reason as above, we also focus on subdivision here. It is done intwo stages: A patch is divided in two subpatches, and these are each again divided in two,giving us a total of four new patches.

Figure 1.12: Subdividing a Bezier surface.

This continues until a required flatness has been reached, exactly as for curves. Whendoing this, we risk getting cracks between 2 patches if they were not both divided to the same

CHAPTER 1. ANALYSIS 14

level. To avoid this, we could subdivide to a very small flatness level, or we could subdivideto a fixed level for each patch. In either case, we solve the problem with cracks at the cost ofunnecessary subdivisions.

1.4 Projection

Projection is the art of taking a 3D scene and visualizing it in 2D, so it seems to be 3D.[FvDFH97, pp. 237] mentions many types of projections. In this section we will concentrateon perspective projection.

1.4.1 Homogeneous coordinates

In two dimensions a point can be described by two coordinates, (x, y). Sometimes (as soonwill become apparent), however, it’s convenient to add an extra coordinate, W . We definethat two points (x, y,W ) and (x, y, W ) represents the same point in 2D if and only if (x, y,W )= a · (x, y, W ), for any real a. To find the point in 2D, we just divide all coordinates by Wand remove the third coordinate. The points in which W = 0 are defined to be at infinity.

Similarly, in 3D, we can add an extra coordinate, yielding similar attributes, which willprove to be very convenient.

1.4.2 Rotation, Translation, Scaling and Shearing

Rotation, translation, scaling and shearing are operations that can be performed on any 2Dimage, and most image editors support at least some of these operations. An example of theeffects of these operations on an image is shown in figure 1.13. However, we’re not going touse them on 2D systems. We are going to use them on 3D systems - or rather, 4D as we aregoing to use homogeneous coordinates.

When one of the four operations is called on an image (in 2D), each of them can be said towork on each point P in the image, and change it into P’. In a simple translation the contentsof the image are moved by some vector, so each component of the vector is simply added tothe corresponding coordinate of each point of the image. Scaling is done by multiplyingeach coordinate of each point by a scale, which doesn’t have to be the same value on eachcoordinate. To do this, however, we will need to use a 2 × 2 matrix. To rotate a point byan angle θ around the origin, we would also have to multiply the point by a 2 × 2 matrix.Shearing is also best done by multiplying the point with a matrix.

a) b) c) d) e)

Figure 1.13: The geometrical transformations. a) is the original scene, and the followingfigures show different transformations on this scene: b) translation, c) scaling, d) rotation,and e) shearing.

CHAPTER 1. ANALYSIS 15

So scaling, rotation, and shearing is done by multiplication with a 2 × 2 matrix, whiletranslation is done by adding a vector. This is unfortunate, as we would like to represent allfour transformations in a consistent and compatible way, for ease and convenience of use.

In order to achieve this, we switch to homogeneous coordinates (i.e. add an extra coordi-nate), so each point, previously described by (x, y), must now be described by (x, y,W ). Thiswill allow us to represent the translation operation by a 3× 3 matrix that can be multipliedwith the point.

These matrices will be shown as they are needed, as seeing them will not bring anyincreased understanding1.

1.4.3 The view system

In order to make any sort of projection, we must start by defining variables and assumptionswe will use. First, we have a set of points, lines, and polygons in three dimensions. This setis the scene we want to view. Second, we have the position from which we want to visualizethe scene - that is, the eye of the beholder. And third, we must define the view plane, thatis the plane that we project onto. This plane will later be drawn to the screen.

The actual construction of the scene will not be made in this section, but it is assumedthat it is constructed from points that we will project onto the view plane.

In order to be able to change the view plane we wish to describe the view plane in itsown unique coordinate system, that we call view coordinates. Because of this we will have todefine a few extra variables and vectors, but it will be well worth the effort! We will call thecoordinate system of the scene world coordinates.

VRP - the view reference point - this point is the origin of the view coordinate systemin world coordinates.

VPN - the view plane normal - this vector is the normal of the view plane - if we normalizeit, we will have one of the axes of the view coordinate system. This vector is given in theworld coordinate system.

VUP - the view up vector - this vector defines the “up” direction of the view coordinatesystem, by projecting this vector onto the view plane, we can find a second axis (actually doneby vector cross product VUP ×VPN. From this vector, we can calculate the third vectorto define the view coordinate system. This vector is given in the world coordinate system.

CW - center of window, a point - usually one cannot see all of the world, one could saythat we look at the world through a window. We assume that the window is rectangular, andthus, only need two points to define it. The center of window is the center of this window.This point is in view coordinates.

PRP - the projection reference point - also known as the eye of the beholder, given inview coordinates.

DOP - the direction of projection - this vector will be used to find out whether or not agiven point is on the same side of the view plane as the PRP.

In the “nice” situation, the CW and VRP is the same point, VPN parallel with the zaxis, VUP parallel with the y axis, and PRP somewhere on the z axis. In general, however,we can’t assume that. This can be realized by an analogy. Suppose you are in a room witha window. When you look out the window, you can stand up, sit on a chair or lie in bed.So the PRP is independent of the center of window. Maybe the window can be tilted and

1The interested reader could check out [FvDFH97, pg. 215 and 216].

CHAPTER 1. ANALYSIS 16

Figure 1.14: The view system c©Knud Henriksen

moved relative to you and the world coordinate system, changing both the VRP and VPN.Neither does the window have to be square - any rectangular shape will do.

Figure 1.14 show the coordinate systems, points and vectors in a more general case.While the preceding presentation has tried to give an intuitive understanding of these

definitions, we will need more than that. We will need to be able to calculate a number ofvectors. The basis vectors of the view plane can be found by:

n =VPN

|VPN|

u =VUP×VPN

|VUP×VPN|

v =VPN× (VUP×VPN)

|VPN× (VUP×VPN)|The center of window is

CW = (umin + umax

2,vmin + vmax

2)

And the direction of projection is:

DOP = PRP−CW

We note that we will need to know the VRP in world coordinates, the vectors VPN andVUP to setup the view coordinate system. We will need the PRP in view coordinates, andtwo points to specify the boundaries of the window.

1.4.4 Construction of the normalization matrix

The first step of the projection is to normalize the scene. This is done in order to make aconvenient representation of the scene in the view plane. The central goals are to transformour scene so that the PRP is in the origin, the view plane is orthogonal on the z axis, and

CHAPTER 1. ANALYSIS 17

the CW is placed on the z-axis. If we were to implement clipping, the last step would beextremely useful, as clipping is easier to do against simple planes.

This section is based on ”The projection cookbook” by Knud Henriksen, and follows thesebasic steps:

1. Translate VRP to the origin

2. Rotate the view coordinate system so it is axis parallel to the the world coordinatesystem.

3. Translate PRP to the origin

4. Shear so that the line from PRP to CW becomes equal to the z axis

5. Scale to the canonical perspective view volume

In the following each of these five steps will be described, and finally we will put it alltogether.

1.4.4.1 Translate VRP to the origin

In order to rotate the view coordinate system to have axes parallel to the world coordinatesystem, we would have to place VRP in the origin of the world coordinate system. Thiscan be achieved by a simple translation. If VRP = (vrpx, vrpy, vrpz) the translation matrixTV RP is:

TV RP =

1 0 0 −vrpx0 1 0 −vrpy0 0 1 −vrpz0 0 0 1

1.4.4.2 Rotate view coordinate system

After translation of VRP into the origin of the world coordinate system, it’s now possible torotate the view system, so that it has axis parallel to the world coordinate system. This couldbe done by projecting one view axis onto a plane spanned by two world axes, and calculatingthe angle between the projection of the view axis and one of the two world axes that spanthis plane, and rotate the view axis by this angle around the third world axis. This shouldthen be repeated for the other two view axis. This is, however, a very involved process (notto mention three matrix multiplications), and we would very much like to find an easier path.

Fortunately this process can be simplified considerably, by noting that the resulting rota-tional matrix, R, is an orthogonal matrix. This allows us, by knowing the basis of the systemwe wish to rotate into (the simple world coordinate system), to insert the basis vectors ofthe first system directly into the rows of the rotation matrix. If the basis vectors of the viewcoordinate system are (u, v, n), rotated into the basis vectors of the world coordinate system,(x, y, z), the rotation matrix is:

R =

u1 u2 u3 0v1 v2 v3 0n1 n2 n3 00 0 0 1

CHAPTER 1. ANALYSIS 18

Note the basic assumption that we rotate into a “traditional” (x, y, z) basis.

1.4.4.3 Translate PRP to the origin

After the rotation of the world coordinate system, we wish to have PRP in the origin ofour coordinate system. Why this is clever, will be apparent later. As PRP is given in viewcoordinates, it’s given relative to VRP (at present our origin), so a simple translation willdo:

TPRP =

1 0 0 −prpx0 1 0 −prpy0 0 1 −prpz0 0 0 1

1.4.4.4 Shearing

In this step we wish to shear so that the center line of the view volume becomes the z axis.This is where CW (center of window) comes into play, as this point and PRP lie on thecenter line. From these two points, we can calculate the direction of the center line (bycalculating the DOP - direction of projection). We wish to shear so that DOP is parallel tothe z axis. Since we wish to shear in the x and y direction, but not in the z direction, we mustuse the xy-shear matrix. The shearing matrix can be calculated by solving this equation forthe matrix Shxy:

00

dopn0

= Shxy ·

dopudopvdopn

0

=

dopu + shxdopndopv + shydopn

dopn0

By simple algebraic manipulations we get that the shearing matrix Shxy must be:

Shxy =

1 0 −dopx

dopz0

0 1 −dopydopz

0

0 0 1 00 0 0 1

1.4.4.5 Scale to the canonical perspective view volume

In this step we wish to scale from the perspective view volume into the canonical perspectiveview volume. The scaling matrix is calculated in two steps. First we make sure that the slopeof the planes bounding the view volume is ±45◦. Then we scale all the three axis uniformlyso that the back clipping plane is scaled from z = vrp′z + B to z = −1, where vrp′z is the zcoordinate of VRP after translation (step 3) and shearing (step 4), and B is the distance ofthe back clipping plane from PRP. As the shearing operation in step 4 doesn’t affect the zcoordinates, vrp′z = −prpn.

At the z coordinate of CW, −prpn, the y coordinate must be y = vmax−umin2 . We wish

this to be equal to −prpn. This gives:

CHAPTER 1. ANALYSIS 19

−prpn = syvmax − umin

2⇒ sy =

−2prpnvmax − umin

Similarly, the scaling factor for x is:

sx =−2prpn

umax − vminThe second factor in the scaling is the uniform scaling of all axis. Here we wish that the

z value on the back clipping plane is equal to -1. B is the signed distance from VRP to theback clipping plane. So in order for the elements between the back clipping plane and theview plane to be “visible”, B must be negative (the same goes for the distance to the frontclipping plane, F ). This yields:

sall(B − prpn) = −1⇒ sall = − 1

B − prpnThis gives the scaling matrix S:

S =

sallsx 0 0 0

0 sallsy 0 00 0 sall 00 0 0 1

=

−2prpn

(umax−vmin)(B−prpn) 0 0 0

0 −2prpn(vmax−umin)(B−prpn) 0 0

0 0 − 1prpn+B

0

0 0 0 1

Putting it all together

Now we know all the matrices needed to transform the objects in our scene in world coordi-nates into the canonical perspective view volume. The transformation matrix N is:

N = S · Shxy ·TPRP ·R ·TV RP

So if we have a point P in world coordinates, its coordinates in the canonical perspectiveview volume P’ can be found by:

P’ = N ·P

1.4.5 Construction of the projection matrix

In this section, we will show the basic math involved in calculating a matrix that can take apoint P in the 4D homogeneous coordinates and project it onto the view plane and give usback the (xp, yp) coordinates of the projected point Pp. We will assume that we have startedby calculating and applying the N matrix (as specified in the previous section), as this willplace us in the “nice” situation. This makes the math significantly simpler.

As mentioned above, we assume that PRP is in the origin, that the view plane is orthog-onal to the z axis in a distance d from PRP. Furthermore, we assume that CW is on the zaxis, and that there is no clipping left to be done. The basic situation is shown in figure 1.15,but it’s more convenient to split it into two figures, as shown in figure 1.16. Given the pointP and the value of d, and wish to calculate the coordinates xp and yp of the point Pp. Thiscan be done by noting that P and Pp act as a delimiter of two similar triangles. These two

CHAPTER 1. ANALYSIS 20

Figure 1.15: A general overview of the current scene. c©Knud Henriksen

Figure 1.16: The situation in the xz and the yz plane. c©Knud Henriksen

triangles must have the same angles. The angle θ at PRP in the XZ plane must be givenby:

tan θ =X

z=xpd⇒ xp =

Xd

Z=

X

Z/d

And the angle φ at PRP in the Y Z plane must be given by:

tanφ =Y

Z=ypd⇒ yp =

Y d

Z=

Y

Z/d

So what we have is a scale factor Z/d that is applied to the x and y coordinates. As weare working in homogeneous coordinates the scaling factor can be applied simply by equatingthe W coordinate to 1/d, assuming W = 1, as this will correspond to dividing all coordinatesby z/d.

This yields the projection matrix P:

CHAPTER 1. ANALYSIS 21

P =

1 0 0 00 1 0 00 0 1 00 0 1

d 0

Now all we need is to calculate d. We know that CW and VRP has the same z coordinate

as d. So we must be able to find d by applying N to VRP (as CW is in view coordinates,applying the normalization wouldn’t give the desired result).

1.4.6 Transformation of view volumes

An alternative to the geometric projection of the previous section is to transform the canonicalperspective view volume into the canonical parallel view volume. The two view volumes areshown in figure 1.17. In this view volume the values stored in the x and y coordinatesare the same as we would, get if we made a geometric projection. There is, however, acrucial difference: We will still have access to the relative z coordinate. In order to find

Figure 1.17: The canonical perspective and parallel view volume c©Knud Henriksen

the transformation matrix C, we note that the two points furthest away from PRP muststay unchanged, and a point in the corner of the front clipping plane (±zmax,±zmax, zmax)must be transformed into the corresponding corner of the canonical parallel view volume, i.e.(±1,±1, 0). This transformation can be accomplished by the conversion matrix C:

C =

1 0 0 00 1 0 00 0 1

1+zmax

−zmax1+zmax

0 0 −1 0

CHAPTER 1. ANALYSIS 22

Note that zmax is given by:

zmax = −F − prpnB − prpn

,

where B and F is the signed distance from VRP front and back clipping plane, respectively,as defined in section 1.4.4.5.

1.4.7 Mapping into device coordinates

After normalization and transformation, the x and y coordinates of our points have valuesbetween -1 and 1. However, we wish to show the scene on some device that uses pixels to showthe scene, and usually it’ll also have a different coordinate system, sometimes only supportingpositive integer coordinates. Thus, we need to translate the x and y coordinates into the newcoordinate system, and scale into the device window (and round of to the nearest integervalue).

If the coordinate system of the device is a regular cartesian (x, y) coordinate system,such as the one used by DotDevice, the translation can be done by moving the origin of thecanonical view volume from (0, 0, 0) to (1, 1, 1), and thus, all coordinates would have positivevalues. Then the translation is:

Tv =

1 0 0 10 1 0 10 0 1 10 0 0 1

If the device has dimensions xmax × ymax pixels, then we must use these as scale factors,

and get the scale matrix:

Sv =

xmax 0 0 0

0 ymax 0 00 0 1 00 0 0 1

Note, that there is no scaling of the z coordinate, as we’ll only need to know the relative

values of the z coordinates in the z buffer algorithm. So the mapping can be done by themapping matrix M:

M = Sv ·Tv

In the more complicated case, in which we paint into a window defined by xmin ≤ x ≤ xmaxand ymin ≤ y ≤ ymax, the scaling factors will be the average of the min and max coordinates,and we must end by translating the scene into the lower left corner of the window.

1.4.8 The process of projection

The full process of projection is:

1. Normalization

2. Projection

CHAPTER 1. ANALYSIS 23

3. Mapping into device coordinates

If we are projecting the point P into the point P’ on the view device, we would do thecalculation:

P’ = M ·C ·N ·P

This would give us P’ in homogeneous coordinates. So in order to get the ”real” points,we would have to divide by W , discard z and W , and round (in order to get integer values).

1.5 Illumination

The color of an object is seldom just one color. Depending on lighting and the position of theviewer, the perceived color of an object can not only change tremendously, there can even becolor-changes over the surface of the object, i.e. highlights and shadows. The focus of thissection is to build a model that can color an object so it’ll look good.

The best result may come from building a physical model, but this is a very complexproblem. One would have to calculate light intensity from the light source on any surface, thelight reflected from each surface (depending on the material properties of this surface), thereflected light intensity on the surfaces ”visible” from the reflecting surfaces, the reflectionof the reflected light and so on. But not only that: The light source may not be a perfectmathematical point (that is, have zero volume), but will often have some extent, which aphysical model will have to take into account. And there may very well be more than onelight source, with intensities and colors changing over their extent.

One should also note that if an object is visible, it’s because light is reflected from thesurface of the object towards the eye of the viewer.

This complexity is the central reason why researchers have tried to find simpler modelsthat work well in practice. These are, however, built more on trial and error (“what looksgood?”) than on a physical understanding.

1.5.1 Ambient light

Ambient light adds a constant amount of light everywhere (see the left triangle in figure1.18). That means that each object is displayed as having a single color, that is intrinsic to it,regardless of light sources. If one assumes a constant and all-present light source with intensityIa, then one could define a material constant ka, called the ambient reflection coefficient, thatcontrols the fraction of light reflected from the surface (and thus, is visible to the viewer). Sothe intensity I of the light on a surface could be described by:

I = kaIa

One could view ambient light as a way of modeling the reflected light in the physicalmodel above. In this context, the ambient intensity should be dependent on the number andintensity of the light sources. In a brightly lit scene (a summers’ day), the intensity of theambient light should be quite high, but in a dark cave, lit only by a flashlight, it should bevery low (or nil).

CHAPTER 1. ANALYSIS 24

Figure 1.18: Types of illuminations: a) ambient light, b) diffuse reflection c) specular reflec-tion

1.5.2 The source of light

In order to make good looking scenes, we must take the sources of light into account. In thefollowing we will look at the case of just one source of light, and assume this to be shapedlike a point.

1.5.2.1 Diffuse reflection

A point on matte surfaces appear equally bright regardless of the position of the viewer (seecenter triangle in figure 1.18). This can be modeled by assuming that the intensity is onlydependent on the angle θ between the normal N of the matte surface and the vector L fromthe point in question to the light source. If N and L have been normalized, then cos θ = N ·L,and so the equation of diffuse illumination must be:

I = Ipkd(N · L),

where Ip is the intensity of the light source, and kd is the diffuse reflection coefficient and isa constant of the material. Note that if N · L is negative, the surface faces away from thesource of light, and thus, the light doesn’t illuminate the surface in question. From this itfollows that the light from the light source shouldn’t be added to the light reflected from thepoint in question, and thus, N · L is defined as being zero. This could be expressed as:

N · L = max(N · L, 0)

In the remainder of this section, we will assume that any vector dot product is eitherpositive or zero, even if it’s not explicitly written.

There is, however, a central problem in this model. If we assume that the light doesn’tmeet any obstacles, the amount of light at a distance dL from the light source is a constant,as the light doesn’t disappear. So the amount of light passing through the surface of a sphere

CHAPTER 1. ANALYSIS 25

with radius dL at a given point in time is a constant. From this it follows that the intensity2

Ip of the light at a point on the sphere must be

Ip =I

4πd2L.

Using this to model the real intensity of the light at a given point has a few drawbacks. First,at small dL (say dL = 10−3) the fraction blows up. Close to the light source there is greatvariation, even if the angle between N and L is unchanged. Second, far away from the lightsource there is too little variation.

Therefore, the attenuation due to distance from the light source can be given greater rangeof effects by defining the attenuation factor fatt as:

fatt = min(1

c1 + c2dL + c3d2L, 1),

where c1, c2 and c3 are just user defined constants. Thus, the equation for the diffuse reflectionis:

I = fattIpkd(N · L)

1.5.2.2 Color of light and surfaces

Light and surfaces are not generally monochromatic. In the real world light consists of manydifferent wavelengths. We will assume that light consists of just three “wavelengths” - red,green and blue.

This leads to giving light sources an intensity for each color, so each light source is repre-sented by a triple (Ir, Ig, Ib). Similarly the material can be said to have a diffuse color, givenby the triple (Odr, Odg, Odb). For a color, λ, the intensity is:

Iλ = kaλOdλIaλ + fattkdOdλ(N · L)Ipλ

1.5.3 Phong illumination

On a shiny surface we get highlights that move with the viewer, as seen on figure 1.18. Thisis called specular reflection. Phong illumination is a way to model specular reflection. Ona reflecting surface the direction of the ”strongest” highlight will be given by the directionof the reflected light R. Thus the maximum highlight happens when the angle α betweenthe direction V to the viewpoint and R is zero, and falls off when α increases. Phong Bui-Tuong approximated this falloff to cosn α, where n is called the specular reflection exponent.The higher the value of n, the more sharp is the falloff. If both R and V is normalized,cosα = R ·V. As earlier, this dot product must be positive or zero, as the total amount oflight can’t be reduced and. Furthermore, we must also require that N · L ≥ 0.

Even though the angle of incidence θ does have an influence on the amount of specularreflected light, it’s typically set to the product of ks, the specular reflection constant, and Osλ,the objects specular color. This gives the total equation for illumination:

Iλ = kaλOdλIaλ + fattIpλ[kdOdλ(N · L) + ksOsλ(R ·V)n]

2Remember that the intensity is the amount of light pr area.

CHAPTER 1. ANALYSIS 26

Note, that we haven’t given an explicit expression for R. This vector can be calculatedby mirroring L around N. This gives the following equation for R:

R = 2N(N · L)− L

Now, we can calculate the color of each point on every object in the world! However, thiscalculation is quite involved, with many floating point operations. So we would like to do thecalculation as few times as possible, and this is the topic of the next section.

1.6 Shading and Coloring

Using an illumination model such as the one described in section 1.5 we can determine thefinal color of every point on the screen. This process is called shading. The brute force methodwould be to determine every point and normal of every surface on the screen and then applythe desired illumination model to these data. This is the correct and precise way to do it,but it is also very cumbersome and slow. As usual when discussing computer graphics we willneed to make some sensible approximations that will reduce the work needed to be done bythe computer.

1.6.1 Flat shading

The easiest way to approximate shading would be to divide surfaces in the model worldinto polygons and simply shade each polygon according to its normal. This takes littlecomputational effort but it looks it. Particularly, edges between polygons are visible as asudden change of color and the whole scene looks edged. To smooth things out the numberof polygons can be increased, but this increases the number of calculations considerably andit does not really pay off in the results. Ideally we would like to obtain a nicer and smootherpicture with not too many polygons.

1.6.2 Interpolated shading

Instead of coloring the whole polygon with a single color, we can make the color changegradually across polygons. To do this we interpolate data from the polygon’s vertices acrossthe inside of the polygon. Exactly what data from the vertices we interpolate determinethe shading model. As long as we use linear interpolation we can make use of an iterativeinterpolation method which lessens the calculation burden substantially. Doing this we canget away with drawing fewer polygons and still achieve good pictures.

1.6.2.1 Interpolation

Generally speaking, interpolation is the process of constructing new data points from a discreteset of points. In computer graphics this is typically used to color something where only avery limited number of pairs of colors and points are known. For example, we might want tocolor a line from point A to B, where point A is red and point B is blue. We want the line togradually change its color from red to blue when we traverse the line from A to B. We useinterpolation to deduce the intermediate colors of the points between A and B. Note thatthe intermediate colors are dependent on the color model used.

CHAPTER 1. ANALYSIS 27

Intuitively the colors of the two end points are considered of equal weight, thus leading toa scale of colors where the color is represented linearly dependent on the distance to the endpoints. This is called linear interpolation and it will be the main focus in this project.

Colors are not the only thing that can be interpolated. We will later need to interpolatevectors along a line for example. Generally an interpolation function takes a point, in whichwe would like to calculate the corresponding subject, and returns the subject (e.g. colors orvectors) we are seeking. The two points and two subjects to interpolate between are constantfor a given interpolation function. Thus it can be described as a function of the form

fS2×P2 : P 7→ S,

where S is the set of subjects and P is the set of points.When interpolating colors from xbegin to xend where xbegin has color cbegin and xend has

color cend using linear interpolation, the function looks as follows:

fcend,cbegin,xend,xbegin(x) = cend − (cend − cbegin)xend − x

xend − xbegin.

From this point forward we will drop the subscripts to f for brevity.We can derive an iteration method so that when we know f(x) we can calculate f(x+∆x)

provided we know the difference ∆f(x) between the two. The huge advantage with the linearinterpolation function over other interpolation functions is that the difference function isconstant. We need to calculate it only once for given end points and colors. Since thisproperty is exactly what constitutes “linear functions” it is really no surprise, but let uscalculate it anyway and see for ourselves:

∆f(x) = f(x+ ∆x)− f(x)

= cend − (cend − cbegin)xend − x−∆x

xend − xbegin− cend + (cend − cbegin)

xend − xxend − xbegin

= (cend − cbegin)

(xend − x

xend − xbegin− xend − x−∆x

xend − xbegin

)= ∆x

cend − cbeginxend − xbegin

.

We notice that ∆f(x) depends only on end points and on the incrementing parameter ∆x,but not on x.

For a computer the iterative method going from one point to the next is much faster thanrepeatedly calculating the interpolation function for each point on the path. The scheme isof course similar when interpolating vectors or other subjects different from colors.

1.6.2.2 Gouraud shading

In Gouraud shading we apply an illumination model to the three vertices of each polygon,and then interpolate the obtained colors to determine the color of the inside of the polygon.We thus avoid applying the illumination model to each and every point of the inside of thepolygon.

This presumes that each vertex has a normal and that each of these normals is determinedfrom the original surface which the collection of polygons model. If the original surface is notknown, each normal can be determined as an average of the surrounding polygon normals.

CHAPTER 1. ANALYSIS 28

Since colors are determined solely from the polygon’s end point colors, any spot in themiddle of the polygon will not be visible. A highlight will need to be near one of the polygonend points to be visible.

If we use Gouraud shading, we will need to apply the illumination model to each ofthe original polygon’s vertices and map the calculated colors to the screen polygon’s vertices.Using these colors and the difference in y-coordinates we calculate an interpolation differencingfunction which determines the change in color per y-step for each edge. This is not muchdifferent from what we did in section 1.6.2.1 only this time we use the y-coordinate insteadof the x-coordinate and we know that our ∆y is 1. The interpolation function becomes

f(y) = cend + (cend − cbegin)yend − y

yend − ybegin,

and with ∆y = 1 the differencing color (i.e. the constant differencing function) becomes:

∆c ( = ∆f(y)) =cend − cbeginyend − ybegin

.

Thus beginning with the color cbegin of the start point (x0, y0) = (xbegin, ybegin), the color at(x1, y1) becomes c1 = c0 + ∆c = cbegin + ∆c. Generally we have cn = cn−1 + ∆c.

Now we know the colors of the edge points of the right and the left edges, we can interpolatebetween right and left color for a given scan line when drawing the horizontal line. The samescheme as before applies: at height y = yn we have color cn,left at the left point (xn,left, yn)and color cn,right at the right point (xn,right, yn). So to find the color at some point (x, yn) inbetween we interpolate. This interpolation function looks as follows:

f(x) = cn,right + (cn,right − cn,left)xn,right − x

xn,right − xn,left,

with a difference color of

∆c =cn,right − cn,leftxn,right − xn,left

.

All this can be integrated in the scan line algorithm from section 1.2.1, such that wecalculate the difference color per y-step when we initialize the other variables before the firstphase. During the iterations we make sure to update the color as well by adding the differencecolor. When changing edges we update the difference color also.

1.6.2.3 Phong shading

Another method is to interpolate the normals of the vertices across the inside of the polygon,and then apply the illumination model to each point and normal. This is known as Phongshading. This borders the brute force method except that we determine normals and pointsusing interpolation, which can be boosted using an interpolation differencing function assketched above.

Phong shading requires that we interpolate the end points and their normals of the originalworld polygon across the screen polygon, and then let the illumination model determine thecolor of each point on the screen polygon from the interpolated world point and normal.

CHAPTER 1. ANALYSIS 29

1.6.2.4 Problems with interpolated shading

When interpolating linearly we do not take into consideration the perspective distortioncaused by the projection from the three dimensional world coordinate system onto the twodimensional screen coordinate system. For instance, the world middle point of a rectanglewhich is seen from an angle is not the middle point of the figure seen on the screen. This isbecause a constant change in screen coordinates does not map to constant changes in worldcoordinates.

Another problem is that the orientation of the polygon in question matters. For instance,when rotating the viewing plane, a point or color calculated with interpolation might differbefore and after the rotation. This is a consequential error of perspective distortion.

Another obvious issue is that since we are keen on not increasing the number of polygonstoo much, the silhouette of a surface will still look edged even though the inside looks smooth.

1.7 Visible surface determination

We want to determine the visible surfaces of objects in a scene, in order to avoid drawing thosethat are not visible. This process is also called hidden surface elimination. In principle it isnot complicated, but it can be time consuming. [FvDFH97] talks about image- and object-precision algorithms. Image-precision means that we handle the task from a pixel level, i.e.for each pixel in the window we determine which object is the closest. Object-precision meansthat we handle it from an object level, i.e. for each object in the scene, we determine whichparts of it are unobscured by other objects, and then draw those.

1.7.1 The Z-buffer algorithm.

This image-precision algorithm has at its center a two dimensional array with the samedimensions as the window we display our scene in. Each element in the array contains az-value and a color. Initially the buffer contains the z-value of the back clipping plane andan arbitrary color. When we scan-convert the polygons, we calculate a z-value, zxy, for eachpixel (by interpolation). This is compared to the z-value in the same (x,y)-position in thebuffer. If the buffer’s z-value is closer to the viewer than zxy, we skip to the next pixel. Ifzxy is closer, then we overwrite this buffer element with zxy and its color. When we havescan converted the entire scene, the contents of the buffer can be drawn on the screen. Oneattractive thing about this is, that we can draw in any order we like. We can be sure thatthe pixels with the z-value closest to the viewer is the one whose color will be drawn last.

1.7.2 List-priority algorithms.

This is a different type of algorithm. The central aspect is to create a list of the objects todraw, sorted on z-value. This way, objects can be drawn such that the one closest to theviewer is drawn last, thereby ensuring that it overwrites what it hides. In certain cases, thereis no order that will solve the problem, in which case it is necessary to split polygons intosmaller pieces, sort the new polygons and then draw.

An example of a list-priority algorithm is the binary space partitioning algorithm, BSP.The idea is as follows: By splitting the plane into two half planes, front of P1 and back ofP1, we know that if viewed from the front of P1, no object from the back of P1 can obscure

CHAPTER 1. ANALYSIS 30

� � � � � � � � � � � � � � � � � � � � � � � " $ � � � � � ( *

+ , . / 0 2 �

� � � 3 5 6 � 7 8 5 7 � � �

Q

P

+ , . / 0 : �

� � � 3 5 6 � 7 8 5 7 � � �

Q

R

P

; = ? @ A � BC E F G I K @ F L N O P @ F

Figure 1.19: Circular overlap. c©Knud Henriksen, DIKU.

an object from the front side. The splitting of planes continues recursively, so the back of P1

is split into front and back of P2. This results in a binary tree. The internal nodes of the

3

2

P1

P2

1

P1

P21

32

front

front

back

back

Figure 1.20: Binary space partition and corresponding binary tree.

binary tree are splitting lines; the left child of a node N contains what is on the front side ofthis line, and the right child contains what is on the back side of this line. The leaves containsthe regions that result from the partitioning. BSP works at object-precision, and is good forscenes with static objects and changing viewpoint.

1.7.3 Area subdivision.

This type of algorithm works by examining an area of the projected image. If the visiblepolygons in this area are easily found, then they are displayed, otherwise the area is subdivideduntil the decision becomes easy.

1.7.4 Ray tracing.

Ray tracing in its simplest form consists of tracing a ray from the viewer’s eye into the scene.The color of the object that is hit first is the color we will draw at this pixel.

2 Design

2.1 Doing the projection

In this section different ways of implementing a way to do the projection will be discussed.In section 1.4 it became clear that the calculation of the projection matrices are only

dependent on the definitions of the view plane and projection reference point. So it seemsreasonable to encapsulate the calculations in a class that can either access these definitions orcontain these definitions. So the calculation of the projection matrices is dependent on howwe chose to represent this data.

One way could be to setup the view plane in one class, and the projection reference pointin another. This would, however, make it complicated to make changes to the view planeand PRP. Thus, it seems convenient to setup the whole view coordinate system in one class.This class could be called Camera, and could also contain methods to calculate the projectionmatrices.

2.1.1 The Camera class

From section 1.4 we note that we need VRP in world coordinates, PRP in view coordinates,the vectors VPN and VUP, and two points to specify the boundaries of the window in orderto setup the system (and later to calculate the projection matrices). These values should bespecified and set in the constructor. In order to increase ease of use, one could also definesome sensible default values.

From these we would like to calculate the unit vectors of the view coordinate system,(u, v, n), the center of window, CW, and the direction of projection, DOP. Should these bemade into specific fields? The class would need more memory, but the fields would only haveto be recalculated when the values from the constructor is reset. On the other hand they areonly needed to calculate the projection matrices, which is only done once anyway.

The Camera class shouldn’t know anything about the device that will show the scene.However, we will need to calculate a mapping matrix from the canonical parallel view volume.This mapping matrix need to know the height and width of the screen and the coordinatesystem of the device (to make sure the whole calculated scene is shown). If one expectedto alternate between different devices to show the scene, it would be prudent to place thisfunctionality in the device class.

As we’ll only be using the class DotDevice, and the device will be known when theprojection matrix will be calculated, it does make sense to let the camera calculate both theprojection matrix and the mapping matrix in one go.

31

CHAPTER 2. DESIGN 32

2.1.1.1 Moving the camera

It would be nice to be able to change the camera after the program has started, so the samescene can be visualized differently, such as zooming or panning. While this is beyond thescope of this assignment, the Camera class should be constructed so that it would be easyto implement. Changing the camera does give some possible problems. A number of vectorsand points and a single matrix is calculated from the original values. So if these change, thesevalues might be inconsistent with the new values. So a method to update the system aftereach change will be needed.

There are a lot of calculations in calculating the total projection matrix, so recalculatingevery time the user changes something might not be very efficient. Having a boolean valueshowing whether the projection matrix is in an inconsistent state or not is preferable. Thisadvantage becomes even more pronounced because of the fact that we’ll need the total pro-jection matrix many, many times. So making sure it’s always in a consistant state, and nothaving to recalculate it every time it’s needed is a definate advantage. As we only have onecamera the increased memory usage will be insignificant.

From this discussion we get an outline of the Camera class:

Camera

Know ...

5× point Position of VRP, PRP, CW and the two cor-ner points of the view window.

6× vector The following vectors: VPN, VUP and thethree basis vectors u, v and n of the view co-ordinate system.

matrix The projection matrix.

Know how to ...

calculate projection matrix Given the necessary vectors and points, theCamera should be able to calculate the pro-jection matrix.

2.2 Design of illumination

2.2.1 Source of Light

In this assignment we make the simplifying assumption that we use a single light source,shaped like a point. The light source can be represented by a class, containing the intensityof each of the three colors (RGB) and the coordinates of the light source. If the light sourcewere to have specific properties (we may want to model it as a flashlight or the moon) theseshould be placed here.

If we had more than one light source, we would need to make some sort of containerclass, that should contain attenuation functionality and ambient light intensities, as these are“global” values, and only should be defined in one place. As we’ll only support one lightsource, all this functionality might as well be placed in the light source.

CHAPTER 2. DESIGN 33

2.2.2 Properties of the object

The object has some properties, such as the specular reflection coefficient. These propertieswill have to be contained somewhere. As we know that we’ll be making a lot of polygons,it’ll be a waste of memory to let each polygon contain their own copy of these properties.If we contain all the object properties in a material class, all the polygon will need to knowis a pointer to its instance material-class. This will also make it easy to represent scenes ofdifferent objects with different properties.

For each material, we’ll need a diffuse color, Odλ, and a specular color, Osλ. On top ofthis, we’ll need an ambient reflection coefficient ka, a diffuse reflection coefficient kd, and aspecular reflection coefficient ks. Furthermore, we’ll need a specular reflection coefficient nthat we might as well define as an integer.

2.2.3 The illumination function

As stated in the assignment, we must support Phong illumination. This means that we mustbe able to calculate the color of a given point. The function to do the calculation could beplaced in the light source class. Then it would take a material and a point as argumentsand do the calculations. Another possibility would be to make it as a function. This would,however, be in violation of the object oriented way of thinking, and as there is no advantageto implement it like this, it will not be done.

LightSource

Know ...

3 real numbers Three attenuation constants.2 colors The ambient light and a color representing the

color of the light.point The light’s position.

Know how to ...

calculate attenuation factor Given a distance, the light source should cal-culate the attenuation factor.

calculate Phong illumination Given a material and a camera along with apoint and a normal to that point, the lightsource should calculate the color of the point.

Material

Know ...

3 real numbers Three reflection constants.1 integer The specular reflection coefficient.2 colors A diffuse and a specular color.

2.3 Visible surface determination

Due to its simplicity, we have chosen to implement the Z-buffer as our hidden surface removalmethod. In our design, the actual Z-buffer simply contains the buffer structure, and a functionthat, given a z-value, determines if this is closer to the existing one. If so, the existing z-valueand color is overwritten. The interpolation of the z-values takes place in the screen polygon,so there is nothing more to this.

CHAPTER 2. DESIGN 34

2.4 Polygons

Eventually all surfaces will be divided into polygons which then will be drawn on the screen.Conceptually the polygons in our virtual world differs from the polygons on the screen. Forexample, the polygons in the world are three dimensional, they have normals and it wouldprobably also be wise to associate some sort of material with each polygon. Since they residein our virtual world, we would like to separate them from the whole drawing process whichinvolves viewing angle, a light source and other things. The polygon on the screen, on theother hand, is tightly connected with the viewing angle, the light source and how things inthe end will be drawn. It makes good sense to separate these two kinds of polygons into whatwe hereafter will name world polygons and screen polygons.

2.4.1 Polygons in the world

World polygons should model a three dimensional polygon, and it resides in our virtual world.It should have three points determining the position of its vertices, and it should have threenormals, one for each vertex. Of course, an ordinary triangle has only one normal, but inour case the polygons will often model some surface, and we would like the normals of thepolygons to be identical to the normals of the surface which the polygons model. Thesenormals will be used for shading purposes.

Our world polygon should also know what material it is made of, which also will be usedfor shading purposes. Finally the world polygon should know how to react to projections,translations, shearing, rotation and other geometrical operations given a matrix.

In an object oriented language the world polygon’s interface would look as follows:

Polygon

Know ...

3× point Position of vertices3× vector Normals in verticesmaterial Material which the polygon is made of.

Know how to ...

project Given a matrix, the polygon shouldbe able to perform geometrical operations on itself.

2.4.2 Polygons on the screen

Polygon objects on the screen should have different properties than polygons in our virtualworld. Since we will be using a Z-buffer as visible-surface algorithm, the polygon’s verticeshave integral x and y coordinates and floating point z coordinates. The x and y determine thepolygon vertices’ position on the screen (which have no such thing as fractional coordinates)while z determines the depth position of the vertices in the Z-buffer.

We imagine that the screen polygon should be able to determine its screen and Z-buffercoordinates given a world polygon, a light source, and information about how it is viewedfrom the spectator, i.e. a camera. This is done by determining the projection matrix whichprojects the world onto a parallel view volume, and then tell the world polygon to projectitself with this matrix. The coordinates of the projected world polygon equal the screencoordinates if the view volume we have chosen also considers the screen dimensions.

CHAPTER 2. DESIGN 35

This should enable the screen polygon to draw itself to a Z-buffer given a shading model.Both Gouraud and Phong shading models require the points and normals from the worldpolygon’s vertices from which the screen polygon has been created, so it is reasonable thatthe screen polygon should keep a reference of some sort to the original polygon. Anotherway would be for it to keep references to the points and normals and to the material of theoriginal polygon.

Other than this reference, we stress that the screen polygon does not reside in the virtualworld and that it is generally considered another kind of object than the world polygon.

Our screen polygon object could look similar to this:

ScreenPolygon

Know ...

3× point Position of vertices - x and y should be integral,z should be floating point

World polygon A reference to the world polygon from whichit originated.

Know how to ...

construct itself Given a world polygon, a light source, and acamera, the polygon should be able to deter-mine its screen and Z-buffer coordinates.

draw itself Given a shading model, the polygon should beable to draw itself to a Z-buffer.

2.5 Surfaces

We are required to implement parametric surfaces as both Bezier surfaces and as generalparametric surfaces. For the Bezier surfaces, we get data (i.e. the patches and points) usinga function provided by Knud Henriksen. We store one patch in a collection of points, andanother vector then holds these pointvectors. To create displayable polygons from these, wego through each pointvector (i.e. patch) and subdivide it. We have chosen subdivision asthe display method primarily because it is easy to implement. When a patch is divided tothe maximum level, we display it. Assuming it is a well-formed patch, we calculate normalsfor each corner point. The normal for corner a is simply the cross product between a1 anda2, and the other normals are made similarly. The sign of the normals might be wrong, inwhich case we simply invert all normals by multiplying with -1. At this stage we create twotriangles, abd and bcd, and pass these and their corresponding normals on to the next stage,creating world and screen polygons, where lighting, shading and scan conversion takes place.

a

b c

d

a1

a2

Figure 2.1: A patch with vectors from corner a to its two control points.

CHAPTER 2. DESIGN 36

There are cases where a patch is not well-formed, so we have made a check for deformities.As it is, we only check whether one side of the patch is collapsed as seen in figure 2.2; ideallywe would also check for other deformities, such as having more than two points collapsed, orif three (or four) of the corner points are collinear.

a

b c

d

Figure 2.2: A patch with one side collapsed.

If we find that one side has collapsed, we treat the patch as a triangle. This meanscalculating the normals of the three corners accordingly. In figure 2.2, it is the side ad thatis collapsed. This means that the tangent from a to the first control point towards d, mustbe calculated using the first control point towards c instead.Our BezierPatch class reflects the fact that the method is simple, and has only a constructorand a method to draw it. The draw-method takes care of initiating subdivision of the patch.This in turn means subdividing each curve.

2.5.1 General parametric surfaces

As part of the assignment, we must visualise what is called a general parametric surface.This is a surface defined solely by four functions of the type f : R2 7→ R3. As suggested, wewill draw the surface using sampling. This is done by looping over the two parameters, uand v (as you would over a 2D array). In the inner loop, we calculate values in four points,(u, v), (u + ∆u, v), (u + ∆u, v + ∆v), and (u,∆v). This gives us a rectangle, and to get thenormals of each corner, we have made 2 functions for each of the four surfaces, that calculatethe derivative in a given point. These two vectors are crossed, giving us a normal. Now theprocedure is exactly as for the maximally subdivided Bezier patch above. To fix any problemthat might occur with the sign of the normals here, we found that simply inverting it for oneof the function gives us a good loking Klein bottle. It might be pure luck, but it seems towork in this case, i.e. for this camera, stepsize etc.

BezierPatch

Know ...

16× point 16 points defining the Bezier patch.material The material the patch is made of.

Know how to ...

Subdivide itself

CHAPTER 2. DESIGN 37

ParametricSurface

Know ...

12 vector functions The four vector functions defining the surfaceand their 8 derivatives.

material The material the patch is made of.

Know how to ...

Sample itself

3 Implementation

We have implemented our visualization system in C++ with the help of the DotDevice classand other tools provided to us. We have used the template functionality of C++ to tryand make the implementation generic. For instance, the internal data container in all of ourclasses is a template parameter (actually, it is a template template parameter, cf. [VJ03, pp.102–103]) which can easily be changed. Also the default floating point type of most classescan be changed to something different from float if need be.

We have seperated the classes of the program into namespaces on the basis of whatthe classes model and what they do. In the following we will provide an overview of thesenamespaces and classes, and how the chain of events leading from the reading of a data file tothe final output to the screen occur. A printout of the source files are provided in appendixB starting on page 50.

3.1 Namespaces

The classes we have created ourselves are all in the graphic namespace. From the main

function in the global namespace we use our classes to create objects such as Bezier patches,Z-buffers, etc.

3.1.1 The global namespace

The global namespace contains the main function along with the helper functions and classesprovided to us, namely the ReadDataFile function in readdata.cpp source file and theDotDevice class in the DotDevice.cpp and DotDevice.h source files.

The main function dispatches control to other functions and member functions of objectsand is where the strings connect, so to speak.

3.1.2 The graphic namespace

The graphic namespace is divided into three sub-namespaces, tools, world and draw. Theheader file graphic.h bring these together by including the source files for the three sub-namespaces.

3.1.2.1 The graphic::tools namespace

The graphic::tools namespace contains the basic building blocks used throughout theclasses. Here reside the Vector, Point and Matrix template classes along with Color. TheVector and Point template classes share a common base class named BasicPoint which

38

CHAPTER 3. IMPLEMENTATION 39

implement the common methods used by both, such as the subscript operator operator[].Also, a base class to Matrix, BasicMatrix is defined, so that it can be used as a simplecontainer. We do not use this class directly, though.

All of the above templates use the Container template class, which defines what kindof internal container all the classes use to store data. As default the Container templateimplements a standard C array with bounds check.

3.1.2.2 The graphic::world namespace

The graphic::world namespace holds the classes for the objects which we intuitively wouldplace in a virtual world. This includes the Polygon, BezierPatch and ParametricSurface

classes, but also the Camera, LightSource, and Material classes. All these classes use objectsfrom the graphic::tools namespace, and some also use objects or pointers to objects fromthe graphic::draw namespace.

3.1.2.3 The graphic::draw namespace

The graphic::world namespace includes the ScreenPolygon and Zbuffer classes which doesnot really belong in the world since they are both specific as to how we want to visualize ascene.

3.2 The pipeline

Generally our program will read data from a file with the ReadDataFile to create a seriesof instances of BezierPatches. The BezierPatch class has a draw function which firstsubdivides the patch into Polygons which are then used to create ScreenPolygons whichis then drawn to a Zbuffer. To create ScreenPolygons we will need to provide a Camera

object, a Zbuffer object and a LightSource object as well. The Zbuffer object will need aDotDevice object so that it knows where to draw to.

We do not save the intermediate steps from BezierPatch to the update of the Zbuffer.In other words, we provide the BezierPatch with the objects needed, and then temporaryobjects such as the Polygons and ScreenPolygons are created and drawn directly to theZbuffer. There are a maximum of two Polygons and two ScreenPolygons in scope at atime. This lessens the memory requirements.

In the case where we visualize a surface given a set of paramatric functions the pipelinediffers. In this case we are not reading from a file and we are not creating Bezier surfaceseither. Instead we create the polygons from the parametric functions directly by hard codingthe functions into our program. In the same way as above, the Polygons are converted toScreenPolygons and thereafter drawn to the Zbuffer before going out of scope.

4 Test and Visualizations

Programmers run tests on their programs in order to document what the program can andcannot do.

4.1 Building the test

A thorough test of a program should contain a test of each class and method (for each set ofpossible input) to investigate if they work as intended (by means of equivalency classes), andtests of the programs execution as a whole (black-box testing).

It is, however, a very big task to construct a full test of this program and it’s really notthe point of this assignment. Thus, we will make a less thorough testing. The program canbe divided into parts that can be tested seperately. These parts could be the math functions,drawing of polygons, reading data and constructing Bezier surfaces, testing the z-buffer, andtesting the combined program.

The test functions can be found in appendix B starting at page 114.

4.1.1 Math functions

While these functions are central to the execution of the program, each method will not betested for each possible input. In most cases each method will be called once or twice, and ifthese calls give the expected results, the functionality will be assumed to work. Due to lackof time, the tests will not be described closer, but the test function testMath.cpp is includedin appendix B. Prints from the test run can be found in appendix A.1.

4.1.2 Drawing polygons

Being able to correctly draw a polygon is another central feature of the program. This will betested by usage of the DotDevice method TestLine to investigate if the polygons are drawnas expected. Seven different polygons will be drawn and investigated (see figure 1.1). Ontop of this it must be investigated if two polygons, placed side by side, draw the same pixels.This is best done by drawing them with a little distance, so it will become obvious. This testis included in the mentioned test.

4.1.3 Bezier surfaces

The more times the Bezier surface is subdivided, the more continuous it should appear. Thiscan be tested by drawing a figure with more and more subdivisions. The results of this test is

40

CHAPTER 4. TEST AND VISUALIZATIONS 41

shown in figure 4.10. A second way of testing the Bezier functionality is to draw the outlinesof the shapes, as seen in figure 4.11 and 4.12

4.1.4 Z-buffer

The Z-buffer can be tested by placing one polygon in front of another and viewing the result.A more difficult test is to investigate if intersection between two polygons can be handledcorrectly, i.e. if one polygon can cut through the surface of another.

4.1.5 The combined program

Testing the whole is done by running the data-files given in the assignment. These will bemade using the same source of light and reflection constants. They will be visualised fromthree different directions, from the side, from the top and from the front.

4.2 Results of the test

The results of the test runs are shown in the following pages. Most of the tests act as expected.There are, however, a few deviations.

One problem happened while testing if one polygon can cut through another. The blackpolygon in figure 4.4 should be a triangle cutting through another triangle. It most certainlyshouldn’t appear be round! A similar problem can be seen in the test run of smart.data

(figure 4.10), for less than two subdivisions of the bezier surface. In these test runs, black anddark polygons are shown in the figure. The problem seems to disappear when the number ofsubdivisions are increased - or maybe they simply get so small, that they aren’t visible.

There also seem to be some problems with visualizing the disc. There doesn’t seem to beany shading effects on the disc, regardless of the shading function used. This could happen ifthe disc is in fact just a plane. Thus there would be no difference in normal vectors, and thehighlights non-existing. If it also were small, the difference from one edge to the other wouldbe neglegent, and thus Gouraud shading wouldn’t add much.

In the visualization of the Klein bottle, viewed from the bottom, one can se a highlightedtube. This tube is highlighted as shadows are not implemented (so that was kind of expected).

All in all, we get som nice visualizations and much of the functionality seems to work.There are some problems that need to be solved, though.

CHAPTER 4. TEST AND VISUALIZATIONS 42

Figure 4.1: Test output from testing of polygon drawing.

Figure 4.2: Test output from testing of Gouraud shading.

CHAPTER 4. TEST AND VISUALIZATIONS 43

Figure 4.3: Test output from testing of Phong shading.

Figure 4.4: Test output from z-buffer testing.

Figure 4.5: Drawing Cone.data from different PRPs. The center one is drawn used Gouraudshading, the others with Phong shading.

CHAPTER 4. TEST AND VISUALIZATIONS 44

Figure 4.6: Drawing Disk.data from different PRPs. The left is drawn using Phong shading,the right with Gouraud shading.

Figure 4.7: Drawing Normal1.data from different PRPs. The center one is drawn using Phongshading, the others with Gouraud shading.

Figure 4.8: Drawing Normal2.data from different PRPs. The center one is drawn usingGouraud shading, the others with Phong shading.

CHAPTER 4. TEST AND VISUALIZATIONS 45

Figure 4.9: Drawing pain.data from different PRPs. The one on the left is drawn usingGouraud shading, the others using Phong shading.

Figure 4.10: Drawing from Smarts.data. The first four figures are subdivided 0, 1, 2 and 3times, respectively. The bottom center is using Phong shading and the bottom right is usingGouraud shading

CHAPTER 4. TEST AND VISUALIZATIONS 46

Figure 4.11: Drawing Sphere.data from different PRPs. The left one is drawn using Gouraudshading, the center one using Phong shading and the right is an outline of the polygons.

Figure 4.12: Drawing teapot.data from different PRPs. The top left uses Gouraud shading, thetop and bottom rigth uses Phong shading, and the bottom left draws outlines of the polygons

CHAPTER 4. TEST AND VISUALIZATIONS 47

Figure 4.13: Drawing the parametric curves presented in the assignment. From left, the firstand third uses line art, the second and the fifth uses Phong shading and the fourth usesGouraud shading.

5 Conclusion

We believe that the final result is satisfactory. We have analysed the important and necessaryaspects of 3D visualizations and have all aquired a good understanding of the basics. Webelieve that we have made a useful design which we might be able to build on in the future.The implementation runs and correctly reads the required data files and produces the requiredimages. Not all tests went as expected, so there is still room for improvement.

48

A Test Runs

A.1 Output from testMath.cpp

Point constructors and assignment worked as expected

Vector operations worked as expected

Basic matrix operations worked as expected

Rotation, Scaling, Shearing and Translation works as expected

Color constructor ran as expected

Methods setRed, setGreen, and setBlue worked as expected!

Projection matrix of C1 and worldPRP as expected

Projection matrix and worldPRP of C2 as expected

Material constructor and get funcitonality works as expected

Illumination calculated as expeced

Press ENTER to continue ...

49

B Source files

B.1 graphic tools.hpp

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗2 Toolbox3 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/4 #ifndef GRAPHIC TOOLS HPP5 #define GRAPHIC TOOLS HPP6

7 #include<vector>8 #include<s t r i ng>9

10

11

12

13 namespace graph ic {14 namespace t o o l s {15 /∗16 Container temp la te ”Container<T,N>” − where T i s17 the type o f e lements − to be used in Vectors ,18 Points and matr ices need to have at l e a s t the f o l l ow i n g19 header ( re turn and arg t ype s omit ted ) :20 Container ( ) ; // standard c to r21 Container (T) ; // va lue c to r22 opera tor [ ] ( i ) ; // s u b s c r i p t opera tor23 opera tor [ ] ( i ) cons t ; // cons t s u b s c r i p t o p e r a t o r24

25 T i s presumed to be a numeral type which works wi th26 s tandard a r i t hme t i c s such as +, −, / , ∗ .27 ∗/28

29 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/30 /∗ Simple conta iner temp la te us ing arrays . ∗/31 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/32 template<typename T, unsigned int N>33 class Container {34 protected :35 T data [N ] ;36 public :37 Container ( ) { // standard c to r38 for (unsigned int i = 0 ; i < N; ++i ){39 data [ i ] = T( ) ;40 }41 }42

50

APPENDIX B. SOURCE FILES 51

43 Container (T value ) { // va lue c t o r44 for (unsigned int i = 0 ; i < N; ++i ){45 data [ i ] = value ;46 }47 }48

49 Container ( Container<T,N> const& c ) { // copy c to r50 for (unsigned int i = 0 ; i < N; ++i ){51 data [ i ] = c . data [ i ] ;52 }53 }54

55 // assignment opera tor :56 Container<T,N>& operator=(Container<T,N> const& c ) {57 for (unsigned int i = 0 ; i < N; ++i ){58 data [ i ] = c . data [ i ] ;59 }60 return ∗ this ;61 }62

63 // s u b s c r i p t opera tor :64 T& operator [ ] ( unsigned int i ){65 return data [ i ] ;66 }67

68 // cons t s u b s c r i p t o p e r a t o r :69 T const& operator [ ] ( unsigned int i ) const {70 return data [ i ] ;71 }72 } ;73

74

75 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/76 /∗ BasicPoint t emp la te d e c l a r a t i on ∗/77 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/78 template<unsigned int N, typename T = f loat ,79 template <typename , unsigned int> class C = Container >80 class BasicPoint81 {82 protected :83 //Member v a r i a b l e s84 C<T,N> mCoords ;85 public :86 BasicPoint ( ) ; //Constuctor87

88 // Constructor from member type :89 BasicPoint (C<T,N> newVal ) ;90

91 // c ’ t o r from array :92 BasicPoint (T newVal [N ] ) ;93

94 // s u b s c r i p t opera tor :95 T& operator [ ] (unsigned int i ) ;96

97 // s u b s c r i p t opera tor :98 T const & operator [ ] (unsigned int i ) const ;99

APPENDIX B. SOURCE FILES 52

100 // BasicPoint e q u a l i t y opera tor :101 bool operator==(BasicPoint<N,T,C> const & p) const ;102

103 // s e t s BasicPoint to va lue in type array :104 void s e t (T newVal [N ] ) ;105

106 // p r i n t s BasicPoint to screen :107 void pr in t ( ) const ;108

109 // t h i s p r i n t s s t r i n g p r i o r to p r i n t i n g the BasicPoint :110 void pr in t ( std : : s t r i n g s t r ) const ;111

112 } ;113

114

115 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/116 /∗ Vector temp la te d e c l a r a t i on ∗/117 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/118 template<unsigned int N, typename T = f loat ,119 template <typename , unsigned int> class C = Container >120 class Vector : public BasicPoint<N,T,C>121 {122 public :123 Vector ( ) : Bas icPoint ( ) { } ; //Constuctor124

125 // Constructor from member type :126 Vector (C<T,N> newVal ) : Bas icPoint ( newVal ) { } ;127

128 // c ’ t o r from array :129 Vector (T newVal [N] ) : Bas icPoint ( newVal ) { } ;130

131 //dot−product ( Vector−Vector ) :132 T operator ∗( const Vector<N,T,C>& v) const ;133

134 //Vector−add i t i on :135 Vector<N,T,C> operator+(Vector<N,T,C> const& v) const ;136

137 //Vector−add i t i on :138 Vector<N,T,C> & operator+=(Vector<N,T,C> const& v ) ;139

140 //Vector−s u b t r a c t i on :141 Vector<N,T,C> operator−(Vector<N,T,C> const& v) const ;142

143 // the Vector−s c a l a r and sca la r−Vector mu l t i p l i c a t i o n144 // w i l l be de f ined in g l o b a l scope .145

146 // f unc t i on s147 T length ( ) const ; // c a l c u l a t e s / re turns l e n g t h o f the Vector148 void normal ize ( ) ; // normal i zes the Vector149 //we need a Vector crossproduct , but on ly f o r 3D Vectors ,150 // so i t ’ l l be de f ined in g l o b a l scope .151 } ; // Vector temp la te152

153

154

155 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/156 /∗ Point t emp la te d e c l a r a t i on ∗/

APPENDIX B. SOURCE FILES 53

157 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/158 //Point i s i n h e r i t e d from BasicPoint to avoid im p l i c i t c a s t from159 //Vector to Point .160 template<unsigned int N, typename T = f loat ,161 template <typename , unsigned int> class C = Container >162 class Point : public BasicPoint<N,T,C>163 {164 public :165 Point ( ) : Bas icPoint ( ) { } ; //Constuctor166

167 // Constructor from member type :168 Point (C<T,N> newVal ) : Bas icPoint ( newVal ) { } ;169

170 // c ’ t o r from array :171 Point (T newVal [N] ) : Bas icPoint ( newVal ) { } ;172

173 // moving po in t :174 void move( Vector<N,T,C> const & v ) ;175 } ; //Point temp la te176

177

178

179 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/180 /∗ Basic matrix t emp la te d e c l a r a t i on ∗/181 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/182 template<unsigned int N, typename T = f loat ,183 template <typename , unsigned int> class C = Container>184 class BasicMatrix185 {186 protected :187 // members188 C<C<T,N>,N> mElements ;189 public :190 BasicMatrix ( ) ; // cons t ruc tor , c on s t r u c t s i d e n t i t y Matrix191 BasicMatrix (T newVal [N ] [N ] ) ; // cons t ruc t o r from 2−dim array192 void s e t (T newVal [N ] [N ] ) ; // va lue assignment from array193 // s u b s c r i p t : Matrix [ i ] r e tu rns i ’ th row . Matrix [ i ] [ j ]194 // re turns e lement on i ’ th row in j ’ th column .195 C<T,N>& operator [ ] ( unsigned int i ) ; // s u b s c r i p t opera tor196 C<T,N> const& operator [ ] ( unsigned int i ) const ; // s u b s c r i p t op .197 bool operator==(BasicMatrix<N,T,C> const & m) const ; // Equa l i t y op .198 void pr in t ( ) const ; // i n s t u c t i o n to p r i n t Vector to screen199 // t h i s p r i n t s s t r i n g p r i o r to p r i n t i n g the Vector :200 void pr in t ( std : : s t r i n g s t r ) const ;201 } ;202

203 /∗ Matrix temp la te d e c l a r a t i on ∗/204 template<unsigned int N, typename T = f loat ,205 template <typename , unsigned int> class C = Container>206 class Matrix : public BasicMatrix<N,T,C>207 {208 public :209 // cons t ruc tor , c on s t r u c t s i d e n t i t y Matrix :210 Matrix ( ) : BasicMatrix ( ) { } ;211

212 // cons t ruc t o r from 2−dim array :213 Matrix (T newVal [N ] [N] ) : BasicMatrix ( newVal ) { } ;

APPENDIX B. SOURCE FILES 54

214

215 // Matrix mu l t i p l i c a t i o n :216 Matrix<N,T,C> operator ∗(Matrix<N,T,C> const & m) const ;217

218 // Matrix−Vector product :219 Vector<N,T,C> operator ∗( Vector<N,T,C> const & v) const ;220

221 // Matrix add i t i on :222 Matrix<N,T,C> operator+(Matrix<N,T,C> const & m) const ;223

224 // Matrix s u b t r a c t i on :225 Matrix<N,T,C> operator−(Matrix<N,T,C> const & m) const ;226

227 void t ranspose ( ) ; // Matrix t ranspose on t h i s Matrix228 Vector<N,T,C> row (unsigned int ) const ;229 Vector<N,T,C> c o l (unsigned int ) const ;230

231 void rotateX ( const T angle ) ; // ro t a t i on around the x−ax i s232 void rotateY ( const T angle ) ; // ro t a t i on around the y−ax i s233 void rotateZ ( const T angle ) ; // ro t a t i on around the z−ax i s234

235 // t r a n s l a t i o n by the s p e c i f i e d amount :236 void t r a n s l a t e ( const Vector<N,T,C> v ) ;237

238 // t r a n s l a t i o n by the s p e c i f i e d amount :239 void t r a n s l a t e ( const Point<N,T,C> p ) ;240

241 // mVec conta ins the va l u e s f o r each xyz−s c a l i n g :242 void s c a l e ( const Vector<N,T,C> v ) ;243

244 // mVec conta ins the va l u e s f o r each xyz−s c a l i n g :245 void s c a l e ( const Point<N,T,C> p ) ;246

247 //xy shear ing :248 void shearXY( const f loat shx , const f loat shy ) ;249

250 // xz shear ing :251 void shearXZ ( const f loat shx , const f loat shy ) ;252

253 // yz shear ing :254 void shearYZ ( const f loat shx , const f loat shy ) ;255 } ;256

257 // temp la te <typename T = double>258 class Color {259 protected :260 double mRed, mGreen , mBlue ;261 public :262 Color ( ) ; // d e f a u l t c ’ t o r263

264 // c ’ t o r i n i t i a l i z i n g wi th doub l e s [ 0 , 1 ] :265 Color (double red , double green , double blue ) ;266

267 // c ’ t o r i n i t i a l i z i n g wi th i n t s [ 0 , 255 ]268 //Color ( unsigned shor t i n t red , unsigned shor t i n t green ,269 // unsigned shor t i n t b l u e ) ;270 Color const & setCo lo r ( Color const & co l o r ) ;

APPENDIX B. SOURCE FILES 55

271 double setRed (double value ) ; // echoes va lue as re turn va lue .272 double setGreen (double value ) ;273 double se tBlue (double value ) ;274

275 // echoes mRed/mGreen/mBlue as re turn va lue .276 double changeRed (double value ) ;277 double changeGreen (double value ) ;278 double changeBlue (double value ) ;279

280 double getRed ( ) const ;281 double getGreen ( ) const ;282 double getBlue ( ) const ;283

284 bool operator==(Color const & c ) const ; // co l o r e q u a l i t y op .285 void pr in t ( ) const ;286 void pr in t ( std : : s t r i n g s t r ) const ;287 } ;288

289 Color const green ( 0 , 1 . 0 , 0 ) ;290 Color const red ( 1 . 0 , 0 , 0 ) ;291 Color const blue ( 0 , 0 , 1 . 0 ) ;292 Color const orange ( 1 . 0 , 0 . 5 , 0 ) ;293 Color const ye l low ( 1 . 0 , 1 . 0 , 0 ) ;294 Color const magenta ( 1 . 0 , 0 , 0 . 5 ) ;295 Color const v i o l e t ( 1 . 0 , 0 , 1 . 0 ) ;296 Color const cyan ( 0 , 1 . 0 , 1 . 0 ) ;297 Color const white ( 1 . 0 , 1 . 0 , 1 . 0 ) ;298 Color const grey ( 0 . 5 , 0 . 5 , 0 . 5 ) ;299 Color const black ( 0 . 0 , 0 . 0 , 0 . 0 ) ;300

301 template <typename T>302 inl ine T s ign (T value ) {303 i f ( va lue < 0)304 return (T) −1;305 else i f ( va lue == 0)306 return (T) 0 ;307 return (T) 1 ;308 }309

310 }311 }312 #endif // GRAPHIC TOOLS HPP

B.2 graphic tools.cpp

1 #include <cmath> // s q r t ( x )2 #include <stdexcept>3 #include <iostream>4 #include ” g r aph i c t o o l s . hpp”5

6 #define PI 3.141592653589793238467

8 using namespace graph ic : : t o o l s ;9

10 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗11 ∗ BasicPoint t emp la te implementat ion ∗

APPENDIX B. SOURCE FILES 56

12 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/13

14 // BasicPoint temp la te d e f a u l t c ons t ruc t o r15 template<unsigned int N, typename T,16 template <typename , unsigned int> class C>17 inl ine BasicPoint<N,T,C> : : Bas icPoint ( ) : mCoords ( ) {}18

19 // BasicPoint temp la te member conta iner type cons t ruc t o r20 template<unsigned int N, typename T,21 template <typename , unsigned int> class C>22 inl ine BasicPoint<N,T,C> : : Bas icPoint (C<T,N> c ) : mCoords ( c ) {}23

24 // BasicPoint temp la te array cons t ruc t o r25 template<unsigned int N, typename T,26 template <typename , unsigned int> class C>27 inl ine BasicPoint<N,T,C> : : Bas icPoint (T newVal [N] ) {28 for (unsigned int i = 0 ; i<N; ++i ){29 mCoords [ i ] = newVal [ i ] ;30 }31 }32

33 // BasicPoint temp la te s u b s c r i p t opera tor s34 template<unsigned int N, typename T,35 template <typename , unsigned int> class C>36 inl ine T& BasicPoint<N,T,C> : : operator [ ] ( unsigned int i ) {37 return mCoords [ i ] ;38 }39

40 template<unsigned int N, typename T,41 template <typename , unsigned int> class C>42 inl ine T const & BasicPoint<N,T,C> : : operator [ ] (unsigned int i ) const {43 return mCoords [ i ] ;44 }45

46 // BasicPoint e q u a l i t y opera tor47 template<unsigned int N, typename T,48 template <typename , unsigned int> class C>49 inl ine bool BasicPoint<N,T,C> : : operator==(BasicPoint<N,T,C> const & p) const{50 for (unsigned int i = 0 ; i < N; ++i ) {51 T compareVal = abs (mCoords [ i ] / 1 0 0 0 0 . ) ;52 i f ( compareVal < 0 .0001 )53 compareVal = 0 . 0001 ;54 i f ( abs (mCoords [ i ] − p [ i ] ) > compareVal ){55 /∗ s t d : : cout << ”Error in coord ina te ” << i << ” , go t ”56 << p [ i ] << ” and expec ted ”57 << mCoords [ i ] << s t d : : end l ; ∗/58 /∗ s t d : : cout << ” error a l l owed : ”59 << (mElements [ i ] [ j ] / 1 0 . ) << ” ”60 << abs (mElements [ i ] [ j ] − m[ i ] [ j ] ) << s t d : : end l ; ∗/61 return fa lse ;62 }63 }64 return true ;65 }66

67 // s e t s va lue o f BasicPoint coord ina t e s to va l u e s g i ven in array68 template<unsigned int N, typename T, template <typename , unsigned int> class C>

APPENDIX B. SOURCE FILES 57

69 inl ine void BasicPoint<N,T,C> : : s e t (T newVal [N] ) {70 for (unsigned int i = 0 ; i<N; ++i ){71 mCoords [ i ] = newVal [ i ] ;72 }73 }74

75 // p r i n t s the BasicPoint to the screen76 template<unsigned int N, typename T, template <typename , unsigned int> class C>77 inl ine void BasicPoint<N,T,C> : : p r i n t ( ) const{78 std : : cout << ” ( ” ;79 for (unsigned int i = 0 ; i<N−1 ; ++i )80 std : : cout << mCoords [ i ] << ” , ” ;81 std : : cout << mCoords [N−1] << ” ) ” << std : : endl ;82 }83

84 // p r i n t s s t r to screen be f o r e p r i n t i n g BasicPoint85 template<unsigned int N, typename T, template <typename , unsigned int> class C>86 inl ine void BasicPoint<N,T,C> : : p r i n t ( std : : s t r i n g s t r ) const{87 std : : cout << s t r ;88 this−>pr in t ( ) ;89 }90

91

92 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗93 ∗ Point t emp la te implementat ion ∗94 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/95

96 // moving po in t97 template<unsigned int N, typename T, template <typename , unsigned int> class C>98 inl ine void Point<N,T,C> : :move( Vector<N,T,C> const & v){99 for ( int i = 0 ; i < N; ++i ) {

100 mCoords [ i ] += v [ i ] ;101 }102 }103

104

105 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗106 ∗ Vector temp la te implementat ion ∗107 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/108

109 //dot−product ( Vector−Vector )110 template<unsigned int N, typename T, template <typename , unsigned int> class C>111 inl ine T Vector<N,T,C> : : operator ∗( const Vector<N,T,C>& v) const {112 T r e s u l t = 0 ;113 for (unsigned int i =0; i<N ; i++){114 r e s u l t += mCoords [ i ]∗ v [ i ] ;115 }116 return r e s u l t ;117 }118 // mu l t i p l i c a t i o n o f Vector wi th a s c a l a r119 // the f i r s t f unc t i on a l l ows sca la r−Vector mu l t i p l i c a t i o n120

121 template<unsigned int N, typename T1 , typename T2 ,122 template <typename , unsigned int> class C>123 inl ine Vector<N,T1 ,C> operator ∗(T2 const& s , Vector<N,T1 ,C> const& v) {124 Vector<N,T1 ,C> r e s u l t ;125 for (unsigned int i=0 ; i<N ; i++){

APPENDIX B. SOURCE FILES 58

126 r e s u l t [ i ] = s ∗v [ i ] ;127 }128 return r e s u l t ;129 }130

131 // the second func t i on a l l ows Vector−s c a l a r mu l t i p l i c a t i o n132 template<unsigned int N, typename T1 , typename T2 ,133 template <typename , unsigned int> class C>134 inl ine Vector<N,T1 ,C> operator ∗( Vector<N,T1 ,C> const& v , T2 const& s ) {135 return s ∗v ;136 }137

138 //Vector−Vector add i t i on139 template<unsigned int N, typename T, template <typename , unsigned int> class C>140 inl ine Vector<N,T,C> Vector<N,T,C> : : operator+(Vector<N,T,C> const& v) const{141 Vector<N,T,C> r e s u l t ;142 for (unsigned int i =0; i<N ; i++){143 r e s u l t [ i ] = mCoords [ i ]+v [ i ] ;144 }145 return r e s u l t ;146 }147

148 template<unsigned int N, typename T, template <typename , unsigned int> class C>149 inl ine Vector<N,T,C> & Vector<N,T,C> : : operator+=(Vector<N,T,C> const& v) {150 for (unsigned int i =0; i<N ; i++){151 mCoords [ i ] += v [ i ] ;152 }153 return ∗ this ;154 }155

156 //Vector−Vector add i t i on157 template<unsigned int N, typename T, template <typename , unsigned int> class C>158 inl ine Vector<N,T,C> Vector<N,T,C> : :operator−(Vector<N,T,C> const& v) const{159 Vector<N,T,C> r e s u l t ;160 for (unsigned int i =0; i<N ; i++){161 r e s u l t [ i ] = mCoords [ i ]−v [ i ] ;162 }163 return r e s u l t ;164 }165

166 // Vector temp la te l e n g t h func t i on167 // t h i s f unc t i on c a l c u l a t e s the l e n g t h o f the Vector168 // the l e n g t h i s the square roo t o f the sum over the square o f a l l e lements169 template<unsigned int N, typename T, template <typename , unsigned int> class C>170 inl ine T Vector<N,T,C> : : l ength ( ) const{171 T length = 0 ;172 for (unsigned int i = 0 ; i<N ; ++i ){173 l ength += mCoords [ i ] ∗ mCoords [ i ] ;174 }175 l ength = sq r t ( l ength ) ;176 return l ength ;177 }178

179 // Vector normal ize f unc t i on180 // t h i s f unc t i on normal i zes the Vector , so i t has a l en g t h o f 1181 template<unsigned int N, typename T, template <typename , unsigned int> class C>182 inl ine void Vector<N,T,C> : : normal ize ( ){

APPENDIX B. SOURCE FILES 59

183 T length = this−>l ength ( ) ;184 for (unsigned int i = 0 ; i<N; ++i ){185 mCoords [ i ] /= length ;186 }187 }188

189 // the Vector c ro s s product i s on ly a l l owed f o r 3d Vectors190 template<typename T, template <typename , unsigned int> class C>191 inl ine Vector<3,T,C> c r o s s ( Vector<3,T,C>& v1 , Vector<3,T,C>& v2 ){192 Vector<3,T,C> newVector ;193 newVector [ 0 ] = v1 [ 1 ] ∗ v2 [ 2 ] − v1 [ 2 ] ∗ v2 [ 1 ] ;194 newVector [ 1 ] = v1 [ 2 ] ∗ v2 [ 0 ] − v1 [ 0 ] ∗ v2 [ 2 ] ;195 newVector [ 2 ] = v1 [ 0 ] ∗ v2 [ 1 ] − v1 [ 1 ] ∗ v2 [ 0 ] ;196 return newVector ;197 }198

199 // c a l c u l a t e s the v ec t o r po in t i n g from p1 to p2200 template<unsigned int N, typename T,201 template <typename , unsigned int> class C>202 inl ine Vector<N,T,C> vectorFromPoints ( const Point<N,T,C>& p1 ,203 const Point<N,T,C>& p2 ){204 Vector<N,T,C> newVector ;205 for ( int i =0; i<N; ++i )206 {207 newVector [ i ] = p2 [ i ] − p1 [ i ] ;208 }209 return newVector ;210 }211

212

213

214 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗215 ∗ Basic matrix implementat ion ∗216 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/217

218 // BasicMatrix d e f a u l t c ons t ruc t o r219 template<unsigned int N, typename T,220 template <typename , unsigned int> class C>221 inl ine BasicMatrix<N,T,C> : : BasicMatrix ( ) : mElements (C<T,N>()){222 for (unsigned int i = 0 ; i < N; ++i ){223 mElements [ i ] [ i ] = 1 ;224 }225 }226

227 // BasicMatrix cons t ruc t o r from array228 template<unsigned int N, typename T,229 template <typename , unsigned int> class C>230 inl ine BasicMatrix<N,T,C> : : BasicMatrix (T value [N ] [N] ) {231 s e t ( va lue ) ;232 }233

234 template<unsigned int N, typename T,235 template <typename , unsigned int> class C>236 inl ine void BasicMatrix<N,T,C> : : s e t (T value [N ] [N] ) {237 for (unsigned int i = 0 ; i < N; ++i ){238 for (unsigned int j = 0 ; j < N; ++j ){239 mElements [ i ] [ j ] = value [ i ] [ j ] ;

APPENDIX B. SOURCE FILES 60

240 }241 }242 }243

244 // BasicMatrix s u b s c r i p t opera tor s245 template<unsigned int N, typename T,246 template <typename , unsigned int> class C>247 inl ine C<T,N>& BasicMatrix<N,T,C> : : operator [ ] ( unsigned int i ) {248 return mElements [ i ] ;249 }250 template<unsigned int N, typename T,251 template <typename , unsigned int> class C>252 inl ine C<T,N> const& BasicMatrix<N,T,C> : : operator [ ] ( unsigned int i ) const {253 return mElements [ i ] ;254 }255

256 // BasicMatrix e q u a l i t y operator , r e tu rns t rue257 // i f a l l v a l u e s in the matrix are equa l258 // used in t e s t i n g by a s s e r t259 template<unsigned int N, typename T,260 template <typename , unsigned int> class C>261 inl ine bool BasicMatrix<N,T,C> : : operator==(BasicMatrix<N,T,C> const & m) const{262 for (unsigned int i = 0 ; i < N; ++i ) {263 for (unsigned int j = 0 ; j < N; ++j ) {264 T compareVal = abs (mElements [ i ] [ j ] / 1 0 0 0 0 . ) ;265 i f ( compareVal < 0 .0001 )266 compareVal = 0 . 0001 ;267

268 //aka f l o a t i n g po in t ==269 i f ( abs (mElements [ i ] [ j ] − m[ i ] [ j ] ) > compareVal ){270 std : : cout << ”Error in ( ” << i << ” , ” << j << ” ) , got ”271 << m[ i ] [ j ] << ” and expected ”272 << mElements [ i ] [ j ] << std : : endl ;273 /∗ s t d : : cout << ” error a l l owed : ” << (mElements [ i ] [ j ] / 1 0 . )274 << ” ”275 << abs (mElements [ i ] [ j ] − m[ i ] [ j ] ) << s t d : : end l ; ∗/276 return fa lse ;277 }278 }279 }280 return true ;281 }282

283 // p r i n t ∗ t h i s BasicMatrix284 template<unsigned int N, typename T,285 template <typename , unsigned int> class C>286 inl ine void BasicMatrix<N,T,C> : : p r i n t ( ) const{287 std : : cout << ” [ [ ” ;288 for (unsigned int j = 0 ; j < N−1; ++j ) {289 std : : cout << mElements [ 0 ] [ j ] << ” ; ” ;290 }291 std : : cout << mElements [ 0 ] [ N−1] << ” ] ” << std : : endl ;292 for (unsigned int i = 1 ; i < N−1; ++i ) {293 std : : cout << ” [ ” ;294 for (unsigned int j = 0 ; j < N−1; ++j ) {295 std : : cout << mElements [ i ] [ j ] << ” ; ” ;296 }

APPENDIX B. SOURCE FILES 61

297 std : : cout << mElements [ i ] [ N−1] << ” ] ” << std : : endl ;298 }299 std : : cout << ” [ ” ;300 for (unsigned int j = 0 ; j < N−1; ++j ) {301 std : : cout << mElements [N−1] [ j ] << ” ; ” ;302 }303 std : : cout << mElements [N−1] [N−1] << ” ] ] ” << std : : endl ;304 }305

306 // p r i n t ∗ t h i s BasicMatrix wi th p r e f i x .307 template<unsigned int N, typename T,308 template <typename , unsigned int> class C>309 inl ine void BasicMatrix<N,T,C> : : p r i n t ( std : : s t r i n g s t r ) const{310 std : : cout << s t r << std : : endl ;311 pr in t ( ) ;312 }313

314

315

316 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗317 ∗ Matrix implementat ion ∗318 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/319

320 // Matrix mu l t i p l i c a t i o n321 template<unsigned int N, typename T,322 template <typename , unsigned int> class C>323 inl ine Matrix<N,T,C> Matrix<N,T,C> : : operator ∗(Matrix<N,T,C> const & m) const{324 Matrix<N,T,C> returnMatr ix ;325 for (unsigned int i = 0 ; i < N; ++i ) {326 for (unsigned int j = 0 ; j < N; ++j ) {327 T sum = 0 ;328 for (unsigned int k = 0 ; k < N; ++k) {329 sum += mElements [ i ] [ k ] ∗ m[ k ] [ j ] ;330 returnMatr ix [ i ] [ j ] = sum ;331 }332 }333 }334 return returnMatr ix ;335 }336

337

338 // Matrix−Vector product339 template<unsigned int N, typename T, template <typename , unsigned int> class C>340 inl ine Vector<N,T,C> Matrix<N,T,C> : : operator ∗( Vector<N,T,C> const & v) const{341 Vector<N,T,C> returnVector ;342 for (unsigned int i = 0 ; i < N; ++i ){343 T sum = 0 ;344 for (unsigned int k = 0 ; k < N; ++k){345 sum += mElements [ i ] [ k ] ∗ v [ k ] ;346 }347 returnVector [ i ] = sum ;348 }349 return returnVector ;350 }351

352 // Matrix add i t i on353 template<unsigned int N, typename T, template <typename , unsigned int> class C>

APPENDIX B. SOURCE FILES 62

354 inl ine Matrix<N,T,C> Matrix<N,T,C> : : operator+(Matrix<N,T,C> const & m) const{355 Matrix<N,T,C> returnMatr ix ;356 for (unsigned int i = 0 ; i < N; ++i ) {357 for (unsigned int j = 0 ; j < N; ++j ) {358 returnMatr ix [ i ] [ j ] = mElements [ i ] [ j ] + m[ i ] [ j ] ;359 }360 }361 return returnMatr ix ;362 }363

364 // Matrix s u b t r a c t i on365 template<unsigned int N, typename T, template <typename , unsigned int> class C>366 inl ine Matrix<N,T,C> Matrix<N,T,C> : :operator−(Matrix<N,T,C> const & m) const{367 Matrix<N,T,C> returnMatr ix ;368 for (unsigned int i = 0 ; i < N; ++i ) {369 for (unsigned int j = 0 ; j < N; ++j ) {370 returnMatr ix [ i ] [ j ] = mElements [ i ] [ j ] − m[ i ] [ j ] ;371 }372 }373 return returnMatr ix ;374 }375

376 // Matrix t ranspose377 template<unsigned int N, typename T, template <typename , unsigned int> class C>378 inl ine void Matrix<N,T,C> : : t ranspose ( ) {379 Matrix<N,T,C> copy (∗ this ) ;380 for (unsigned int i = 0 ; i < N; ++i ) {381 for (unsigned int j = 0 ; j < N; ++ j ) {382 mElements [ i ] [ j ] = copy [ j ] [ i ] ;383 }384 }385 }386

387 template<unsigned int N, typename T, template <typename , unsigned int> class C>388 inl ine Vector<N,T,C> Matrix<N,T,C> : : row (unsigned int i ) const{389 i f ( i < N){390 return Vector<N,T,C>(mElements [ i ] ) ;391 } else {392 throw std : : ou t o f r ange ( ”Matrix row index out o f range ! ” ) ;393 }394 }395

396 template<unsigned int N, typename T, template <typename , unsigned int> class C>397 inl ine Vector<N,T,C> Matrix<N,T,C> : : c o l (unsigned int j ) const{398 i f ( j < N){399 C<T,N> mColumn ;400 for (unsigned int i = 0 ; i < N; ++i ) {401 mColumn [ i ] = mElements [ i ] [ j ] ;402 }403 return Vector<N,T,C>(mColumn ) ;404

405 } else {406 throw std : : ou t o f r ange ( ”Matrix column index out o f range ! ” ) ;407 }408 }409

410 // r o t a t e s the matrix around the x−ax is , by the va lue in ang l e

APPENDIX B. SOURCE FILES 63

411 template<unsigned int N, typename T, template <typename , unsigned int> class C>412 inl ine void Matrix<N,T,C> : : rotateX ( const T angle ) {413 i f (N == 4){414 T rad = angle ∗ PI /180 ; // conver t ing from ang le to radian415 T rotArray [ 4 ] [ 4 ] = { {1 ,0 ,0 ,0} , {0 , cos ( rad ) ,− s i n ( rad ) , 0} ,416 {0 , s i n ( rad ) , cos ( rad ) , 0} , {0 ,0 ,0 ,1} } ;417 Matrix<N,T,C> ro tat ionMatr ix ( rotArray ) ;418 mElements = ( rotat ionMatr ix ∗ (∗ this ) ) . mElements ;419 }420 else {421 throw std : : inva l id argument ( ”May only r o t a t e 4x4 mat r i c i e s ! ” ) ;422 }423 }424

425 // r o t a t e s the matrix around the y−ax is , by the va lue in ang l e426 template<unsigned int N, typename T, template <typename , unsigned int> class C>427 inl ine void Matrix<N,T,C> : : rotateY ( const T angle ) {428 i f (N == 4){429 T rad = angle ∗ PI /180 ; // conver t ing from ang le to radian430 T rotArray [ 4 ] [ 4 ] = { { cos ( rad ) , 0 , s i n ( rad ) , 0} , {0 ,1 ,0 ,0} ,431 {− s i n ( rad ) , 0 , cos ( rad ) , 0} , {0 ,0 ,0 ,1} } ;432 Matrix<N,T,C> ro tat ionMatr ix ( rotArray ) ;433 mElements = ( rotat ionMatr ix ∗ (∗ this ) ) . mElements ;434 }435 else {436 throw std : : inva l id argument ( ”May only r o t a t e 4x4 mat r i c i e s ! ” ) ;437 }438 }439

440 // r o t a t e s the matrix around the z−ax is , by the va lue in ang l e441 template<unsigned int N, typename T, template <typename , unsigned int> class C>442 inl ine void Matrix<N,T,C> : : ro tateZ ( const T angle ) {443 i f (N == 4){444 T rad = angle ∗ PI /180 ; // conver t ing from ang le to radian445 T rotArray [ 4 ] [ 4 ] = { { cos ( rad ) ,− s i n ( rad ) , 0 , 0} , { s i n ( rad ) , cos ( rad ) , 0 , 0} ,446 {0 ,0 ,1 ,0} , {0 ,0 ,0 ,1} } ;447 Matrix<N,T,C> ro tat ionMatr ix ( rotArray ) ;448 mElements = ( rotat ionMatr ix ∗ (∗ this ) ) . mElements ;449 }450 else {451 throw std : : inva l id argument ( ”May only r o t a t e 4x4 mat r i c i e s ! ” ) ;452 }453 }454

455 // t r a n s l a t e s by the va l u e s s t o r ed in vec t o r456 template<unsigned int N, typename T, template <typename , unsigned int> class C>457 inl ine void Matrix<N,T,C> : : t r a n s l a t e ( const Vector<N,T,C> v ){458 i f (N == 4){459 T transArray [ 4 ] [ 4 ] = { {1 ,0 ,0 , v [ 0 ] } , {0 ,1 ,0 , v [ 1 ] } , {0 ,0 ,1 , v [ 2 ] } ,460 {0 ,0 , 0 , 1}} ;461 Matrix<N,T,C> t r an s l a t i onMat r i x ( transArray ) ;462 mElements = ( t ran s l a t i onMat r i x ∗ (∗ this ) ) . mElements ;463 }464 else {465 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;466 }467 }

APPENDIX B. SOURCE FILES 64

468

469 // t r a n s l a t e s by the va l u e s s t o r ed in po in t470 template<unsigned int N, typename T, template <typename , unsigned int> class C>471 inl ine void Matrix<N,T,C> : : t r a n s l a t e ( const Point<N,T,C> p){472 i f (N == 4){473 T transArray [ 4 ] [ 4 ] = { {1 ,0 ,0 , p [ 0 ] } , {0 ,1 ,0 , p [ 1 ] } , {0 ,0 ,1 , p [ 2 ] } ,474 {0 ,0 , 0 , 1}} ;475 Matrix<N,T,C> t r an s l a t i onMat r i x ( transArray ) ;476 mElements = ( t ran s l a t i onMat r i x ∗ (∗ this ) ) . mElements ;477 }478 else {479 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;480 }481 }482

483 // mVec conta ins the va l u e s f o r each xyz−s c a l i n g484 template<unsigned int N, typename T, template <typename , unsigned int> class C>485 inl ine void Matrix<N,T,C> : : s c a l e ( const Vector<N,T,C> v ){486 i f (N == 4){487 T sca l eArray [ 4 ] [ 4 ] = { {v [ 0 ] , 0 , 0 , 0 } , {0 , v [ 1 ] , 0 , 0 } , {0 ,0 , v [ 2 ] , 0 } ,488 {0 ,0 ,0 ,1} } ;489 Matrix<N,T,C> s ca l eMatr ix ( sca l eArray ) ;490 mElements = ( sca l eMatr ix ∗ (∗ this ) ) . mElements ;491 }492 else {493 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;494 }495 }496

497 // mVec conta ins the va l u e s f o r each xyz−s c a l i n g498 template<unsigned int N, typename T, template <typename , unsigned int> class C>499 inl ine void Matrix<N,T,C> : : s c a l e ( const Point<N,T,C> p){500 i f (N == 4){501 T sca l eArray [ 4 ] [ 4 ] = { {p [ 0 ] , 0 , 0 , 0 } , {0 ,p [ 1 ] , 0 , 0 } , {0 ,0 , p [ 2 ] , 0 } ,502 {0 ,0 ,0 ,1} } ;503 Matrix<N,T,C> s ca l eMatr ix ( sca l eArray ) ;504 mElements = ( sca l eMatr ix ∗ (∗ this ) ) . mElements ;505 }506 else {507 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;508 }509 }510 //xy shear ing511 template<unsigned int N, typename T, template <typename , unsigned int> class C>512 inl ine void Matrix<N,T,C> : : shearXY( const f loat shx , const f loat shy ){513 i f (N == 4){514 T shearArray [ 4 ] [ 4 ] = { {1 ,0 , shx ,0} , {0 ,1 , shy ,0} , {0 ,0 ,1 ,0} ,515 {0 ,0 ,0 ,1} } ;516 Matrix<N,T,C> shearMatr ix ( shearArray ) ;517 mElements = ( shearMatr ix ∗ (∗ this ) ) . mElements ;518 }519 else {520 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;521 }522 }523

524 // xz shear ing , l e c t u r e s l i d e s

APPENDIX B. SOURCE FILES 65

525 template<unsigned int N, typename T, template <typename , unsigned int> class C>526 inl ine void Matrix<N,T,C> : : shearXZ ( const f loat shx , const f loat shz ){527 i f (N == 4){528 T shearArray [ 4 ] [ 4 ] = { {1 , shx , 0 , 0} , {0 ,1 ,0 ,0} , {0 , shz , 1 , 0} ,529 {0 ,0 ,0 ,1} } ;530 Matrix<N,T,C> shearMatr ix ( shearArray ) ;531 mElements = ( shearMatr ix ∗ (∗ this ) ) . mElements ;532 }533 else {534 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;535 }536 }537

538 //xy shear ing , l e c t u r e s l i d e s539 template<unsigned int N, typename T, template <typename , unsigned int> class C>540 inl ine void Matrix<N,T,C> : : shearYZ ( const f loat shy , const f loat shz ){541 i f (N == 4){542 T shearArray [ 4 ] [ 4 ] = { {1 ,0 ,0 ,0} , {shy , 1 , 0 , 0} , { shz , 0 , 1 , 0} ,543 {0 ,0 ,0 ,1} } ;544 Matrix<N,T,C> shearMatr ix ( shearArray ) ;545 mElements = ( shearMatr ix ∗ (∗ this ) ) . mElements ;546 }547 else {548 throw std : : inva l id argument ( ”May only r o t a t e 4x4 matr i ce s ! ” ) ;549 }550 }551

552

553

554 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗555 ∗ Color implementat ion ∗556 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/557

558 // d e f a u l t c ’ t o r559 Color : : Color ( ) : mRed( ) , mGreen ( ) , mBlue ( ) {}560

561 // c ’ t o r i n i t i a l i z i n g wi th doub l e s [ 0 , 1 ]562 inl ine Color : : Color (double red , double green , double blue ){563 // s e t t i n g red564 i f ( red > 1)565 mRed = 1 ;566 else i f ( red < 0)567 mRed = 0 ;568 else569 mRed = red ;570 // s e t t i n g green571 i f ( green > 1)572 mGreen = 1 ;573 else i f ( green < 0)574 mGreen = 0 ;575 else576 mGreen = green ;577 // b l u e578 i f ( b lue > 1)579 mBlue = 1 ;580 else i f ( b lue < 0)581 mBlue = 0 ;

APPENDIX B. SOURCE FILES 66

582 else583 mBlue = blue ;584 }585

586 // s e t s the co l o r in t h i s o b j e c t as the co lor−va lue in the587 inl ine Color const & Color : : s e tCo lo r ( Color const & newColor ){588 mRed = newColor . getRed ( ) ;589 mGreen = newColor . getGreen ( ) ;590 mBlue = newColor . getBlue ( ) ;591 return newColor ;592 }593

594 // s e t s the va lue in mRed to va lue595 inl ine double Color : : setRed (double red ){596 // s e t t i n g red597 i f ( red > 1)598 mRed = 1 ;599 else i f ( red < 0)600 mRed = 0 ;601 else602 mRed = red ;603 return mRed;604 }605

606 // s e t s the va lue in mGreen to va lue607 inl ine double Color : : setGreen (double green ){608 i f ( green > 1)609 mGreen = 1 ;610 else i f ( green < 0)611 mGreen = 0 ;612 else613 mGreen = green ;614 return mGreen ;615 }616

617 // s e t s the va lue in mBlue to va lue618 inl ine double Color : : s e tBlue (double blue ){619 i f ( b lue > 1)620 mBlue = 1 ;621 else i f ( b lue < 0)622 mBlue = 0 ;623 else624 mBlue = blue ;625 return mBlue ;626 }627

628 // changes mRed with va lue629 inl ine double Color : : changeRed (double value ){630 mRed += value ;631 i f (mRed < 0 . 0 )632 mRed = 0 . 0 ;633 i f (mRed > 1 . 0 )634 mRed = 1 . 0 ;635 return mRed;636 }637

638 // changes mGreen wi th va lue

APPENDIX B. SOURCE FILES 67

639 inl ine double Color : : changeGreen (double value ){640 mGreen += value ;641 i f (mGreen < 0 . 0 )642 mGreen = 0 . 0 ;643 i f (mGreen > 1 . 0 )644 mGreen = 1 . 0 ;645 return mGreen ;646 }647

648 // changes mBlue wi th va lue649 inl ine double Color : : changeBlue (double value ){650 mBlue += value ;651 i f (mBlue < 0 . 0 )652 mBlue = 0 . 0 ;653 i f (mBlue > 1 . 0 )654 mBlue = 1 . 0 ;655 return mBlue ;656 }657

658 // re tu rns the va lue in Red659 inl ine double Color : : getRed ( ) const{660 return mRed;661 }662

663 // re tu rns the va lue in Green664 inl ine double Color : : getGreen ( ) const{665 return mGreen ;666 }667

668 // re tu rns the va lue in Blue669 inl ine double Color : : getBlue ( ) const{670 return mBlue ;671 }672

673 // Color e q u a l i t y opera tor674 bool Color : : operator==(Color const & c ) const{675 i f ( abs (mRed − c . getRed ( ) ) > 0 .001 | |676 abs (mGreen − c . getGreen ( ) ) > 0 .001 | |677 abs (mBlue − c . getBlue ( ) ) > 0 .001 )678 {679 std : : cout << ”Error in c o l o r e qua l i t y ! Had : ( ” << mRed680 << ” , ” << mGreen << ” , ” << mBlue << ” ) Got : ”681 << std : : cout << ” ( ” << c . getRed ( ) << ” , ”682 << c . getGreen ( ) << ” , ” << c . getBlue ( )683 << ” ) ” << std : : endl ;684 // t h i s−>p r i n t (” Error in co l o r e q u a l i t y ! Had : ” ) ;685 //c . p r i n t (” go t : ” ) ;686 return fa lse ;687 }688 return true ;689 }690

691 void Color : : p r i n t ( ) const692 {693 std : : cout << ” ( ” << mRed << ” , ” << mGreen << ” , ”694 << mBlue << ” ) ” << std : : endl ;695 }

APPENDIX B. SOURCE FILES 68

696

697 void Color : : p r i n t ( std : : s t r i n g s t r ) const698 {699 std : : cout << s t r ;700 pr in t ( ) ;701 }

B.3 graphic world.hpp

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗2 ’World ’ c l a s s e s3 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/4 #ifndef GRAPHIC WORLD HPP5 #define GRAPHIC WORLD HPP6

7 #include<s t r i ng>8 #include <vector>9 //#inc l ude ” g r a p h i c t o o l s . cpp”

10

11

12

13 using namespace graph ic : : t o o l s ;14

15 namespace graph ic {16 namespace draw {17 template<typename T>18 class Zbuf f e r ;19 }20 using namespace draw ;21 namespace world {22 template<typename T = f loat> class Mater ia l ;23

24 template<typename T = f loat>25 class Polygon {26 protected :27 Point<3,T> mPoints [ 3 ] ;28 Vector<3,T> mNormals [ 3 ] ;29 Mater ia l<T> const∗ mMaterial ;30 public :31 Polygon ( Point<3,T> const& p0 , Point<3,T> const& p1 ,32 Point<3,T> const& p2 , Vector<3,T> const& v0 ,33 Vector<3,T> const& v1 , Vector<3,T> const& v2 ,34 Mater ia l<T> const& m) ;35 Polygon ( Polygon<T> const & p ) ;36 Polygon ( ) {} ;37 Point<3,T> const& point (unsigned int i , Point<3,T> const& p ) ;38 Point<3,T> const& point (unsigned int i ) const ;39 Vector<3,T> const& normal (unsigned int i , Vector<3,T> const& v ) ;40 Vector<3,T> const& normal (unsigned int i ) const ;41 Mater ia l<T> const& mate r i a l ( Mater ia l<T> const& m) ;42 Mater ia l<T> const& mate r i a l ( ) const ;43 void pro j e c tPo in t s (Matrix<4,T> const& matrix ) ;44 void projectNormals (Matrix<4,T> const& matrix ) ;45 void pr in t ( std : : s t r i n g s t r = ”” ) ;46 } ;47

APPENDIX B. SOURCE FILES 69

48 // This c l a s s con ta ins the p r o j e c t i on p lane and i s used to49 // s e t up the system50 template<typename T = f loat> class Camera{51 protected :52 // the s e are s e t by the cons t ruc tor , and can be accessed53 // and modi f ied by ge t and s e t f u n c t i o n a l i t y .54

55 // the o r i g i n o f view coord ina te system in world coord ina t e s :56 Point<3,T> VRP;57 // the eye o f the beho l de r in view coord ina t e s :58 Point<3,T> PRP;59 // the eye o f the beho l de r in world coord ina t e s :60 Point<3,T> worldPRP ;61 // the view p lane normal :62 Vector<3,T> VPN;63 // view up vec to r :64 Vector<3,T> VUP;65 // d e l im i t e r o f window , must have minimum va lue s ( u min , v min ) :66 Point<3,T> w1 ;67 // d e l im i t e r o f window , must have maximum va lu e s (u max , v max ) :68 Point<3,T> w2 ;69 T B; // the s i gned d i s t ance from VRP to back c l i p p i n g p lane70 T F; // the s i gned d i s t ance from VRP to f r on t c l i p p i n g p lane71 // the s e can only be modi f ied by modi fy ing the f i e l d s above72 // ( in which case the f i e l d s be low must be r e c a l c u l a t e d73 Point<3,T> CW; // cen ter o f window74 Vector<3,T> DOP; // d i r e c t i o n o f p r o j e c t i on75 Vector<3,T> u ; // ”x” ax i s76 Vector<3,T> v ; // ”y” ax i s77 Vector<3,T> n ; // ” z” ax i s78 Matrix<4,T> ProjMatr ; // the p r o j e c t i on matrix79 // making sure i f the p r o j e c t i on matrix i s in a v a l i d s t a t e :80 bool pro jMatr ix I sVa l id ;81

82 public :83 // d e f a u l t c ons t ruc t o r84 //Camera ( ) ;85 // e x p l i c i t c ons t ruc t o r86 Camera ( Point<3,T> mVRP, Point<3,T> mPRP, Vector<3,T> mVPN,87 Vector<3,T> mVUP, Point<3,T> mw1, Point<3,T> mw2, T mB, T mF) ;88 // handy cons t ruc t o r89 // po s i t i o n : p o s i t i o n ( po in t ) o f p e r s p e c t i v e r e f e r ence po in t in world coords90 // aim : po in t camera i s aiming f o r91 // up : up−vec t o r92 // s i z e : v e r t i c a l and ho r i z on t a l s i z e o f view plane93 // zoom :94 Camera ( Point<3,T> pos i t i on , Point<3,T> aim , Vector<3,T> up ,95 T s i z e = 1 , T zoom = 1 , T f rontC l ipp ingP lane = 0 ,96 T backCl ippingPlane = −20);97 // s e t f u n c t i o n a l i t y − note t ha t t h e s e methods w i l l need98 // to update a number o f f i e l d s99 void setVRP( Point<3,T> newVRP) ;

100 void setPRP( Point<3,T> newPRP) ;101 void setVPN(Vector<3,T> newVPN) ;102 void setVUP(Vector<3,T> newVUP) ;103 void setW1( Point<3,T> newW1) ;104 void setW2( Point<3,T> newW2) ;

APPENDIX B. SOURCE FILES 70

105

106 // i f pan , zoom and s im i l a r f u n c t i o n a l i t y i s to be added ,107 // t h i s i s the p l ace !108

109 // t h i s method f o r c e s an update , i . e . a f t e r use o f a s e t f unc t i on :110 void update ( ) ;111

112 // t h i s method c a l c u l a t e s the norma l i za t ion matrix N:113 Matrix<4,T> ca l cu l a t eNorma l i z a t i on ( ) ;114 // t h i s method c a l c u l a t e s the p r o j e c t i on matrix M x N:115 Matrix<4,T> c a l c u l a t eP r o j e c t i o n ( ) ;116 // t h i s method c a l c u l a t e s the convers ion matrix C from canonica l117 // p e r s p e c t i v e to canonica l p a r a l l e l view volume :118 Matrix<4,T> calculateParPalConv ( ) ;119 // t h i s method c a l c u l a t e s mapping matrix MAP from canonica l120 // p a r a l l e l view volume in to DotDevice coord ina t e s in width x121 // h e i g t h system :122 Matrix<4,T> calculateMapping ( int width , int he ig th ) ;123 // t h i s method c a l c u l a t e s MAP x C x N:124 Matrix<4,T> c a l c u l a t eTo t a lP r o j e c t i o n ( int width , int he ig th ) ;125 // t h i s method re turns ProjMatr i f i t e x i s t s , or r e c a l c u l a t e s126 // i f needed :127 Matrix<4,T> ge tPro j ec t i onMatr ix ( int width , int he ig th ) ;128 // re turns the PRP in world coord ina t e s :129 Point<3,T> const& getWorldPRP ( ) const ;130

131 // p r i n t s the f i e l d s o f the Camera to the screen :132 void pr in t ( ) ;133 // preceeds the p r i n t i n g o f Camera f i e l d s by p r i n t i n g s t r :134 void pr in t ( std : : s t r i n g s t r ) ;135

136 } ;137

138

139 template<typename T = f loat>140 class Mater ia l {141 protected :142 Color d i f f u s eCo l o r ; // O d143 Color specu la rCo lo r ; // O s144 T ka ; // ambient r e f l e c t i o n c o e f f i c i e n t145 T kd ; // d i f f u s e r e f l e c t i o n c o e f f i c i e n t146 T ks ; // specu l a r r e f l e c t i o n c o e f f i c i e n t147 int n ; // specu l a r r e f l e c t i o n exponent148

149 public :150 // cons t ruc t o r151 Mater ia l ( Color mDColor , Color mSColor , T mKa, T mKd, T mKs, int mN) ;152 Color g e tD i f f u s eCo l o r ( ) const ;153 Color getSpecu la rCo lor ( ) const ;154 T getKa ( ) const ;155 T getKd ( ) const ;156 T getKs ( ) const ;157 // re turns specu l a r r e f l e c t i o n exponent :158 int getN ( ) const ;159 // p r i n t s mate r ia l f i e l d s to screen :160 void pr in t ( ) ;161 // p r i n t s s t r to screen and then mater ia l f i e l d s to screen :

APPENDIX B. SOURCE FILES 71

162 void pr in t ( std : : s t r i n g s t r ) ;163 } ;164

165

166 template<typename T = f loat>167 class LightSource {168 protected :169 // the coord ina t e s o f the l i g h t source :170 Point<3,T> coo rd ina t e s ;171 // the c o e f f i c i e n t s o f the a t t enua t i on func t i on :172 Point<3,T> at t enuat ion ;173 // the l e v e l o f ambient l i g h t :174 Color ambient ;175 // the i n t e n s i t i e s o f the l i g h t source :176 Color i n t e n s i t i e s ;177 public :178 // LightSource ( ) ;179 // cons t ruc t o r :180 LightSource ( Point<3,T> const& mCoordinates ,181 Point<3,T> const& mAttenuation , Color const& mAmbient ,182 Color const& mIn t en s i t i e s = white ) ;183 LightSource ( Point<3,T> const& pos i t i on , T c1 = 0 ,184 T c2 = 0 . 1 , T c3 = 0 ) ;185

186 // re turns the coord ina t e s o f the l i g h t source :187 Point<3,T> const & getCoord inates ( ) const ;188

189 // re turns the c o e f f i c i e n t s o f the a t t enua t i on func t i on :190 Point<3,T> const & getAttenuat ion ( ) const ;191

192 // re turns the a t t enua t i on fac to r , g i ven the d i s t ance193 // from the l i g h t source :194 T getAttenuat ionFactor (T d i s t ance ) const ;195

196 // re turns the l e v e l o f ambient l i g h t :197 Color const & getAmbient ( ) const ;198

199 // re turns the i n t e n s i t i e s o f the l i g h t source :200 Color const & g e t I n t e n s i t i e s ( ) const ;201

202 // c a l c u l a t e s i l l um ina t i o n at g i ven po in t :203 Color PhongI l luminat ion ( const Mater ia l<T>& mMaterial ,204 const Point<3,T>& mPoint , const Vector<3,T>& normal ,205 Camera<T>& mCamera) const ;206

207 // p r i n t s l i g h t source f i e l d s to screen :208 void pr in t ( ) const ;209

210 // p r i n t s s t r to screen and then l i g h t source211 // f i e l d s to screen :212 void pr in t ( std : : s t r i n g s t r ) const ;213 } ;214

215

216 // The BezierPatch c l a s s hand les s u b d i v i s i o n o f pa tches .217 // When su b d i v i s i o n ends , t h i s c l a s s c r e a t e s a WorldPolygon218 // and a Screenpolygon , and c a l l s draw on the ScreenPolygon .

APPENDIX B. SOURCE FILES 72

219 template<typename T>220 class BezierPatch {221 public :222 BezierPatch ( std : : vector<Point<3, T> > patch , Mater ia l<T>223 const &mater ia l , int maxlvl , char shading , int s i gn ) ;224

225 void drawPatch ( Zbuf fer<T> &zbu f f e r , Camera<T> &camera ,226 LightSource<T> const &l i g h t ) ;227

228 private :229 void subdiv idePatch ( Point<3, T> patch [ 4 ] [ 4 ] , int count ,230 Zbuf fer<T> &zbu f f e r , Camera<T> &camera ,231 LightSource<T> const &l i g h t ) ;232

233

234 // Subd i v i d ing a patch means s u b d i v i d i n g235 // the i n d i v i d u a l curves o f the patch :236 void subdivideCurve ( Point<3, T> curve [ 4 ] ,237 Point<3, T> returnVal [ 7 ] ) ;238

239 Point<3, T> mPatch [ 4 ] [ 4 ] ;240 Mater ia l<T> const∗ mMaterial ;241 int maxlevel ; // How many t imes we l e t the r e cu r s i v e242 // s u b d i v i s i o n run .243 char mShading ; // type o f shading244 T mSign ; // s i gn o f normals245 } ;246

247 // The Parametr icSurface c l a s s hand les c a l c u l a t i n g and248 // drawing the genera l parametr ic su r f a c e (a Klein b o t t l e in t h i s case ) .249 // This genera l su r f a c e i s de f ined by 4 d i f f e r e n t f unc t i on .250 template<typename T = f loat>251 class Parametr icSur face {252 public :253 Parametr icSur face ( Mater ia l<T> const& mater ia l ,254 char shading , T s i gn ) ;255

256 void drawBottom( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,257 LightSource<T> const & l i g h t ) ;258

259 void drawHandle ( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,260 LightSource<T> const & l i g h t ) ;261

262 void drawTop( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,263 LightSource<T> const & l i g h t ) ;264

265 void drawMiddle ( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,266 LightSource<T> const & l i g h t ) ;267

268 private :269 Point<3, T> bottom ( f loat u , f loat v ) ;270 Point<3, T> handle ( f loat u , f loat v ) ;271 Point<3, T> top ( f loat u , f loat v ) ;272 Point<3, T> middle ( f loat u , f loat v ) ;273

274 // The du bottom func t i on i s the d e r i v a t i v e o f the275 // bottom func t i on above here wi th r e s p e c t to u .

APPENDIX B. SOURCE FILES 73

276 // The dv bottom func t i on i s the d e r i v a t i v e o f the bottom277 // func t i on above here wi th r e s p e c t to v .278 // The 2 v e c t o r s t o g e t h e r d e f i n e the tangent p lane to the279 // funct ion , and hence the can be crossed280 // to g i v e us a normal in a g iven po in t .281 // The r e s t be low here f o l l ow the same pa t t e rn .282 Vector<3, T> du bottom ( f loat u , f loat v ) ;283 Vector<3, T> dv bottom ( f loat u , f loat v ) ;284 Vector<3, T> du handle ( f loat u , f loat v ) ;285 Vector<3, T> dv handle ( f loat u , f loat v ) ;286 Vector<3, T> du top ( f loat u , f loat v ) ;287 Vector<3, T> dv top ( f loat u , f loat v ) ;288 Vector<3, T> du middle ( f loat u , f loat v ) ;289 Vector<3, T> dv middle ( f loat u , f loat v ) ;290

291 Mater ia l<T> const∗ mMaterial ;292 char mShading ; // Gouraud or Phong or ?293 T mSign ; // We may want to i n v e r t the s i gn f o r294 // our normals .295 // This makes i t e a s i e r to do t ha t .296

297 f loat deltaU ; // Step s i z e .298 f loat deltaV ; // Step s i z e .299 } ;300

301 }302 }303 #endif // GRAPHIC WORLD HPP

B.4 graphic world.cpp

1 #include <stdexcept>2 #include <cmath> //pow3 #include <vector>4 #include ” graph ic wor ld . hpp”5

6 using namespace graph ic : : t o o l s ;7 using namespace graph ic : : world ;8 using namespace graph ic : : draw ;9

10 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/11 /∗ Polygon implementat ion ∗/12 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/13

14 // c ’ t o r15 template<typename T>16 Polygon<T> : : Polygon ( Point<3,T> const& p0 , Point<3,T> const& p1 ,17 Point<3,T> const& p2 , Vector<3,T> const& v0 ,18 Vector<3,T> const& v1 , Vector<3,T> const& v2 ,19 Mater ia l<T> const& m) : mMaterial(&m){20 mPoints [ 0 ] = p0 ;21 mPoints [ 1 ] = p1 ;22 mPoints [ 2 ] = p2 ;23 mNormals [ 0 ] = v0 ;24 mNormals [ 1 ] = v1 ;25 mNormals [ 2 ] = v2 ;

APPENDIX B. SOURCE FILES 74

26 }27

28 template<typename T>29 Polygon<T> : : Polygon ( Polygon<T> const & p) {30 for ( int i = 0 ; i < 3 ; ++i ){31 mPoints [ i ] = p . mPoints [ i ] ;32 mNormals [ i ] = p . mNormals [ i ] ;33 }34 mMaterial = p . mMaterial ;35 }36

37 // po in t mutator38 template<typename T>39 Point<3,T> const& Polygon<T> : : po int (unsigned int i , Point<3,T> const& p) {40 i f ( i >= 3)41 throw std : : ou t o f r ange ( ”Polygon po int index out o f range ! ” ) ;42 return mPoints [ i ] = p ;43 }44

45 // po in t acces sor46 template<typename T>47 Point<3,T> const& Polygon<T> : : po int (unsigned int i ) const{48 i f ( i >= 3)49 throw std : : ou t o f r ange ( ”Polygon po int index out o f range ! ” ) ;50 return mPoints [ i ] ;51 }52

53 // normal v e c t o r mutator54 template<typename T>55 Vector<3,T> const& Polygon<T> : : normal (unsigned int i , Vector<3,T> const& v){56 i f ( i >= 3)57 throw std : : ou t o f r ange ( ”Polygon po int index out o f range ! ” ) ;58 return mNormals [ i ] = v ;59 }60

61 // normal v e c t o r acces sor62 template<typename T>63 Vector<3,T> const& Polygon<T> : : normal (unsigned int i ) const{64 i f ( i >= 3)65 throw std : : ou t o f r ange ( ”Polygon po int index out o f range ! ” ) ;66 return mNormals [ i ] ;67 }68

69 // co l o r mutator70 template<typename T>71 Mater ia l<T> const& Polygon<T> : : mate r i a l ( Mater ia l<T> const& m){72 mMaterial = &m;73 return ∗mMaterial ;74 }75

76 // co l o r acces sor77 template<typename T>78 Mater ia l<T> const& Polygon<T> : : mate r i a l ( ) const{79 return ∗mMaterial ;80 }81

82 template<typename T>

APPENDIX B. SOURCE FILES 75

83 void Polygon<T> : : p r o j e c tPo in t s (Matrix<4,T> const& matrix ){84 Vector<4,T> v ;85 Point<3,T> p [ 3 ] ;86 for ( int i = 0 ; i < 3 ; ++i ) {87 v [ 0 ] = mPoints [ i ] [ 0 ] ;88 v [ 1 ] = mPoints [ i ] [ 1 ] ;89 v [ 2 ] = mPoints [ i ] [ 2 ] ;90 v [ 3 ] = (T) 1 ;91 v = matrix ∗ v ;92 v = 1/v [ 3 ] ∗ v ;93 mPoints [ i ] [ 0 ] = v [ 0 ] ;94 mPoints [ i ] [ 1 ] = v [ 1 ] ;95 mPoints [ i ] [ 2 ] = v [ 2 ] ;96 }97 }98

99 template<typename T>100 void Polygon<T> : : pro jectNormals (Matrix<4,T> const& matrix ){101 Vector<4,T> v ;102 for ( int i = 0 ; i < 3 ; ++i ) {103 v [ 0 ] = mNormals [ i ] [ 0 ] ;104 v [ 1 ] = mNormals [ i ] [ 1 ] ;105 v [ 2 ] = mNormals [ i ] [ 2 ] ;106 v [ 3 ] = (T) 1 ;107 v = matrix ∗ v ;108 mNormals [ i ] [ 0 ] = v [ 0 ] ;109 mNormals [ i ] [ 1 ] = v [ 1 ] ;110 mNormals [ i ] [ 2 ] = v [ 2 ] ;111 mNormals [ i ] . normal ize ;112 }113 }114

115 // p r i n t i n g out data116 template<typename T>117 void Polygon<T> : : p r i n t ( std : : s t r i n g s t r = ”” ){118 i f ( s t r != ”” )119 std : : cout << s t r << std : : endl ;120 for (unsigned int i = 0 ; i < 3 ; ++i ){121 std : : cout << ”Point #” << i << ” : ” ;122 mPoints [ i ] . p r i n t ( ) ;123 std : : cout << ”Normal at that po int i s : ” ;124 mNormals [ i ] . p r i n t ( ) ;125 }126 }127

128

129

130 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/131 /∗ BezierPatch implementat ion ∗/132 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/133

134 template<typename T>135 BezierPatch<T> : : BezierPatch ( std : : vector<Point<3, T>> patch ,136 Mater ia l<T> const &mater ia l , int maxlvl , char shading , int s i gn ) {137 mMaterial = &mate r i a l ;138 maxlevel = maxlvl ;139 mShading = shading ;

APPENDIX B. SOURCE FILES 76

140 mSign = s ign ;141

142 for ( int j =0; j <4; j++) { mPatch [ 0 ] [ j ] = patch [ j ] ; }143 for ( int j =4; j <8; j++) { mPatch [ 1 ] [ j −4] = patch [ j ] ; }144 for ( int j =8; j <12; j++) { mPatch [ 2 ] [ j −8] = patch [ j ] ; }145 for ( int j =12; j <16; j++) { mPatch [ 3 ] [ j −12] = patch [ j ] ; }146

147 }148

149

150 template<typename T>151 void BezierPatch<T> : : drawPatch ( Zbuf fer<T> &zbu f f e r , Camera<T> &camera ,152 LightSource<T> const &l i g h t ) {153 subdiv idePatch (mPatch , 0 , zbu f f e r , camera , l i g h t ) ;154 }155

156

157 template<typename T>158 void BezierPatch<T> : : subdiv idePatch ( Point<3, T> patch [ 4 ] [ 4 ] ,159 int count , Zbuf fer<T> &zbu f f e r , Camera<T> &camera ,160 LightSource<T> const &l i g h t ) {161

162 // When count reaches maxleve l , r ecur s ion ends .163 // At t ha t point , the corner po in t s are the po in t s we use164 // f o r drawing , and they are p laced l i k e t h i s :165 //166 // a d167 // o o168 //169 //170 //171 // o o172 // b c173 // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−174 //175 i f ( count >= maxlevel ) {176 char shading = ’p ’ ;177 T s ign = −1;178

179 // a & b co l l a p s e d .180 i f ( patch [ 0 ] [ 0 ] == patch [ 1 ] [ 0 ] && patch [ 0 ] [ 0 ] == patch [ 2 ] [ 0 ] &&181 patch [ 0 ] [ 0 ] == patch [ 3 ] [ 0 ] ) {182 Vector<3, T> a1 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 1 ] ) ;183 Vector<3, T> a2 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 0 ] [ 1 ] ) ;184 Vector<3, T> c1 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 2 ] [ 3 ] ) ;185 Vector<3, T> c2 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 3 ] [ 2 ] ) ;186 Vector<3, T> d1 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 0 ] [ 2 ] ) ;187 Vector<3, T> d2 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 1 ] [ 3 ] ) ;188

189 Vector<3, T> Na = mSign∗ c r o s s ( a1 , a2 ) ; Na . normal ize ( ) ;190 Vector<3, T> Nc = mSign∗ c r o s s ( c1 , c2 ) ; Nc . normal ize ( ) ;191 Vector<3, T> Nd = mSign∗ c r o s s (d1 , d2 ) ; Nd . normal ize ( ) ;192

193 Polygon<T> worldpoly ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 3 ] , patch [ 0 ] [ 3 ] ,194 Na , Nc , Nd, ∗mMaterial ) ;195 ScreenPolygon<T> s c r e enpo ly ( worldpoly , zbu f f e r , camera , l i g h t ) ;196 s c r e enpo ly . draw (mShading ) ;

APPENDIX B. SOURCE FILES 77

197 }198 // b & c c o l l a p s e d .199 else i f ( patch [ 3 ] [ 0 ] == patch [ 3 ] [ 1 ] && patch [ 3 ] [ 0 ] == patch [ 3 ] [ 2 ] &&200 patch [ 3 ] [ 0 ] == patch [ 3 ] [ 3 ] ) {201 Vector<3, T> a1 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 1 ] [ 0 ] ) ;202 Vector<3, T> a2 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 0 ] [ 1 ] ) ;203 Vector<3, T> b1 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 2 ] [ 3 ] ) ;204 Vector<3, T> b2 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 2 ] [ 0 ] ) ;205 Vector<3, T> d1 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 0 ] [ 2 ] ) ;206 Vector<3, T> d2 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 1 ] [ 3 ] ) ;207

208 Vector<3, T> Na = mSign∗ c r o s s ( a1 , a2 ) ; Na . normal ize ( ) ;209 Vector<3, T> Nb = mSign∗ c r o s s (b1 , b2 ) ; Nb . normal ize ( ) ;210 Vector<3, T> Nd = mSign∗ c r o s s (d1 , d2 ) ; Nd . normal ize ( ) ;211

212 Polygon<T> worldpoly ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 0 ] , patch [ 0 ] [ 3 ] ,213 Na , Nb, Nd, ∗mMaterial ) ;214 ScreenPolygon<T> s c r e enpo ly ( worldpoly , zbu f f e r , camera , l i g h t ) ;215 s c r e enpo ly . draw (mShading ) ;216 }217 // c & d co l l a p s e d .218 else i f ( patch [ 3 ] [ 3 ] == patch [ 2 ] [ 3 ] && patch [ 3 ] [ 3 ] == patch [ 1 ] [ 3 ] &&219 patch [ 3 ] [ 3 ] == patch [ 0 ] [ 3 ] ) {220 Vector<3, T> a1 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 1 ] [ 0 ] ) ;221 Vector<3, T> a2 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 0 ] [ 1 ] ) ;222 Vector<3, T> b1 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 3 ] [ 1 ] ) ;223 Vector<3, T> b2 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 2 ] [ 0 ] ) ;224 Vector<3, T> c1 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 0 ] [ 2 ] ) ;225 Vector<3, T> c2 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 3 ] [ 2 ] ) ;226

227 Vector<3, T> Na = mSign∗ c r o s s ( a1 , a2 ) ; Na . normal ize ( ) ;228 Vector<3, T> Nb = mSign∗ c r o s s (b1 , b2 ) ; Nb . normal ize ( ) ;229 Vector<3, T> Nc = mSign∗ c r o s s ( c1 , c2 ) ; Nc . normal ize ( ) ;230

231 Polygon<T> worldpoly ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 0 ] , patch [ 3 ] [ 3 ] ,232 Na , Nb, Nc , ∗mMaterial ) ;233 ScreenPolygon<T> s c r e enpo ly ( worldpoly , zbu f f e r , camera , l i g h t ) ;234 s c r e enpo ly . draw (mShading ) ;235 }236 // d & a co l l a p s e d .237 else i f ( patch [ 0 ] [ 3 ] == patch [ 0 ] [ 2 ] && patch [ 0 ] [ 3 ] == patch [ 0 ] [ 1 ] &&238 patch [ 0 ] [ 3 ] == patch [ 0 ] [ 0 ] ) {239 Vector<3, T> a1 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 1 ] [ 0 ] ) ;240 Vector<3, T> a2 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 1 ] [ 3 ] ) ;241 Vector<3, T> b1 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 3 ] [ 1 ] ) ;242 Vector<3, T> b2 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 2 ] [ 0 ] ) ;243 Vector<3, T> c1 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 2 ] [ 3 ] ) ;244 Vector<3, T> c2 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 3 ] [ 2 ] ) ;245

246 Vector<3, T> Na = mSign∗ c r o s s ( a1 , a2 ) ; Na . normal ize ( ) ;247 Vector<3, T> Nb = mSign∗ c r o s s (b1 , b2 ) ; Nb . normal ize ( ) ;248 Vector<3, T> Nc = mSign∗ c r o s s ( c1 , c2 ) ; Nc . normal ize ( ) ;249

250 Polygon<T> worldpoly ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 0 ] , patch [ 3 ] [ 3 ] ,251 Na , Nb, Nc , ∗mMaterial ) ;252 ScreenPolygon<T> s c r e enpo ly ( worldpoly , zbu f f e r , camera , l i g h t ) ;253 s c r e enpo ly . draw (mShading ) ;

APPENDIX B. SOURCE FILES 78

254 }255 // Here we assume a l l 4 corner po in t s are d i s t i n c t .256 else {257

258 Vector<3, T> a1 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 1 ] [ 0 ] ) ;259 Vector<3, T> a2 = vectorFromPoints ( patch [ 0 ] [ 0 ] , patch [ 0 ] [ 1 ] ) ;260 Vector<3, T> b1 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 3 ] [ 1 ] ) ;261 Vector<3, T> b2 = vectorFromPoints ( patch [ 3 ] [ 0 ] , patch [ 2 ] [ 0 ] ) ;262 Vector<3, T> c1 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 2 ] [ 3 ] ) ;263 Vector<3, T> c2 = vectorFromPoints ( patch [ 3 ] [ 3 ] , patch [ 3 ] [ 2 ] ) ;264 Vector<3, T> d1 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 0 ] [ 2 ] ) ;265 Vector<3, T> d2 = vectorFromPoints ( patch [ 0 ] [ 3 ] , patch [ 1 ] [ 3 ] ) ;266

267 Vector<3, T> Na = mSign∗ c r o s s ( a1 , a2 ) ; Na . normal ize ( ) ;268 Vector<3, T> Nb = mSign∗ c r o s s (b1 , b2 ) ; Nb . normal ize ( ) ;269 Vector<3, T> Nc = mSign∗ c r o s s ( c1 , c2 ) ; Nc . normal ize ( ) ;270 Vector<3, T> Nd = mSign∗ c r o s s (d1 , d2 ) ; Nd . normal ize ( ) ;271

272

273 Polygon<T> worldpoly1 ( patch [ 0 ] [ 0 ] , patch [ 3 ] [ 0 ] , patch [ 0 ] [ 3 ] ,274 Na , Nb, Nd, ∗mMaterial ) ;275 ScreenPolygon<T> s c r eenpo ly1 ( worldpoly1 , zbu f f e r , camera , l i g h t ) ;276 s c r eenpo ly1 . draw (mShading ) ;277

278 Polygon<T> worldpoly2 ( patch [ 3 ] [ 0 ] , patch [ 3 ] [ 3 ] , patch [ 0 ] [ 3 ] ,279 Nb, Nc , Nd, ∗mMaterial ) ;280 ScreenPolygon<T> s c r eenpo ly2 ( worldpoly2 , zbu f f e r , camera , l i g h t ) ;281 s c r eenpo ly2 . draw (mShading ) ;282 }283 }284 else {285 Point<3, T> l e f t [ 4 ] [ 4 ] ;286 Point<3, T> r i g h t [ 4 ] [ 4 ] ;287 Point<3, T> t o p l e f t [ 4 ] [ 4 ] ;288 Point<3, T> t op r i gh t [ 4 ] [ 4 ] ;289 Point<3, T> b o t l e f t [ 4 ] [ 4 ] ;290 Point<3, T> bo t r i gh t [ 4 ] [ 4 ] ;291 Point<3, T> t h i s cu rv e [ 4 ] ;292

293 // Subd iv ide patch in l e f t and r i g h t .294 for ( int i = 0 ; i < 4 ; i++) {295

296 t h i s cu rv e [ 0 ] = patch [ i ] [ 0 ] ; // The297 t h i s cu rv e [ 1 ] = patch [ i ] [ 1 ] ; // curve298 t h i s cu rv e [ 2 ] = patch [ i ] [ 2 ] ; // we299 t h i s cu rv e [ 3 ] = patch [ i ] [ 3 ] ; // d i v i d e .300

301 Point<3, T> newcurves1 [ 7 ] ;302 // The 2 new curves a f t e r d i v i d i n g are in newcurves :303 subdivideCurve ( th i s curve , newcurves1 ) ;304

305 l e f t [ i ] [ 0 ] = newcurves1 [ 0 ] ;306 l e f t [ i ] [ 1 ] = newcurves1 [ 1 ] ;307 l e f t [ i ] [ 2 ] = newcurves1 [ 2 ] ;308 l e f t [ i ] [ 3 ] = newcurves1 [ 3 ] ;309 r i g h t [ i ] [ 0 ] = newcurves1 [ 3 ] ;310 r i g h t [ i ] [ 1 ] = newcurves1 [ 4 ] ;

APPENDIX B. SOURCE FILES 79

311 r i g h t [ i ] [ 2 ] = newcurves1 [ 5 ] ;312 r i g h t [ i ] [ 3 ] = newcurves1 [ 6 ] ;313 }314

315 // Now both l e f t and r i g h t must each be subd i v i d ed again ,316 // in to top and bottom .317 for ( int i = 0 ; i < 4 ; i++) {318 t h i s cu rv e [ 0 ] = l e f t [ 0 ] [ i ] ;319 t h i s cu rv e [ 1 ] = l e f t [ 1 ] [ i ] ;320 t h i s cu rv e [ 2 ] = l e f t [ 2 ] [ i ] ;321 t h i s cu rv e [ 3 ] = l e f t [ 3 ] [ i ] ; // The curve we d i v i d e .322

323 Point<3, T> newcurves2 [ 7 ] ;324 // The 2 new curves a f t e r d i v i d i n g are in newcurves :325 subdivideCurve ( th i s curve , newcurves2 ) ;326

327 t o p l e f t [ 0 ] [ i ] = newcurves2 [ 0 ] ;328 t o p l e f t [ 1 ] [ i ] = newcurves2 [ 1 ] ;329 t o p l e f t [ 2 ] [ i ] = newcurves2 [ 2 ] ;330 t o p l e f t [ 3 ] [ i ] = newcurves2 [ 3 ] ;331 b o t l e f t [ 0 ] [ i ] = newcurves2 [ 3 ] ;332 b o t l e f t [ 1 ] [ i ] = newcurves2 [ 4 ] ;333 b o t l e f t [ 2 ] [ i ] = newcurves2 [ 5 ] ;334 b o t l e f t [ 3 ] [ i ] = newcurves2 [ 6 ] ;335

336 t h i s cu rv e [ 0 ] = r i gh t [ 0 ] [ i ] ;337 t h i s cu rv e [ 1 ] = r i gh t [ 1 ] [ i ] ;338 t h i s cu rv e [ 2 ] = r i gh t [ 2 ] [ i ] ;339 t h i s cu rv e [ 3 ] = r i gh t [ 3 ] [ i ] ; // The curve we d i v i d e .340

341 Point<3, T> newcurves3 [ 7 ] ;342 // The 2 new curves a f t e r d i v i d i n g are in newcurves :343 subdivideCurve ( th i s curve , newcurves3 ) ;344

345 t op r i gh t [ 0 ] [ i ] = newcurves3 [ 0 ] ;346 t op r i gh t [ 1 ] [ i ] = newcurves3 [ 1 ] ;347 t op r i gh t [ 2 ] [ i ] = newcurves3 [ 2 ] ;348 t op r i gh t [ 3 ] [ i ] = newcurves3 [ 3 ] ;349 bo t r i gh t [ 0 ] [ i ] = newcurves3 [ 3 ] ;350 bo t r i gh t [ 1 ] [ i ] = newcurves3 [ 4 ] ;351 bo t r i gh t [ 2 ] [ i ] = newcurves3 [ 5 ] ;352 bo t r i gh t [ 3 ] [ i ] = newcurves3 [ 6 ] ;353 }354

355 // Here the 4 r e cu r s i v e c a l l s :356 subdiv idePatch ( t op l e f t , count+1, zbu f f e r , camera , l i g h t ) ;357 subdiv idePatch ( bo t l e f t , count+1, zbu f f e r , camera , l i g h t ) ;358 subdiv idePatch ( topr ight , count+1, zbu f f e r , camera , l i g h t ) ;359 subdiv idePatch ( botr ight , count+1, zbu f f e r , camera , l i g h t ) ;360

361 }362 }363

364 template<typename T>365 void BezierPatch<T> : : subdivideCurve ( Point<3, T> curve [ 4 ] ,366 Point<3, T> returnVal [ 7 ] ) {367

APPENDIX B. SOURCE FILES 80

368 T Hx = ( curve [ 1 ] [ 0 ] + curve [ 2 ] [ 0 ] ) / 2 ;369 T Hy = ( curve [ 1 ] [ 1 ] + curve [ 2 ] [ 1 ] ) / 2 ;370 T Hz = ( curve [ 1 ] [ 2 ] + curve [ 2 ] [ 2 ] ) / 2 ;371

372 // Le f t s u b d i v i s i o n here :373

374 // X−va l u e s .375 returnVal [ 0 ] [ 0 ] = curve [ 0 ] [ 0 ] ;376 returnVal [ 1 ] [ 0 ] = ( curve [ 0 ] [ 0 ] + curve [ 1 ] [ 0 ] ) / 2 ;377 returnVal [ 2 ] [ 0 ] = (Hx + returnVal [ 1 ] [ 0 ] ) / 2 ;378 // returnVal [ 3 ] [ 0 ] done l a t e r . . .379

380 // Y−va l u e s .381 returnVal [ 0 ] [ 1 ] = curve [ 0 ] [ 1 ] ;382 returnVal [ 1 ] [ 1 ] = ( curve [ 0 ] [ 1 ] + curve [ 1 ] [ 1 ] ) / 2 ;383 returnVal [ 2 ] [ 1 ] = (Hy + returnVal [ 1 ] [ 1 ] ) / 2 ;384

385 // Z−va l u e s .386 returnVal [ 0 ] [ 2 ] = curve [ 0 ] [ 2 ] ;387 returnVal [ 1 ] [ 2 ] = ( curve [ 0 ] [ 2 ] + curve [ 1 ] [ 2 ] ) / 2 ;388 returnVal [ 2 ] [ 2 ] = (Hz + returnVal [ 1 ] [ 2 ] ) / 2 ;389

390 // Right s u b d i v i s i o n here :391 // X−va l u e s .392 returnVal [ 5 ] [ 0 ] = ( curve [ 2 ] [ 0 ] + curve [ 3 ] [ 0 ] ) / 2 ;393 returnVal [ 4 ] [ 0 ] = (Hx + returnVal [ 5 ] [ 0 ] ) / 2 ;394 returnVal [ 3 ] [ 0 ] = ( returnVal [ 2 ] [ 0 ] + returnVal [ 4 ] [ 0 ] ) / 2 ;395 returnVal [ 6 ] [ 0 ] = curve [ 3 ] [ 0 ] ;396

397 // Y−va l u e s .398 returnVal [ 5 ] [ 1 ] = ( curve [ 2 ] [ 1 ] + curve [ 3 ] [ 1 ] ) / 2 ;399 returnVal [ 4 ] [ 1 ] = (Hy + returnVal [ 5 ] [ 1 ] ) / 2 ;400 returnVal [ 3 ] [ 1 ] = ( returnVal [ 2 ] [ 1 ] + returnVal [ 4 ] [ 1 ] ) / 2 ;401 returnVal [ 6 ] [ 1 ] = curve [ 3 ] [ 1 ] ;402

403 // Z−va l u e s .404 returnVal [ 5 ] [ 2 ] = ( curve [ 2 ] [ 2 ] + curve [ 3 ] [ 2 ] ) / 2 ;405 returnVal [ 4 ] [ 2 ] = (Hz + returnVal [ 5 ] [ 2 ] ) / 2 ;406 returnVal [ 3 ] [ 2 ] = ( returnVal [ 2 ] [ 2 ] + returnVal [ 4 ] [ 2 ] ) / 2 ;407 returnVal [ 6 ] [ 2 ] = curve [ 3 ] [ 2 ] ;408 }409

410

411

412 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/413 /∗ Parametr icSurface implementat ion ∗/414 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/415

416 template<typename T>417 Parametr icSurface<T> : : Parametr icSur face ( Mater ia l<T> const &mater ia l ,418 char shading , T s i gn ) {419 deltaU = PI / 1 4 . 9 ;420 deltaV = PI / 6 . 9 ;421

422 mMaterial = &mate r i a l ;423 mShading = shading ;424 mSign = s ign ;

APPENDIX B. SOURCE FILES 81

425 }426

427 template<typename T>428 void Parametr icSurface<T> : : drawBottom( Zbuf fer<T> & zbu f f e r ,429 Camera<T> & camera , LightSource<T> const & l i g h t ) {430

431 for ( f loat u = 0 . 0 ; u < 2∗PI ; u += deltaU ) {432 for ( f loat v = 0 . 0 ; v < PI ; v += deltaV )433 {434 Point<3, T> p1 = bottom (u , v ) ;435 Point<3, T> p2 = bottom (u+deltaU , v ) ;436 Point<3, T> p3 = bottom (u+deltaU , v+deltaV ) ;437 Point<3, T> p4 = bottom (u , v+deltaV ) ;438

439 Vector<3, T> N1 = −1∗mSign∗ c r o s s ( du bottom (u , v ) ,440 dv bottom (u , v ) ) ;441 N1 . normal ize ( ) ;442

443 Vector<3, T> N2 = −1∗mSign∗ c r o s s ( du bottom (u+deltaU , v ) ,444 dv bottom (u+deltaU , v ) ) ;445 N2 . normal ize ( ) ;446

447 Vector<3, T> N3 = −1∗mSign∗ c r o s s ( du bottom (u+deltaU , v+deltaV ) ,448 dv bottom (u+deltaU , v+deltaV ) ) ;449 N3 . normal ize ( ) ;450

451 Vector<3, T> N4 = −1∗mSign∗ c r o s s ( du bottom (u , v+deltaV ) ,452 dv bottom (u , v+deltaV ) ) ;453 N4 . normal ize ( ) ;454

455 Polygon<T> worldpoly1 (p1 , p3 , p4 , N1 , N3 , N4 , ∗mMaterial ) ;456 ScreenPolygon<T> s c r eenpo ly1 ( worldpoly1 , zbu f f e r , camera , l i g h t ) ;457 s c r eenpo ly1 . draw (mShading ) ;458

459 Polygon<T> worldpoly2 (p1 , p2 , p3 , N1 , N2 , N3 , ∗mMaterial ) ;460 ScreenPolygon<T> s c r eenpo ly2 ( worldpoly2 , zbu f f e r , camera , l i g h t ) ;461 s c r eenpo ly2 . draw (mShading ) ;462 }463 }464

465 }466

467

468 template<typename T>469 void Parametr icSurface<T> : : drawHandle ( Zbuf fer<T> & zbu f f e r ,470 Camera<T> & camera , LightSource<T> const & l i g h t ) {471

472 for ( f loat u = 0 . 0 ; u < 2∗PI ; u += deltaU ) {473 for ( f loat v = 0 . 0 ; v < PI ; v += deltaV )474 {475 Point<3, T> p1 = handle (u , v ) ;476 Point<3, T> p2 = handle (u+deltaU , v ) ;477 Point<3, T> p3 = handle (u+deltaU , v+deltaV ) ;478 Point<3, T> p4 = handle (u , v+deltaV ) ;479

480 Vector<3, T> N1 = −1∗mSign∗ c r o s s ( du handle (u , v ) ,481 dv handle (u , v ) ) ;

APPENDIX B. SOURCE FILES 82

482 N1 . normal ize ( ) ;483 Vector<3, T> N2 = −1∗mSign∗ c r o s s ( du handle (u+deltaU , v ) ,484 dv handle (u+deltaU , v ) ) ;485 N2 . normal ize ( ) ;486 Vector<3, T> N3 = −1∗mSign∗ c r o s s ( du handle (u+deltaU , v+deltaV ) ,487 dv handle (u+deltaU , v+deltaV ) ) ;488 N3 . normal ize ( ) ;489 Vector<3, T> N4 = −1∗mSign∗ c r o s s ( du handle (u , v+deltaV ) ,490 dv handle (u , v+deltaV ) ) ;491 N4 . normal ize ( ) ;492

493 Polygon<T> worldpoly1 (p1 , p3 , p4 , N1 , N3 , N4 , ∗mMaterial ) ;494 ScreenPolygon<T> s c r eenpo ly1 ( worldpoly1 , zbu f f e r , camera , l i g h t ) ;495 s c r eenpo ly1 . draw (mShading ) ;496

497 Polygon<T> worldpoly2 (p1 , p2 , p3 , N1 , N2 , N3 , ∗mMaterial ) ;498 ScreenPolygon<T> s c r eenpo ly2 ( worldpoly2 , zbu f f e r , camera , l i g h t ) ;499 s c r eenpo ly2 . draw (mShading ) ;500 // s t d : : cout << ” u : ” << u << ” , v : ” << v << s t d : : end l ;501

502 }503 }504

505 }506

507 template<typename T>508 void Parametr icSurface<T> : : drawTop( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,509 LightSource<T> const & l i g h t ) {510

511 for ( f loat u = 0 . 0 ; u < 2∗PI ; u += deltaU ) {512 for ( f loat v = 0 . 0 ; v < PI ; v += deltaV )513 {514 Point<3, T> p1 = top (u , v ) ;515 Point<3, T> p2 = top (u+deltaU , v ) ;516 Point<3, T> p3 = top (u+deltaU , v+deltaV ) ;517 Point<3, T> p4 = top (u , v+deltaV ) ;518

519 Vector<3, T> N1 = mSign∗ c r o s s ( du top (u , v ) ,520 dv top (u , v ) ) ;521 N1 . normal ize ( ) ;522

523 Vector<3, T> N2 = mSign∗ c r o s s ( du top (u+deltaU , v ) ,524 dv top (u+deltaU , v ) ) ;525 N2 . normal ize ( ) ;526

527 Vector<3, T> N3 = mSign∗ c r o s s ( du top (u+deltaU , v+deltaV ) ,528 dv top (u+deltaU , v+deltaV ) ) ;529 N3 . normal ize ( ) ;530

531 Vector<3, T> N4 = mSign∗ c r o s s ( du top (u , v+deltaV ) ,532 dv top (u , v+deltaV ) ) ;533 N4 . normal ize ( ) ;534

535 Polygon<T> worldpoly1 (p1 , p3 , p4 , N1 , N3 , N4 , ∗mMaterial ) ;536 ScreenPolygon<T> s c r eenpo ly1 ( worldpoly1 , zbu f f e r , camera , l i g h t ) ;537 s c r eenpo ly1 . draw (mShading ) ;538

APPENDIX B. SOURCE FILES 83

539 Polygon<T> worldpoly2 (p1 , p2 , p3 , N1 , N2 , N3 , ∗mMaterial ) ;540 ScreenPolygon<T> s c r eenpo ly2 ( worldpoly2 , zbu f f e r , camera , l i g h t ) ;541 s c r eenpo ly2 . draw (mShading ) ;542 // s t d : : cout << ” u : ” << u << ” , v : ” << v << s t d : : end l ;543 }544 }545

546 }547

548 template<typename T>549 void Parametr icSurface<T> : : drawMiddle ( Zbuf fer<T> & zbu f f e r , Camera<T> & camera ,550 LightSource<T> const & l i g h t ) {551

552 for ( f loat u = 0 . 0 ; u < 2∗PI ; u += deltaU ) {553 for ( f loat v = 0 . 0 ; v < PI ; v += deltaV )554 {555 Point<3, T> p1 = middle (u , v ) ;556 Point<3, T> p2 = middle (u+deltaU , v ) ;557 Point<3, T> p3 = middle (u+deltaU , v+deltaV ) ;558 Point<3, T> p4 = middle (u , v+deltaV ) ;559

560 Vector<3, T> N1 = mSign∗ c r o s s ( du middle (u , v ) ,561 dv middle (u , v ) ) ;562 N1 . normal ize ( ) ;563

564 Vector<3, T> N2 = mSign∗ c r o s s ( du middle (u+deltaU , v ) ,565 dv middle (u+deltaU , v ) ) ;566 N2 . normal ize ( ) ;567

568 Vector<3, T> N3 = mSign∗ c r o s s ( du middle (u+deltaU , v+deltaV ) ,569 dv middle (u+deltaU , v+deltaV ) ) ;570 N3 . normal ize ( ) ;571

572 Vector<3, T> N4 = mSign∗ c r o s s ( du middle (u , v+deltaV ) ,573 dv middle (u , v+deltaV ) ) ;574 N4 . normal ize ( ) ;575

576 Polygon<T> worldpoly1 (p1 , p3 , p4 , N1 , N3 , N4 , ∗mMaterial ) ;577 ScreenPolygon<T> s c r eenpo ly1 ( worldpoly1 , zbu f f e r , camera , l i g h t ) ;578 s c r eenpo ly1 . draw (mShading ) ;579

580 Polygon<T> worldpoly2 (p1 , p2 , p3 , N1 , N2 , N3 , ∗mMaterial ) ;581 ScreenPolygon<T> s c r eenpo ly2 ( worldpoly2 , zbu f f e r , camera , l i g h t ) ;582 s c r eenpo ly2 . draw (mShading ) ;583 }584 }585

586 }587

588 template<typename T>589 Point<3, T> Parametr icSurface<T> : : bottom ( f loat u , f loat v ) {590 Point<3, T> point ;591

592 point [ 0 ] = ( 2 . 5 + 1.5∗ cos ( v ) )∗ cos (u ) ;593 point [ 1 ] = ( 2 . 5 + 1.5∗ cos ( v ) )∗ s i n (u ) ;594 point [ 2 ] = −2.5∗ s i n (v ) ;595

APPENDIX B. SOURCE FILES 84

596 return point ;597 }598

599 template<typename T>600 Point<3, T> Parametr icSurface<T> : : handle ( f loat u , f loat v ) {601 Point<3, T> point ;602

603 point [ 0 ] = 2 .0 − 2 .0∗ cos ( v ) + s i n (u ) ;604 point [ 1 ] = cos (u ) ;605 point [ 2 ] = 3 .0∗ v ;606

607 return point ;608 }609

610 template<typename T>611 Point<3, T> Parametr icSurface<T> : : top ( f loat u , f loat v ) {612 Point<3, T> point ;613

614 point [ 0 ] = 2 .0 + (2 . 0 + cos (u ) )∗ cos ( v ) ;615 point [ 1 ] = s i n (u ) ;616 point [ 2 ] = 3 .0∗PI + (2 . 0 + cos (u ) )∗ s i n (v ) ;617

618 return point ;619 }620

621 template<typename T>622 Point<3, T> Parametr icSurface<T> : : middle ( f loat u , f loat v ) {623 Point<3, T> point ;624

625 point [ 0 ] = ( 2 . 5 + 1.5∗ cos ( v ) )∗ cos (u ) ;626 point [ 1 ] = ( 2 . 5 + 1.5∗ cos ( v ) )∗ s i n (u ) ;627 point [ 2 ] = 3∗v ;628

629 return point ;630 }631

632 // Here are the 8 d e r i v a t i v e s o f the above 4 f unc t i on s :633 // du XXX i s d e r i v a t i v e wi th r e s p e c t to u .634 // dv XXX i s d e r i v a t i v e wi th r e s p e c t to v .635

636 template<typename T>637 Vector<3, T> Parametr icSurface<T> : : du bottom ( f loat u , f loat v ) {638 Vector<3, T> tangent ;639

640 tangent [ 0 ] = −0.5∗ s i n (u )∗ ( 3 . 0∗ cos ( v ) + 5 ) ;641 tangent [ 1 ] = cos (u )∗ ( 1 . 5∗ cos ( v ) + 2 . 5 ) ;642 tangent [ 2 ] = 0 . 0 ;643

644 return tangent ;645 }646

647 template<typename T>648 Vector<3, T> Parametr icSurface<T> : : dv bottom ( f loat u , f loat v ) {649 Vector<3, T> tangent ;650

651 tangent [ 0 ] = −1.5∗ s i n (v )∗ cos (u ) ;652 tangent [ 1 ] = −1.5∗ s i n (v )∗ s i n (u ) ;

APPENDIX B. SOURCE FILES 85

653 tangent [ 2 ] = −2.5∗ cos ( v ) ;654

655 return tangent ;656 }657

658 template<typename T>659 Vector<3, T> Parametr icSurface<T> : : du handle ( f loat u , f loat v ) {660 Vector<3, T> tangent ;661

662 tangent [ 0 ] = cos (u ) ;663 tangent [ 1 ] = −s i n (u ) ;664 tangent [ 2 ] = 0 . 0 ;665

666 return tangent ;667 }668

669 template<typename T>670 Vector<3, T> Parametr icSurface<T> : : dv handle ( f loat u , f loat v ) {671 Vector<3, T> tangent ;672

673 tangent [ 0 ] = 2 .0∗ s i n (v ) ;674 tangent [ 1 ] = 0 . 0 ;675 tangent [ 2 ] = 3 . 0 ;676

677 return tangent ;678 }679

680 template<typename T>681 Vector<3, T> Parametr icSurface<T> : : du top ( f loat u , f loat v ) {682 Vector<3, T> tangent ;683

684 tangent [ 0 ] = −s i n (u)∗ cos ( v ) ;685 tangent [ 1 ] = cos (u ) ;686 tangent [ 2 ] = −s i n (u)∗ s i n (v ) ;687

688 return tangent ;689 }690

691 template<typename T>692 Vector<3, T> Parametr icSurface<T> : : dv top ( f loat u , f loat v ) {693 Vector<3, T> tangent ;694

695 tangent [ 0 ] = −s i n (v )∗ ( cos (u) + 2 . 0 ) ;696 tangent [ 1 ] = 0 . 0 ;697 tangent [ 2 ] = cos ( v )∗ ( cos (u) + 2 . 0 ) ;698

699 return tangent ;700 }701

702 template<typename T>703 Vector<3, T> Parametr icSurface<T> : : du middle ( f loat u , f loat v ) {704 Vector<3, T> tangent ;705

706 tangent [ 0 ] = −0.5∗ s i n (u )∗ ( 3 . 0∗ cos ( v ) + 5 . 0 ) ;707 tangent [ 1 ] = cos (u )∗ ( 1 . 5∗ cos ( v ) + 2 . 5 ) ;708 tangent [ 2 ] = 0 . 0 ;709

APPENDIX B. SOURCE FILES 86

710 return tangent ;711 }712

713 template<typename T>714 Vector<3, T> Parametr icSurface<T> : : dv middle ( f loat u , f loat v ) {715 Vector<3, T> tangent ;716

717 tangent [ 0 ] = −1.5∗ s i n (v )∗ cos (u ) ;718 tangent [ 1 ] = −1.5∗ s i n (v )∗ s i n (u ) ;719 tangent [ 2 ] = 3 . 0 ;720

721 return tangent ;722 }723

724

725

726 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/727 /∗ Camera temp la te implementat ion ∗/728 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/729

730 // Camera pr e f e r ed cons t ruc t o r731 template<typename T>732 Camera<T> : :Camera ( Point<3,T> mVRP, Point<3,T> mPRP, Vector<3,T> mVPN,733 Vector<3,T> mVUP, Point<3,T> mw1, Point<3,T> mw2, T mB, T mF)734 : CW( ) ,DOP( ) , u ( ) , v ( ) , n ( )735 {736 VRP = mVRP; // world coords737 PRP = mPRP; // view coords738 VPN = mVPN; // world coords739 VUP = mVUP; // world coords740 w1 = mw1; // view coords741 w2 = mw2; // view coords742 B = mB; // r e l a t i v e to view p lane743 F = mF; // r e l a t i v e to view p lane744 this−>update ( ) ;745 }746

747 template<typename T>748 Camera<T> : :Camera ( Point<3,T> pos i t i on , Point<3,T> aim , Vector<3,T> up ,749 T s i z e = 1 , T zoom = 1 , T f rontC l ipp ingP lane = 0 , T backCl ippingPlane = −20){750 T tPRP [ ] = {0 ,0 , 1} ;751 tPRP [ 0 ] ∗= s i z e ; tPRP [ 1 ] ∗= s i z e ; tPRP [ 2 ] ∗= s i z e ;752 Point<3,T> pPRP(tPRP ) ;753 PRP = pPRP;754 Vector<3,T> vPRP(tPRP ) ;755 Vector<3,T> aimVector = vectorFromPoints ( po s i t i on , aim ) ;756 VPN = T(−1) ∗ aimVector ;757 VPN. normal ize ( ) ;758 VRP = po s i t i o n ;759 VRP.move(T(−1)∗VPN) ;760 VUP = up ;761 T tW1 [ ] = { 0 . 5 , 0 . 5 , 0 } ;762 T tW2 [ ] = { −0.5 ,−0.5 ,0} ;763 tW1 [ 0 ] ∗= ( s i z e /zoom ) ; tW1 [ 1 ] ∗= ( s i z e /zoom ) ;764 tW2 [ 0 ] ∗= ( s i z e /zoom ) ; tW2 [ 1 ] ∗= ( s i z e /zoom ) ;765 Point<3,T> pW1(tW1) ;766 Point<3,T> pW2(tW2) ;

APPENDIX B. SOURCE FILES 87

767 w1 = pW1;768 w2 = pW2;769 B = backCl ippingPlane ;770 F = frontC l ipp ingP lane ;771 update ( ) ;772 }773

774 // This method updates CW,DOP, u , v , n775 // I t i s used to secure t ha t t h e s e va l u e s are a l lway s co r r e c t776 template<typename T>777 void Camera<T> : : update ( )778 {779 // update cen te r o f window780 CW[ 0 ] = (w1 [ 0 ] + w2 [ 0 ] ) / 2 ;781 CW[ 1 ] = (w1 [ 1 ] + w2 [ 1 ] ) / 2 ;782 CW[ 2 ] = 0 ;783

784 // update DOP785 DOP[ 0 ] = PRP[ 0 ] − CW[ 0 ] ;786 DOP[ 1 ] = PRP[ 1 ] − CW[ 1 ] ;787 DOP[ 2 ] = PRP[ 2 ] − CW[ 2 ] ;788

789 // update n790 n = VPN;791 n . normal ize ( ) ;792

793 // update u794 u = c ro s s (VUP,VPN) ;795 u . normal ize ( ) ;796

797 // update v798 Vector<3,T> tmp = c ro s s (VUP,VPN) ;799 v = c r o s s (VPN, tmp ) ;800 v . normal ize ( ) ;801

802 // c a l c u l a t e WorldPRP803 // This i s done by making the r o t a t i on matrix R as s p e c i f i e d804 T valR [ 4 ] [ 4 ] = { {u [ 0 ] , u [ 1 ] , u [ 2 ] , 0 } , {v [ 0 ] , v [ 1 ] , v [ 2 ] , 0 } ,805 {n [ 0 ] , n [ 1 ] , n [ 2 ] , 0 } , {0 ,0 ,0 ,1} } ;806 Matrix<4,T> R( valR ) ;807 T valPRP [ 4 ] = {PRP[ 0 ] , PRP[ 1 ] , PRP[ 2 ] , 1} ;808 Vector<4,T> wPRP(valPRP ) ;809 wPRP = R ∗ wPRP;810 T valWPRP [ 3 ] = {wPRP[ 0 ] /wPRP[3]+VRP[ 0 ] , wPRP[ 1 ] /wPRP[3]+VRP[ 1 ] ,811 wPRP[ 2 ] /wPRP[3]+VRP[ 2 ] } ;812 worldPRP . s e t (valWPRP) ;813

814 pro jMatr ix I sVa l id = fa l se ;815 }816

817 // s e t s VRP to the va lue s p e c i f i e d818 template<typename T>819 void Camera<T> : : setVRP( Point<3,T> newVRP)820 {821 VRP = newVRP;822 this−>update ( ) ;823 }

APPENDIX B. SOURCE FILES 88

824

825 // s e t s PRP to the va lue s p e c i f i e d826 template<typename T>827 void Camera<T> : : setPRP( Point<3,T> newPRP)828 {829 PRP = newPRP;830 this−>update ( ) ;831 }832

833 // s e t s VPN to the va lue s p e c i f i e d834 template<typename T>835 void Camera<T> : : setVPN(Vector<3,T> newVPN)836 {837 VPN = newVPN;838 this−>update ( ) ;839 }840

841 // s e t s VUP to the va lue s p e c i f i e d842 template<typename T>843 void Camera<T> : : setVUP(Vector<3,T> newVUP)844 {845 VUP = newVUP;846 this−>update ( ) ;847 }848 // s e t s w1 to the va lue s p e c i f i e d849 template<typename T>850 void Camera<T> : : setW1( Point<3,T> newW1)851 {852 w1 = newW1;853 this−>update ( ) ;854 }855

856 // s e t s w2 to the va lue s p e c i f i e d857 template<typename T>858 void Camera<T> : : setW2( Point<3,T> newW2)859 {860 w2 = newW2;861 this−>update ( ) ;862 }863

864 // t h i s method c a l c u l a t e s the norma l i za t ion matrix865 template<typename T>866 Matrix<4,T> Camera<T> : : c a l cu l a t eNorma l i z a t i on ( )867 {868 // Firs t , we make sure a l l v a l u e s are updated869 this−>update ( ) ;870 // Second , we make the Normal izat ion matrix and871 // i n i t i a l i z e i t to i d e n t i t y872 T id en t i t y [ 4 ] [ 4 ] = {{1 ,0 ,0 ,0} , {0 ,1 ,0 ,0} , {0 ,0 ,1 ,0} , {0 ,0 , 0 , 1}} ;873 Matrix<4,T> N( i d e n t i t y ) ;874

875 // s t ep 1 : Trans la te VRP to the o r i g i n876 T valTVRP [ 4 ] [ 4 ] = { {1 ,0 ,0 ,−1∗VRP[ 0 ] } , {0 ,1 ,0 ,−1∗VRP[ 1 ] } ,877 {0 ,0 ,1 ,−1∗VRP[ 2 ] } , {0 ,0 ,0 ,1} } ;878 Matrix<4,T> TVRP(valTVRP ) ;879 //TVRP. p r i n t (”TVRP: ” ) ;880

APPENDIX B. SOURCE FILES 89

881 // s t ep 2 : Rotate882 // This i s done by making the r o t a t i on matrix R as s p e c i f i e d883 T valR [ 4 ] [ 4 ] = { {u [ 0 ] , u [ 1 ] , u [ 2 ] , 0 } , {v [ 0 ] , v [ 1 ] , v [ 2 ] , 0 } ,884 {n [ 0 ] , n [ 1 ] , n [ 2 ] , 0 } , {0 ,0 ,0 ,1} } ;885 Matrix<4,T> R( valR ) ;886 //R. p r i n t (”R: ” ) ;887

888 // s t ep 3 : Trans la te PRP889 T valTPRP [ 4 ] [ 4 ] = { {1 ,0 ,0 ,−1∗PRP[ 0 ] } , {0 ,1 ,0 ,−1∗PRP[ 1 ] } ,890 {0 ,0 ,1 ,−1∗PRP[ 2 ] } , {0 ,0 ,0 ,1} } ;891 Matrix<4,T> TPRP(valTPRP ) ;892 //TPRP. p r i n t (”TPRP: ” ) ;893

894 // s t ep 4 : Shear895 T valSh [ 4 ] [ 4 ] = { {1 ,0 ,−DOP[ 0 ] /DOP[ 2 ] , 0 } , {0 ,1 ,−DOP[ 1 ] /DOP[ 2 ] , 0 } ,896 {0 ,0 ,1 ,0} , {0 ,0 ,0 ,1} } ;897 Matrix<4,T> Sh( valSh ) ;898 //Sh . p r i n t (”Sh : ” ) ;899

900 // s t ep 5 : Sca l e901 T sx = (2 ∗ PRP[ 2 ] ) / (w2 [ 0 ] − w1 [ 0 ] ) ;902 T sy = (2 ∗ PRP[ 2 ] ) / (w2 [ 1 ] − w1 [ 1 ] ) ;903 T s a l l = (−1) / (B − PRP[ 2 ] ) ;904 T valSc [ 4 ] [ 4 ] = { { sx∗ s a l l , 0 , 0 , 0} , {0 , sy∗ s a l l , 0 , 0} ,905 {0 ,0 , s a l l , 0} , {0 ,0 ,0 ,1} } ;906 Matrix<4,T> Sc ( va lSc ) ;907 //Sc . p r i n t (”Sc : ” ) ;908

909 //Matrix<4,T> m1 = R ∗ TVRP;910 //m1. p r i n t (”R ∗ TVRP: ” ) ;911 //Matrix<4,T> m2 = TPRP ∗ R ∗ TVRP;912 //m2. p r i n t (”TPRP ∗ R ∗ TVRP: ” ) ;913 //Matrix<4,T> m3 = Sh ∗ TPRP ∗ R ∗ TVRP;914 //m3. p r i n t (”Sh ∗ TPRP ∗ R ∗ TVRP: ” ) ;915 //Matrix<4,T> m4 = Sc ∗ Sh ∗ TPRP ∗ R ∗ TVRP;916 //m4. p r i n t (”Sc ∗ Sh ∗ TPRP ∗ R ∗ TVRP: ” ) ;917

918

919 // c a l c u l a t i n g N920 N = Sc ∗ Sh ∗ TPRP ∗ R ∗ TVRP;921 //N. p r i n t (”N: ” ) ;922 return N;923 }924

925 // c a l c u l a t e s the p r o j e c t i on matrix926 template<typename T>927 Matrix<4,T> Camera<T> : : c a l c u l a t eP r o j e c t i o n ( )928 {929 // f i r s t , make sure a l l v a l u e s are in a l e g a l s t a t e930 this−>update ( ) ;931

932 // c a l c u l a t e d , done by f i n d i n g N, and l e t t i n g i t work on CW933 T arVRP [ 4 ] = { VRP[ 0 ] , VRP[ 1 ] , VRP[ 2 ] , 1 } ;934 Vector<4,T> vecVRP(arVRP ) ;935 Matrix<4,T> N = this−>ca l cu l a t eNorma l i z a t i on ( ) ;936 vecVRP = N ∗ vecVRP ;937 T d = vecVRP [ 2 ] ;

APPENDIX B. SOURCE FILES 90

938

939 // s t d : : cout << ”d i s : ” << d << s t d : : end l ;940

941 // now , we make the p r o j e c t i on matrix942 T valM [ 4 ] [ 4 ] = {{1 ,0 ,0 ,0} , {0 ,1 ,0 ,0} , {0 ,0 ,1 ,0} , {0 ,0 ,1/d , 0 } } ;943 Matrix<4,T> M(valM ) ;944 //M. p r i n t (”M: ” ) ;945

946 Matrix<4,T> P = M ∗ N;947

948 return P;949

950 }951

952 // t h i s method c a l c u l a t e s the t rans format ion matrix from canonica l953 // p e r s p e c t i v e view volume in to canonica l p a r a l l e l view volume954 template<typename T>955 Matrix<4,T> Camera<T> : : ca lculateParPalConv ( )956 {957 // f i r s t , make sure a l l v a l u e s are in a l e g a l s t a t e958 this−>update ( ) ;959

960 // now , c a l c u l a t e zmax961 T zmax = −1 ∗ (F − PRP[ 2 ] ) / (B − PRP[ 2 ] ) ;962 T valC [ 4 ] [ 4 ] = {{1 ,0 ,0 ,0} , {0 ,1 ,0 ,0} , {0 ,0 ,1/(1+zmax) ,−zmax/(1+zmax )} ,963 {0 ,0 ,−1 ,0}} ;964 Matrix<4,T> C( valC ) ;965 //C. p r i n t (”C: ” ) ;966

967 return C;968

969 }970

971 // t h i s method c a l c u l a t e s the mapping matrix from pro j e c t e d po in t s i n t o972 // screen po in t s i t assumes usage o f DotDevice973 template<typename T>974 Matrix<4,T> Camera<T> : : ca lculateMapping ( int width , int he ig th )975 {976 // f i r s t , make sure a l l v a l u e s are in a l e g a l s t a t e977 this−>update ( ) ;978

979 // second , the t r a n s l a t i o n matrix980 T valT1 [ 4 ] [ 4 ] = {{1 ,0 ,0 ,1} , {0 ,1 ,0 ,1} , {0 ,0 ,1 ,1} , {0 ,0 , 0 , 1}} ;981 Matrix<4,T> T1( valT1 ) ;982

983 // th i rd , the s c a l e matrix984 T scx = width /2 ;985 T scy = he igth /2 ;986 T scz = 1 ; // we ’ re on ly i n t e r e s t e d in r e l a t i v e z anyway987 T valSc [ 4 ] [ 4 ] = {{ scx , 0 , 0 , 0} , {0 , scy , 0 , 0} , {0 ,0 ,1 ,0} , {0 ,0 , 0 , 1}} ;988 Matrix<4,T> Sc ( va lSc ) ;989

990 // four th , combine to c a l c u l a t e the mapping matrix MAP991 Matrix<4,T> MAP = Sc ∗ T1 ;992 //MAP. p r i n t (”MAP: ” ) ;993

994 return MAP;

APPENDIX B. SOURCE FILES 91

995 }996

997 // t h i s method c a l c u l a t e s the t o t a l p r o j e c t i on matrix998 // t ha t i s from world po in t s i n t o screen coord ina t e s999 template<typename T>

1000 Matrix<4,T> Camera<T> : : c a l c u l a t eTo t a lP r o j e c t i o n ( int width , int he ig th )1001 {1002 // f i r s t , make sure a l l v a l u e s are in a l e g a l s t a t e1003 this−>update ( ) ;1004

1005 // c a l c u l a t e the matr ices1006 Matrix<4,T> N = this−>ca l cu l a t eNorma l i z a t i on ( ) ;1007 Matrix<4,T> C = this−>calculateParPalConv ( ) ;1008 Matrix<4,T> MAP = this−>calculateMapping ( width , he ig th ) ;1009

1010 // c a l c u l a t e the p r o j e c t i on matrix1011 Matrix<4,T> P = MAP ∗ C ∗ N;1012 //P. p r i n t (”P: ” ) ;1013

1014 return P;1015

1016 }1017

1018 // i f t h e r e i s a co r r e c t p r o j e c t i on matrix , t h i s w i l l be returned ,1019 // in not , c a l c u l a t e a new one1020 template<typename T>1021 Matrix<4,T> Camera<T> : : g e tPro j ec t i onMatr ix ( int width , int he ig th )1022 {1023 i f ( ! p ro jMatr ix I sVa l id )1024 {1025 ProjMatr = this−>c a l c u l a t eTo t a lP r o j e c t i o n ( width , he ig th ) ;1026 pro jMatr ix I sVa l id = true ;1027 }1028 return ProjMatr ;1029 }1030

1031 // re turns the worldPRP1032 template<typename T>1033 Point<3,T> const& Camera<T> : : getWorldPRP ( ) const1034 { return worldPRP ; }1035

1036 // Pr in t s a l l t he f i e l d s in Camera to the screen1037 template<typename T>1038 void Camera<T> : : p r i n t ( )1039 {1040 VRP. p r in t ( ”VRP: ” ) ;1041 PRP. p r i n t ( ”PRP: ” ) ;1042 worldPRP . p r i n t ( ”worldPRP : ” ) ;1043 VPN. p r in t ( ”VPN: ” ) ;1044 VUP. p r in t ( ”VUP: ” ) ;1045 w1 . p r i n t ( ”w1 : ” ) ;1046 w2 . p r i n t ( ”w2 : ” ) ;1047 CW. pr in t ( ”CW: ” ) ;1048 DOP. p r in t ( ”DOP: ” ) ;1049 u . p r i n t ( ”u : ” ) ;1050 v . p r i n t ( ”v : ” ) ;1051 n . p r i n t ( ”n : ” ) ;

APPENDIX B. SOURCE FILES 92

1052 }1053

1054 // Pr in t s s t r to screen and then a l l the f i e l d s in Camera to the screen1055 template<typename T>1056 void Camera<T> : : p r i n t ( std : : s t r i n g s t r )1057 {1058 std : : cout << s t r << std : : endl ;1059 this−>pr in t ( ) ;1060 }1061

1062 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/1063 /∗ Mater ia l t emp la te implementat ion ∗/1064 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/1065

1066 // cons t ruc t o r1067 template<typename T>1068 Mater ia l<T> : : Mater ia l ( Color mDColor , Color mSColor , T mKa,1069 T mKd, T mKs, int mN)1070 {1071 d i f f u s eCo l o r = mDColor ;1072 specu la rCo lo r = mSColor ;1073 //ka1074 i f ( 1 >= mKa && mKa >= 0)1075 ka = mKa;1076 else {1077 ka = 0 . 1 ;1078 std : : cout << ”WARNING: ka s e t to i l l e g a l va lue . Set to 0 .1 ”1079 << std : : endl ;1080 }1081 //kd1082 i f ( 1 >= mKd && mKd >= 0)1083 kd = mKd;1084 else {1085 kd = 0 . 1 ;1086 std : : cout << ”WARNING: kd s e t to i l l e g a l va lue . Set to 0 .1 ”1087 << std : : endl ;1088 }1089 // ks1090 i f ( 1 >= mKs && mKs >= 0)1091 ks = mKs;1092 else {1093 ks = 0 . 1 ;1094 std : : cout << ”WARNING: ks s e t to i l l e g a l va lue . Set to 0 .1 ”1095 << std : : endl ;1096 }1097 n = mN;1098 }1099

1100 // re tu rns red cons tan t s1101 template<typename T>1102 Color Mater ia l<T> : : g e tD i f f u s eCo l o r ( ) const1103 {1104 return d i f f u s eCo l o r ;1105 }1106

1107 // re tu rns green cons tan t s1108 template<typename T>

APPENDIX B. SOURCE FILES 93

1109 Color Mater ia l<T> : : g e tSpecu la rCo lor ( ) const1110 {1111 return specu la rCo lo r ;1112 }1113

1114 // re tu rns ka1115 template<typename T>1116 T Mater ia l<T> : : getKa ( ) const { return ka ; }1117

1118 // re tu rns kd1119 template<typename T>1120 T Mater ia l<T> : : getKd ( ) const { return kd ; }1121

1122 // re tu rns ks1123 template<typename T>1124 T Mater ia l<T> : : getKs ( ) const { return ks ; }1125

1126 // re tu rns n1127 template<typename T>1128 int Mater ia l<T> : : getN ( ) const { return n ; }1129

1130 // p r i n t s mate r ia l to screen1131 template<typename T>1132 void Mater ia l<T> : : p r i n t ( )1133 {1134 std : : cout << ” D i f f u s e Color : ” ;1135 d i f f u s eCo l o r . p r i n t ( ) ;1136 std : : cout << ” Specu lar Color : ” ;1137 specu la rCo lo r . p r i n t ( ) ;1138 std : : cout << ”ka : ” << ka << ” , kd : ” << kd << ” , ks : ”1139 << ks << ” , n : ” << n << std : : endl ;1140 }1141

1142 // p r i n t s mate r ia l to screen1143 template<typename T>1144 void Mater ia l<T> : : p r i n t ( std : : s t r i n g s t r )1145 {1146 std : : cout << s t r << std : : endl ;1147 pr in t ( ) ;1148 }1149

1150

1151

1152 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/1153 /∗ LightSource temp la te implementat ion ∗/1154 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/1155

1156 // cons t ruc t o r1157 template<typename T>1158 LightSource<T> : : L ightSource ( const Point<3,T>& mCoordinates ,1159 const Point<3,T>& mAttenuation ,1160 const Color& mAmbient ,1161 const Color& mIn t en s i t i e s )1162 {1163 coo rd ina t e s = mCoordinates ;1164 at t enuat ion = mAttenuation ;1165 ambient = mAmbient ;

APPENDIX B. SOURCE FILES 94

1166 i n t e n s i t i e s = mIn t en s i t i e s ;1167 }1168

1169 template<typename T>1170 LightSource<T> : : L ightSource ( Point<3,T> const& pos i t i on ,1171 T c1 = 0 , T c2 = 0 . 1 , T c3 = 0){1172 Point<3,T> p ;1173 p [ 0 ] = c1 ;1174 p [ 1 ] = c2 ;1175 p [ 2 ] = c3 ;1176 coo rd ina t e s = po s i t i o n ;1177 at tenuat ion = p ;1178 ambient = grey ;1179 i n t e n s i t i e s = white ;1180 }1181

1182 // re turns the coord ina t e s o f the l i g h t source1183 template<typename T>1184 Point<3,T> const & LightSource<T> : : ge tCoord inates ( ) const1185 {1186 return coo rd ina t e s ;1187 }1188

1189 // re turns the c o e f f i c i e n t s o f the a t t enua t i on func t i on1190 template<typename T>1191 Point<3,T> const & LightSource<T> : : getAttenuat ion ( ) const1192 {1193 return at t enuat ion ;1194 }1195

1196 // re turns a t t enua t i on fac to r , g i ven the d i s t ance from the l i g h t source1197 template<typename T>1198 T LightSource<T> : : getAttenuat ionFactor (T d i s t ance ) const1199 {1200 T f a t t = 1 / ( at t enuat ion [ 0 ] + at tenuat ion [ 1 ] ∗ d i s t ance +1201 at tenuat ion [ 2 ] ∗ d i s t ance ∗ d i s t ance ) ;1202 i f ( f a t t > 1)1203 return 1 ;1204 else1205 return f a t t ;1206 }1207

1208 // re turns the l e v e l o f ambient l i g h t1209 template<typename T>1210 Color const & LightSource<T> : : getAmbient ( ) const1211 {1212 return ambient ;1213 }1214

1215 // re turns the i n t e n s i t i e s o f the l i g h t source1216 template<typename T>1217 Color const & LightSource<T> : : g e t I n t e n s i t i e s ( ) const1218 {1219 return i n t e n s i t i e s ;1220 }1221 // c a l c u l a t e s i l l um ina t i o n at g i ven po in t1222 // note t ha t normal i s expec ted to be normal ized

APPENDIX B. SOURCE FILES 95

1223 template<typename T>1224 Color LightSource<T> : : PhongI l luminat ion ( const Mater ia l<T> & mMaterial ,1225 const Point<3,T>& mPoint , const Vector<3,T>& N,1226 Camera<T> & myCamera) const1227 {1228 // f o r each o f the t h r e e co lo r s , we w i l l have to b u i l d the i l l um ina t i on I1229 // to l e s s e n the number o f c a l c u l a t i o n s , we s t a r t by c a l c u l a t i n g a few1230 // cons tan t s making normal non−cons t NB: A hack i s t a k ing p l ace1231 Point<3,T> worldPRP = myCamera . getWorldPRP ( ) ;1232 //worldPRP . p r i n t (”WorldPRP : ” ) ;1233 // c a l c u l a t i n g the vec t o r L and d i s t ance d1234 Vector<3,T> L = vectorFromPoints (mPoint , c oo rd ina t e s ) ;1235 T d i s t ance = L . l ength ( ) ;1236 L . normal ize ( ) ;1237 //L . p r i n t (”L : ” ) ;1238 //N. p r i n t (”N: ” ) ;1239 // c a l c u l a t i n g N∗L, must be p o s i t i v e or zero1240 T NdotL = N∗L ;1241 i f ( NdotL < 0 )1242 {1243 // s t d : : cout << ”NdotL s e t to 0 , were ” << NdotL << s t d : : end l ;1244 NdotL = 0 ;1245 }1246 // c a l c u l a t i n g V, vec t o r from mPoint to v i ewpo in t1247 Vector<3,T> V = vectorFromPoints (mPoint , worldPRP ) ;1248 V. normal ize ( ) ;1249 //V. p r i n t (”V: ” ) ;1250 // c a l c u l a t i n g R∗V, must be p o s i t i v e or zero1251 T RdotV = 0 ;1252 // only c a l c u l a t e RdotV i f l i g h t s o u r c e i s on the same s i d e o f1253 // sur f a c e as v iewer1254 i f ( NdotL > 0 .0001 )1255 {1256 RdotV = ((2∗NdotL) ∗ N − L) ∗ V;1257 i f ( RdotV < 0)1258 {1259 RdotV = 0 ;1260 }1261 }1262 T RdotVn = pow(RdotV , mMaterial . getN ( ) ) ;1263 // the a t t enua t i on f a c t o r1264 T f a t t = this−>getAttenuat ionFactor ( d i s t ance ) ;1265 //N. p r i n t (”N: ” ) ;1266 //L . p r i n t (”L : ” ) ;1267 /∗ s t d : : cout << ”N∗L = ” << NdotL << ” , R∗V = ” << RdotV1268 << ” , RdotVn = ”1269 << RdotVn << ” , d = ” << d i s t ance << ” , f a t t = ”1270 << f a t t << s t d : : end l ; ∗/1271

1272 // red1273 T IAmbientRed = ambient . getRed ( ) ∗ mMaterial . getKa ( ) ∗1274 mMaterial . g e tD i f f u s eCo l o r ( ) . getRed ( ) ;1275 T IDi f fuseRed = i n t e n s i t i e s . getRed ( ) ∗ mMaterial . getKd ( ) ∗1276 mMaterial . g e tD i f f u s eCo l o r ( ) . getRed ( ) ∗ NdotL ;1277 T ISpecularRed = i n t e n s i t i e s . getRed ( ) ∗ mMaterial . getKs ( ) ∗1278 mMaterial . ge tSpecu la rCo lor ( ) . getRed ( ) ∗ RdotVn ;1279 /∗ s t d : : cout << ” Iar = ” << IAmbientRed << ” , Idr = ”

APPENDIX B. SOURCE FILES 96

1280 << IDi f fuseRed << ” , I s r = ” << ISpecularRed << s t d : : end l ; ∗/1281

1282 // green1283 T IAmbientGreen = ambient . getGreen ( ) ∗ mMaterial . getKa ( ) ∗1284 mMaterial . g e tD i f f u s eCo l o r ( ) . getGreen ( ) ;1285 T IDi f fuseGreen = i n t e n s i t i e s . getGreen ( ) ∗ mMaterial . getKd ( ) ∗1286 mMaterial . g e tD i f f u s eCo l o r ( ) . getGreen ( ) ∗ NdotL ;1287 T ISpecularGreen = i n t e n s i t i e s . getGreen ( ) ∗ mMaterial . getKs ( ) ∗1288 mMaterial . ge tSpecu la rCo lor ( ) . getGreen ( ) ∗ RdotVn ;1289 /∗ s t d : : cout << ” Iag = ” << IAmbientGreen << ” , Idg= ”1290 << IDi f fuseGreen << ” , I s g = ” << ISpecularGreen1291 << s t d : : end l ; ∗/1292

1293 // b l u e1294 T IAmbientBlue = ambient . getBlue ( ) ∗ mMaterial . getKa ( ) ∗1295 mMaterial . g e tD i f f u s eCo l o r ( ) . getBlue ( ) ;1296 T IDi f f u s eB lue = i n t e n s i t i e s . getBlue ( ) ∗ mMaterial . getKd ( ) ∗1297 mMaterial . g e tD i f f u s eCo l o r ( ) . getBlue ( ) ∗ NdotL ;1298 T ISpecu larBlue = i n t e n s i t i e s . getBlue ( ) ∗ mMaterial . getKs ( ) ∗1299 mMaterial . ge tSpecu la rCo lor ( ) . getBlue ( ) ∗ RdotVn ;1300 /∗ s t d : : cout << ” Iab = ” << IAmbientBlue << ” , Idb = ”1301 << ID i f f u s eB lue << ” , I s b = ” << ISpecu larB lue << s t d : : end l ; ∗/1302

1303 // a dummy fo r now1304 Color phongI l lCo lo r ( 0 , 0 , 0 ) ;1305 phongI l lCo lo r . setRed ( IAmbientRed + f a t t ∗1306 ( IDi f fuseRed + ISpecularRed ) ) ;1307

1308 phongI l lCo lo r . setGreen ( IAmbientGreen + f a t t ∗1309 ( IDi f fu seGreen + ISpecularGreen ) ) ;1310

1311 phongI l lCo lo r . s e tBlue ( IAmbientBlue + f a t t ∗1312 ( ID i f f u s eB lue + ISpecu larBlue ) ) ;1313 return phongI l lCo lo r ;1314 }1315

1316 // p r i n t s l i g h t source f i e l d s to screen1317 template<typename T>1318 void LightSource<T> : : p r i n t ( ) const1319 {1320 std : : cout << ”Coordinates : ” ;1321 coo rd ina t e s . p r i n t ( ) ;1322 std : : cout << ”Attenuation cons tant s : ” ;1323 at tenuat ion . p r i n t ( ) ;1324 std : : cout << ”Ambient l i g h t : ” ;1325 ambient . p r i n t ( ) ;1326 std : : cout << ”Color ( i n t e n s i t y ) o f l i g h t : ” ;1327 i n t e n s i t i e s . p r i n t ( ) ;1328 }1329

1330

1331 // p r i n t s s t r to screen and then l i g h t source f i e l d s to screen1332 template<typename T>1333 void LightSource<T> : : p r i n t ( std : : s t r i n g s t r ) const1334 {1335 std : : cout << s t r << std : : endl ;1336 pr in t ( ) ;

APPENDIX B. SOURCE FILES 97

1337 }

B.5 graphic draw.hpp

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗2 ’Draw ’ c l a s s e s3 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/4 #ifndef GRAPHIC DRAWHPP5 #define GRAPHIC DRAWHPP6

7 #include<vector>8 #include<s t r i ng>9 #include ”DotDevice/DotDevice . h”

10

11 using namespace graph ic : : world ;12

13 namespace graph ic {14 namespace draw {15 class ScreenLine {16 protected :17 Point<2, int> mStartPoint ;18 Color mStartColor ;19 Point<2, int> mEndPoint ;20 Color mEndColor ;21 public :22 ScreenLine ( ) ; // d e f a u l t c ’ t o r23

24 //c ’ t o r t a k ing two po in t s as argument :25 ScreenLine ( Point<2, int> const & star tPo int ,26 Point<2, int> const & endPoint ) ;27

28 Point<2, int> const & se tS ta r tPo in t (29 Point<2, int> const & newStartPoint ) ;30

31 Point<2, int> const & setEndPoint (32 Point<2, int> const & newEndPoint ) ;33

34 // s e t s the s t a r t and end po in t to newColor :35 Color const & setCo lo r ( Color const & newColor ) ;36

37 void s e tCo lo r ( Color const & newStartColor ,38 Color const & newEndColor ) ;39

40 Point<2, int> const & getSta r tPo in t ( ) const ;41 Point<2, int> const & getEndPoint ( ) const ;42

43 // draws the l i n e to the screen :44 // vo id drawMonocolor ( DotDevice∗ dev i c e ) cons t ;45 } ;46

47

48

49 // The Zbu f f e r c l a s s implements our z−b u f f e r ( not s u r p r i s i n g l y ) .50 // I t s imply con ta ins an array o f ColorPoints , i . e . a z−coord51 // and a co l o r .52 template<typename T>

APPENDIX B. SOURCE FILES 98

53 class Zbuf f e r {54 public :55 Zbuf f e r ( ) ;56 Zbuf f e r ( DotDevice& device , Color const & co l o r = grey ) ;57

58 // I f z i s c l o s e r then wr i t e new z and new co l o r .59 void s e tP i x e l ( int x , int y , T z , Color const& c ) ;60

61 // Checks i f z i s c l o s e r . As above , but w i thout wr i t i n g62 // to the b u f f e r .63 bool checkPixe l ( int x , int y , T z ) ;64

65 // When done wi th a l l o b j e c t s , t h i s w i l l draw the z−b u f f e r66 // to screen .67 void drawBuffer ( ) ;68

69 int he ight ;70 int width ;71

72 private :73 DotDevice∗ mDevice ;74

75 struct ColorPoint {76 T zcoord ;77 Color c l r ;78 } ;79

80 // The ac t ua l z−b u f f e r .81 std : : vector<std : : vector<ColorPoint>> mBuffer ;82 } ;83

84

85 template<typename T>86 class ScreenPolygon {87 protected :88 // s t r u c t con ta in ing p ro j e c t e d polygon end po in t rounded89 // to i n t e g e r s f o r use on screen , r e f e r ence to z−coord90 // from pro j e c t e d end point , r e f e r ence to91 // po in t and normal in o r i g i n a l po lygon .92 struct Vertexdata {93 int x ;94 int y ;95 T z ;96 Point<3,T> const ∗ p ;97 Vector<3,T> const ∗ n ;98 //Vertexdata ( Point<3,T> cons t & p , Vector<3,T> cons t & n )99 // : p(& p ) , n(& n ) {} ;

100 } v0 , v1 , v2 ;101 Camera<T> ∗ mCamera ;102 Zbuf fer<T>∗ mZbuffer ;103 LightSource<T> const∗ mLight ;104 Polygon<T> const∗ mOriginalPolygon ;105 Polygon<T> mProjected ;106 // draw he l p e r f unc t i on s :107 void hLineGouraud ( int const & x0 , int const & x1 , int const & y ,108 T const & z0 , T const & z1 , Color const & c0 , Color const & c1 ) ;109 void hLinePhong ( int const & x0 , int const & x1 , int const & y ,

APPENDIX B. SOURCE FILES 99

110 T const & z0 , T const & z1 ,111 Vector<3,T> const & n0 , Vector<3,T> const & n1 ,112 Point<3,T> const & p0 , Point<3,T> const & p1 ) ;113 void hLineFlat ( int const& xLeft , int const& xRight , int const& y ,114 T const & z0 , T const & z1 , Color f l a tCo l o r ) ;115 void hLineLine ( int const& xLeft , int const& xRight , int const& y ,116 T const & z0 , T const & z1 , Color l i n eCo l o r ) ;117 public :118 //c ’ t o r119 ScreenPolygon ( Polygon<T> const& polygon , Zbuf fer<T>& zbu f f e r ,120 Camera<T>& camera , LightSource<T> const& l i g h t ) ;121 void forceXYs ( int x0 , int y0 , int x1 , int y1 , int x2 , int y2 ) ; // f o r t e s t i n g ONLY122 void draw (char shading ) ; // draws the l i n e to the screen123 void pr in t ( ) ; // p r i n t s the f i e l d s o f the screen polygon to the screen124 } ;125

126 }127 }128

129 #endif // GRAPHIC DRAW HPP

B.6 graphic draw.cpp

1 #include <stdexcept>2 #include <cmath>3 #include <a s s e r t . h>4 #include ” graphic draw . hpp”5

6 using namespace graph ic : : draw ;7 using namespace graph ic : : t o o l s ;8

9

10

11 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗12 ∗ Line implementat ion ∗13 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/14

15 // d e f a u l t c ’ t o r16 ScreenLine : : ScreenLine ( ) {}17

18 //c ’ t o r t a k ing two Point<2, in t>s as argument19 ScreenLine : : ScreenLine ( Point<2, int> const & StartPoint ,20 Point<2, int> const & EndPoint ){21 mStartPoint = StartPo int ;22 mEndPoint = EndPoint ;23 }24

25 Point<2, int> const & ScreenLine : : s e tS ta r tPo in t (26 Point<2, int> const & newStartPoint ){27 return mStartPoint = newStartPoint ;28 }29

30 Point<2, int> const & ScreenLine : : setEndPoint (31 Point<2, int> const & newEndPoint ) {32 return mEndPoint = newEndPoint ;33 }

APPENDIX B. SOURCE FILES 100

34

35 // s e t s the s t a r t and end Point<2, in t> to newColor36 Color const & ScreenLine : : s e tCo lo r ( Color const & newColor ) {37 mStartColor = newColor ;38 mEndColor = newColor ;39 return newColor ;40 }41

42 void ScreenLine : : s e tCo lo r ( Color const & newStartColor ,43 Color const & newEndColor ) {44 mStartColor = newStartColor ;45 mEndColor = newEndColor ;46 }47

48 Point<2, int> const & ScreenLine : : g e tS ta r tPo in t ( ) const {49 return mStartPoint ;50 }51

52 Point<2, int> const & ScreenLine : : getEndPoint ( ) const {53 return mEndPoint ;54 }55

56

57

58 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗59 ∗ Zbu f f e r implementat ion ∗60 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/61

62 // c ’ t o r63 template<typename T>64 Zbuf fer<T> : : Zbu f f e r ( ) {65 he ight = 1 ; // maxX66 width = 1 ; // maxY67

68 mBuffer . r e s i z e ( he ight ) ;69 for ( int x=0; x< mBuffer . s i z e ( ) ; x++) {70 mBuffer [ x ] . r e s i z e ( width ) ;71 }72

73 for ( int x=0; x< mBuffer . s i z e ( ) ; x++) {74 for ( int y=0; y< mBuffer . s i z e ( ) ; y++) {75 mBuffer [ x ] [ y ] . zcoord = 0 ;76 }77 }78 }79

80 template<typename T>81 Zbuf fer<T> : : Zbu f f e r ( DotDevice& device , Color const& co l o r = grey ) {82 he ight = std : : f l o o r (T( dev i c e . Height ( )/ dev i c e . UnitLength ( ) ) ) ;83 width = std : : f l o o r (T( dev i ce .Width ( )/ dev i c e . UnitLength ( ) ) ) ;84

85 mBuffer . r e s i z e ( width ) ;86 for ( int x=0; x< width ; x++) {87 mBuffer [ x ] . r e s i z e ( he ight ) ;88 }89

90 for ( int x=0; x< width ; x++) {

APPENDIX B. SOURCE FILES 101

91 for ( int y=0; y< he ight ; y++) {92 mBuffer [ x ] [ y ] . zcoord = 0 ;93 mBuffer [ x ] [ y ] . c l r = co l o r ;94 }95 }96

97 mDevice = &dev i ce ;98 }99

100 template<typename T>101 void Zbuf fer<T> : : s e tP i x e l ( int x , int y , T z , Color const& c ) {102 // only draw id coord ina t e s i n s i d e z b u f f e r103 i f ( checkPixe l (x , y , z ) ) {104 mBuffer [ x ] [ y ] . zcoord = z ;105 mBuffer [ x ] [ y ] . c l r = c ;106 }107 }108

109 template<typename T>110 bool Zbuf fer<T> : : checkPixe l ( int x , int y , T z ) {111 return x>=0 && x<width && y>=0 && y<width && z>mBuffer [ x ] [ y ] . zcoord && z<=1;112 }113

114 template<typename T>115 void Zbuf fer<T> : : drawBuffer ( ) {116

117 for ( int x = 0 ; x < width ; x++) {118 for ( int y = 0 ; y < he ight ; y++) {119 mDevice−>Se tP ixe l (120 x , y ,121 mBuffer [ x ] [ y ] . c l r . getRed ( ) ,122 mBuffer [ x ] [ y ] . c l r . getGreen ( ) ,123 mBuffer [ x ] [ y ] . c l r . getBlue ( )124 ) ;125 }126 }127 device−>Update ( ) ;128

129 }130

131

132

133 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗134 ∗ ScreenPolygon implementat ion ∗135 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/136

137

138 template<typename T>139 ScreenPolygon<T> : : ScreenPolygon ( Polygon<T> const& polygon ,140 Zbuf fer<T>& zbu f f e r , Camera<T>& camera , LightSource<T> const& l i g h t )141 {142 //mCamera(&camera ) , mLight(& l i g h t ) {143 mZbuffer = &zbu f f e r ;144 mCamera = &camera ;145 mLight = &l i g h t ;146 mOriginalPolygon = &polygon ;147 mProjected = polygon ;

APPENDIX B. SOURCE FILES 102

148 v0 . p = &polygon . po int ( 0 ) ;149 v0 . n = &polygon . normal ( 0 ) ;150 v1 . p = &polygon . po int ( 1 ) ;151 v1 . n = &polygon . normal ( 1 ) ;152 v2 . p = &polygon . po int ( 2 ) ;153 v2 . n = &polygon . normal ( 2 ) ;154 // p r o j e c t i on matrix c a l c u l a t e d from camera155 Matrix<4,T> pro j e c t i onMatr ix =156 camera . ge tPro j ec t i onMatr ix ( z bu f f e r . width , z bu f f e r . he ight ) ;157 // polygon ’ s po in t s p r o j e c t e d wi th p r o j e c t i on matrix −158 // normals are unchanged .159 mProjected . p r o j e c tPo in t s ( p ro j e c t i onMatr ix ) ;160 // bottom ve r t e x161 v0 . x = int ( f l o o r ( mProjected . po int ( 0 ) [ 0 ] + 0 . 5 ) ) , // x162 v0 . y = int ( f l o o r ( mProjected . po int ( 0 ) [ 1 ] + 0 . 5 ) ) , // y163 v0 . z = mProjected . po int ( 0 ) [ 2 ] ; // z164 // middle v e r t e x ( might be top or bottom )165 v1 . x = int ( f l o o r ( mProjected . po int ( 1 ) [ 0 ] + 0 . 5 ) ) , // x166 v1 . y = int ( f l o o r ( mProjected . po int ( 1 ) [ 1 ] + 0 . 5 ) ) , // y167 v1 . z = mProjected . po int ( 1 ) [ 2 ] ; // z168 // top v e r t e x169 v2 . x = int ( f l o o r ( mProjected . po int ( 2 ) [ 0 ] + 0 . 5 ) ) , // x170 v2 . y = int ( f l o o r ( mProjected . po int ( 2 ) [ 1 ] + 0 . 5 ) ) , // y171 v2 . z = mProjected . po int ( 2 ) [ 2 ] ; // z172 // s o r t v e r t i c e s ascending by y−va lue .173 // i f y o f p o s i t i o n 1 > y o f p o s i t i o n 2 −OR− i f they are equa l174 // but x o f p o s i t i o n 1 > x o f p o s i t i o n 2 then swap p o s i t i o n s .175 i f ( v1 . y > v2 . y | | ( v1 . y == v2 . y && v1 . x > v2 . x ) )176 std : : swap ( v1 , v2 ) ;177 // d i t t o f o r p o s i t i o n s 0 and 1178 i f ( v0 . y > v1 . y | | ( v0 . y == v1 . y && v0 . x > v1 . x ) ) {179 std : : swap ( v0 , v1 ) ;180 // i f p o s i t i o n 0 and 1 has been swapped ,181 // i t might be necessary to swap 1 and 2 again .182 i f ( v1 . y > v2 . y | | ( v1 . y == v2 . y && v1 . x > v2 . x ) )183 std : : swap ( v1 , v2 ) ;184 }185 }186

187

188 // This method f o r c e s the xy va l u e s in t o s p e c i f i c va l u e s .189 // I t ’ s f o r t e s t i n g ONLY.190 template<typename T>191 void ScreenPolygon<T> : : forceXYs ( int x0 , int y0 , int x1 ,192 int y1 , int x2 , int y2 )193 {194 v0 . x = x0 ;195 v1 . x = x1 ;196 v2 . x = x2 ;197 v0 . y = y0 ;198 v1 . y = y1 ;199 v2 . y = y2 ;200 // s o r t v e r t i c e s ascending by y−va lue .201 // i f y o f p o s i t i o n 1 > y o f p o s i t i o n 2 −OR− i f they are equa l202 // but x o f p o s i t i o n 1 > x o f p o s i t i o n 2 then swap po s i t i o n s .203 i f ( v1 . y > v2 . y | | ( v1 . y == v2 . y && v1 . x > v2 . x ) )204 std : : swap ( v1 , v2 ) ;

APPENDIX B. SOURCE FILES 103

205 // d i t t o f o r p o s i t i o n s 0 and 1206 i f ( v0 . y > v1 . y | | ( v0 . y == v1 . y && v0 . x > v1 . x ) ) {207 std : : swap ( v0 , v1 ) ;208 // i f p o s i t i o n 0 and 1 has been swapped ,209 // i t might be necessary to swap 1 and 2 again .210 i f ( v1 . y > v2 . y | | ( v1 . y == v2 . y && v1 . x > v2 . x ) )211 std : : swap ( v1 , v2 ) ;212 }213 }214

215

216 template<typename T>217 void ScreenPolygon<T> : : hLineGouraud ( int const & x0 , int const & x1 ,218 int const & y , T const & z0 , T const & z1 ,219 Color const & c0 , Color const & c1 ) {220 i f ( x0 == x1 ) // noth ing needs to be drawn221 return ;222 // t o t a l change o f x223 int deltaX = x1 − x0 ;224 // change o f z per x−s t ep225 T dZ = ( z1 − z0 )/ deltaX ;226 // change o f co l o r per x−s t ep227 double dRed = ( c1 . getRed ( ) − c0 . getRed ( ) ) / deltaX ;228 double dGreen = ( c1 . getGreen ( ) − c0 . getGreen ( ) ) / deltaX ;229 double dBlue = ( c1 . getBlue ( ) − c0 . getBlue ( ) ) / deltaX ;230

231 // loop vars232 int x = x0 ; T z = z0 ; Color c = c0 ;233 for ( x = x0 , z = z0 , c = c0 ; x < x1 ; ++x){234 mZbuffer−>s e tP i x e l (x , y , z , c ) ;235 c . changeRed (dRed ) ;236 c . changeGreen ( dGreen ) ;237 c . changeBlue ( dBlue ) ;238 z += dZ ;239 }240

241 }242

243 template<typename T>244 void ScreenPolygon<T> : : hLinePhong ( int const & x0 , int const & x1 ,245 int const & y , T const & z0 , T const & z1 ,246 Vector<3,T> const & n0 , Vector<3,T> const & n1 ,247 Point<3,T> const & p0 , Point<3,T> const & p1 ){248 i f ( x0 == x1 ) // noth ing needs to be drawn249 return ;250 // t o t a l change o f x251 int deltaX = x1 − x0 ;252 // r ep roca l253 T rDeltaX = 1/T( deltaX ) ;254 // change o f z per x−s t ep255 T dZ = ( z1 − z0 )/T( deltaX ) ;256 // change o f normal per x−s t ep257 Vector<3,T> dN = (n1 − n0 ) ∗ rDeltaX ;258 // change o f po in t per x−s t ep259 Vector<3,T> dP = vectorFromPoints (p0 , p1 ) ∗ rDeltaX ;260 // loop vars261 int x ; T z ; Vector<3,T> n ; Point<3,T> p ;

APPENDIX B. SOURCE FILES 104

262 for ( x = x0 , z = z0 , n = n0 , p = p0 ; x < x1 ; ++x){263 Color c = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,264 p , n , ∗mCamera ) ;265 //we check i f we want to draw in s e tP i x e l266 mZbuffer−>s e tP i x e l (x , y , z , c ) ;267 n += dN;268 n . normal ize ( ) ;269 p .move(dP ) ;270 z += dZ ;271 }272 }273

274 template<typename T>275 void ScreenPolygon<T> : : hLineFlat ( int const& xLeft , int const& xRight ,276 int const& y , T const & z0 , T const & z1 , Color f l a tCo l o r )277 {278 // t o t a l change o f x279 int deltaX = xRight − xLeft ;280 T dZ = ( z1 − z0 )/T( deltaX ) ;281 int x ;282 T z = z0 ;283 /∗ s t d : : cout << y << ” , ” << xLe f t << ” , ” << xRight284 << ” , ” << ( xRight − xLe f t ) << s t d : : end l ; ∗/285 for ( x = xLeft ; x < xRight ; ++x){286 mZbuffer−>s e tP i x e l (x , y , z , f l a tCo l o r ) ;287 z += dZ ;288 }289 // i f ( z != z1 )290 // s t d : : cout << ” error in hLineFlat , z i s ” << z << ” , z0 i s ”291 // << z0 << ” , z1 i s ” << z1 << ” , dx i s ” << de l taX292 // << ” , dZ i s ” << dZ << s t d : : end l ;293 }294

295 template<typename T>296 void ScreenPolygon<T> : : hLineLine ( int const& xLeft , int const& xRight ,297 int const& y , T const & z0 , T const & z1 , Color l i n eCo l o r )298 {299 mZbuffer−>s e tP i x e l ( xLeft , y , z0 , l i n eCo l o r ) ;300 mZbuffer−>s e tP i x e l ( xRight−1,y , z1 , l i n eCo l o r ) ;301 }302

303 template<typename T>304 void ScreenPolygon<T> : : draw (char shading ) {305 // determining shading model306 bool f l a t = fa l se ;307 bool gouraud = fa l se ;308 bool l i n e = fa l se ;309 bool phong = fa l se ;310

311 i f ( shading== ’ g ’ | | shading == ’G’ )312 gouraud = true ;313 else i f ( shading == ’p ’ | | shading == ’P ’ )314 phong = true ;315 else i f ( shading == ’ f ’ | | shading == ’F ’ )316 f l a t = true ;317 else i f ( shading == ’ l ’ | | shading == ’L ’ )318 l i n e = true ;

APPENDIX B. SOURCE FILES 105

319

320 // co l o r s f o r use wi th gouraud shading321 Color colorTopLeft , colorTopRight , colorBottomLeft , colorBottomRight ;322 // determining v e r t i c e s o f po lygon323 Vertexdata ∗ topLeft , ∗ topRight , ∗ bottomLeft , ∗ bottomRight ;324 i f ( v0 . y == v1 . y ) { // i f po lygon has bottom edge . . .325 topLe f t = &v2 ;326 topRight = &v2 ; // . . . s i d e edges have common top po in t . . .327

328 co lorTopLeft = colorTopRight329 = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,330 ∗( v2 . p ) , ∗v2 . n , ∗mCamera ) ;331

332 bottomLeft = &v0 ; // . . . but d i f f e r e n t bottom po in t s333

334 co lorBottomLeft = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,335 ∗( v0 . p ) , ∗( v0 . n ) , ∗mCamera ) ;336 bottomRight = &v1 ;337 colorBottomRight = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,338 ∗( v1 . p ) , ∗( v1 . n ) , ∗mCamera ) ;339 } else { // i f po lygon has ’ po in ty ’ bottom340 // make the v e c t o r s from v0 to v1 and v2341 T vecVAr0 [ 2 ] = {(T) v0 . x , (T) v0 . y } ;342 T vecVAr1 [ 2 ] = {(T) v1 . x , (T) v1 . y } ;343 T vecVAr2 [ 2 ] = {(T) v2 . x , (T) v2 . y } ;344 Point<2,T> poiP0 ( vecVAr0 ) ;345 Point<2,T> poiP1 ( vecVAr1 ) ;346 Point<2,T> poiP2 ( vecVAr2 ) ;347 Vector<2,T> vecV01 = vectorFromPoints ( poiP0 , poiP1 ) ;348 Vector<2,T> vecV02 = vectorFromPoints ( poiP0 , poiP2 ) ;349 // c a l c u l a t e determinant350 T determinant = vecV01 [ 0 ] ∗ vecV02 [ 1 ] − vecV01 [ 1 ] ∗ vecV02 [ 0 ] ;351

352 i f ( determinant < 0 ) { // determinant nega t i v e => vecV01 l e f t edge353 // s i d e edges have d i f f e r e n t top po in t s354 topLe f t = &v1 ;355

356 co lorTopLeft = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,357 ∗( v1 . p ) , ∗( v1 . n ) , ∗mCamera ) ;358

359 topRight = &v2 ;360

361 colorTopRight = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,362 ∗( v2 . p ) , ∗( v2 . n ) , ∗mCamera ) ;363

364 }365 // i f ( determinant >= 0 ) { // determinant p o s i t i v e or zero => vecV02366 // l e f t edge , ca t che s l i n e ! .367 else {368 // s i d e edges have d i f f e r e n t top po in t s369 topLe f t = &v2 ;370 co lorTopLeft = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,371 ∗( v2 . p ) , ∗( v2 . n ) , ∗mCamera ) ;372 topRight = &v1 ;373 colorTopRight = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,374 ∗( v1 . p ) , ∗( v1 . n ) , ∗mCamera ) ;375 }

APPENDIX B. SOURCE FILES 106

376 // s i d e edges have common bottom po in t377 bottomLeft = bottomRight = &v0 ;378 co lorBottomLeft = colorBottomRight379 = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,380 ∗( v0 . p ) , ∗( v0 . n ) , ∗mCamera ) ;381 }382 // x−coords o f s t a r t i n g po in t s383 int xLeft = bottomLeft−>x ;384 int xRight = bottomRight−>x ;385 // numerators o f i n v e r s e s l o p e c o e f f i c i e n t s386 int numLeft = topLeft−>x − bottomLeft−>x ;387 int numRight = topRight−>x − bottomRight−>x ;388 // d e l t a x = s i gn o f numerators389 int dXLeft = graph ic : : t o o l s : : s i gn ( numLeft ) ;390 int dXRight = graphic : : t o o l s : : s i gn ( numRight ) ;391 // denominators o f i n v e r s e s l o p e c o e f f i c i e n t s392 int denLeft = topLeft−>y − bottomLeft−>y ;393 int denRight = topRight−>y − bottomRight−>y ;394 // incrementors c o n t r o l l i n g overrun/underrun395 int i n cLe f t = denLeft ;396 int incRight = denRight ;397 // z−coords o f s t a r t i n g po in t s398 T zLe f t = bottomLeft−>z ;399 T zRight = bottomRight−>z ;400 // change o f z−coords per y−s t ep401 T dZLeft = ( topLeft−>z − bottomLeft−>z )/ denLeft ;402 T dZRight = ( topRight−>z − bottomRight−>z )/ denRight ;403 // normals f o r use wi th phong shading404 // (∗ bottomLeft−>p ) . p r i n t (” bot tomLef t : ” ) ;405 // (∗ topLe f t−>p ) . p r i n t (” t opLe f t : ” ) ;406 // (∗ bottomRight−>p ) . p r i n t (” bottomRight : ” ) ;407 // (∗ topRight−>p ) . p r i n t (” topRigh t : ” ) ;408 Vector<3,T> normalLeft = ∗( bottomLeft−>n ) ;409 Vector<3,T> normalRight = ∗( bottomRight−>n ) ;410 // change o f normals per y−s t ep411 Vector<3,T> dNormalLeft = (∗ ( topLeft−>n) − ∗( bottomLeft−>n ) )∗412 (1/(T) denLeft ) ;413

414 Vector<3,T> dNormalRight = (∗ ( topRight−>n) − ∗( bottomRight−>n ) )∗415 (1/(T) denRight ) ;416

417 // po in t s f o r use wi th phong shading418 Point<3,T> po in tLe f t = ∗bottomLeft−>p ;419 Point<3,T> pointRight = ∗bottomRight−>p ;420 // change o f po in t s per y−s t ep421 Vector<3,T> dPointLeft422 = vectorFromPoints (∗ bottomLeft−>p , ∗ topLeft−>p) ∗ (1/(T) denLeft ) ;423 Vector<3,T> dPointRight424 = vectorFromPoints (∗ bottomRight−>p , ∗ topRight−>p) ∗ (1/(T) denRight ) ;425 // co l o r s f o r use wi th gouraud shading426 Color c o l o rL e f t = colorBottomLeft ;427 Color co lo rR ight = colorBottomRight ;428 // change o f co l o r per y−s t ep429 double dRedLeft430 = ( co lorTopLeft . getRed ( ) − co lorBottomLeft . getRed ( ) ) / denLeft ;431 double dGreenLeft432 = ( co lorTopLeft . getGreen ( ) − co lorBottomLeft . getGreen ( ) ) / denLeft ;

APPENDIX B. SOURCE FILES 107

433 double dBlueLeft434 = ( co lorTopLeft . getBlue ( ) − co lorBottomLeft . getBlue ( ) ) / denLeft ;435 double dRedRight436 = ( colorTopRight . getRed ( ) − colorBottomRight . getRed ( ) ) / denRight ;437 double dGreenRight438 = ( colorTopRight . getGreen ( ) − colorBottomRight . getGreen ( ) ) / denRight ;439 double dBlueRight440 = ( colorTopRight . getBlue ( ) − colorBottomRight . getBlue ( ) ) / denRight ;441 // scan−l i n e loop , drawing l i n e s from y−h e i g h t v0 to v1442 for ( int y = v0 . y ; y < v1 . y ; ++y) {443 i f ( gouraud ) { // gouraud shading : i n t e r p o l a t e c o l o r s444 hLineGouraud ( xLeft , xRight , y , zLeft , zRight , c o l o rLe f t ,445 co lo rR ight ) ;446

447 c o l o rL e f t . changeRed ( dRedLeft ) ;448 c o l o rL e f t . changeGreen ( dGreenLeft ) ;449 c o l o rL e f t . changeBlue ( dBlueLeft ) ;450 co lo rR ight . changeRed ( dRedRight ) ;451 co lo rR ight . changeGreen ( dGreenRight ) ;452 co lo rR ight . changeBlue ( dBlueRight ) ;453 }454 //phong shading : i n t e r p o l a t e world po in t s and normals :455 else i f ( phong ) {456 hLinePhong ( xLeft , xRight , y , zLeft , zRight ,457 normalLeft , normalRight , po intLe f t , po intRight ) ;458 normalLeft += dNormalLeft ;459 normalLeft . normal ize ( ) ;460 po in tLe f t . move( dPointLeft ) ;461 normalRight += dNormalRight ;462 normalRight . normal ize ( ) ;463 pointRight . move( dPointRight ) ;464 } else i f ( f l a t ){ // f l a t shading : c o l o r in one co l o r465 Vector<3,T> avrNormal = (∗ v0 . n + ∗v1 . n + ∗v2 . n) ∗ ( 1 / 3 . 0 ) ;466 avrNormal . normal ize ( ) ;467 Color f l a tCo l o r = mLight−>PhongI l luminat ion (468 mProjected . mate r i a l ( ) , ∗( v1 . p ) ,469 avrNormal , ∗mCamera ) ;470

471 // a s s e r t ( xLe f t <= xRight ) ;472 i f ( xLeft > xRight )473 {474 std : : cout << xLeft << ” , ” << xRight475 << std : : endl ;476 std : : cout << ”Bottom : ( ” << bottomRight−>x << ” , ”477 << bottomRight−>y << ” ) ” << std : : endl ;478 std : : cout << ”TopRight : ( ” << topRight−>x << ” , ”479 << topRight−>y << ” ) ” << std : : endl ;480 std : : cout << ”TopLeft : ( ” << topLeft−>x << ” , ”481 << topLeft−>y << ” ) ” << std : : endl ;482 }483 hLineFlat ( xLeft , xRight , y , zLeft , zRight , f l a tCo l o r ) ;484 } else i f ( l i n e ) {485 Color l i n eCo l o r = mProjected . mate r i a l ( ) . g e tD i f f u s eCo l o r ( ) ;486 hLineLine ( xLeft , xRight , y , zLeft , zRight , l i n eCo l o r ) ;487 }488 i n cLe f t += numLeft ;489 while ( i n cLe f t > denLeft | | 0 >= incLe f t ) {

APPENDIX B. SOURCE FILES 108

490 xLeft += dXLeft ;491 i n cLe f t −= dXLeft ∗ denLeft ;492 }493 zLe f t += dZLeft ;494 incRight += numRight ;495 while ( incRight > denRight | | 0 >= incRight ) {496 xRight += dXRight ;497 incRight −= dXRight ∗ denRight ;498 }499 zRight += dZRight ;500 }501 // I n i t i a l i z i n g vars f o r next scan−l i n e loop .502 // I f both o f the f o l l ow i n g cond i t i on s are f a l s e :503 // e i t h e r po lygon has top edge and has a l r eady been drawn , or504 // polygon has bottom edge and no v a r i a b l e s has changed .505 // In e i t h e r case no vars need to be updated .506 i f ( topLeft−>y < topRight−>y ) { // Le f t edge dominated po lygon507 // Le f t edge loop parameters need to be updated508 // Right edge loop parameters are unchanged509 topLe f t = &v2 ;510 co lorTopLeft = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,511 ∗( v2 . p ) , ∗( v2 . n ) , ∗mCamera ) ;512 bottomLeft = &v1 ;513 co lorBottomLeft = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,514 ∗( v1 . p ) , ∗( v1 . n ) , ∗mCamera ) ;515 numLeft = topLeft−>x − bottomLeft−>x ;516 dXLeft = graph ic : : t o o l s : : s i gn ( numLeft ) ;517 denLeft = topLeft−>y − bottomLeft−>y ;518 i n cLe f t = denLeft ;519 dZLeft = ( topLeft−>z − bottomLeft−>z )/ denLeft ;520 dNormalLeft = (∗ ( topLeft−>n) − ∗( bottomLeft−>n ) )521 ∗ (1/(T) denLeft ) ;522

523 dPointLeft = vectorFromPoints (∗ bottomLeft−>p , ∗ topLeft−>p)524 ∗ (1/(T) denLeft ) ;525

526 dRedLeft = ( co lorTopLeft . getRed ( ) − co lorBottomLeft . getRed ( ) ) /527 denLeft ;528

529 dGreenLeft = ( co lorTopLeft . getGreen ( ) − co lorBottomLeft . getGreen ( ) ) /530 denLeft ;531

532 dBlueLeft = ( co lorTopLeft . getBlue ( ) − co lorBottomLeft . getBlue ( ) ) /533 denLeft ;534 } else i f ( topLeft−>y > topRight−>y ) { // Right edge dominated polygon535 // Right edge loop parameters need to be updated536 // Le f t edge loop parameters are unchanged537 topRight = &v2 ;538 colorTopRight = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,539 ∗( v2 . p ) , ∗( v2 . n ) , ∗mCamera ) ;540 bottomRight = &v1 ;541 colorBottomRight = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,542 ∗( v1 . p ) , ∗( v1 . n ) , ∗mCamera ) ;543

544 numRight = topRight−>x − bottomRight−>x ;545 dXRight = graphic : : t o o l s : : s i gn ( numRight ) ;546 denRight = topRight−>y − bottomRight−>y ;

APPENDIX B. SOURCE FILES 109

547 incRight = denRight ;548 dZRight = ( topRight−>z − bottomRight−>z )/ denRight ;549 dNormalRight = (∗ ( topRight−>n) − ∗( bottomRight−>n ) ) ∗550 (1/(T) denRight ) ;551

552 dPointRight = vectorFromPoints (∗ bottomRight−>p , ∗ topRight−>p) ∗553 (1/(T) denRight ) ;554

555 dRedRight = ( colorTopRight . getRed ( ) − colorBottomRight . getRed ( ) ) /556 denRight ;557

558 dGreenRight = ( colorTopRight . getGreen ( ) − colorBottomRight . getGreen ( ) ) /559 denRight ;560

561 dBlueRight = ( colorTopRight . getBlue ( ) − colorBottomRight . getBlue ( ) ) /562 denRight ;563 }564 // scan−l i n e loop , drawing l i n e s from y−h e i g h t v1 to v2565 for ( int y = v1 . y ; y < v2 . y ; ++y) {566 i f ( gouraud ) { // gouraud shading : i n t e r p o l a t e c o l o r s567 hLineGouraud ( xLeft , xRight , y , zLeft , zRight ,568 co l o rLe f t , co l o rR ight ) ;569 c o l o rL e f t . changeRed ( dRedLeft ) ;570 c o l o rL e f t . changeGreen ( dGreenLeft ) ;571 c o l o rL e f t . changeBlue ( dBlueLeft ) ;572 co lo rR ight . changeRed ( dRedRight ) ;573 co lo rR ight . changeGreen ( dGreenRight ) ;574 co lo rR ight . changeBlue ( dBlueRight ) ;575 }576 //phong shading : i n t e r p o l a t e world po in t s and normals :577 else i f ( phong ) {578 hLinePhong ( xLeft , xRight , y , zLeft , zRight ,579 normalLeft , normalRight , po intLe f t , po intRight ) ;580 normalLeft += dNormalLeft ;581 normalLeft . normal ize ( ) ;582 po in tLe f t . move( dPointLeft ) ;583 normalRight += dNormalRight ;584 normalRight . normal ize ( ) ;585 pointRight . move( dPointRight ) ;586 } else i f ( f l a t ){ // f l a t shading : c o l o r in one co l o r587 Vector<3,T> avrNormal = (∗ v0 . n + ∗v1 . n + ∗v2 . n) ∗ ( 1 / 3 . 0 ) ;588 avrNormal . normal ize ( ) ;589 i f ( xLeft > xRight )590 {591 std : : cout << xLeft << ” , ” << xRight << std : : endl ;592 std : : cout << ”Bottom : ( ” << bottomRight−>x << ” , ”593 << bottomRight−>y << ” ) ” << std : : endl ;594 std : : cout << ”TopRight : ( ” << topRight−>x << ” , ”595 << topRight−>y << ” ) ” << std : : endl ;596 std : : cout << ”TopLeft : ( ” << topLeft−>x << ” , ”597 << topLeft−>y << ” ) ” << std : : endl ;598 }599 Color f l a tCo l o r = mLight−>PhongI l luminat ion ( mProjected . mate r i a l ( ) ,600 ∗( v1 . p ) , avrNormal , ∗mCamera ) ;601 hLineFlat ( xLeft , xRight , y , zLeft , zRight , f l a tCo l o r ) ;602 } else i f ( l i n e ) {603 Color l i n eCo l o r = mProjected . mate r i a l ( ) . g e tD i f f u s eCo l o r ( ) ;

APPENDIX B. SOURCE FILES 110

604 hLineLine ( xLeft , xRight , y , zLeft , zRight , l i n eCo l o r ) ;605 }606 i n cLe f t += numLeft ;607 while ( i n cLe f t > denLeft | | 0 >= incLe f t ) {608 xLeft += dXLeft ;609 i n cLe f t −= dXLeft ∗ denLeft ;610 }611 zLe f t += dZLeft ;612 incRight += numRight ;613 while ( incRight > denRight | | 0 >= incRight ) {614 xRight += dXRight ;615 incRight −= dXRight ∗ denRight ;616 }617 zRight += dZRight ;618 }619 }620

621 template<typename T>622 void ScreenPolygon<T> : : p r i n t ( ) {623 (∗ v0 . p ) . p r i n t ( ”v0 po int : ” ) ;624 (∗ v0 . n ) . p r i n t ( ”n0 po int : ” ) ;625 (∗ v1 . p ) . p r i n t ( ”v1 po int : ” ) ;626 (∗ v0 . n ) . p r i n t ( ”n1 po int : ” ) ;627 (∗ v2 . p ) . p r i n t ( ”v2 po int : ” ) ;628 (∗ v0 . n ) . p r i n t ( ”n2 po int : ” ) ;629 }

B.7 readdata.cpp

1 #include <c s td io>2 #include <iostream>3 #include <iomanip>4 #include <f stream>5

6 #include <vector>7

8 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗\9 ∗ ∗

10 ∗ R e a d D a t a F i l e ( c o n s t c h a r ∗ ) ∗11 ∗ ∗12 ∗ The f i l e con ta ins the s p e c i f i c a t i o n o f a number o f Bez ier pa tches ∗13 ∗ ∗14 ∗ This f unc t i on ‘ ReadDataFile ( cons t char∗ f i l ename ) ’ which can read ∗15 ∗ the s p e c i f i c f i l e ‘ pa tches . data ’ are prov ided by knud henr ik sen ∗16 ∗ ∗17 ∗ The func t i on i s by no means genera l ! I t can only read the ∗18 ∗ data f i l e ‘ pa tches . data ’ , and t ha t i s a l s o the in t en s i on ! ∗19 ∗ ∗20 ∗ The purpose o f the t h i s f unc t i on i s to make i t easy f o r the ∗21 ∗ s t uden t s to g e t the con t r o l po in t s o f the s p e c i f i c ∗22 ∗ Bez ier sur faces , which are o b l i g a t o r y in the r epor t . ∗23 ∗ ∗24 \∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/25

26 // t yp ede f g raph i c s : : t o o l s : : Point Point ;27 typedef double T;

APPENDIX B. SOURCE FILES 111

28

29 using std : : cout ; using std : : c e r r ; using std : : endl ; using std : : f l u s h ;30 using std : : i f s t r e am ; using std : : setw ;31

32 0000000001000000000100000000010000000001000000000100000000010000000001000000000133

34 int ReadDataFile ( const char∗ f i l ename ,35 std : : vector<std : : vector<Point<3, T>>> &patches ) {36 const int NVERTEX = 0 ;37 const int READ VERTICES = 1 ;38 const int PATCHNAME = 2 ;39 const int SEARCH PATCHES = 3 ;40 const int READ PATCHES = 4 ;41

42 std : : vector<Point<3, T>> v e r t i c e s ;43 int patchCounter=0;44

45 char ch ;46 const int MAXBUFFER = 256 ;47 char InputBuf f e r [MAXBUFFER] ;48

49 int NumberOfVertices ;50 int VertexNumber ;51 double x ;52 double y ;53 double z ;54

55 char PatchName [MAXBUFFER] ;56 int PatchNumber ;57 int index 11 , index 12 , index 13 , index 14 ;58 int index 21 , index 22 , index 23 , index 24 ;59 int index 31 , index 32 , index 33 , index 34 ;60 int index 41 , index 42 , index 43 , index 44 ;61

62 i f s t r e am d a t a f i l e ( f i l ename ) ;63 i f ( ! d a t a f i l e ) {64 c e r r << ”Cannot open data f i l e : ”65 << f i l ename << endl << f l u s h ;66 return −1;67 }68

69 int s t a t e = NVERTEX;70 while ( d a t a f i l e . get ( InputBuf fer , MAXBUFFER, ’ \n ’ ) ) {71 i f ( d a t a f i l e . get ( ch ) && ch != ’ \n ’ ) {72 d a t a f i l e . c l o s e ( ) ;73 c e r r << ”Eof on data f i l e : ” << f i l ename74 << endl << f l u s h ;75 return −1;76 }77

78 // Now one l i n e o f data i s in Inpu tBuf f e r79 // Use s s can f to e x t r a c t the numeric va l u e s80

81 // Bui ld a data s t r u c t u r e which r ep r e s en t s the d i f f e r e n t82 // v e r t i c e s and pa tches83 //84 // There are s e v e r a l p o s s i b i l i t i e s f o r the input l i n e s :

APPENDIX B. SOURCE FILES 112

85 //86 // 1 : a comment l i n e , i . e . Inpu tBu f f e r [ 0 ] == ’#’87 // 2 : a ’ number o f v e r t i c e s l i n e ’ , i . e . j u s t one number88 // s s can f ( InputBuf fer , ”%d” , &NumberOfVertices )89 // 3 : a ’ v e r t e x l i n e ’ , i . e . 4 numbers90 // s s can f ( InputBuf fer , ”%d%l f%l f%l f ” ,91 // &VertexNumber , &x , &y , &z )92 // 4 : a ’ patch l i n e ’ , i . e . 17 numbers93 // s s can f ( InputBuf fer ,94 // ”%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d” ,95 // &PatchNumber ,96 // &index 11 , &index 12 , &index 13 , &index 14 ,97 // &index 21 , &index 22 , &index 23 , &index 24 ,98 // &index 31 , &index 32 , &index 33 , &index 34 ,99 // &index 41 , &index 42 , &index 43 , &index 44 )

100

101 switch ( s t a t e ) {102 case NVERTEX:103 i f ( InputBuf f e r [ 0 ] != ’#’ ) {104 i f ( s s c an f ( InputBuf fer , ”%d” ,105 &NumberOfVertices ) != 1) {106 c e r r << ”number o f v e r t i c e s ”107 << ” not found in data f i l e : ”108 << f i l ename << endl << f l u s h ;109 return −1;110 }111

112 v e r t i c e s . r e s i z e ( NumberOfVertices ) ;113

114 cout << ”Number o f Ve r t i c e s = ”115 << NumberOfVertices116 << endl << endl ;117

118 s t a t e = READ VERTICES;119 }120 break ;121 case READ VERTICES:122 i f ( InputBuf f e r [ 0 ] != ’#’ ) {123 i f ( s s c an f ( InputBuf fer , ”%d%l f%l f%l f ” ,124 &VertexNumber , &x , &y , &z ) != 4) {125 c e r r << ” ver tex not found in data f i l e : ”126 << f i l ename << endl << f l u s h ;127 return −1;128 }129 else {130 // i n s e r t the v e r t e x in a131 // data s t r u c t u r e132 v e r t i c e s [ VertexNumber −1 ] [ 0 ] = x ;133 v e r t i c e s [ VertexNumber −1 ] [ 1 ] = y ;134 v e r t i c e s [ VertexNumber −1 ] [ 2 ] = z ;135

136 i f (VertexNumber == NumberOfVertices ) {137 s t a t e = PATCHNAME;138 }139 }140 }141 break ;

APPENDIX B. SOURCE FILES 113

142 case PATCHNAME:143 i f ( InputBuf f e r [ 0 ] == ’#’ ) {144 i f ( s t r l e n ( InputBuf f e r ) > 2) {145 // read the name o f the patch146 i f ( s s c an f ( InputBuf fer , ”# %s” ,147 PatchName) != 1) {148 c e r r << ”patch name not found”149 << endl << f l u s h ;150 return −1;151 }152 cout << ”patch name : ” << PatchName153 << endl << f l u s h ;154 s t a t e = SEARCH PATCHES;155 }156 }157 break ;158 case SEARCH PATCHES:159 case READ PATCHES:160 i f ( InputBuf f e r [ 0 ] == ’#’ ) {161 i f ( s t a t e == READ PATCHES) {162 s t a t e = PATCHNAME;163 }164 }165 else {166 s t a t e = READ PATCHES;167 i f ( s s c an f ( InputBuf fer ,168 ”%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d” ,169 &PatchNumber ,170 &index 11 , &index 12 , &index 13 , &index 14 ,171 &index 21 , &index 22 , &index 23 , &index 24 ,172 &index 31 , &index 32 , &index 33 , &index 34 ,173 &index 41 , &index 42 , &index 43 , &index 44 ) != 17) {174 c e r r << ”No patch found in data f i l e : ”175 << f i l ename176 << endl << f l u s h ;177 return −1;178 }179 else {180 // i n s e r t patch in a data s t r u c t u r e181 ++patchCounter ;182 patches . r e s i z e ( patchCounter ) ;183 patches [ patchCounter −1] . r e s i z e ( 1 6 ) ;184

185 patches [ patchCounter −1 ] [ 0 ] =186 v e r t i c e s [ index 11 −1] ;187 patches [ patchCounter −1 ] [ 1 ] =188 v e r t i c e s [ index 12 −1] ;189 patches [ patchCounter −1 ] [ 2 ] =190 v e r t i c e s [ index 13 −1] ;191 patches [ patchCounter −1 ] [ 3 ] =192 v e r t i c e s [ index 14 −1] ;193 patches [ patchCounter −1 ] [ 4 ] =194 v e r t i c e s [ index 21 −1] ;195 patches [ patchCounter −1 ] [ 5 ] =196 v e r t i c e s [ index 22 −1] ;197 patches [ patchCounter −1 ] [ 6 ] =198 v e r t i c e s [ index 23 −1] ;

APPENDIX B. SOURCE FILES 114

199 patches [ patchCounter −1 ] [ 7 ] =200 v e r t i c e s [ index 24 −1] ;201 patches [ patchCounter −1 ] [ 8 ] =202 v e r t i c e s [ index 31 −1] ;203 patches [ patchCounter −1 ] [ 9 ] =204 v e r t i c e s [ index 32 −1] ;205 patches [ patchCounter −1 ] [ 10 ] =206 v e r t i c e s [ index 33 −1] ;207 patches [ patchCounter −1 ] [ 11 ] =208 v e r t i c e s [ index 34 −1] ;209 patches [ patchCounter −1 ] [ 12 ] =210 v e r t i c e s [ index 41 −1] ;211 patches [ patchCounter −1 ] [ 13 ] =212 v e r t i c e s [ index 42 −1] ;213 patches [ patchCounter −1 ] [ 14 ] =214 v e r t i c e s [ index 43 −1] ;215 patches [ patchCounter −1 ] [ 15 ] =216 v e r t i c e s [ index 44 −1] ;217 }218 }219 break ;220 }221 }222 i f ( ! d a t a f i l e . e o f ( ) ) {223 c e r r << ”Something s t range happend on data f i l e : ”224 << f i l ename << endl ;225 return −1;226 }227 d a t a f i l e . c l o s e ( ) ;228

229 return 0 ;230 }

B.8 showObligatory.cpp

1 //#inc l ude ”DotDevice/DotDevice . h”2 #include <vector>3 #include ” graphic . h”4 #include ” readdata . cpp”5

6 typedef double T;7

8 DotDevice∗ dev i ce ;9 Zbuf fer<T>∗ zbuf ;

10

11

12 void showObligatory ( char shading , int s ign , char f i l ename [ ] , int depth , T zoom , T pos [ ] , Color matCol ) {13 using namespace graph ic ;14

15 std : : vector<std : : vector<Point<3,T>>> patches ;16 int r e s u l t = ReadDataFile ( f i l ename , patches ) ;17

18 // z b u f f e r19 zbuf = new Zbuf fer<T>(∗device , white ) ;20

21 // s e t t i n g up the world system

APPENDIX B. SOURCE FILES 115

22 world : : Mater ia l<T> mate r i a l (matCol , white , 0 . 4 , 0 . 6 , 0 . 7 , 3 ) ;23

24 //camera25 T aim [ ] = {0 ,0 , 0} ;26 T up [ ] = {0 ,0 ,−1} ;27 Point<3,T> pAim(aim ) ;28 Point<3,T> pPos ( pos ) ;29 Vector<3,T> pUp(up ) ;30 Camera<T> camera ( pos , aim , up , 1 . 2 , zoom ) ;31

32 // l i g h t s o u r c e33 T tLightPo int [ ]={0 , 5 , 7} ;34 Point<3,T> l i g h tPo i n t ( tL ightPo int ) ;35 LightSource<T> l i g h t ( l i g h tPo i n t ) ;36

37 // p r i n t the b e z i e r su r f a c e38

39

40 for ( int i =0; i<patches . s i z e ( ) ; i++) {41 BezierPatch<T> bp( patches [ i ] , mater ia l , depth , shading , s i gn ) ;42 bp . drawPatch (∗ zbuf , camera , l i g h t ) ;43 std : : cout << ”patch ” << i << std : : endl ;44 }45 }46

47 void showParametric ( char shading , int s ign , T zoom , T pos [ ] , Color matCol ) {48 using namespace graph ic ;49

50 // z b u f f e r51 zbuf = new Zbuf fer<T>(∗device , white ) ;52

53 // s e t t i n g up the world system54 world : : Mater ia l<T> mate r i a l (matCol , white , 0 . 4 , 0 . 6 , 0 . 7 , 3 ) ;55

56 //camera57 T aim [ ] = {−6 ,−6 ,0};58 T up [ ] = {0 ,0 ,−3} ;59 Point<3,T> pAim(aim ) ;60 Point<3,T> pPos ( pos ) ;61 Vector<3,T> pUp(up ) ;62 Camera<T> camera ( pos , aim , up , 1 . 2 , zoom , 0 , −100);63

64 // l i g h t s o u r c e65 T tLightPo int [ ]={0 , 5 , 7} ;66 Point<3,T> l i g h tPo i n t ( tL ightPo int ) ;67 LightSource<T> l i g h t ( l i g h tPo i n t ) ;68

69 Parametr icSurface<T> ps ( mater ia l , shading , s i gn ) ;70 std : : cout << ”Here comes bottom : ” << std : : endl ;71 ps . drawBottom(∗ zbuf , camera , l i g h t ) ;72 std : : cout << ”Here comes handle : ” << std : : endl ;73 ps . drawHandle (∗ zbuf , camera , l i g h t ) ;74 std : : cout << ”Here comes top : ” << std : : endl ;75 ps . drawTop(∗ zbuf , camera , l i g h t ) ;76 std : : cout << ”Here comes middle : ” << std : : endl ;77 ps . drawMiddle (∗ zbuf , camera , l i g h t ) ;78 }

APPENDIX B. SOURCE FILES 116

79 void DisplayCal lBack ( ){80 cout << ”−−>DisplayCal lBack ” << endl << f l u s h ;81 int un i t l eng th = device−>UnitLength ( 1 ) ; // c l e a r i n g d i s p l a y82 device−>Clear ( ) ;83 device−>Update ( ) ;84 device−>UnitLength ( un i t l eng th ) ; // r e s t o r i n g un i t l e n g h t85

86 zbuf−>drawBuffer ( ) ;87

88 device−>Update ( ) ;89 }90

91 int main ( int argc , char∗∗ argv )92 {93 using std : : cout ;94 using std : : endl ;95 using std : : f l u s h ;96

97 dev i ce = new DotDevice (700 , 700 , ”Obl igatory ” ) ;98 device−>UnitLength ( 1 ) ;99 device−>Clear ( ) ;

100

101 char tea [ ] = ” teapot . data” ;102 char nor1 [ ] = ”Normal1 . data” ;103 char nor2 [ ] = ”Normal2 . data” ;104 char cone [ ] = ”Cone . data” ;105 char sma [ ] = ”Smarty . data” ;106 char sph [ ] = ”Sphere . data” ;107 char pain [ ] = ”pain . data” ;108 char d i sk [ ] = ” d i sk . data” ;109

110 T f r on t [ 3 ] = { 8 . 0 , 0 , 4 . 0 } ; // f r o n t a l p o s i t i o n111 T s id e [ 3 ] = { 3 . 0 , 6 . 0 , 5 . 0 } ; // s i d e p o s t i t i o n112 T top [ 3 ] = { 3 . 0 , 0 . 0 , 1 0 . 0 } ; // top113 T topD [ 3 ] = { 3 . 0 , 2 . 0 , 1 0 . 0 } ; // top114

115 // type o f shade , s i gn o f formal , f i l e , depth , zoom fac to r , p o s i t i o n o f eye , c o l o r116 // showObl iga tory ( ’ g ’ , −1, tea , 3 , 0 .8 , f ront , b l u e ) ;117 showObligatory ( ’p ’ , −1, tea , 3 , 0 . 8 , s ide , b lue ) ;118 // showObl iga tory ( ’ l ’ , −1, tea , 2 , 0 .9 , s ide , b l u e ) ;119 // showObl iga tory ( ’ p ’ , −1, tea , 3 , 0 .8 , top , b l u e ) ;120

121 // showObl iga tory ( ’ g ’ , −1, nor1 , 3 , 2 .5 , f ront , green ) ;122 // showObl iga tory ( ’ p ’ , −1, nor1 , 3 , 2 .5 , s ide , green ) ;123 // showObl iga tory ( ’ g ’ , −1, nor1 , 3 , 2 .5 , top , green ) ;124

125 // showObl iga tory ( ’ p ’ , −1, nor2 , 3 , 2 .5 , f ront , red ) ;126 // showObl iga tory ( ’ g ’ , −1, nor2 , 3 , 2 .5 , s ide , red ) ;127 // showObl iga tory ( ’ p ’ , −1, nor2 , 3 , 2 .5 , top , red ) ;128

129 // showObl iga tory ( ’ p ’ , −1, cone , 3 , 2 .5 , f ront , y e l l ow ) ;130 // showObl iga tory ( ’ g ’ , −1, cone , 3 , 2 .5 , s ide , y e l l ow ) ;131 // showObl iga tory ( ’ p ’ , −1, cone , 3 , 2 .5 , top , y e l l ow ) ;132

133 // smart used to comment on be z i e r−su r f a c e usage134 // showObl iga tory ( ’ f ’ , −1, sma , 0 , 2 .5 , s ide , v i o l e t ) ;135 // showObl iga tory ( ’ f ’ , −1, sma , 1 , 2 .5 , s ide , v i o l e t ) ;

APPENDIX B. SOURCE FILES 117

136 // showObl iga tory ( ’ f ’ , −1, sma , 2 , 2 .5 , s ide , v i o l e t ) ;137 // showObl iga tory ( ’ p ’ , −1, sma , 3 , 2 .5 , s ide , v i o l e t ) ;138 // showObl iga tory ( ’ g ’ , −1, sma , 3 , 2 .5 , s ide , v i o l e t ) ;139

140 // note the l i n e ar t141 // showObl iga tory ( ’ g ’ , −1, sph , 3 , 2 .5 , f ront , magenta ) ;142 // showObl iga tory ( ’ p ’ , −1, sph , 3 , 2 .5 , s ide , magenta ) ;143 // showObl iga tory ( ’ l ’ , −1, sph , 3 , 2 .5 , top , magenta ) ;144

145 // showObl iga tory ( ’ g ’ , 1 , pain , 3 , 2 .5 , f ront , cyan ) ;146 // showObl iga tory ( ’ p ’ , 1 , pain , 3 , 2 .5 , s ide , cyan ) ;147 // showObl iga tory ( ’ p ’ , 1 , pain , 3 , 2 .5 , top , cyan ) ;148

149 // showObl iga tory ( ’ g ’ , −1, d i sk , 3 , 2 .5 , f ront , green ) ; // noshow150 // showObl iga tory ( ’ p ’ , −1, d i sk , 3 , 2 .5 , s ide , green ) ; // d i s k1151 // showObl iga tory ( ’ g ’ , −1, d i sk , 3 , 2 .5 , topD , green ) ;152 // showObl iga tory ( ’ g ’ , −1, d i sk , 3 , 2 .5 , top , green ) ; // noshow153 /∗154 pr e f e r ed s i gn s o f normals :155 pain : 1156 a l l o t h e r s : −1157 ∗/158

159 T bottomP [ 3 ] = { −15.0 ,30.0 ,−50.0} ; // top160 T frontP [ 3 ] = {40 . 0 , 0 , 2 0 . 0} ; // f r o n t a l p o s i t i o n161 T sideP [ 3 ] = { 1 5 . 0 , 3 0 . 0 , 2 5 . 0 } ; // s i d e p o s t i t i o n162 T topP [ 3 ] = { 1 5 . 0 , 0 . 0 , 5 0 . 0 } ; // top163 // showParametric ( ’ l ’ , 1 , 1 .5 , frontP , red ) ;164 // showParametric ( ’ p ’ , 1 , 1 .5 , sideP , red ) ;165 // showParametric ( ’ l ’ , 1 , 1 .5 , sideP , red ) ;166 // showParametric ( ’ g ’ , 1 , 1 .5 , topP , red ) ;167 // showParametric ( ’ p ’ , 1 , 2 .5 , bottomP , red ) ;168

169 glutDisplayFunc ( DisplayCal lBack ) ;170

171 cout << ”For t h i s DisplayCal lBack func t i on you should see : ” << endl ;172 cout << ”=================================================” << endl ;173 cout << ”A very n i c e f i g u r e ” << endl ;174 cout << ”===================” << endl ;175 cout << ”g − to t ogg l e the g r id on and o f f . ” << endl ;176 cout << ”d − to r ed i s p l a y the scene . ” << endl ;177 cout << ”q − to qu i t the program . ” << endl ;178 cout << endl ;179

180 // Let GLUT take over and r e l y on the c a l l−back f unc t i on s181 glutMainLoop ( ) ;182

183 return 0 ;184 }

B.9 testPolygons.cpp

1 #include <vector>2 #include ” graphic . h”3 #include ” readdata . cpp”4

APPENDIX B. SOURCE FILES 118

5 DotDevice∗ dev i ce ;6 Zbuf fer<f loat>∗ zbuf ;7

8 // t h i s f unc t i on tak e s 3 po in t s and draw the t r i a n g l e9 void drawTriangle ( int x0 , int y0 , int x1 , int y1 , int x2 , int y2 ){

10 device−>TestLine ( x0 , y0 , x1 , y1 ) ;11 device−>TestLine ( x1 , y1 , x2 , y2 ) ;12 device−>TestLine ( x2 , y2 , x0 , y0 ) ;13 }14

15 void t e s tPo lygons ( ) {16 using namespace graph ic ;17 using namespace graph ic ;18 // f i r s t we b u i l d the camera , mater ia l , l i g h t and z−b u f f e r19 world : : Mater ia l<f loat> mater ia l 1 ( grey , white , 1 , 0 , 0 , 2 ) ; // pure l y ambient20 world : : Mater ia l<f loat> mater ia l 2 ( black , white , 1 , 0 , 0 , 2 ) ; // pure l y ambient21 f loat aim [ ] = {1 ,1 , 0} ;22 f loat pos [ ] = {0 , 0 , 1 0 . 0} ;23 f loat up [ ] = {0 ,−1 ,0} ;24 Point<3, f loat> pAim(aim ) ;25 Point<3, f loat> pPos ( pos ) ;26 Vector<3, f loat> pUp(up ) ;27 Camera<f loat> camera ( pos , aim , up ,1 , 0 . 1 , 0 , −100) ;28

29 f loat tL ightPo int [ ]= { 0 . 0 , 0 . 0 , 2 . 0 } ;30 Point<3, f loat> l i g h tPo i n t ( tL ightPo int ) ;31 LightSource<f loat> l i g h t ( l i g h tPo i n t ) ;32 zbuf = new Zbuf fer<f loat >(∗device , white ) ;33

34 // s e t t i n g up the f i r s t t r i a n g l e35 f loat t1 [ ] = {10 . 0 , 1 0 . 0 , 0} ;36 f loat t2 [ ] = {80 . 0 , 1 0 . 0 , 0} ;37 f loat t3 [ ] = {40 . 0 , 8 0 . 0 , 0} ;38 Point<3> p1 ( t1 ) ;39 Point<3> p2 ( t2 ) ;40 Point<3> p3 ( t3 ) ;41

42 // s e t t i n g up the second t r i a n g l e43 f loat t4 [ ] = {20 ,20 ,3} ;44 f loat t5 [ ] = {80 ,85 ,−2} ;45 f loat t6 [ ] = {95 ,30 ,−2} ;46 Point<3> p4 ( t4 ) ;47 Point<3> p5 ( t5 ) ;48 Point<3> p6 ( t6 ) ;49

50 // j u s t a few dummy va lu e s − don ’ t matter51 f loat nA1 [ 3 ] = {0 ,0 , 1} ;52 f loat nA2 [ 3 ] = {0 ,0 , 1} ;53 f loat nA3 [ 3 ] = {0 ,0 , 1} ;54 Vector<3, f loat> n1 (nA1 ) ;55 Vector<3, f loat> n2 (nA2 ) ;56 Vector<3, f loat> n3 (nA3 ) ;57 n1 . normal ize ( ) ;58 n2 . normal ize ( ) ;59 n3 . normal ize ( ) ;60

61 //world po lygon

APPENDIX B. SOURCE FILES 119

62 world : : Polygon<f loat> polygon1 (p1 , p2 , p3 , n1 , n2 , n3 , mate r i a l 1 ) ;63 world : : Polygon<f loat> polygon2 (p4 , p5 , p6 , n1 , n2 , n3 , mate r i a l 2 ) ;64 ScreenPolygon<f loat> screenPoly1 ( polygon1 , ∗ zbuf , camera , l i g h t ) ;65 ScreenPolygon<f loat> screenPoly2 ( polygon2 , ∗ zbuf , camera , l i g h t ) ;66

67 screenPoly1 . draw ( ’ f ’ ) ;68 screenPoly2 . draw ( ’ f ’ ) ;69 }70

71 // the va lue in s i gn i s mu l t i p l i e d on the normal v e c t o r s72 // in e f f e c t one can i n v e r t a l l normals in one go73 // the va lue in shading i s used to de s i de which shading shou ld be used74 void te s tShad ing ( int s ign , char shading ){75 using namespace graph ic ;76 f loat t1 [ ] = {2 . 0 , 1 . 0 , −1 . 0} ;77 f loat t2 [ ] = { −1.0 ,−2.0 ,−2.0} ;78 f loat t3 [ ] = {0 . 5 , −0 . 5 , 1 . 0} ;79 Point<3> p1 ( t1 ) ;80 Point<3> p2 ( t2 ) ;81 Point<3> p3 ( t3 ) ;82

83 f loat nA1 [ 3 ] = {0.7 ,−1.3 ,−0.3} ;84 f loat nA2 [ 3 ] = {1.3 ,−0.7 ,−0.3} ;85 f loat nA3 [ 3 ] = {1 ,−1 ,0 .3} ;86 Vector<3, f loat> n1 (nA1 ) ;87 Vector<3, f loat> n2 (nA2 ) ;88 Vector<3, f loat> n3 (nA3 ) ;89 n1 . normal ize ( ) ;90 n2 . normal ize ( ) ;91 n3 . normal ize ( ) ;92 world : : Mater ia l<f loat> mater ia l 1 ( red , white , 0 . 5 , 0 . 9 , 0 . 8 , 5 ) ;93 world : : Polygon<f loat> polygon1 (p1 , p2 , p3 , s i gn ∗n1 , s i gn ∗n2 , s i gn ∗n3 , mate r i a l 1 ) ;94 f loat aim [ ] = {0 ,0 , 0} ;95 f loat pos [ ] = {4 . 0 , −8 . 0 , 0 . 0} ;96 f loat up [ ] = {0 ,0 , 1} ;97 Point<3, f loat> pAim(aim ) ;98 Point<3, f loat> pPos ( pos ) ;99 Vector<3, f loat> pUp(up ) ;

100 Camera<f loat> camera ( pos , aim , up , 1 , 1 . 5 ) ;101 f loat tL ightPo int [ ]={2 ,−1 ,0} ;102 Point<3, f loat> l i g h tPo i n t ( tL ightPo int ) ;103 LightSource<f loat> l i g h t ( l i gh tPo in t , 0 . 1 , 0 . 1 , 0 . 1 ) ;104 zbuf = new Zbuf fer<f loat >(∗device , white ) ;105 ScreenPolygon<f loat> screenPoly1 ( polygon1 , ∗ zbuf , camera , l i g h t ) ;106 screenPoly1 . draw ( shading ) ;107

108 camera . p r i n t ( ”Camera : ” ) ;109 }110

111 void DisplayCal lBack ( ){112 cout << ”−−>DisplayCal lBack ” << endl << f l u s h ;113 int un i t l eng th = device−>UnitLength ( 1 ) ; // c l e a r i n g d i s p l a y114 device−>Clear ( ) ;115 device−>Update ( ) ;116 device−>UnitLength ( un i t l eng th ) ; // r e s t o r i n g un i t l e n g h t117

118 //draw z b u f f e r

APPENDIX B. SOURCE FILES 120

119 zbuf−>drawBuffer ( ) ;120

121 // adding g r i d s as the very l a s t122 device−>Update ( ) ;123 }124

125 int main ( int argc , char∗∗ argv )126 {127 using std : : cout ;128 using std : : endl ;129 using std : : f l u s h ;130

131 dev i ce = new DotDevice (400 , 300 , ”Shading” ) ;132 device−>Clear ( ) ;133 device−>Update ( ) ;134 device−>UnitLength ( 1 ) ;135

136 // c a l l i n g t e s t f unc t i on137 // t e s tPo l y gons ( ) ;138 // t e s tShad ing (1 , ’ g ’ ) ; // gouraud139 // t e s tShad ing (−1, ’ g ’ ) ; //gouraud , i n v e r t e d normals140 // t e s tShad ing (1 , ’ p ’ ) ; //phong141 te s tShad ing (−1 , ’p ’ ) ; //phong , i n v e r t e d normals142

143 glutDisplayFunc ( DisplayCal lBack ) ;144

145 cout << ”=================================================” << endl ;146 cout << ”This w i l l show a whole bunch o f polygons ” << endl ;147 cout << ” In the window type : ” << endl ;148 cout << ”===================” << endl ;149 cout << ”g − to t ogg l e the g r id on and o f f . ” << endl ;150 cout << ”d − to r ed i s p l a y the scene . ” << endl ;151 cout << ”q − to qu i t the program . ” << endl ;152 cout << endl ;153

154 // Let GLUT take over and r e l y on the c a l l−back f unc t i on s155 glutMainLoop ( ) ;156

157 return 0 ;158 }

B.10 testZbuffer.cpp

1 #include <vector>2 #include ” graphic . h”3 #include ” readdata . cpp”4

5 DotDevice∗ dev i ce ;6 Zbuf fer<f loat>∗ zbuf ;7

8 // t h i s f unc t i on tak e s 3 po in t s and draw the t r i a n g l e9 void drawTriangle ( int x0 , int y0 , int x1 , int y1 , int x2 , int y2 ){

10 device−>TestLine ( x0 , y0 , x1 , y1 ) ;11 device−>TestLine ( x1 , y1 , x2 , y2 ) ;12 device−>TestLine ( x2 , y2 , x0 , y0 ) ;13 }

APPENDIX B. SOURCE FILES 121

14

15 void t e s tZBu f f e r ( ) {16 using namespace graph ic ;17

18 // i n i t i a l i z i n g c on s i s t e n t v a r i a b l e s : ma t e r i a l s po lygons , cameras and l i g h t i n g19 f loat t1 [ ] = { 2 . 0 , 1 . 0 , 0 } ;20 f loat t2 [ ] = { −1.0 ,−2.0 ,−0.2} ;21 f loat t3 [ ] = {0 .5 , −0 .5 ,0} ;22 f loat t4 [ ] = {2 .0 ,1 .0 , −1} ;23 f loat t5 [ ] = { −1.0 ,−2.0 ,−0.5} ;24 f loat t6 [ ] = {0.5 ,−0.5 ,−1} ;25 Point<3> p1 ( t1 ) ;26 Point<3> p2 ( t2 ) ;27 Point<3> p3 ( t3 ) ;28 Point<3> p4 ( t4 ) ;29 Point<3> p5 ( t5 ) ;30 Point<3> p6 ( t6 ) ;31 f loat nA1 [ 3 ] = {0 ,0 ,−1} ;32 f loat nA2 [ 3 ] = {0 ,0 ,−1} ;33 f loat nA3 [ 3 ] = {0 ,0 ,−1} ;34 Vector<3, f loat> n1 (nA1 ) ;35 Vector<3, f loat> n2 (nA2 ) ;36 Vector<3, f loat> n3 (nA3 ) ;37 n1 . normal ize ( ) ;38 n2 . normal ize ( ) ;39 n3 . normal ize ( ) ;40 world : : Mater ia l<f loat> mater ia l 1 ( grey , white , 1 , 0 , 0 , 2 ) ;41 world : : Mater ia l<f loat> mater ia l 2 ( v i o l e t , white , 1 , 0 , 0 , 2 ) ;42 world : : Polygon<f loat> polygon1 (p1 , p2 , p3 , n1 , n2 , n3 , mate r i a l 1 ) ;43 world : : Polygon<f loat> polygon2 (p4 , p5 , p6 , n1 , n2 , n3 , mate r i a l 2 ) ;44 f loat aim [ ] = {6 ,6 , 0} ;45 f loat pos [ ] = {6 ,6 , 2} ;46 f loat up [ ] = {0 ,1 , 0} ;47 Point<3, f loat> pAim(aim ) ;48 Point<3, f loat> pPos ( pos ) ;49 Vector<3, f loat> pUp(up ) ;50 Camera<f loat> camera ( pos , aim , up ) ;51 f loat tL ightPo int [ ]={5 , 5 , 2} ;52 Point<3, f loat> l i g h tPo i n t ( tL ightPo int ) ;53 LightSource<f loat> l i g h t ( l i g h tPo i n t ) ;54

55 // the z b u f f e r56 zbuf = new Zbuf fer<f loat >(∗device , white ) ;57

58 // f r on t po lygon59 ScreenPolygon<f loat> polyH1 ( polygon1 , ∗ zbuf , camera , l i g h t ) ;60 polyH1 . forceXYs (1 , 1 , 7 ,2 , 5 , 8 ) ;61 polyH1 . draw ( ’ f ’ ) ;62

63 // back polygon64 ScreenPolygon<f loat> polyH2 ( polygon2 , ∗ zbuf , camera , l i g h t ) ;65 polyH2 . forceXYs (12 ,1 , 4 ,3 , 8 , 9 ) ;66 polyH2 . draw ( ’ f ’ ) ;67

68 }69

70 void DisplayCal lBack ( ){

APPENDIX B. SOURCE FILES 122

71 cout << ”−−>DisplayCal lBack ” << endl << f l u s h ;72 int un i t l eng th = device−>UnitLength ( 1 ) ; // c l e a r i n g d i s p l a y73 device−>Clear ( ) ;74 device−>Update ( ) ;75 device−>UnitLength ( un i t l eng th ) ; // r e s t o r i n g un i t l e n g h t76

77 //draw z b u f f e r78 zbuf−>drawBuffer ( ) ;79

80 //draw l i n e s o f the t r i a n g l e s81 drawTriangle (1 , 1 , 7 ,2 , 5 , 8 ) ; //polyH182 drawTriangle (12 ,1 , 4 ,3 , 8 , 9 ) ; //polyH283

84 // adding g r i d s as the very l a s t85 device−>Grid (1 , 1 ) ;86 device−>Update ( ) ;87 }88

89 int main ( int argc , char∗∗ argv )90 {91 using std : : cout ;92 using std : : endl ;93 using std : : f l u s h ;94

95 dev i ce = new DotDevice (400 , 300 , ”DotDevice Example” ) ;96 device−>Clear ( ) ;97 device−>Update ( ) ;98 device−>UnitLength ( 2 5 ) ;99

100 // c a l l i n g t e s t f unc t i on101 t e s tZBu f f e r ( ) ;102

103 glutDisplayFunc ( DisplayCal lBack ) ;104

105 cout << ”=================================================” << endl ;106 cout << ”This w i l l show a whole bunch o f polygons ” << endl ;107 cout << ” In the window type : ” << endl ;108 cout << ”===================” << endl ;109 cout << ”g − to t ogg l e the g r id on and o f f . ” << endl ;110 cout << ”d − to r ed i s p l a y the scene . ” << endl ;111 cout << ”q − to qu i t the program . ” << endl ;112 cout << endl ;113

114 // Let GLUT take over and r e l y on the c a l l−back f unc t i on s115 glutMainLoop ( ) ;116

117 return 0 ;118 }

B.11 testPolyDrawing.cpp

1 #include <vector>2 #include ” graphic . h”3 #include ” readdata . cpp”4

5 DotDevice∗ dev i ce ;

APPENDIX B. SOURCE FILES 123

6 Zbuf fer<f loat>∗ zbuf ;7

8 // t h i s f unc t i on tak e s 3 po in t s and draw the t r i a n g l e9 void drawTriangle ( int x0 , int y0 , int x1 , int y1 , int x2 , int y2 ){

10 device−>TestLine ( x0 , y0 , x1 , y1 ) ;11 device−>TestLine ( x1 , y1 , x2 , y2 ) ;12 device−>TestLine ( x2 , y2 , x0 , y0 ) ;13 }14

15 void tes tPo lygon ( ) {16 using namespace graph ic ;17

18 //we s t a r t out by c l e a r i n g the d i s p l a y19 // dev ice−>Clear ( ) ;20 // i n i t i a l i z i n g c on s i s t e n t v a r i a b l e s : ma t e r i a l s po lygons , cameras and l i g h t i n g21 f loat t1 [ ] = {2 . 0 , 1 . 0 , −1 . 0} ;22 f loat t2 [ ] = { −1.0 ,−2.0 ,−2.0} ;23 f loat t3 [ ] = {0 . 5 , −0 . 5 , 1 . 0} ;24 Point<3> p1 ( t1 ) ;25 Point<3> p2 ( t2 ) ;26 Point<3> p3 ( t3 ) ;27 f loat nA1 [ 3 ] = {0.7 ,−1.3 ,−0.3} ;28 f loat nA2 [ 3 ] = {1.3 ,−0.7 ,−0.3} ;29 f loat nA3 [ 3 ] = {1 ,−1 ,0 .3} ;30 Vector<3, f loat> n1 (nA1 ) ;31 Vector<3, f loat> n2 (nA2 ) ;32 Vector<3, f loat> n3 (nA3 ) ;33 n1 . normal ize ( ) ;34 n2 . normal ize ( ) ;35 n3 . normal ize ( ) ;36 world : : Mater ia l<f loat> mate r i a l ( green , white , 1 , 0 , 0 , 2 ) ;37 world : : Polygon<f loat> polygon (p1 , p2 , p3 , n1 , n2 , n3 , mate r i a l ) ;38 //Point<3> pVRP; pVRP[ 0 ] =39 f loat aim [ ] = {0 ,0 , 0} ;40 f loat pos [ ] = {4 . 0 , −8 . 0 , 0 . 0} ;41 f loat up [ ] = {0 ,0 , 1} ;42 Point<3, f loat> pAim(aim ) ;43 Point<3, f loat> pPos ( pos ) ;44 Vector<3, f loat> pUp(up ) ;45 Camera<f loat> camera ( pos , aim , up ) ;46 f loat tL ightPo int [ ]={2 ,−1 ,0} ;47 Point<3, f loat> l i g h tPo i n t ( tL ightPo int ) ;48 LightSource<f loat> l i g h t ( l i g h tPo i n t ) ;49

50 // the z b u f f e r51 zbuf = new Zbuf fer<f loat >(∗device , white ) ;52

53 // polygon wi th h o r i z o n t a l bottom54 ScreenPolygon<f loat> polyH1 ( polygon , ∗ zbuf , camera , l i g h t ) ;55 polyH1 . forceXYs (1 , 2 , 7 ,2 , 3 , 1 0 ) ;56 polyH1 . draw ( ’ f ’ ) ;57

58 // polygon wi th h o r i z o n t a l top59 ScreenPolygon<f loat> polyH2 ( polygon , ∗ zbuf , camera , l i g h t ) ;60 polyH2 . forceXYs (9 , 2 , 5 ,10 , 12 , 10 ) ;61 polyH2 . draw ( ’ f ’ ) ;62

APPENDIX B. SOURCE FILES 124

63 // s t r e ched polygon 164 ScreenPolygon<f loat> polyS1 ( polygon , ∗ zbuf , camera , l i g h t ) ;65 polyS1 . forceXYs (11 ,2 , 13 ,7 , 19 , 10 ) ;66 polyS1 . draw ( ’ f ’ ) ;67

68 // s t r e ched polygon 269 ScreenPolygon<f loat> polyS2 ( polygon , ∗ zbuf , camera , l i g h t ) ;70 polyS2 . forceXYs (10 ,12 , 14 ,15 , 15 , 20 ) ;71 polyS2 . draw ( ’ f ’ ) ;72

73 // r e gu l a r po lygon 174 ScreenPolygon<f loat> polyR1 ( polygon , ∗ zbuf , camera , l i g h t ) ;75 polyR1 . forceXYs (14 ,2 , 20 ,2 , 2 0 , 8 ) ;76 polyR1 . draw ( ’ f ’ ) ;77

78 // r e gu l a r po lygon 279 ScreenPolygon<f loat> polyR2 ( polygon , ∗ zbuf , camera , l i g h t ) ;80 polyR2 . forceXYs (5 ,12 , 1 ,15 , 5 , 2 0 ) ;81 polyR2 . draw ( ’ f ’ ) ;82

83 // r e gu l a r po lygon 384 ScreenPolygon<f loat> polyR3 ( polygon , ∗ zbuf , camera , l i g h t ) ;85 polyR3 . forceXYs (6 ,12 , 10 ,15 , 6 ,20 ) ;86 polyR3 . draw ( ’ f ’ ) ;87 }88

89 void DisplayCal lBack ( ){90 cout << ”−−>DisplayCal lBack ” << endl << f l u s h ;91 int un i t l eng th = device−>UnitLength ( 1 ) ; // c l e a r i n g d i s p l a y92 device−>Clear ( ) ;93 device−>Update ( ) ;94 device−>UnitLength ( un i t l eng th ) ; // r e s t o r i n g un i t l e n g h t95

96 //draw z b u f f e r97 zbuf−>drawBuffer ( ) ;98

99 //draw l i n e s o f the t r i a n g l e s100 drawTriangle (1 , 2 , 7 ,2 , 3 , 1 0 ) ; //polyH1101 drawTriangle (9 , 2 , 5 ,10 , 12 , 10 ) ; // po ly2102 drawTriangle (11 ,2 , 13 ,7 , 19 , 10 ) ; // polyS1103 drawTriangle (10 ,12 , 14 ,15 , 15 , 20 ) ; // polyS2104 drawTriangle (14 ,2 , 20 ,2 , 2 0 , 8 ) ; //polyR1105 drawTriangle (5 ,12 , 1 ,15 , 5 , 2 0 ) ; //polyR2106 drawTriangle (6 ,12 , 10 ,15 , 6 ,20 ) ; //polyR3107

108 // adding g r i d s as the very l a s t109 device−>Grid (1 , 1 ) ;110 device−>Update ( ) ;111 }112

113 int main ( int argc , char∗∗ argv )114 {115 using std : : cout ;116 using std : : endl ;117 using std : : f l u s h ;118

119 dev i ce = new DotDevice (600 , 600 , ”DotDevice Example” ) ;

APPENDIX B. SOURCE FILES 125

120 device−>Clear ( ) ;121 device−>Update ( ) ;122 device−>UnitLength ( 2 5 ) ;123

124 // c a l l i n g t e s t f unc t i on125 tes tPo lygon ( ) ;126

127 glutDisplayFunc ( DisplayCal lBack ) ;128

129 cout << ”=================================================” << endl ;130 cout << ”This w i l l show a whole bunch o f polygons ” << endl ;131 cout << ” In the window type : ” << endl ;132 cout << ”===================” << endl ;133 cout << ”g − to t ogg l e the g r id on and o f f . ” << endl ;134 cout << ”d − to r ed i s p l a y the scene . ” << endl ;135 cout << ”q − to qu i t the program . ” << endl ;136 cout << endl ;137

138 // Let GLUT take over and r e l y on the c a l l−back f unc t i on s139 glutMainLoop ( ) ;140

141 return 0 ;142 }

B.12 testMath.cpp

1 //#inc l ude ”DotDevice/DotDevice . h”2 #include <vector>3 #include ” graphic . h”4 #include ” readdata . cpp”5

6 void pause ( std : : s t r i n g s t r ) {7 std : : s t r i n g dummy;8 std : : cout << ”Press ENTER to cont inue . . . ” ;9 std : : g e t l i n e ( std : : c in , dummy) ;

10 }11

12 int t e s tToo l s ( ) {13 /∗∗∗∗∗∗∗ t e s t i n g Point c l a s s ∗∗∗∗∗∗/14 // here f o l l ow a ba s i c t e s t o f the Point c l a s s15 // f i r s t we make a few Points16 Point<2, double> p1 ;17 Point<2, double> p2 ;18 Point<2, double> p3 ;19 p1 [ 0 ] = 1 ;20 p1 [ 1 ] = 2 ;21 a s s e r t ( p1 [ 0 ] == 1 && p1 [ 1 ] == 2 ) ;22 p2 [ 0 ] = 4 ;23 p2 [ 1 ] = 5 ;24 a s s e r t ( p2 [ 0 ] == 4 && p2 [ 1 ] == 5 ) ;25 p2 = p1 ;26 p1 [ 0 ] = 42 ;27 a s s e r t ( p1 [ 0 ] == 42 && p1 [ 1 ] == 2 ) ;28 a s s e r t ( p2 [ 0 ] == 1 && p2 [ 1 ] == 2 ) ;29 double va lues1 [ ] = {3 ,3} ;30 p3 . s e t ( va lues1 ) ;

APPENDIX B. SOURCE FILES 126

31 a s s e r t ( p3 [ 0 ] == 3 && p3 [ 1 ] == 3 ) ;32 std : : cout << ”Point c on s t ru c t o r s and assignment worked as expected ” << std : : endl ;33

34 /∗∗∗∗∗∗∗ t e s t i n g Vector c l a s s ∗∗∗∗∗∗/35 // f i r s t we make a few 3D Vectors36 Vector<3, double> v1 ;37 Vector<3, double> v2 ;38 Vector<3, double> v3 ;39

40 v1 [ 0 ] = 1 ;41 v1 [ 1 ] = 2 ;42 v1 [ 2 ] = 3 ;43 a s s e r t ( v1 [ 0 ] == 1 && v1 [ 1 ] == 2 && v1 [ 2 ] == 3 ) ;44 double va lues2 [ ] = {2 ,5 , 8} ;45 v2 . s e t ( va lues2 ) ;46 a s s e r t ( v2 [ 0 ] == 2 && v2 [ 1 ] == 5 && v2 [ 2 ] == 8 ) ;47 v3 = v2 ;48 a s s e r t ( v3 [ 0 ] == 2 && v3 [ 1 ] == 5 && v3 [ 2 ] == 8 ) ;49

50 // norma l i za t ion51 a s s e r t ( abs ( v3 . l ength ( ) − 9 .64365) < 0 . 0 0 1 ) ;52 v3 . normal ize ( ) ;53 double v3nExpAr [ 3 ] = { 0 .20739 ,0 . 518476 ,0 .829561 } ;54 Vector<3,double> v3nExp(v3nExpAr ) ;55 a s s e r t ( v3 == v3nExp && abs ( v3 . l ength ()−1) < 0 .001 ) ;56

57 // dot product58 double r e s u l t = ( v1 ∗ v2 ) ;59 a s s e r t ( abs ( v1 ∗ v2 − 36) < 0 .001 ) ;60

61 // vec tor−s k a l a r mu l t i p l i c a t on62 double mult i = 3 ;63 v3 = v1 ∗ mult i ;64 a s s e r t ( v3 [ 0 ] == 3 && v3 [ 1 ] == 6 && v3 [ 2 ] == 9 ) ;65 v3 = 2 .0 ∗ v1 ;66 a s s e r t ( v3 [ 0 ] == 2 && v3 [ 1 ] == 4 && v3 [ 2 ] == 6 ) ;67

68 // vec t o r add i t i on69 v3 = v1 + v2 ;70 a s s e r t ( v3 [ 0 ] == 3 && v3 [ 1 ] == 7 && v3 [ 2 ] == 11 ) ;71 v3 = v1 − v2 ;72 a s s e r t ( v3 [ 0 ] == −1 && v3 [ 1 ] == −3 && v3 [ 2 ] == −5 ) ;73

74 // vec t o r c ro s s product75 v3 = c r o s s ( v1 , v2 ) ;76 a s s e r t ( v3 [ 0 ] == 1 && v3 [ 1 ] == −2 && v3 [ 2 ] == 1 ) ;77 v3 = c r o s s ( v1 , v1 ) ;78 a s s e r t ( v3 [ 0 ] == 0 && v3 [ 1 ] == 0 && v3 [ 2 ] == 0 ) ;79

80 // vec t o r from po in t s81 f loat arP1 [ 3 ] = {4 ,4 , 4} ;82 Point<3, f loat> P1( arP1 ) ;83 f loat arP2 [ 3 ] = {4 ,4 , 4} ;84 Point<3, f loat> P2( arP2 ) ;85 Vector<3, f loat> V1 = vectorFromPoints (P1 , P2 ) ;86 a s s e r t ( V1 [ 0 ] == 0 && V1 [ 1 ] == 0 && V1 [ 2 ] == 0 ) ;87 f loat arP12 [ 3 ] = {0 ,0 , 0} ;

APPENDIX B. SOURCE FILES 127

88 P1 . s e t ( arP12 ) ;89 V1 = vectorFromPoints (P1 , P2 ) ;90 a s s e r t ( V1 [ 0 ] == 4 && V1 [ 1 ] == 4 && V1 [ 2 ] == 4 ) ;91 std : : cout << ”Vector ope ra t i on s worked as expected ” << std : : endl ;92

93 /∗∗∗∗∗∗∗ t e s t i n g Matrix c l a s s ∗∗∗∗∗∗/94 f loat mVal [ 2 ] [ 2 ] = {{1 ,2} ,{3 ,4}} ;95 Matrix<2> m1(mVal ) ;96 a s s e r t ( m1 [ 0 ] [ 0 ] == 1 && m1 [ 0 ] [ 1 ] == 2 && m1 [ 1 ] [ 0 ] == 3 && m1 [ 1 ] [ 1 ] == 4 ) ;97

98 // t ranspos ing99 m1. t ranspose ( ) ;

100 a s s e r t ( m1 [ 0 ] [ 0 ] == 1 && m1 [ 0 ] [ 1 ] == 3 && m1 [ 1 ] [ 0 ] == 2 && m1 [ 1 ] [ 1 ] == 4 ) ;101

102 // s e t103 Matrix<2> m2;104 f loat mVal2 [ 2 ] [ 2 ] = {{5 ,6} ,{7 ,8}} ;105 m2. s e t (mVal2 ) ;106 a s s e r t ( m2 [ 0 ] [ 0 ] == 5 && m2 [ 0 ] [ 1 ] == 6 && m2 [ 1 ] [ 0 ] == 7 && m2 [ 1 ] [ 1 ] == 8 ) ;107

108 //matrix mu l t i p l i c a t i o n109 Matrix<2> m3 = m1 ∗ m2;110 a s s e r t ( m3 [ 0 ] [ 0 ] == 26 && m3 [ 0 ] [ 1 ] == 30 && m3 [ 1 ] [ 0 ] == 38 && m3 [ 1 ] [ 1 ] == 44 ) ;111

112 //matrix add i t i on and su b t r a c t i on113 Matrix<2> m4 = m1 + m2;114 Matrix<2> m5 = m1 − m2;115 a s s e r t ( m4 [ 0 ] [ 0 ] == 6 && m4 [ 0 ] [ 1 ] == 9 && m4 [ 1 ] [ 0 ] == 9 && m4 [ 1 ] [ 1 ] == 12 ) ;116 a s s e r t ( m5 [ 0 ] [ 0 ] == −4 && m5 [ 0 ] [ 1 ] == −3 && m5 [ 1 ] [ 0 ] == −5 && m5 [ 1 ] [ 1 ] == −4 ) ;117

118 // cons t ruc t o r i n i t i a l i z a t i o n119 double mVal3 [ 3 ] [ 3 ] = {{1 ,2 , 3} ,{4 ,5 , 6} ,{7 ,8 , 9}} ;120 Matrix<3,double> m6(mVal3 ) ;121 a s s e r t ( m6 [ 0 ] [ 0 ] == 1 && m6 [ 0 ] [ 1 ] == 2 && m6 [ 0 ] [ 2 ] == 3122 && m6 [ 1 ] [ 0 ] == 4 && m6 [ 1 ] [ 1 ] == 5 && m6 [ 1 ] [ 2 ] == 6123 && m6 [ 2 ] [ 0 ] == 7 && m6 [ 2 ] [ 1 ] == 8 && m6 [ 2 ] [ 2 ] == 9 ) ;124

125 //matrix v e c t o r mu l t i p l i c a t i o n126 Vector<3, double> v4 = m6 ∗ v2 ;127 a s s e r t ( v4 [ 0 ] == 36 && v4 [ 1 ] == 81 && v4 [ 2 ] == 126 ) ;128

129 //row and co l130 a s s e r t ( m6. c o l ( 0 ) [ 0 ] == 1 && m6. c o l ( 0 ) [ 1 ] == 4 && m6. c o l ( 0 ) [ 2 ] == 7 ) ;131 a s s e r t ( m6. row ( 1 ) [ 0 ] == 4 && m6. row ( 1 ) [ 1 ] == 5 && m6. row ( 1 ) [ 2 ] == 6 ) ;132 std : : cout << ”Bas ic matrix ope ra t i on s worked as expected ” << std : : endl ;133

134 /∗∗∗∗∗∗∗ t e s t i n g r o t a t i on ∗∗∗∗∗∗/135 f loat matVal1 [ 4 ] [ 4 ] = {{1 ,2 ,3 ,4} , {5 ,6 ,7 ,8} , {9 ,1 ,2 ,3} , {4 ,5 , 6 , 7}} ;136 f loat matVal2 [ 4 ] [ 4 ] = {{1 ,0 ,0 ,0} , {0 ,1 ,0 ,0} , {0 ,0 ,1 ,0} , {0 ,0 , 0 , 1}} ; // i d e n t i t y137 Matrix<4> mat1 (matVal1 ) ;138 Matrix<4> mat2 ;139

140 //RotateX141 f loat expectedX1 [ 4 ] [ 4 ] = {{1 ,2 ,3 ,4} , { −2 .82843 ,3 .53553 ,3 .53553 ,3 .53553} , {9 .89949 ,4 . 94975 ,6 . 36396 ,7 . 77817} , {4 ,5 , 6 , 7}} ;142 f loat expectedX2 [ 4 ] [ 4 ] = {{1 ,0 ,0 ,0} , {0 ,0 ,−1 ,0} , {0 ,1 ,0 ,0} , {0 ,0 , 0 , 1}} ;143 Matrix<4> matExp1( expectedX1 ) ;144 Matrix<4> matExp2( expectedX2 ) ;

APPENDIX B. SOURCE FILES 128

145 mat1 . rotateX ( 4 5 ) ;146 a s s e r t ( mat1 == matExp1 ) ;147 mat2 . rotateX ( 9 0 ) ;148 a s s e r t ( mat2 == matExp2 ) ;149 // s t d : : cout << ”RotateX worked as expec ted ” << s t d : : end l ;150

151 //RotateY152 mat1 . s e t (matVal1 ) ;153 mat2 . s e t (matVal2 ) ;154 f loat expectedY1 [ 4 ] [ 4 ] = { {7 .07107 ,2 . 12132 ,3 . 53553 ,4 . 94975} , {5 ,6 ,7 ,8} , {5.65685 ,−0.707107 ,−0.707107 ,−0.707107} , {4 ,5 ,6 ,7} } ;155 f loat expectedY2 [ 4 ] [ 4 ] = { {0 ,0 ,1 ,0} , {0 ,1 ,0 ,0} , {−1 ,0 ,0 ,0} , {0 ,0 ,0 ,1} } ;156 matExp1 . s e t ( expectedY1 ) ;157 matExp2 . s e t ( expectedY2 ) ;158 mat1 . rotateY ( 4 5 ) ;159 mat2 . rotateY ( 9 0 ) ;160 a s s e r t ( mat1 == matExp1 ) ;161 a s s e r t ( mat2 == matExp2 ) ;162 // s t d : : cout << ”RotateY worked as expec ted ” << s t d : : end l ;163

164 //RotateZ165 mat1 . s e t (matVal1 ) ;166 mat2 . s e t (matVal2 ) ;167 f loat expectedZ1 [ 4 ] [ 4 ] = { {−2.82843 ,−2.82843 ,−2.82843 ,−2.82843} , {4 .24264 ,5 . 65685 ,7 . 07107 ,8 . 48528} , {9 ,1 ,2 ,3} , {4 ,5 ,6 ,7} } ;168 f loat expectedZ2 [ 4 ] [ 4 ] = { {0 ,−1 ,0 ,0} , {1 ,0 ,0 ,0} , {0 ,0 ,1 ,0} , {0 ,0 ,0 ,1} } ;169 matExp1 . s e t ( expectedZ1 ) ;170 matExp2 . s e t ( expectedZ2 ) ;171 mat1 . rotateZ ( 4 5 ) ;172 mat2 . rotateZ ( 9 0 ) ;173 a s s e r t ( mat1 == matExp1 ) ;174 a s s e r t ( mat2 == matExp2 ) ;175 // s t d : : cout << ”RotateZ worked as expec ted ” << s t d : : end l ;176

177 // t r a n s l a t i n g178 mat1 . s e t (matVal1 ) ;179 mat2 . s e t (matVal2 ) ;180 f loat vecVal1 [ 4 ] = {1 , 2 , 3 , 1} ;181 f loat vecVal2 [ 4 ] = { 0 . 5 , 0 . 5 , 0 . 5 , 1 } ;182 Vector<4, f loat> vec1 ( vecVal1 ) ;183 Vector<4, f loat> vec2 ( vecVal2 ) ;184 f loat expectedT1 [ 4 ] [ 4 ] = { {5 ,7 ,9 ,11} , {13 ,16 ,19 ,22} , {21 ,16 ,20 ,24} , {4 ,5 ,6 ,7} } ;185 f loat expectedT2 [ 4 ] [ 4 ] = { {1 ,0 , 0 , 0 . 5} , {0 ,1 , 0 , 0 . 5} , {0 ,0 , 1 , 0 . 5} , {0 ,0 ,0 ,1} } ;186 matExp1 . s e t ( expectedT1 ) ;187 matExp2 . s e t ( expectedT2 ) ;188 mat1 . t r a n s l a t e ( vec1 ) ;189 mat2 . t r a n s l a t e ( vec2 ) ;190 a s s e r t ( mat1 == matExp1 ) ;191 a s s e r t ( mat2 == matExp2 ) ;192 // s t d : : cout << ” t r a n s l a t i o n worked as expec ted ” << s t d : : end l ;193

194 // t r a n s l a t i n g − the v e c t o r s used are de f ined under t r a n s l a t i o n above , but shown below195 mat1 . s e t (matVal1 ) ;196 mat2 . s e t (matVal2 ) ;197 /∗ f l o a t vecVal1 [ 4 ] = {1 ,2 ,3 ,1} ;198 f l o a t vecVal2 [ 4 ] = {0 . 5 , 0 . 5 , 0 . 5 , 1} ;199 Vector<4, f l o a t> vec1 ( vecVal1 ) ;200 Vector<4, f l o a t> vec2 ( vecVal2 ) ; ∗/201 f loat expectedSc1 [ 4 ] [ 4 ] = { {1 ,2 ,3 ,4} , {10 ,12 ,14 ,16} , {27 ,3 ,6 ,9} , {4 ,5 ,6 ,7} } ;

APPENDIX B. SOURCE FILES 129

202 f loat expectedSc2 [ 4 ] [ 4 ] = { {0 .5 , 0 , 0 , 0} , {0 ,0 . 5 , 0 , 0} , {0 ,0 , 0 . 5 , 0} , {0 ,0 ,0 ,1} } ;203 matExp1 . s e t ( expectedSc1 ) ;204 matExp2 . s e t ( expectedSc2 ) ;205 mat1 . s c a l e ( vec1 ) ;206 mat2 . s c a l e ( vec2 ) ;207 a s s e r t ( mat1 == matExp1 ) ;208 a s s e r t ( mat2 == matExp2 ) ;209 // s t d : : cout << ” s c a l i n g worked as expec ted ” << s t d : : end l ;210

211 //xy shear ing212 mat1 . s e t (matVal1 ) ;213 mat2 . s e t (matVal2 ) ;214 f loat expectedShXY1 [ 4 ] [ 4 ] = { {46 ,7 ,13 ,19} , {23 ,8 ,11 ,14} , {9 ,1 ,2 ,3} , {4 ,5 ,6 ,7} } ;215 f loat expectedShXY2 [ 4 ] [ 4 ] = { {1 ,0 ,5 ,0} , {0 ,1 ,2 ,0} , {0 ,0 ,1 ,0} , {0 ,0 ,0 ,1} } ;216 matExp1 . s e t ( expectedShXY1 ) ;217 matExp2 . s e t ( expectedShXY2 ) ;218 mat1 . shearXY ( 5 , 2 ) ;219 mat2 . shearXY ( 5 , 2 ) ;220 a s s e r t ( mat1 == matExp1 ) ;221 a s s e r t ( mat2 == matExp2 ) ;222 // s t d : : cout << ”xy shear ing worked as expec ted ” << s t d : : end l ;223

224 // xz shear ing225 mat1 . s e t (matVal1 ) ;226 mat2 . s e t (matVal2 ) ;227 f loat expectedShXZ1 [ 4 ] [ 4 ] = { {26 ,32 ,38 ,44} , {5 ,6 ,7 ,8} , {19 ,13 ,16 ,19} , {4 ,5 ,6 ,7} } ;228 f loat expectedShXZ2 [ 4 ] [ 4 ] = { {1 ,5 ,0 ,0} , {0 ,1 ,0 ,0} , {0 ,2 ,1 ,0} , {0 ,0 ,0 ,1} } ;229 matExp1 . s e t ( expectedShXZ1 ) ;230 matExp2 . s e t ( expectedShXZ2 ) ;231 mat1 . shearXZ ( 5 , 2 ) ;232 mat2 . shearXZ ( 5 , 2 ) ;233 a s s e r t ( mat1 == matExp1 ) ;234 a s s e r t ( mat2 == matExp2 ) ;235 // s t d : : cout << ” xz shear ing worked as expec ted ” << s t d : : end l ;236

237 // yz shear ing238 mat1 . s e t (matVal1 ) ;239 mat2 . s e t (matVal2 ) ;240 f loat expectedShYZ1 [ 4 ] [ 4 ] = { {1 ,2 ,3 ,4} , {10 ,16 ,22 ,28} , {11 ,5 ,8 ,11} , {4 ,5 ,6 ,7} } ;241 f loat expectedShYZ2 [ 4 ] [ 4 ] = { {1 ,0 ,0 ,0} , {5 ,1 ,0 ,0} , {2 ,0 ,1 ,0} , {0 ,0 ,0 ,1} } ;242 matExp1 . s e t ( expectedShYZ1 ) ;243 matExp2 . s e t ( expectedShYZ2 ) ;244 mat1 . shearYZ ( 5 , 2 ) ;245 mat2 . shearYZ ( 5 , 2 ) ;246 a s s e r t ( mat1 == matExp1 ) ;247 a s s e r t ( mat2 == matExp2 ) ;248 // s t d : : cout << ”yz shear ing worked as expec ted ” << s t d : : end l ;249

250 std : : cout << ”Rotation , Sca l ing , Shear ing and Trans la t i on works as expected ” << std : : endl ;251 return 0 ;252 }253

254 //Test ing some co l o r f u n c t i o n a l i t y255 int t e s tCo l o r ( ){256 // t e s t i n g cons t ruc t o r co r r e c tn e s s257 Color c1 ( 2 . 5 , 0 . 2 , 0 . 5 ) ;258 Color c1s ( 1 . 0 , 0 . 2 , 0 . 5 ) ;

APPENDIX B. SOURCE FILES 130

259 Color c2 ( 0 . 2 , 2 . 6 , 0 . 3 ) ;260 Color c2s ( 0 . 2 , 1 . 0 , 0 . 3 ) ;261 Color c3 ( 0 . 3 , 0 . 5 , 5 0 0 ) ;262 Color c3s ( 0 . 3 , 0 . 5 , 1 . 0 ) ;263 Color c4 ( −1 , 0 . 4 , 0 . 6 ) ;264 Color c4s ( 0 , 0 . 4 , 0 . 6 ) ;265 Color c5 ( 0 . 5 , −0 . 1 , 0 . 6 ) ;266 Color c5s ( 0 . 5 , 0 , 0 . 6 ) ;267 Color c6 (0 . 3 , 0 . 6 , −700 ) ;268 Color c6s ( 0 . 3 , 0 . 6 , 0 ) ;269 a s s e r t ( c1 == c1s && c2 == c2s && c3 == c3s && c4 == c4s && c5 == c5s && c6 == c6s ) ;270 std : : cout << ”Color con s t ruc to r ran as expected ” << std : : endl ;271

272 // setRed273 c1 . setRed ( −0 .1) ;274 Color c11 ( 0 . 0 , 0 . 2 , 0 . 5 ) ;275 a s s e r t ( c1 == c11 ) ;276 c1 . setRed ( 1 0 . 0 ) ;277 Color c12 ( 1 . 0 , 0 . 2 , 0 . 5 ) ;278 a s s e r t ( c1 == c12 ) ;279 c1 . setRed ( 0 . 3 ) ;280 Color c13 ( 0 . 3 , 0 . 2 , 0 . 5 ) ;281 a s s e r t ( c1 == c13 ) ;282 std : : cout << ”Methods setRed , ” ;283

284 // setGreen285 c2 . setGreen ( −0 .1) ;286 Color c21 ( 0 . 2 , 0 . 0 , 0 . 3 ) ;287 a s s e r t ( c2 == c21 ) ;288 c2 . setGreen ( 1 0 . 0 ) ;289 Color c22 ( 0 . 2 , 1 . 0 , 0 . 3 ) ;290 a s s e r t ( c2 == c22 ) ;291 c2 . setGreen ( 0 . 3 ) ;292 Color c23 ( 0 . 2 , 0 . 3 , 0 . 3 ) ;293 a s s e r t ( c2 == c23 ) ;294 std : : cout << ” setGreen , ” ;295

296 // se tB lue297 c3 . se tBlue (−1);298 Color c31 ( 0 . 3 , 0 . 5 , 0 ) ;299 a s s e r t ( c3 == c31 ) ;300 c3 . se tBlue ( 1 . 1 ) ;301 Color c32 ( 0 . 3 , 0 . 5 , 1 . 0 ) ;302 a s s e r t ( c3 == c32 ) ;303 c3 . se tBlue ( 0 . 4 ) ;304 Color c33 ( 0 . 3 , 0 . 5 , 0 . 4 ) ;305 a s s e r t ( c3 == c33 ) ;306 std : : cout << ”and setBlue worked as expected ! ” << std : : endl ;307

308 return 0 ;309 }310

311 // Testprogram fo r Camera − j u s t the math312 int testCameraMath ( ){313 // f i r s t we t e s t the cons t ruc t o r314 // us ing nice coord ina t e s315 f loat arVRP1 [ 3 ] = {0 ,0 , 2} ;

APPENDIX B. SOURCE FILES 131

316 Point<3, f loat> VRP1(arVRP1 ) ;317 f loat arPRP1 [ 3 ] = {0 ,0 , 4} ;318 Point<3, f loat> PRP1(arPRP1 ) ;319 f loat arVPN1 [ 3 ] = {0 ,0 , 1} ;320 Vector<3, f loat> VPN1(arVPN1 ) ;321 f loat arVUP1 [ 3 ] = {0 ,1 , 0} ;322 Vector<3, f loat> VUP1(arVUP1 ) ;323 f loat arW11 [ 3 ] = {−2 ,−2 ,0};324 Point<3, f loat> w11(arW11 ) ;325 f loat arW21 [ 3 ] = {2 ,2 , 0} ;326 Point<3, f loat> w21(arW21 ) ;327 f loat B1 = −10;328 f loat F1 = −1;329

330 Camera<f loat> C1(VRP1, PRP1, VPN1, VUP1, w11 , w21 , B1 , F1 ) ;331 //C1 . p r i n t (”C1 i s : ” ) ;332

333 Matrix<4, f loat> P1 = C1 . ge tPro j ec t i onMatr ix ( 300 , 300 ) ;334

335 f loat expProj1 [ 4 ] [ 4 ] = { {21 .4286 , 0 , −10.7143 , 64 .2857} ,336 {0 , 21 .4286 , −10.7143 , 64 .2857} ,337 {0 , 0 , 0 .039683 , 0 .317459} ,338 {0 , 0 , −0.071429 , 0 .428571} } ;339 Matrix<4, f loat> expMat1 ( expProj1 ) ;340 f loat expWPRPAr1 [ 3 ] = {0 ,0 , 6} ;341 Point<3, f loat> expWPRP1(expWPRPAr1 ) ;342 a s s e r t ( P1 == expMat1 && expWPRP1 == C1 . getWorldPRP ( ) ) ;343

344 std : : cout << ” Pro j e c t i on matrix o f C1 and worldPRP as expected ” << std : : endl ;345

346 // second t e s t , no l onger ” nice ” coord ina t e s347 f loat arVRP2 [ 3 ] = {7 ,3 , 4} ;348 Point<3, f loat> VRP2(arVRP2 ) ;349 f loat arPRP2 [ 3 ] = {6 , 3 . 5 , 7} ;350 Point<3, f loat> PRP2(arPRP2 ) ;351 f loat arVPN2 [ 3 ] = { −0.5 ,−0.5 ,1} ;352 Vector<3, f loat> VPN2(arVPN2 ) ;353 f loat arVUP2 [ 3 ] = {1 , 4 , 0 . 5} ;354 Vector<3, f loat> VUP2(arVUP2 ) ;355 f loat arW12 [ 3 ] = {−1 ,−1 ,0};356 Point<3, f loat> w12(arW12 ) ;357 f loat arW22 [ 3 ] = {3 ,4 , 0} ;358 Point<3, f loat> w22(arW22 ) ;359 f loat B2 = −10;360 f loat F2 = −1;361

362 Camera<f loat> C2(VRP2, PRP2, VPN2, VUP2, w12 , w22 , B2 , F2 ) ;363 //C2 . p r i n t (”C2 i s : ” ) ;364

365 Matrix<4, f loat> P2 = C2 . ge tPro j ec t i onMatr ix ( 300 , 300 ) ;366 f loat expProj2 [ 4 ] [ 4 ] =367 { {40 .6701 , 4 .35405 , −15.3111 , −205.625} ,368 {8 .64045 , 28 .0491 , −1.10715 , −115.495} ,369 {−0.021347 , −0.021347 , 0 .042694 , 0 .565562} ,370 {0 .024015 , 0 .024015 , −0.04803 , 0 .363739} } ;371 Matrix<4, f loat> expMat2 ( expProj2 ) ;372 f loat expWPRPAr2 [ 3 ] = {13 . 7617 , 9 . 93933 , 5 . 83712} ;

APPENDIX B. SOURCE FILES 132

373 Point<3, f loat> expWPRP2(expWPRPAr2 ) ;374 a s s e r t ( P2 == expMat2 && expWPRP2 == C2 . getWorldPRP ( ) ) ;375

376 a s s e r t ( expMat2 == C2 . ge tPro j ec t i onMatr ix ( 3 00 , 3 00 ) ) ;377

378 std : : cout << ” Pro j e c t i on matrix and worldPRP of C2 as expected ” << std : : endl ;379

380 return 0 ;381 }382

383 int testMater ia lAndLight ( ){384 Color d i fCo l1 ( 0 . 1 , 0 . 2 , 0 . 3 ) ;385 Color specCol1 ( 0 . 4 , 0 . 5 , 0 . 6 ) ;386 f loat ka1 = 0 . 7 ;387 f loat kd1 = 0 . 8 ;388 f loat ks1 = 0 . 9 ;389 int n1 = 4 ;390

391 Mater ia l<f loat> mater ia l 1 ( d i fCol1 , specCol1 , ka1 , kd1 , ks1 , n1 ) ;392 //mater ia l1 . p r i n t (” Mater ia l1 i s : ” ) ;393

394 a s s e r t ( d i fCo l1 == mater i a l 1 . g e tD i f f u s eCo l o r ( ) && specCol1 == mater i a l 1 . ge tSpecu la rCo lor ( )395 && abs ( ka1 − mater ia l 1 . getKa ( ) ) < 0 .001 && abs ( kd1 − mater ia l 1 . getKd ( ) ) < 0 .001396 && abs ( ks1 − mater ia l 1 . getKs ( ) ) < 0 .001 && n1 == mater ia l 1 . getN ( ) ) ;397 std : : cout << ”Mater ia l c on s t ruc to r and get f u n c i t o n a l i t y works as expected ” << std : : endl ;398

399 f loat l ightCoordsAr1 [ 3 ] = {5 ,5 , 5} ;400 f loat attenAr1 [ 3 ] = {1 ,2 , 3} ;401 Point<3, f loat> l i ghtCoords1 ( l ightCoordsAr1 ) ;402 Point<3, f loat> atten1 ( attenAr1 ) ;403 Color ambia1 ( 0 . 3 , 0 . 4 , 0 . 5 ) ;404 Color in t en s1 ( 0 . 1 , 0 . 5 , 0 . 9 ) ;405 LightSource<f loat> l i gh tSou r c e1 ( l ightCoords1 , atten1 , ambia1 , i n t en s1 ) ;406

407 // l i g h t Sou r c e1 . p r i n t (” LightSource1 i s : ” ) ;408

409 // t e s t i n g i l l um ina t i on f u n c t i o n a l i t y410 // f i r s t we make a camera411 f loat arVRP1 [ 3 ] = {0 ,0 , 2} ;412 Point<3, f loat> VRP1(arVRP1 ) ;413 f loat arPRP1 [ 3 ] = {0 ,0 , 4} ;414 Point<3, f loat> PRP1(arPRP1 ) ;415 f loat arVPN1 [ 3 ] = {0 ,0 , 1} ;416 Vector<3, f loat> VPN1(arVPN1 ) ;417 f loat arVUP1 [ 3 ] = {0 ,1 , 0} ;418 Vector<3, f loat> VUP1(arVUP1 ) ;419 f loat arW11 [ 3 ] = {−2 ,−2 ,0};420 Point<3, f loat> w11(arW11 ) ;421 f loat arW21 [ 3 ] = {2 ,2 , 0} ;422 Point<3, f loat> w21(arW21 ) ;423 f loat B1 = −10;424 f loat F1 = −1;425 Camera<f loat> C1(VRP1, PRP1, VPN1, VUP1, w11 , w21 , B1 , F1 ) ;426

427 // then we make the o ther v a r i a b l e s428 f loat pointAr1 [ 3 ] = { 4 . 0 , 3 . 0 , 2 . 0 } ;429 f loat normalAr1 [ 3 ] = { 0 . 1 , 0 . 3 , 0 . 2 } ;

APPENDIX B. SOURCE FILES 133

430 Point<3, f loat> p1 ( pointAr1 ) ;431 Vector<3, f loat> normal1 ( normalAr1 ) ;432 normal1 . normal ize ( ) ;433 // c a l l i n g the i l l um ina t i on func t i on434 Color i l lum1 = l i gh tSou r c e1 . PhongI l luminat ion ( mater ia l1 , p1 , normal1 ,C1 ) ;435 // i l l um1 . p r i n t ( ) ;436 Color il lumExp1 (0 .021147 , 0 .057471 , 0 . 1 08973 ) ;437 a s s e r t ( i l lum1 == illumExp1 ) ;438 // a new t e s t to make sure R∗V i s p o s i t i v e439 f loat normalAr2 [ 3 ] = { −7 ,8 ,5} ;440 Vector<3, f loat> normal2 ( normalAr2 ) ;441 normal2 . normal ize ( ) ;442 Color i l lum2 = l i gh tSou r c e1 . PhongI l luminat ion ( mater ia l1 , p1 , normal2 ,C1 ) ;443 // i l l um2 . p r i n t ( ) ;444 Color il lumExp2 (0 . 02109 , 0 .056887 , 0 . 1 07384 ) ;445 a s s e r t ( i l lum2 == illumExp2 ) ;446

447 std : : cout << ” I l l um ina t i on c a l c u l a t ed as expeced” << std : : endl ;448

449 return 0 ;450 }451

452 int main ( int argc , char∗ argv [ ] ) {453 t e s tToo l s ( ) ;454 t e s tCo l o r ( ) ;455 testCameraMath ( ) ;456 testMater ia lAndLight ( ) ;457

458 pause ( ”” ) ;459 return 0 ;460 }

Bibliography

[FvDFH97] James D. Foley, Andries van Dam, Steven K. Feiner, and John F. Hughes. Com-puter Graphics, Principles and Practice. Addison-Wesley, Boston, 2nd edition,1997.

[Hen06] Knud Henriksen. Visualisering af parametriske flader, 2006.

[VJ03] David Vandevoorde and Nicolai M. Josuttis. C++ Templates, The CompleteGuide. Addison-Wesley, Boston, 2003.

134