Chapter 17

Curves and Curved Surfaces

“Where there is matter, there is geometry.”

—Johannes Kepler

The triangle is a basic atomic rendering primitive. It is what graphics hardware is tuned to rapidly turn into shaded fragments and put into the framebuffer. However, objects and animation paths that are created in modeling systems can have many different underlying geometric descriptions. Curves and curved surfaces can be described precisely by equations. These equations are evaluated and sets of triangles are then created and sent down the pipeline to be rendered.

The beauty of using curves and curved surfaces is at least fourfold: (1) They have a more compact representation than a set of triangles, (2) they provide scalable geometric primitives, (3) they provide smoother and more continuous primitives than straight lines and planar triangles, and (4) animation and collision detection may become simpler and faster.

Compact curve representation offers several advantages for real-time rendering. First, there is savings in memory for model storage (and so some gain in memory cache efficiency). This is especially useful for game consoles, which typically do not have as much memory as a PC. Transforming curved surfaces generally involves fewer matrix multiplications than transforming a mesh representing the surface. If the graphics hardware can accept such curved surface descriptions directly, the amount of data the host CPU has to send to the graphics hardware is usually much less than sending a triangle mesh.

Curved model descriptions such as PN triangles and subdivision surfaces have the worthwhile property that a model with few polygons can be made more convincing and realistic. The individual polygons are treated as curved surfaces, so creating more vertices on the surface. The result of a higher vertex density is better lighting of the surface and silhouette edges with higher quality. See Figure 17.1 for an example.

image

Figure 17.1. A scene from Call of Duty: Advanced Warfare, where the character Ilona’s face was rendered using Catmull-Clark subdivision surfaces with the adaptive quadtree algorithm from Section 17.6.3. (Image from “Call of Duty,” courtesy of Activision Publishing, Inc. 2018.)

Another major advantage of curved surfaces is that they are scalable. A curved surface description could be turned into 2 triangles or 2000. Curved surfaces are a natural form of on the fly level of detail modeling: When the curved object is close, sample the analytical representation more densely and generate more triangles.

For animation, curved surfaces have the advantage that a much smaller number of points needs to be animated. These points can be used to form a curved surface, and a smooth tessellation can then be generated. Also, collision detection can potentially be more efficient and accurate [939,940].

The topic of curves and curved surfaces has been the subject of entire books [458,777,1242,1504,1847]. Our goal here is to cover curves and surfaces that find common use in real-time rendering.

17.1 Parametric Curves

In this section we will introduce parametric curves. These are used in many different contexts and are implemented using a great many different methods. For real-time graphics, parametric curves are often used to move the viewer or some object along a predefined path. This may involve changing both the position and the orientation. However, in this chapter, we consider only positional paths. See Section for information on orientation interpolation. Another use is to render hair, as seen in Figure 17.2.

image

Figure 17.2. Hair rendering using tessellated cubic curves [1274]. (Image from “Nalu” demo, courtesy of NVIDIA Corporation.)

Say you want to move the camera from one point to another in a certain amount of time, independent of the performance of the underlying hardware. As an example, assume that the camera should move between these points in one second, and that the rendering of one frame takes 50 ms. This means that we will be able to render 20 frames along the way during that second. On a faster computer, one frame might take only 25 ms, which would be equal to 40 frames per second, and so we would want to move the camera to 40 different locations. Finding either set of points is possible to do with parametric curves.

A parametric curve describes points using some formula as a function of a parameter t. Mathematically, we write this as p(t)p(t) , which means that this function delivers a point for each value of t. The parameter t may belong to some interval, called the domain, e.g., t[a,b]t[a,b] . The generated points are continuous, that is, as ϵ0ϵ0 then p(t+ϵ)p(t)p(t+ϵ)p(t) . Loosely speaking, this means that if ϵϵ is a minuscule number, then p(t)p(t) and p(t+ϵ)p(t+ϵ) are two points that are extremely close to each other.

In the next section, we will start with an intuitive and geometrical description of Bézier curves, a common form of parametric curves, and then put this into a mathematical setting. Then we discuss how to use piecewise Bézier curves and explain the concept of continuity for curves. In Section 17.1.4 and 17.1.5, we will present two other useful curves, namely cubic Hermites and Kochanek-Bartels splines. Finally, we cover rendering of Bézier curves using the GPU in Section 17.1.2.

17.1.1. Béezier Curves

Linear interpolation traces out a path, which is a straight line, between two points, p0p0 and p1p1 . This is as simple as it gets. See the left illustration in Figure 17.3. Given these points, the following function describes a linearly interpolated point p(t)p(t) , where t is the curve parameter, and t[0,1]t[0,1] :

(17.1)

p(t)=p0+t(p1-p0)=(1-t)p0+tp1.
p(t)=p0+t(p1p0)=(1t)p0+tp1.

The parameter t controls where on the line the point p(t)p(t) will land; p(0)=p0p(0)=p0 , p(1)=p1p(1)=p1 , and 0<t<10<t<1 gives us a point on the straight line between p0p0 and p1p1 . So, if we would like to move the camera from p0p0 to p1p1 linearly in 20 steps during one second, then we would use ti=i/(20-1)ti=i/(201) , where i is the frame number (starting from 0 and ending at 19).

When you are interpolating between only two points, linear interpolation may suffice, but for more points on a path, it often does not. For example, when several points are interpolated, the sudden changes at the points (also called joints) that connect two segments become unacceptable. This is shown at the right of Figure 17.3.

image

Figure 17.3. Linear interpolation between two points is the path on a straight line (left). For seven points, linear interpolation is shown at the upper right, and some sort of smoother interpolation is shown at the lower right. What is most objectionable about using linear interpolation are the discontinuous changes (sudden jerks) at the joints between the linear segments.

