NeHe OpenGL Lesson28 – Bezier Patches(贝叶茨曲面) / Fullscreen Fix
Well, this samples shows us how to create Bzeier Patches based on some math ideas. And OpenGL used to just display those patches.
The main idea underneath the Bzeier Patches math is how to calculate a morph point or continues point given by the control points. How the morphing function will be?
Let assume that we need to morph from one point to another point along a line. Most of time, the function will be written like this:
1) P0*t + P1*(1-t) = Pnew, and
2) t + (1-t) = 1, t belongs [0, 1].
We will create a new parameter named t that will make how the new created point look like other P0 and P1. Here the P0 and P1 called control points. And the function 2) called basis function.
Mathematical theory
The Bezier curve based on the function 2), and make it a bit extend. Here is more details version how Bezier goes on on NeHe Web page:
“Bezier curves are based on a basis function from which more complicated versions are derived. Here’s the function:
t + (1 – t) = 1
Sounds simple enough huh? Well it really is, this is the Bezier most basic Bezier curve, a 1st degree curve. As you may have guessed from the terminology, the Bezier curves are polynomials, and as we remember from algebra, a 1st degree polynomial is just a straight line; not very interesting. Well, since the basis function is true for all numbers t, we can square, cube, whatever, each side and it will still be true right? Well, lets try cubing it.
(t + (1-t))^3 = 1^3
t^3 + 3*t^2*(1-t) + 3*t*(1-t)^2 + (1-t)^3 = 1
This is the equation we use to calculate the most common Bezier, the 3rd degree Bezier curve. This is most common for two reasons, a) it’s the lowest degree polynomial that need not necesarily lie in a plane (there are 4 control points)
b) the tangent lines on the sides are not dependant on one another (with a 2nd degree there would be only 3 control points).
Ok, since the entire left side is equal to 1, it’s safe to assume that if you add all the components they should still equal one. Does this sound like it could be used to decide how much of each control point to use in calculating a point on the curve? (hint: just say yes? ) Well you’re right! When we want to calculate the value of a point some percent along the curve we simply multiply each part by a control point (as a vector) and find the sum. Generally, we’ll work with 0
P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew
Because polynomials are always continuous, this makes for a good way to morp between the 4 points. The only points it actually reaches though are P1 and P4, when t = 1 and 0 respectively.
Now, that’s all well and good, but how can I use these in 3D you ask? Well it’s actually quite simple, in order to form a Bezier patch, you need 16 control points (4*4), and 2 variables t and v. What you do from there is calculate a point at v along 4 of the parallel curves then use those 4 points to make a new curve and calculate t along that curve. By calculating enough of these points, we can draw triangle strips to connect them, thus drawing the Bezier patch.”
Implementation
In other worlds, with the above method, we could easily calculate one point given by the v, t (range from 0 to 1, a bit like the texture coordinates) and 16 control points. A Bezeir surface points generation function would write like this:
Point3D CalculateBezeirCurvePoint(float v, Point3D _Points[4]) { // Do Bezeir basis functions calculations here // t^3 + 3*t^2*(1-t) + 3*t*(1-t)^2 + (1-t)^3 = 1 } // Calculate Bezeir patch with 16 control points Point3D CalculateBezeirSurfacePoint(float v, float t, Point3D _Points[16]) { Point3D tmp[4]; tmp[0] = CalculateBezeirCurvePoint(v, &_Points[0]); tmp[1] = CalculateBezeirCurvePoint(v, &_Points[4]); tmp[2] = CalculateBezeirCurvePoint(v, &_Points[8]); tmp[3] = CalculateBezeirCurvePoint(v, &_Points[12]); return CalculateBezeirCurvePoint(t, tmp); }
The full source code could be downloaded from here.