“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.
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.
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.
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)
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.
Linear interpolation traces out a path, which is a straight line, between two points, p0
(17.1)
p(t)=p0+t(p1-p0)=(1-t)p0+tp1.The parameter t controls where on the line the point p(t)
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.
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].
First, to be able to repeat the interpolation, we have to add more points. For example, three points, a
(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, which is a parabola since the maximum degree of t is two. In fact, given n+1
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 a
(17.3)
pki(t)=(1-t)pk-1i(t)+tpk-1i+1(t),{k=1⋯n,i=0⋯n-k. Note that a point on the curve is described by p(t)=pn0(t)
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.
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.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.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],and∑ni=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, pi
In Figure 17.7 the Bernstein polynomials for n=1
As an example on how the Bernstein version of the Bézier curve works, assume that n=2
(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,which is the same as Equation 17.2. Note
that the blending functions above, (1-t)2
(17.8)
p(t)=(1-t)3p0+3t(1-t)2p1+3t2(1-t)p2+t3p3.This equation can be rewritten in matrix form as
(17.9)
p(t)=(1tt2t3)(1000-33003-630-13-31)(p0p1p2p3),which is sometimes useful when doing mathematical simplifications.
By collecting terms of the form tk
(17.10)
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)=n∑n-1i=0Bn-1i(t)(pi+1-pi).The derivative is, in fact, also a Bézier curve, but with one degree lower than 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.3–17.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)pi∑ni=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, wi
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.
We use a quadratic, i.e., degree two, Bézier curve, with control points p0
(17.13)
f(u,v)=u2-v.The pixel shader then determines whether the pixel is inside ( f(u,v)<0
This type of technique can be used to render TrueType fonts, for example. This is illustrated in Figure 17.9.
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.
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.
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<t≤3.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.
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,∂p∂t(0)=m0,∂p∂t(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.
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.
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).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 s′i and d′i , are
(17.23)
s′i=si2ΔiΔi-1+Δiandd′i=di2Δi-1Δi-1+Δi,where Δi=ti+1-ti .
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.
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.
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].
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.
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.
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 [0⋯n] . 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=1⋯n,i=0⋯n-k,j=0⋯n-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)=m∑i=0Bmi(u)n∑j=0Bnj(v)pi,j=m∑i=0n∑j=0Bmi(u)Bnj(v)pi,j,=m∑i=0n∑j=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.
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=0⋯m . 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=0∑nj=0Bmi(u)Bnj(v)=1for (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=mn∑j=0m-1∑i=0Bm-1i(u)Bnj(v)[pi+1,j-pi,j],[3pt]∂p(u,v)∂v=nm∑i=0n-1∑j=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.
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=0∑nj=0wi,jBmi(u)Bnj(v)pi,j∑mi=0∑nj=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.
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,k≥0 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: u≥0 , v≥0 , and 1-(u+v)≥0⇔u+v≤1 . 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=1⋯n,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.
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.
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 0≤i,j≤3 . 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.