To solve this, we take the approach of linear interpolation one step further, and linearly interpolate repeatedly. By doing this, we arrive at the geometrical construction of the Bézier (pronounced beh-zee-eh) curve. As a historical note, the Bézier curves were developed independently by Paul de Casteljau and Pierre Bézier for use in the French car industry. They are called Bézier curves because Bézier was able to make his research publicly available before de Casteljau, even though de Casteljau wrote his technical report before Bézier [458].

image

Figure 17.4. Repeated linear interpolation gives a Bézier curve. This curve is defined by three control points, aa , bb , and cc . Assuming we want to find the point on the curve for the parameter t=1/3t=1/3 , we first linearly interpolate between aa and bb to get dd . Next, ee is interpolated from bb and cc . The final point, p(1/3)=fp(1/3)=f is found by interpolating between dd and ee .

First, to be able to repeat the interpolation, we have to add more points. For example, three points, aa , bb , and cc , called the control points, could be used. Say we want to find p(1/3)p(1/3) , that is, the point on the curve for t=1/3t=1/3 . We compute two new points dd and ee by linear interpolation from aa & bb and bb & cc using t=1/3t=1/3 . See Figure 17.4. Finally, we compute ff by linear interpolation from dd and ee again using t=1/3t=1/3 . We define p(t)=fp(t)=f . Using this technique, we get the following relationship:

(17.2)

p(t)=(1-t)d+te=(1-t)[(1-t)a+tb]+t[(1-t)b+tc]=(1-t)2a+2(1-t)tb+t2c,
p(t)=(1t)d+te=(1t)[(1t)a+tb]+t[(1t)b+tc]=(1t)2a+2(1t)tb+t2c,

which is a parabola since the maximum degree of t is two. In fact, given n+1n+1 control points, it turns out that the degree of the curve is n. This means that more control points gives more degrees of freedom for the curve. A first degree curve is a straight line (called linear), a second degree curve is called a quadratic, a third degree curve is called a cubic, a fourth degree curve is called a quartic, and so on.

image

Figure 17.5. Repeated linear interpolation from five points gives a fourth degree (quartic) Bézier curve. The curve is inside the convex hull (green region) of the control points, marked by black dots. Also, at the first point, the curve is tangent to the line between the first and second point. The same also holds for the other end of the curve.

This kind of repeated or recursive linear interpolation is often referred to as the de Casteljau algorithm [458,777]. An example of what this looks like when using five control points is shown in Figure 17.5. To generalize, instead of using points aa ff , as in this example, the following notation is used. The control points are denoted pipi , so in the example, p0=ap0=a , p1=bp1=b , and p2=cp2=c . Then, after linear interpolation has been applied k times, intermediate control points pkipki are obtained. In our example, we have p10=dp10=d , p11=ep11=e , and p20=fp20=f . The Bézier curve for n+1n+1 control points can be described with the recursion formula shown below, where p0i=pip0i=pi are the initial control points:

(17.3)

