C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[905] 각 점을 지나는 곡선 그리기 (Catmull-Rom Spline)
Starlet [starlet5] 20446 읽음    2009-07-13 03:26
ss.JPG 14.1KB 실행화면
안녕하세요.
4-5개의 Point를 지정하면 그 점을 지나는 부드러운 곡선이 필요해서 검색을 좀 해봤습니다. Catmull-Rom Spline이 제가 원하는 결과에 가장 근접해서 여기저기 정보를 참고해서 만들어 봤습니다. 이게 베이지어 곡선과 다른 점은 베이지어 곡선은 중간중간의 Point를 지나지 않는 근접한 곡선을 그리지만 Catmull-Rom은 Point를 모두 지나도록 되어 있습니다.(스샷 참고)
게임에서는 AI 케릭터가 이동 경로를 부드럽게 움직이도록 하는데 사용한다는군요. 이동 경로를 몇군데 지정하면 직선으로 달리다가 휙 꺽어서 또 직선으로 달리는게 아니라 자연스럽게 움직이도록...
DirectX에 있는 API나 몇몇 공개된 소스들은 4개의 Point값만을 입력받을 수 있게 되어있고 4개 이상의 Point를 사용하려면 두번째 세번째 Point를 계속해서 연결시켜줘야 하는데 그 부분도 같이 구현했습니다. 필요하신 분이 있을지 모르겠지만 제가 찾는데 애 좀 먹어서 공유하고자 올립니다.
(코드 대부분을 참고한 사이트가 있는데 다시 찾으니 보이지 않는군요...)

TPoint tangent(TPoint p1, TPoint p2)
{
        return TPoint((p1.x - p2.x) / 2, (p1.y - p2.y) / 2);
}

void Curve(TCanvas *Canvas, TPoint *p, int num, float rez)
{
        int px = 0, py = 0, n=0;
        float tt, _1_t, _2t, h00, h10, h01, h11;
        TPoint m0;
        TPoint m1;
        TPoint m2;
        TPoint m3;

Canvas->Brush->Color = clRed;
        for (n=0; nFillRect(TRect(p[n].x-2, p[n].y-2, p[n].x+2, p[n].y+2));
                for (float t=0; t<1; t+=rez)
                {
                        tt = t * t;
                        _1_t = 1 - t;
                        _2t = 2 * t;
                        h00 =  (1 + _2t) * (_1_t) * (_1_t);
                        h10 =  t  * (_1_t) * (_1_t);
                        h01 =  tt * (3 - _2t);
                        h11 =  tt * (t - 1);

                        if (!n)
                        {
                                m0 = tangent(p[n+1], p[n]);
                                m1 = tangent(p[n+2], p[n]);
                                px = h00 * p[n].x + h10 * m0.x + h01 * p[n+1].x + h11 * m1.x;
                                py = h00 * p[n].y + h10 * m0.y + h01 * p[n+1].y + h11 * m1.y;
                                Canvas->Pixels[px][py] = clBlack;
                        }
                        else if (n < num-2)
                        {
                                m1 = tangent(p[n+1], p[n-1]);
                                m2 = tangent(p[n+2], p[n]);
                                px = h00 * p[n].x + h10 * m1.x + h01 * p[n+1].x + h11 * m2.x;
                                py = h00 * p[n].y + h10 * m1.y + h01 * p[n+1].y + h11 * m2.y;
                                Canvas->Pixels[px][py] = clBlack;
                        }
                        else if (n == num-1)
                        {
                                m2 = tangent(p[n], p[n-2]);
                                m3 = tangent(p[n], p[n-1]);
                                px = h00 * p[n-1].x + h10 * m2.x + h01 * p[n].x + h11 * m3.x;
                                py = h00 * p[n-1].y + h10 * m2.y + h01 * p[n].y + h11 * m3.y;
                                Canvas->Pixels[px][py] = clBlack;
                        }
                }
        }
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        TPoint p[7] = {TPoint(100,100), TPoint(120,180), TPoint(220,180), TPoint(250,250), TPoint(300,150), TPoint(350,200), TPoint(400,100)};

        Curve(Form1->Canvas, p, 7, 0.005);
}


곡선을 그리는 함수입니다.
void Curve(TCanvas *Canvas, TPoint *p, int num, float rez)

p에는 TPoint 배열을, num에 Point 갯수를 넣으면 됩니다. rez값으로 두 점 사이에 몇개의 점을 찍느냐가 결정되는데 작을수록 더 많은 점이 찍힙니다.(rez = 0~1 사이의 값)


(이상하게 코드 일부가 깨져 보이는 군요... cpp 파일도 첨부합니다.)
장성호 [nasilso]   2009-07-13 12:16 X
아.. 좋네요.
옛날에 보간법이 필요한 프로젝트를 한적이 있었는데.. 그때 "Catmull-Rom Spline"라는게 있는줄 몰랐는데..
"Catmull-Rom Spline"을 썼으면 더 좋았을듯 하네요.
김태선 [cppbuilder]   2009-07-15 16:47 X
멋지네요 ^^;
공도리 [sun2674]   2017-01-25 21:12 X
헤더파일은 어떻게 만드셧는지 궁금합니다.

+ -

관련 글 리스트
905 각 점을 지나는 곡선 그리기 (Catmull-Rom Spline) Starlet 20446 2009/07/13
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.