์ง๋ณด๋ ๋จ์์ฑ์ ๋ณต์กํ๊ฒ ๋ง๋๋ ์ธ๊ฐ์ ๋ฅ๋ ฅ. โํฌ๋ฅด ํ์ด์๋ฅด๋ฌ(๋
ธ๋ฅด์จ์ด ์ธ๋ฅํ์, 1914โผ)
๏ปฟ * ์๋ฌธ๋งํฌ :
http://www.gamedev.net/reference/articles/article888.asp
http://www.gamedev.net/reference/articles/article888.asp
- ๊ตฌ์ด์ฒด์ธ๋ฐ๋ค๊ฐ ์กฐ๊ธ์ ์ธ๋ฐ์๋ ์ฌ์กฑ์ด ๋ง์ ๊ธ์
๋๋ค.
์ด๋์ ๋ ์ฒจ์ญํ์์ ๋ฐํ๋๋ค.
๊ฐ์ #
๊ณก์ ๋ฐ ๊ณก๋ฉด์ ๋ค๋ฃจ๋ ๊ต์ฅํ ์ ๊ธฐ์ ์ ๋ํ์ฌ ๋ค์ด๋ดค์ผ๋ฆฌ๋ผ ์๊ฐํฉ๋๋ค. 2์ฐจ ๋ฒ ์ง์ด ํจ์น, 3์ฐจ ๋ฒ ์ง์ด ๊ณก์ , NURBS... ์ฌ๋ฌ๋ถ์ ์ด ๋ชจ๋ ๋ฏธ์น ๊ฒ๋ค์ ์ดํดํ๋ ค๊ณ ์๋ํ์ ์ด ์์๊ฒ๋๋ค. ์๋ง๋ ์ด๋ค ๊ธฐ์ ์ ์ฌ๋ฌ๋ถ์ด ๋ง๋ค๊ณ ์๋ ๊ฒ์ ๋๋ ๋ฐ๋ชจ์ ๋ฃ์ผ๋ ค๊ณ ํ์ ์๋ ์๊ฒ ์ง์.
์ด ์ํฐํด์ ์ด๋ค์ ๋ํ ๋ฏธ์คํ
๋ฆฌ๋ฅผ ํธ๋๋ฐ ์์ด ์ข์ ์์์ ์ด ๋ ๊ฒ์
๋๋ค.
์ด ์ํฐํด์์๋, ์ด๋ค ๋ฒ ์ง์ด ๊ณก์ ๋ค์ ๊น๋ ค์๋ ์ํ์๋ฆฌ์ (๊ณก์ ์ค์์ ๊ฐ์ฅ ๊ฐ๋จํ) 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ๊ทธ๋ฆฌ๊ธฐ์ํ ์ฝ๋, ๊ทธ๋ฆฌ๊ณ 3์ฐจ, 4์ฐจ, 5์ฐจ ๋๋ ๊ทธ ์ด์์ ์ฌ๋ฌ๋ถ์ด ํ์ํ ์์ค์ ๋ฒ ์ง์ด ๊ณก์ ์ ๋ง๋ค๊ธฐ์ํ ๋ฐฉ๋ฒ๋ค์ ์ ์ถํ๊ธฐ์ํด ์ฌ์ฉํ๋ ๋ช๊ฐ์ง ๊ธฐ์ ์ ์ค๋ช
ํ ๊ฒ์
๋๋ค.
๋ฒ ์ง์ด ๊ณก์ ๋ค์ ์จ๊ฒจ์ง ์ํ์๋ฆฌ #
์ข์ต๋๋ค. ๊ฐ์ฅ๋จผ์ ์ง๊ณ ๋์ด๊ฐ์ผํ ๊ฒ์ ๋ฒ์คํ์ธ(Bernstein) ์ ๋ฆฌ ๊ณต์"๋ค"์
๋๋ค. ์, ์ด์ ๊ณต์ํ๋๋ฅผ ๋ณด์ฌ์ค ์์ ์ธ๋ฐ, ์ด์กฐํดํ ํ์๋ ์์ต๋๋ค. ๋จ์ง ์ด ๊ณต์์ ๋ณด๋ฉด ์ ๋ง๋ก ๊ฐ๋จํ๋ค๋ ๊ฒ์ ๊ธ๋ฐฉ ์ ์ ์์๊ฑฐ๋๊น์.
1 = t + (1 - t)t๋ ์ด๋ ํ ์์๋ผ๋ ๋ ์ ์์ผ๋ฉฐ ์ด ๊ณต์์ ๋ชจ๋ ๊ฒฝ์ฐ์ ์์ ๋ํ์ฌ ์ธ์ ๋ ์ฐธ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ํฐํด์์๋ t๊ฐ 0๊ณผ 1์ฌ์ด์ผ ๊ฒฝ์ฐ๋ง ๊ณ ๋ คํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด์ ๋ฒ์คํ์ธ ์ ๋ฆฌ ๊ณต์์ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด์ ์ ์ ๊ฐ ๊ณต์"๋ค"์ด๋ผ๊ณ ๋ณต์ํ์ผ๋ก ๋งํ๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์! ์, ์ ๋์ํ๋ ๊ณก์ ์ ์ป๊ธฐ์ํ ๋ค์ ๋จ๊ณ๋ ์ฐ๋ฆฌ์ ์๊ทธ๋งํ ๋ฐ๋ชจ์์ ์ด๋ค ์ข
๋ฅ์ ๊ณก์ ์ ์ฌ์ฉํ ๊ฒ์ธ์ง ์ ํํ๋ ๊ฒ์
๋๋ค. ์ด์ฌ์๋ฅผ ์ํด์, ์ฌ๊ธฐ์๋ ๊ฐ์ฅ ์ฌ์ด ํํ์ธ 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ์ฌ์ฉํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์, ๊ทธ๋ฆฌํ์ฌ 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ํํ๊ฒ ๋์์ต๋๋ค. ์ด์ ์ ์ง์ ๋ฅํ ์ ๋ฆฌ ๊ณต์์ผ๋ก๋ถํฐ ๋ช๊ฐ์ง ๊ณต์๋ค์ ๋์ด๋ด์ผํ ํ์๊ฐ ์์ต๋๋ค. 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ์ํด์๋, ์ฐ์ ๋ฒ์คํ์ธ ์ ๋ฆฌ ๊ณต์์ ์๋ณ์ ์ ๊ณฑํฉ๋๋ค. 3์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ์ป์ผ๋ ค๋ฉด, ์๋ณ์ 3์ ๊ณฑํฉ๋๋ค. ๊ทธ ์ด์์ ์ฐจ์์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ์๋ณ์ ์ ๊ณฑํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ๊ฒ๋๋ค.
1^2 = (t + (1 - t))^2 1 = t^2 + 2*t*(1-t) + (1-t)*(1-t)
You'll notice that a lot of this I didn't simplify, that's because it's easier to understand and code if you leave it this way.
Ok, now we have our 3 functions, which we derived from our basis. But where you ask. Well, right in front of you! Our functions are each of the terms to the right side of the equation. We'll call our functions Bx(t). It should be noted that the code is in bold.
#define B1(t) (t*t) #define B2(t) (2*t*(1-t)) #define B3(t) ((1-t)*(1-t))
2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ธ ๊ฒฝ์ฐ์๋ ์ 3๊ฐ์ ๊ณต์๋ง ์๊ณ ์์ผ๋ฉด ๋ฉ๋๋ค.
์ฐธ๊ณ ๋ก 3์ฐจ(cubic) ๊ณก์ ์ธ ๊ฒฝ์ฐ๋ ์๋์ ๊ฐ์ต๋๋ค.
B1(t) = t * t * t B2(t) = 3 * t * t * (1 - t) B3(t) = 3 * t * (1 - t) * (1 - t) B4(t) = (1 - t) * (1 - t) * (1 - t)
4์ฐจ(quartic) ๊ณก์ ์ธ ๊ฒฝ์ฐ์
๋๋ค.
B1(t) = t * t * t * t B2(t) = 4 * t * t * t * (1 - t) B3(t) = 6 * t * t * (1 - t) * (1 - t) B4(t) = 4 * t * (1 - x) * (1 - t) * (1 - t) B5(t) = (1 - t) * (1 - t) * (1 - t) * (1 - t)
์ด๋ ๊ฒ ๋ถํดํด๋์ ๊ณต์๋ง์์ผ๋ฉด ์ํ๊ณต์์ ๋ฆฌ๋ฅผ ํ์ง ์์๋ ๋ฉ๋๋ค! ์ด์ ๋ฒ ์ง์ด ๊ณก์ ๋ค์ ์จ์ ๊ฐ๋จํ ์ํ์ ๊ฑด๋๋ฐ์์ต๋๋ค. ์ด๋ค์ ๊ฐ์ง๊ณ ํ๋ก๊ทธ๋จ์ ๋
ผํ๋๋ก ํ์ฃ !
๋ฒ ์ง์ด ๊ณก์ ์ ์ฌ์ฉํ์ฌ ํ๋ก๊ทธ๋๋ฐํ๊ธฐ #
์, ์ด์ ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ ๊ณต์๋ค์ ์ป์์ต๋๋ค. ์ด์ ์ด๋ค์ ์ ๋นํ๊ฒ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
I think that now would be a really good time to mention that along with these functions, you should also have 3 control points, which we'll call Cx. You can save these control points in a structure that looks like this:
typedef struct sCPoint
{
int x;
int y;
} C_POINT;
์ฃผ์ : ์ฌ๊ธฐ์๋ 2D์์์ ๋ฒ ์ง์ด ๊ณก์ ์ ๋
ผํ ๊ฒ์
๋๋ค๋ง, 3D๋ฅผ ๊ตฌํํ๊ณ ์ ํ๋ค๋ฉด ์ด ๊ตฌ์กฐ์ฒด์ z ์์๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
๋ฌผ๋ก ์ด๋ฌํ ์ ์ด์ ์ด 3๊ฐ๊ฐ ํ์ํ๋ฏ๋ก, ๋ฐฐ์ด์ ์ ์ธํ๋๋ก ํ๊ฒ ์ต๋๋ค.
C_POINT controlP[3];
์ด์ ํ๋ฉด์ ๋ฒ ์ง์ด ๊ณก์ ์ ์ค์ ๋ก ๊ทธ๋ฆฌ๋ ๋จ๊ณ์ ์์์ต๋๋ค. Right now, our curve is only imaginary, and only exists as math equations. ํด์ผํ ์ผ์ด๋ผ๋ฉด, ์ป์ด๋ธ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ณก์ ์ ๋ฐ๋ผ ์งํํ๊ณ , ๋ง๋ค์ด์ง ๊ณก์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ ์ ์ฐ์ผ๋ฉด ํ๋ฉด์ ๊ณก์ ์ด ๋ํ๋ ๊ฒ๋๋ค.
Which brings us to the last thing that I want to talk about; Detail Biases. Basically what a detail bias is, is a number that tells us how far we want to move along our curve each time we want to put a pixel along it's path. Detail biases are always decimals, and are most easily thought of as percentages. A detail bias of 0.5 would say "Ok, start at the beginning of our curve, put a point there, move 50% along our curve and put a point there, then move 50% more and put a point there (at the end of our curve).", this would put a point at the start of our curve, in the exact middle, and at the very end. We would need a counter to keep track of how much of the curve we've rendered, and we would increase this counter by 0.5 each time we put a point until it reaches 1, at which point we would stop. The smaller your detail bias, the more points you'll have on your curve, and the more solid it will look. Ok, without further adieu, the code to render a quadratic bézier spline. It should be noted that the macros Bx() where already defined up top, as were the controlP structures.
//์ฃผ์: ๊ฐ๊ฐ์ controlP๋ ์ด๋ฏธ x, y์ขํ๋ก ์ฑ์์ ธ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
double count; // ์นด์ดํฐ ์์๋ณ์
double detailBias; //๊ณก์ ์์ ์ผ๋ง๋ ๋ง์ ์ ๋ค์ ์ฐ์ ๊ฒ์ธ๊ฐ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค
double x,y; //์ฝ๋์ ๊ฐ๋
์ฑ์ ๋์ด๊ธฐ์ํ ๋ณ์
detailBias = 1 / 50; //๊ณก์ ์ 51๊ฐ์ ์ ์ ์ฐ์ต๋๋ค(0.02 ์ ๋ฐ๋)
do
{
x = controlP[0].x*B1(count) + controlP[1].x*B2(count) + controlP.x[2]*B2(count);
y = controlP[0]*B1.y(count) + controlP[1].y*B2(count) + controlP.y[2]*B2(count);
PutPixel(x,y,RGB(255,255,255));
count += detailBias;
}while( count <= 1);
Notice how we get our x and y values. We multiply each control point by the coresponding basis function (B1 with control point 1, B2 with control point 2, etc.), and add them all together. We do this for both the x and y coordinates, and if we're working in the third dimension, the z coordinate as well.
์ด๋ค ๊ณก์ ๋ค ์ธ๋ถ์ ๋ฉด์ ์์ฑํ๊ธฐ #
I'm just going to scratch the surface (pun intended) of how to make curved surfaces out of Bézier curves, because this subject is big enough to fit in an article by it's self, and is beyond the scope of this article. I will only discuss quadratic bézier patches, and I will supply no code for you to look at. I will tell you how to generate points from this surface, which you can then turn into triangles or quads quite easliy.
This image is the basic idea of how a patch, made out of quadratic bézier splines, would look like. It would have 9 control points, and you can think of the surfaces x-axis running along 7,8, and 9. The y would run along 7,4, and 1. To make things simple, we'll say that the detail bias will be 0.25, which we know will generate 5 points along a spline ((1/deatil bias) + 1), but since this is a surface, it will generate 5*5 points, which is 25 points in total. It's nice to think of these points in terms of x and y, so our data structure to hold these data points will be an array that looks like this:
C_POINT points[5][5];
We will also be deriving other control points as we go along, from points on other splines. I'll walk you now, step by step, the process of generating points from this surface. This is probably the most confusing part of this article, and you don't need to know this to get the basic Bézier spline working. It should be noted that when I say evaluate a spline, I mean take it's control points and create points with our equations and our detail bias, which is always 0.25. Ok here we go.
- Use points 1,4, and 7 and evaluate them.
- Derive 3 new control points by evaluating and taking the first point generated by spline 7,8,9, this will be our first control point, we'll call it f1. Do the same with 4,5,6, which will be f2, and 1,2,3 will be f3.
- Evaluate spline f1, f2, and f3, and generate points from this spline.
- Do the same as 2, except f1, f2, and f3 will now be the second point generated by 7-8-9, 4-5-6, and 1-2-3 respectfully.
- Do steps three and four over and over (just make sure that instead of the second point, it's the third, then the fourth etc.) until you fill up our array.
๊ฒฐ๋ก #
I hope that this article gave you a good understanding of what bézier splines are and how you can use them in your games and demos. I also hope that I took out some of the mystery of what these things can do for you. Before I go, I would like to leave you with a few pro's and con's about Bézier splines and curved surfaces.
์ฅ์ #
๊ณก๋ฉด์ ๋๋๋ง๋๋ ํด๋ฆฌ๊ณค์ ์์ ์ค์ด๊ธฐ์ํด LOD ๊ธฐ์ ์ ์ฌ์ฉํ๋ ์์ง์ ํ๋ฅญํ ์ ๋์จ์ด ๋ ์ ์์ต๋๋ค. It's easy to bump these surfaces down to only 4 polygons (for quadratics), and you can do this quite easily (by changing the detail bias). It's also easier to make smooth surfaces, and more organic looking environments with curved surfaces. ๋ํ ์์ง์ด๋ ์นด๋ฉ๋ผ ๊ธฐ๋ฅ์ ์ง์ํ ๊ณํ์ด๋ผ๋ฉด, ๋ฒ ์ง์ด ๊ณก์ ์ ์นด๋ฉ๋ผ ๊ฒฝ๋ก, ์ ๋๋ฉ์ด์
๊ฒฝ๋ก๋ฅผ ๋ถ๋๋ฝ๊ฒ ๋ง๋๋๋ฐ ํ์์ ์ธ ์์์
๋๋ค.
๋จ์ #
๊ณก๋ฉด์ ์ฌ์ฉํ๋ ๋๋ถ๋ถ์ ์์ง๋ค์ด ๊ณ ํต๋ฐ๋ ๋จ ํ๊ฐ์ง ํต์ฌ ๋จ์ ์ tesselate์์
(ํด๋ฆฌ๊ณค์ผ๋ก ๋ณํํ๊ธฐ)์ ํ๋๋ฐ ์๊ฐ์ด ์ค๋๊ฑธ๋ฆฐ๋ค๋ ์ ์
๋๋ค. ์ด๊ฒ์ ๋ก๋ฉ๋ ์ฒ๋ฆฌํ๋ค๋ฉด ํฌ๊ฒ ์ฐจ์ด๋ฅผ ๋๋ ์ ์๊ฒ ์ง๋ง, ํ๋ ์๋น ์ค์๊ฐ์ผ๋ก ์ด ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ฉด ์๋ง๋ ์์ฒญ๋ ์ฑ๋ฅ์์ ๋ถํ๋ผ๋ ๊ฒ์ ์ ์ ์์ ๊ฒ๋๋ค. That's about the only major beef that most engine developers have with curved surfaces.