pki(t)=(1-t)pk-1i(t)+tpk-1i+1(t),{k=1n,i=0n-k.
pki(t)=(1t)pk1i(t)+tpk1i+1(t),{ki=1n,=0nk.

image

Figure 17.6. An illustration of how repeated linear interpolation works for Bézier curves. In this example, the interpolation of a quartic curve is shown. This means there are five control points, p0ip0i , i=0,1,2,3,4i=0,1,2,3,4 , shown at the bottom. The diagram should be read from the bottom up, that is, p10p10 is formed from weighting p00p00 with weight 1-t1t and adding that with p01p01 weighted by t. This goes on until the point of the curve p(t)p(t) is obtained at the top. (Illustration after Goldman [551].)

Note that a point on the curve is described by p(t)=pn0(t)p(t)=pn0(t) . This is not as complicated as it looks. Consider again what happens when we construct a Bézier curve from three points, p0p0 , p1p1 , and p2p2 , which are equivalent to p00p00 , p01p01 , and p02p02 . Three controls points means that n=2n=2 . To shorten the formulae, sometimes “(t)” is dropped from the pp ’s. In the first step k=1k=1 , which gives p10=(1-t)p0+tp1p10=(1t)p0+tp1 , and p11=(1-t)p1+tp2p11=(1t)p1+tp2 . Finally, for k=2k=2 , we get p20=(1-t)p10+tp11p20=(1t)p10+tp11 , which is the same as sought for p(t)p(t) . An illustration of how this works in general is shown in Figure 17.6.

Now that we have the basics in place on how Bézier curves work, we can take a look at a more mathematical description of the same curves.

Béezier Curves Using Bernstein Polynomials

As seen in Equation 17.2, the quadratic Bézier curve could be described using an algebraic formula. It turns out that every Bézier curve can be described with such an algebraic formula, which means that you do not need to do the repeated interpolation. This is shown below in Equation 17.4, which yields the same curve as described by Equation 17.3. This description of the Bézier curve is called the Bernstein form:

(17.4)

p(t)=ni=0Bni(t)pi.
p(t)=ni=0Bni(t)pi.

This function contains the Bernstein polynomials, also sometimes called Bézier basis functions,

(17.5)

Bni(t)=(ni)ti(1-t)n-i=n!i!(n-i)!ti(1-t)n-i.
Bni(t)=(ni)ti(1t)ni=n!i!(ni)!ti(1t)ni.

The first term, the binomial coefficient, in this equation is defined in Equation in Chapter 1. Two basic properties of the Bernstein polynomial are the following:

(17.6)

Bni(t)[0,1],whent[0,1],andni=0Bni(t)=1.
Bni(t)[0,1],whent[0,1],andni=0Bni(t)=1.

The first formula means that the Bernstein polynomials are in the interval between 0 to 1 when t also is from 0 to 1. The second formula means that all the Bernstein polynomial terms in Equation 17.4 sum to one for all different degrees of the curve (this can be seen in Figure 17.7). Loosely speaking, this means that the curve will stay “close” to the control points, pipi . In fact, the entire Bézier curve will be located in the convex hull (see our online linear algebra appendix) of the control points, which follows from Equations 17.4 and 17.6. This is a useful property when computing a bounding area or volume for the curve. See Figure 17.5 for an example.

image

Figure 17.7. Bernstein polynomials for n=1n=1 , n=2n=2 , and n=3n=3 (left to right). The left figure shows linear interpolation, the middle quadratic interpolation, and the right cubic interpolation. These are the blending functions used in the Bernstein form of Bézier curves. So, to evaluate a quadratic curve (middle diagram) at a certain t-value, just find the t-value on the x-axis, and then go vertically until the three curves are encountered, which gives the weights for the three control points. Note that Bni(t)0Bni(t)0 , when t[0,1]t[0,1] , and the symmetry of these blending functions: Bni(t)=Bnn-i(1-t)Bni(t)=Bnni(1t) .

In Figure 17.7 the Bernstein polynomials for n=1n=1 , n=2n=2 , and n=3n=3 are shown. These are also called blending functions. The case when n=1n=1 (linear interpolation) is illustrative, in the sense that it shows the curves y=1-ty=1t and y=ty=t . This implies that when t=0t=0 , then p(0)=p0p(0)=p0 , and when t increases, the blending weight for p0p0 decreases, while the blending weight for p1p1 increases by the same amount, keeping the sum of the weights equal to 1. Finally, when t=1t=1 , p(1)=p1p(1)=p1 . In general, it holds for all Bézier curves that p(0)=p0p(0)=p0 and p(1)=pnp(1)=pn , that is, the endpoints are interpolated (i.e., are on the curve). It is also true that the curve is tangent to the vector p1-p0p1p0 at t=0t=0 , and to pn-pn-1pnpn1 at t=1t=1 . Another useful property is that instead of computing points on a Bézier curve, and then rotating the curve, the control points can first be rotated, and then the points on the curve can be computed. There are usually fewer control points than generated points on the curve, so it is more efficient to transform the control points first.

As an example on how the Bernstein version of the Bézier curve works, assume that n=2n=2 , i.e., a quadratic curve. Equation 17.4 is then

(17.7)

p(t)=B20p0+B21p1+B22p2[4pt]=(20)t0(1-t)2p0+(21)t1(1-t)1p1+(22)t2(1-t)0p2[4pt]=(1-t)2p0+2t(1-t)p1+t2p2,
p(t)[4pt][4pt]=B20p0+B21p1+B22p2=(20)t0(1t)2p0+(21)t1(1t)1p1+(22)t2(1t)0p2=(1t)2p0+2t(1t)p1+t2p2,

which is the same as Equation 17.2. Note

that the blending functions above, (1-t)2(1t)2 , 2t(1-t)2t(1t) , and t2t2 , are the functions displayed in the middle of Figure 17.7. In the same manner, a cubic curve is simplified into

(17.8)

p(t)=(1-t)3p0+3t(1-t)2p1+3t2(1-t)p2+t3p3.
p(t)=(1t)3p0+3t(1t)2p1+3t2(1t)p2+t3p3.

This equation can be rewritten in matrix form as

(17.9)

p(t)=(1tt2t3)(1000-33003-630-13-31)(p0p1p2p3),
p(t)=(1tt2t3)1331036300330001p0p1p2p3,

which is sometimes useful when doing mathematical simplifications.

By collecting terms of the form tktk in Equation 17.4, it can be seen that every Bézier curve can be written in the following form, called the power form, where the cici are points that fall out by collecting terms:

(17.10)

p(t)=ni=0tici.
p(t)=ni=0tici.

It is straightforward to differentiate Equation 17.4, in order to get the derivative of the Bézier curve. The result, after reorganizing and collecting terms, is shown below [458]:

(17.11)

ddtp(t)=nn-1i=0Bn-1i(t)(pi+1-pi).
ddtp(t)=nn1i=0Bn1i(t)(pi+1pi).

The derivative is, in fact, also a Bézier curve, but with one degree lower than p(t)p(t) .

A potential downside of Bézier curves is that they do not pass through all the control points (except the endpoints). Another problem is that the degree increases with the number of control points, making evaluation more and more expensive. A solution to this is to use a simple, low degree curve between each pair of subsequent control points, and see to it that this kind of piecewise interpolation has a high enough degree of continuity. This is the topic of Sections 17.1.317.1.5.

Rational Béezier Curves

While Bézier curves can be used for many things, they do not have that many degrees of freedom—only the position of the control points can be chosen freely. Also, not every curve can be described by Bézier curves. For example, the circle is normally considered a simple shape, but it cannot be defined by one or a collection of Bézier curves. One alternative is the rational Bézier curve. This type of curve is described by the formula shown in Equation 17.12:

(17.12)

p(t)=ni=0wiBni(t)pini=0wiBni(t).
p(t)=ni=0wiBni(t)pini=0wiBni(t).

The denominator is a weighted sum of the Bernstein polynomials, while the numerator is a weighted version of the standard Bézier curve (Equation 17.4). For this type of curve, the user has the weights, wiwi , as additional degrees of freedom. More about these curves can be found in Hoschek and Lasser’s [777] and in Farin’s book [458]. Farin also describes how a circle can be described by three rational Bézier curves.

17.1.2. Bounded Béezier Curves on the GPU

A method for rendering Bézier curves on the GPU will be presented [1068,1069]. Specifically, the target is “bounded Bézier curves,” where the region between the curve and the straight line between the first and last control points is filled. There is a surprisingly simple way to do this by rendering a triangle with a specialized pixel shader.

image

Figure 17.8. Bounded Bézier curve rendering. Left: the curve is shown in canonical texture space. Right: the curve is rendered in screen space. If the condition f(u,v)0f(u,v)0 is used to kill pixels, then the light blue region will result from the rendering.

We use a quadratic, i.e., degree two, Bézier curve, with control points p0p0 , p1p1 , and p2p2 . If we set the texture coordinates at these vertices to t0=(0,0)t0=(0,0) , t1=(0.5,0)t1=(0.5,0) , and t2=(1,1)t2=(1,1) , the texture coordinates will be interpolated as usual during rendering of the triangle Δp0p1p2Δp0p1p2 . We also evaluate the following scalar function inside the triangle for each pixel, where u and v are interpolated texture coordinates:

(17.13)

f(u,v)=u2-v.
f(u,v)=u2v.

The pixel shader then determines whether the pixel is inside ( f(u,v)<0f(u,v)<0 ), or otherwise outside. This is illustrated in Figure 17.8. When rendering a perspective-projected triangle with this pixel shader, we will get the corresponding projected Bézier curve. A proof of this is given by Loop and Blinn [1068,1069].

This type of technique can be used to render TrueType fonts, for example. This is illustrated in Figure 17.9.

image

Figure 17.9. An e is represented by several straight lines and quadratic Bézier curves (left). In the middle, this representation has been “tessellated” into several bounded Bézier curves (red and blue), and triangles (green). The final letter is shown to the right. (Reprinted with permission from Microsoft Corporation.)

Loop and Blinn also show how to render rational quadratic curves and cubic curves, and how do to antialiasing using this representation. Because of the importance of text rendering, research in this area has continued. See Section for related algorithms.

17.1.3. Continuity and Piecewise Béezier Curves

Assume that we have two Bézier curves that are cubic, that is, defined by four control points each. The first curve is defined by qi , and the second by ri , i=0,1,2,3 . To join the curves, we could set q3=r0 . This point is called a joint. However, as shown in Figure 17.10, the joint will not be smooth using this simple technique.

image

Figure 17.10. This figure shows from left to right C0 , G1 , and C1 continuity between two cubic Bézier curves (four control points each). The top row shows the control points, and the bottom row the curves, with 10 sample points for the left curve, and 20 for the right. The following time-point pairs are used for this example: (0.0,q0) , (1.0,q3) , and (3.0,r3) . With C0 continuity, there is a sudden jerk at the join (where q3=r0 ). This is improved with G1 by making the tangents at the join parallel (and equal in length). Though, since 3.0-1.01.0-0.0 , this does not give C1 continuity. This can be seen at the join where there is a sudden acceleration of the sample points. To achieve C1 , the right tangent at the join has to be twice as long as the left tangent.

The composite curve formed from several curve pieces (in this case two) is called a piecewise Bézier curve, and is denoted p(t) here. Further, assume we want p(0)=q0 , p(1)=q3=r0 , and p(3)=r3 . Thus, the times for when we reach q0 , q3=r0 , and r3 , are t0=0.0 , t1=1.0 , and t2=3.0 . See Figure 17.10 for notation. From the previous section we know that a Bézier curve is defined for t[0,1] , so this works out fine for the first curve segment defined by the qi ’s, since the time at q0 is 0.0, and the time at q3 is 1.0. But what happens when 1.0<t3.0 ? The answer is simple: We must use the second curve segment, and then translate and scale the parameter interval from [t1,t2] to [0, 1]. This is done using the formula below:

(17.14)

t=t-t1t2-t1.

Hence, it is the t that is fed into the Bézier curve segment defined by the ri ’s. This is simple to generalize to stitching several Bézier curves together.

A better way to join the curves is to use the fact that at the first control point of a Bézier curve the tangent is parallel to q1-q0 (Section 17.1.1). Similarly, at the last control point the cubic curve is tangent to q3-q2 . This behavior can be seen in Figure 17.5. So, to make the two curves join tangentially at the joint, the tangent for the first and the second curve should be parallel there. Put more formally, the following should hold:

(17.15)

(r1-r0)=c(q3-q2)forc>0.

This simply means that the incoming tangent, q3-q2 , at the joint should have the same direction as the outgoing tangent, r1-r0 .

It is possible to achieve even better continuity than that, using in Equation 17.15 the c defined by Equation 17.16 [458]:

(17.16)

c=t2-t1t1-t0.

This is also shown in Figure 17.10. If we instead set t2=2.0 , then c=1.0 , so when the time intervals on each curve segment are equal, then the incoming and outgoing tangent vectors should be identical. However, this does not work when t2=3.0 . The curves will look identical, but the speed at which p(t) moves on the composite curve will not be smooth. The constant c in Equation 17.16 takes care of this.

Some advantages of using piecewise curves are that lower-degree curves can be used, and that the resulting curves will go through a set of points. In the example above, a degree of three, i.e., a cubic, was used for each of the two curve segments. Cubic curves are often used for this, as those are the lowest-degree curves that can describe an S-shaped curve, called an inflection. The resulting curve p(t) interpolates, i.e., goes through, the points q0 , q3=r0 , and r3 .

At this point, two important continuity measures have been introduced by example. A slightly more mathematical presentation of the continuity concept for curves follows. For curves in general, we use the Cn notation to differentiate between different kinds of continuity at the joints. This means that all the nth first derivatives should be continuous and nonzero all over the curve. Continuity of C0 means that the segment should join at the same point, so linear interpolation fulfills this condition. This was the case for the first example in this section. Continuity of C1 means that if we derive once at any point on the curve (including joints), the result should also be continuous. This was the case for the third example in this section, where Equation 17.16was used.

There is also a measure that is denoted Gn . Let us look at G1 (geometrical) continuity as an example. For this, the tangent vectors from the curve segments that meet at a joint should be parallel and have the same direction, but nothing about the lengths is assumed. In other words, G1 is a weaker continuity than C1 , and a curve that is C1 is always G1 except when the velocities of two curves go to zero at the point where the curves join and they have different tangents just before the join. The concept of geometrical continuity can be extended to higher dimensions. The middle illustration in Figure 17.10 shows G1 -continuity.

image

Figure 17.11. Blending functions for Hermite cubic interpolation. Note the asymmetry of the blending functions for the tangents. Negating the blending function t3-t2 and m1 in Equation 17.17 would give a symmetrical look.

image

Figure 17.12. Hermite interpolation. A curve is defined by two points, p0 and p1 , and a tangent, m0 and m1 , at each point.

17.1.4. Cubic Hermite Interpolation

Bézier curves are good for describing the theory behind the construction of smooth curves, but are sometimes not predictable to work with.

In this section, we will present cubic Hermite interpolation, and these curves tend to be simpler to control. The reason is that instead of giving four control points to describe a cubic Bézier curve, the cubic Hermite curve is defined by starting and ending points, p0 and p1 , and starting and ending tangents, m0 and m1 . The Hermite interpolant, p(t) , where t[0,1] , is

(17.17)

p(t)=(2t3-3t2+1)p0+(t3-2t2+t)m0+(t3-t2)m1+(-2t3+3t2)p1.

We also call p(t) a Hermite curve segment or a cubic spline segment. This is a cubic interpolant, since t3 is the highest exponent in the blending functions in the above formula. The following holds for this curve:

(17.18)

p(0)=p0,p(1)=p1,pt(0)=m0,pt(1)=m1.

This means that the Hermite curve interpolates p0 and p1 , and the tangents at these points are m0 and m1 . The blending functions in Equation 17.17 are shown in Figure 17.11, and they can be derived from Equations 17.4 and 17.18. Some examples of cubic Hermite interpolation can be seen in Figure 17.12. All these examples interpolate the same points, but have different tangents. Note also that different lengths of the tangents give different results; longer tangents have a greater impact on the overall shape.

Cubic Hermite interpolation is used to render the hair in the Nalu demo [1274]. See Figure 17.2. A coarse control hair is used for animation and collision detection, tangents are computed, and cubic curves are tessellated and rendered.

17.1.5. Kochanek-Bartels Curves

When interpolating between more than two points, you can connect several Hermite curves.

However, when doing this, there are degrees of freedom in selecting the shared tangents that provide different characteristics. Here, we will present one way to compute such tangents, called Kochanek-Bartels curves. Assume that we have n points, p0,,pn-1 , which should be interpolated with n-1 Hermite curve segments. We assume that there is only one tangent at each point, and we start to look at the “inner” tangents, m1,,mn-2 . A tangent at pi can be computed as a combination of the two chords [917]: pi-pi-1 , and pi+1-pi , as shown at the left in Figure 17.13.

image

Figure 17.13. One method of computing the tangents is to use a combination of the chords (left). The upper row at the right shows three curves with different tension parameters (a). The left curve has a1 , which means high tension; the middle curve has a0 , which is default tension; and the right curve has a-1 , which is low tension. The bottom row of two curves at the right shows different bias parameters. The curve on the left has a negative bias, and the right curve has a positive bias.

First, a tension parameter, a, is introduced that modifies the length of the tangent vector. This controls how sharp the curve is going to be at the joint. The tangent is computed as

(17.19)

mi=1-a2((pi-pi-1)+(pi+1-pi)).

The top row at the right in Figure 17.13 shows different tension parameters. The default value is a=0 ; higher values give sharper bends (if a>1 , there will be a loop at the joint), and negative values give less taut curves near the joints. Second, a bias parameter, b, is introduced that influences the direction of the tangent (and, indirectly, the length of the tangent).

Using both tension and bias gives us

(17.20)

mi=(1-a)(1+b)2(pi-pi-1)+(1-a)(1-b)2(pi+1-pi),

where the default value is b=0 . A positive bias gives a bend that is more directed toward the chord pi-pi-1 , and a negative bias gives a bend that is more directed toward the other chord: pi+1-pi . This is shown in the bottom row on the right in Figure 17.13. The user can either set the tension and bias parameters or let

them have their default values, which produces what is often called a Catmull-Rom spline [236]. The tangents at the first and the last points can also be computed with these formulae, where one of the chords is simply set to a length of zero.

Yet another parameter that controls the behavior at the joints can be incorporated into the tangent equation [917]. However, this requires the introduction of two tangents at each joint, one incoming, denoted si (for source) and one outgoing, denoted di (for destination). See Figure 17.14. Note that the curve segment between pi and pi+1 uses the tangents di and si+1 . The tangents are computed as below, where c is the continuity parameter:

(17.21)

si=1-c2(pi-pi-1)+1+c2(pi+1-pi),[2pt]di=1+c2(pi-pi-1)+1-c2(pi+1-pi).

image

Figure 17.14. Incoming and outgoing tangents for Kochanek-Bartels curves. At each control point pi , its time ti is also shown, where ti>ti-1 , for all i.

Again, c=0 is the default value, which makes si=di . Setting c=-1 gives si=pi-pi-1 , and di=pi+1-pi , producing a sharp corner at the joint, which is only C0 . Increasing the value of c makes si and di more and more alike. For c=0 , then si=di . When c=1 is reached, we get si=pi+1-pi , and di=pi-pi-1 . Thus, the continuity parameter c is another way to give even more control to the user, and it makes it possible to get sharp corners at the joints, if desired.

The combination of tension, bias, and continuity, where the default parameter values are a=b=c=0 , is

(17.22)

si=(1-a)(1+b)(1-c)2(pi-pi-1)+(1-a)(1-b)(1+c)2(pi+1-pi),[2pt]di=(1-a)(1+b)(1+c)2(pi-pi-1)+(1-a)(1-b)(1-c)2(pi+1-pi).

Both Equations 17.20 and 17.22 work only when all curve segments are using the same time interval length. To account for different time length of the curve segments, the tangents have to be adjusted, similar to what was done in Section 17.1.3. The adjusted tangents, denoted si and di , are

(17.23)

si=si2ΔiΔi-1+Δianddi=di2Δi-1Δi-1+Δi,

where Δi=ti+1-ti .

17.1.6. B-Splines

Here, we will provide a brief introduction to the topic of B-splines, and we will focus in particular on cubic uniform B-splines. In general, a B-spline is quite similar to a Bézier curve, and can be expressed as a function of t (using shifted basis functions), βn (weighted by control points), and ck : e.g.,

(17.24)

sn(t)=kckβn(t-k).

In this case, this is a curve where t is the x-axis and sn(t) is the y-axis, and the control points are simply evenly spaced y-values. For much more extensive coverage, see the texts by the Killer B’s [111], Farin [458], and Hoschek and Lasser [777].

Here, we will follow the presentation by Ruijters et al. [1518] and present the special case of a uniform cubic B-spline. The basis function, β3(t) , is stitched together by three pieces:

(17.25)

β3(t)={0,|t|2,[2pt]16(2-|t|)3,1|t|<2,[2pt]23-12|t|2(2-|t|),|t|<1.

The construction of this basis function is shown on the left in Figure 17.15. This function has C2 continuity everywhere, which means that if several B-spline curve segments are stitched together, the composite curve will also be C2 . A cubic curve has C2 continuity, and in general, a curve of degree n has Cn-1 continuity.

image

Figure 17.15. Left: the β3(t) basis function is shown as a fat black curve, which is constructed from two piecewise cubic functions (red and green). The green curve is used when |t|<1 , the red curve when 1|t|<2 , and the curve is zero elsewhere. Right: to create a curve segment using four control points, ck , k{i-1,i,i+1,i+2} , we will only obtain a curve between the t-coordinate of ci and of ci+1 . The α is fed into the w functions to evaluate the basis function, and these values are then multiplied by the corresponding control point. Finally, all values are added together, which gives us a point on the curve. See Figure 17.16. (Illustration on the right after Ruijters et al. [1518].)

In general, the basis functions are created as follows. The β0(t) is a “square” function, i.e., it is 1 if |t|<0.5 , it is 0.5 if |t|=0.5 , and it is 0 elsewhere. The next basis function, β1(t) is created by integrating β0(t) , which gives us a tent function. The basis function after that is created by integrating β1(t) , which gives a smoother function, which is C1 . This process is repeated to get C2 , and so on.

How to evaluate a curve segment is illustrated on the right in Figure 17.15, and its formula is

(17.26)

s3(i+α)=w0(α)ci-1+w1(α)ci+w2(α)ci+1+w3(α)ci+2.

Note that only four control points will be used at any time, and this means that the curve has local support, i.e., a limited number of control points is needed. The functions wk(α) are defined using β3() as

(17.27)

w0(α)=β3(-α-1),w1(α)=β3(-α),w2(α)=β3(1-α),w3(α)=β3(2-α).

Ruijters et al. [1518] show that these can be rewritten as

(17.28)

w0(α)=16(1-α)3,w1(α)=23-12α2(2-α),w2(α)=23-12(1-α)2(1+α),w3(α)=16α3.

In Figure 17.16, we show the results of stitching two uniform cubic B-spline curves together as one.

image

Figure 17.16. The control points ck (green circles) define a uniform cubic spline in this example. Only the two fat curves are part of the piecewise B-spline curve. The left (green) curve is defined by the four leftmost control points, and the right (red) curve is defined by the four rightmost control points. The curves meet at t=1 with C2 continuity.

A major advantage is that the curves are continuous with the same continuity as the basis functions, β(t) , which are C2 in the case of a cubic B-spline. As can be seen in the figure, there is no guarantee that the curve will go through any of the control points. Note that we can also create a B-spline for the x-coordinates, which would give a general curve in the plane (and not just a function). The resulting two-dimensional points would then be (sx3(i+α),sy3(i+α)) , i.e., simply two different evaluations of Equation 17.26, one for x and one for y.

We have shown how to use only B-splines that are uniform. If the spacing between the control points is nonuniform, the equations become a bit more elaborate but more flexible [111,458,777].

17.2 Parametric Curved Surfaces

A natural extension of parametric curves is parametric surfaces. An analogy is that a triangle or polygon is an extension of a line segment, in which we go from one to two dimensions. Parametric surfaces can be used to model objects with curved surfaces. A parametric surface is defined by a small number of control points. Tessellation of a parametric surface is the process of evaluating the surface representation at several positions, and connecting these to form triangles that approximate the true surface. This is done because graphics hardware can efficiently render triangles. At runtime, the surface can then be tessellated into as many triangles as desired. Thus, parametric surfaces are perfect for making a trade-off between quality and speed, since more triangles take more time to render, but give better shading and silhouettes. Another advantage of parametric surfaces is that the control points can be animated and then the surface can be tessellated. This is in contrast to animating a large triangle mesh directly, which can be more expensive.

This section starts by introducing Bézier patches, which are curved surfaces with rectangular domains. These are also called tensor-product Bézier surfaces. Then Bézier triangles are presented, which have triangular domains, followed by a discussion about continuity in Section 17.2.4. In Sections 17.2.5 and 17.2.6, two methods are presented that replace each input triangle with a Bézier triangle. These techniques are called PN triangles and Phong tessellation, respectively. Finally, B-spline patches are presented in Section 17.2.7.

17.2.1. Béezier Patches

The concept of Bézier curves, introduced in Section 17.1.1, can be extended from using one parameter to using two parameters, thus forming surfaces instead of curves. Let us start with extending linear interpolation to bilinear interpolation. Now, instead of just using two points, we use four points, called a , b , c , and d , as shown in Figure 17.17.

image

Figure 17.17. Bilinear interpolation using four points.

image

Figure 17.18. Left: a biquadratic Bézier surface, defined by nine control points, pij . Right: to generate a point on the Bézier surface, four points p1ij are first created using bilinear interpolation from the nearest control points. Finally, the point surface p(u,v)=p200 is bilinearly interpolated from these created points.

Instead of using one parameter called t, we now use two parameters (u, v). Using u to linearly interpolate a & b and c & d gives e and f :

(17.29)

e=(1-u)a+ub,f=(1-u)c+ud.

Next, the linearly interpolated points, e and f , are linearly interpolated in the other direction, using v. This yields bilinear interpolation:

(17.30)

p(u,v)=(1-v)e+vf=(1-u)(1-v)a+u(1-v)b+(1-u)vc+uvd.

Note that this is the same type of equation used for bilinear interpolation for texture mapping (Equation on page 179). Equation 17.30 describes the simplest nonplanar parametric surface, where different points on the surface are generated using different values of (u, v). The domain, i.e., the set of valid values, is (u,v)[0,1]×[0,1] , which means that both u and v should belong to [0, 1]. When the domain is rectangular, the resulting surface is often called a patch.

To extend a Bézier curve from linear interpolation, more points were added and the interpolation repeated. The same strategy can be used for patches. Assume nine points, arranged in a 3×3 grid, are used. This is shown in Figure 17.18, where the notation is shown as well. To form a biquadratic Bézier patch from these points, we first need to bilinearly interpolate four times to create four intermediate points, also shown in Figure 17.18. Next, the final point on the surface is bilinearly interpolated from the previously created points.

The repeated bilinear interpolation described above is the extension of de Casteljau’s algorithm to patches. At this point we need to define some notation. The degree of the surface is n. The control points are pi,j , where i and j belong to [0n] . Thus, (n+1)2 control points are used for a patch of degree n. Note that the control points should be superscripted with a zero, i.e., p0i,j , but this is often omitted, and sometimes we use the subscript ij instead of i,j when there can be no confusion. The Bézier patch using de Casteljau’s algorithm is described in the equation that follows:

de Casteljau [patches]:

(17.31)

pki,j(u,v)=(1-u)(1-v)pk-1i,j+u(1-v)pk-1i,j+1+(1-u)vpk-1i+1,j+uvpk-1i+1,j+1k=1n,i=0n-k,j=0n-k.

Similar to the Bézier curve, the point at (u, v) on the Bézier patch is pn0,0(u,v) . The Bézier patch can also be described in Bernstein form using Bernstein polynomials, as shown in Equation 17.32:

Bernstein [patches]:

(17.32)

p(u,v)=mi=0Bmi(u)nj=0Bnj(v)pi,j=mi=0nj=0Bmi(u)Bnj(v)pi,j,=mi=0nj=0(mi)(nj)ui(1-u)m-ivj(1-v)n-jpi,j.

Note that in Equation 17.32, there are two parameters, m and n, for the degree of the surface. The “compound” degree is sometimes denoted m×n . Most often m=n , which simplifies the implementation a bit. The consequence of, say, m>n is to first bilinearly interpolate n times, and then linearly interpolate m-n times. This is shown in Figure 17.19.

image

Figure 17.19. Different degrees in different directions.

A different interpretation of Equation 17.32 is found by rewriting it as

(17.33)

p(u,v)=mi=0Bmi(u)nj=0Bnj(v)pi,j[6pt]=mi=0Bmi(u)qi(v).

Here, qi(v)=nj=0Bnj(v)pi,j for i=0m . As can be seen in the bottom row in Equation 17.33, this is just a Bézier curve when we fix a v-value. Assuming v=0.35 , the points qi(0.35) can be computed from a Bézier curve, and then Equation 17.33 describes a Bézier curve on the Bézier surface, for v=0.35 .

Next, some useful properties of Bézier patches will be presented. By setting (u,v)=(0,0) , (u,v)=(0,1) , (u,v)=(1,0) , and (u,v)=(1,1) in Equation 17.32, it is simple to prove that a Bézier patch interpolates, that is, goes through, the corner control points, p0,0 , p0,n , pn,0 , and pn,n . Also, each boundary of the patch is described by a Bézier curve of degree n formed by the control points on the boundary. Therefore, the tangents at the corner control points are defined by these boundary Bézier curves. Each corner control point has two tangents, one in each of the u- and v-directions. As was the case for Bézier curves, the patch also lies within the convex hull of its control points, and

(17.34)

mi=0nj=0Bmi(u)Bnj(v)=1

for (u,v)[0,1]×[0,1] . Finally, rotating the control points and then generating points on the patch is the same mathematically as (though usually faster than) generating points on the patch and then rotating these.

Partially differentiating Equation 17.32 gives [458] the equations below:

Derivatives [patches]:

(17.35)

p(u,v)u=mnj=0m-1i=0Bm-1i(u)Bnj(v)[pi+1,j-pi,j],[3pt]p(u,v)v=nmi=0n-1j=0Bmi(u)Bn-1j(v)[pi,j+1-pi,j].

As can be seen, the degree of the patch is reduced by one in the direction that is differentiated. The unnormalized normal vector is then formed as

(17.36)

n(u,v)=p(u,v)u×p(u,v)v.

In Figure 17.20, the control mesh together with the actual Bézier patch is shown. The effect of moving a control point is shown in Figure 17.21.

Rational Béezier Patches

Just as the Bézier curve could be extended into a rational Bézier curve (Section 17.1.1), and thus introduce more degrees of freedom, so can the Bézier patch be extended into a rational Bézier patch:

(17.37)

p(u,v)=mi=0nj=0wi,jBmi(u)Bnj(v)pi,jmi=0nj=0wi,jBmi(u)Bnj(v).

Consult Farin’s book [458] and Hochek and Lasser’s book [777] for information about this type of patch. Similarly, the rational Bézier triangle is an extension of the Bézier triangle, treated next.

image

Figure 17.20. Left: control mesh of a 4×4 Bézier patch of degree 3×3 . Middle: the actual quadrilaterals that were generated on the surface. Right: shaded Bézier patch.

image

Figure 17.21. This set of images shows what happens to a Bézier patch when one control point is moved. Most of the change is near the moved control point.

image

Figure 17.22. The control points of a Bézier triangle with degree three (cubic).

17.2.2. Béezier Triangles

Even though the triangle often is considered a simpler geometric primitive than the rectangle, this is not the case when it comes to Bézier surfaces: Bézier triangles are not as straightforward as Bézier patches. This type of patch is worth presenting as it is used in forming PN triangles and for Phong tessellation, which are fast and simple.

Note that some game engines, such as the Unreal Engine, Unity, and Lumberyard, support Phong tessellation and PN triangles.

The control points are located in a triangular grid, as shown in Figure 17.22.

The degree of the Bézier triangle is n, and this implies that there are n+1 control points per side. These control points are denoted p0i,j,k and sometimes abbreviated to pijk . Note that i+j+k=n , and i,j,k0 for all control points. Thus, the total number of control points is

(17.38)

n+1x=1x=(n+1)(n+2)2.

It should come as no surprise that Bézier triangles also are based on repeated interpolation. However, due to the triangular shape of the domain, barycentric coordinates (Section ) must be used for the interpolation. Recall that a point within a triangle Δp0p1p2 , can be described as p(u,v)=p0+u(p1-p0)+v(p2-p0)=(1-u-v)p0+up1+vp2 , where (u, v) are the barycentric coordinates. For points inside the triangle the following must hold: u0 , v0 , and 1-(u+v)0u+v1 . Based on this, the de Casteljau algorithm for Bézier triangles is

de Casteljau [triangles]:

(17.39)

pli,j,k(u,v)=upl-1i+1,j,k+vpl-1i,j+1,k+(1-u-v)pl-1i,j,k+1,l=1n,i+j+k=n-l.

The final point on the Bézier triangle at (u, v) is pn000(u,v) . The Bézier triangle in Bernstein form is

(17.40)

Bernstein[triangles]:p(u,v)=i+j+k=nBnijk(u,v)pijk.

The Bernstein polynomials now depend on both u and v, and are therefore computed differently, as shown below:

(17.41)

Bnijk(u,v)=n!i!j!k!uivj(1-u-v)k,i+j+k=n.

The partial derivatives are [475]

Derivatives [triangles]:

(17.42)

p(u,v)u=i+j+k=n-1nBn-1ijk(u,v)(pi+1,j,k-pi,j,k+1),p(u,v)v=i+j+k=n-1nBn-1ijk(u,v)(pi,j+1,k-pi,j,k+1).

Some unsurprising properties of Bézier triangles are that they interpolate (pass through) the three corner control points, and that each boundary is a Bézier curve described by the control points on that boundary. Also, the surfaces lies in the convex hull of the control points. A Bézier triangle is shown in Figure 17.23.

image

Figure 17.23. Left: wireframe of a tessellated Bézier triangle. Right: shaded surface together with control points.

17.2.3. Continuity

When constructing a complex object from Bézier surfaces, one often wants to stitch together several different Bézier surfaces to form one composite surface. To get a good-looking result, care must be taken to ensure that reasonable continuity is obtained across the surfaces. This is in the same spirit as for curves, in Section 17.1.3.

image

Figure 17.24. How to stitch together two Bézier patches with C1 continuity. All control points on bold lines must be collinear, and they must have the same ratio between the two segment lengths. Note that a3j=b0j to get a shared boundary between patches. This can also be seen to the right in Figure 17.25.

Assume two bicubic Bézier patches should be pieced together. These have 4×4 control points each. This is illustrated in Figure 17.24, where the left patch has control points, aij , and the right has control points, bij , for 0i,j3 . To ensure C0 continuity, the patches must share the same control points at the border, that is, a3j=b0j .

However, this is not sufficient to get a nice looking composite surface. Instead, a simple technique will be presented that gives C1 continuity [458]. To achieve this we must constrain the position of the two rows of control points closest to the shared control points. These rows are a2j and b1j . For each j, the points a2j , b0j , and b1j must be collinear, that is, they must lie on a line. Moreover, they must have the same ratio, which means that ||a2j-b0j||=k||b0j-b1j|| . Here, k is a constant, and it must be the same for all j. Examples are shown in Figure 17.24 and 17.25.

This sort of construction uses up many degrees of freedom of setting the control points. This can be seen even more clearly when stitching together four patches, sharing one common corner. The construction is visualized in Figure 17.26.

The result is shown to the right in this figure, where the locations of the eight control points around the shared control point are shown. These nine points must all lie in the same plane, and they must form a bilinear patch, as shown in Figure 17.17. If one is satisfied with G1 continuity at the corners (and only there), it suffices to make the nine points coplanar. This uses fewer degrees of freedom.

Continuity for Bézier triangles is generally more complex, as well as the G1 conditions for both Bézier patches and triangles [458,777]. When constructing a complex object of many Bézier surfaces, it is often hard to see to it that reasonable continuity is obtained across all borders. One solution to this is to turn to subdivision surfaces, treated in Section 17.5.

Note that C1 continuity is required for good-looking texturing across borders. For reflections and shading, a reasonable result is obtained with G1 continuity. C1 or higher gives even better results. An example is shown in Figure 17.25.

In the following two subsections, we will present two methods that exploit the normals at triangle vertices to derive a Bézier triangle per input (flat) triangle.

image

Figure 17.25. The left column shows two Bézier patches joined with only C0 continuity. Clearly, there is a shading discontinuity between the patches. The right column shows similar patches joined with C1 continuity, which looks better. In the top row, the dashed lines indicate the border between the two joined patches. To the upper right, the black lines show the collinearity of the control points of the joining patches.

image

Figure 17.26. (a) Four patches, F, G, H, and I, are to be stitched together, where all patches share one corner. (b) In the vertical direction, the three sets of three points (on each bold line) must use the same ratio, k. This relationship is not shown here; see the rightmost figure. A similar process is done for (c), where, in the horizontal direction, both patches must use the same ratio, l. (d) When stitched together, all four patches must use ratio k vertically, and l horizontally. (e) The result is shown, in which the ratios are correctly computed for the nine control points closest to (and including) the shared control point.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset