zumbs.files. · pdf fileintroduction to computer graphics: visualization of parametric...
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