반응형

http://blog.naver.com/astone94/90101243937



에르미트(Hermite)[1]곡선과 베지에(Bezier)[2]곡선은3차 곡선의 두 예입니다이들은 네가지 매개변수에 의하여 정의됩니다에르미트 곡선은 두 끝점과 이 점에서의 탄젠트 벡터(tangent vectors)로 정의됩니다베지에 곡선은4개의 점으로 정의됩니다이 둘은 수학적으로 다르지만 그 둘의 특징과 한계는 매우 유사합니다



[1]더 많은 정보를 위해서는 http://en.wikipedia.org/wiki/Cubic_Hermite_spline를 참조하세요.

[2]더 많은 정보를 위해서는 http://en.wikipedia.org/wiki/B%C3%A9zier_curve를 참조하세요.

대부분의 경우곡선은 여러가지 요소들에 의하여 만들어집니다이 요소들은 구간적3차 곡선(piecewise Bezier curve)을 만들기 위해서 필요합니다아래는 구간적 베지에 곡선의 예로  10개의 점(storage point)을 이용하여3개의 구간을 가진 곡선(a three-segment curve)를 나타낸 것입니다.이 곡선들이 아래 그림과 같이 연결(join)되어도 이것이 부드럽게 연결되지는 않습니다.

에르미트 곡선이 베지어 곡선과 같은4개의 매개변수를 사용한다고 하여도탄젠트라는 추가적인 방향 정보를 가지고 있습니다에르미트 곡선들을 연결할 때 이러한 방향정보를 이용하여 각 끝점의 방향을 일치키시면 적은 용량으로도 더욱 부드러운 곡선을 표현할 수 있습니다.

[1]더 많은 정보를 위해서는 http://en.wikipedia.org/wiki/B%C3%A9zier_curve를 참조하세요.

더욱 부드럽고 연속적인 곡선을 표현하기 위해 찾아진 방식 중 가장 강력한 것으로, Non Uniform Rational B-Spline[1](NURBS)가 있습니다곡선 조각들은 적은 정보량으로 더욱 부드러운 곡선을 포현하기 위해 더 많은 컨트롤 포인트를 공유하게 됩니다.


NURBS 곡선과 곡면(surface)들은Rhinoceros에서 기하체를 표현하기 위해 사용됩니다. NURBS곡선들의 특징과 요소들은 이 챕터의 뒷 부분을 통해 더욱 자세하게 다뤄질 것입니다.

3차 곡선의 매개변수 방정식은 다음과 같습니다일반적인 모델링 작업에서 이러한 공식을 사용할 가능성은 거의 없지만이것을 참고적으로 이해하는 것은 도움이 될 것입니다.

3차 곡선의 매개변수 방정식은 다음과 같습니다.

이를 아래와 같이 바꿔 쓸 수 있습니다.

x(t) = ax3+ bx2+ cx+ dx

y(t) = ay + by2+ cy+ dy

z(t) = az3+ bz2+ cz+ dz

Q(t방정식은 아래와 같이 써질 수 있습니다.

Q(t) = CT

T가 다음과 같고.

C가 계수 행렬(the matrix of coefficients)이라고 한다면

 

[1]더 많은 정보를 위해서는 http://en.wikipedia.org/wiki/Non-uniform_rational_B-spline를 참조하세요.

행렬의 곱을 이용한 곡선 방정식은 다음과 같습니다.

 

반응형
반응형

ttp://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves





 
 


반응형
반응형

브레슨햄 동영상 강의

http://forum.falinux.com/zbxe/?document_srl=406146









http://blog.naver.com/nowcome/130019875263


#include <iostream>
using namespace std;

#define max( x, y) (((x) > (y)) ? (x) : (y)) // 큰수 찾는거 당연히 아시겠줘? 

#define abs( x ) (((x) > 0) ? (x) : -(x)) // 절대값. 

#define sign( x ) ((x) > 0 ? 1 : ((x) == 0 ? 0: (-1))) // 양수:1, 0, 음:-1 

#define WIDTH   30
#define HEIGHT  25


char array[HEIGHT][WIDTH]={{'\0',},};

void show(){

 for (int j=0;j<HEIGHT;++j)
 {
  for (int i=0;i<WIDTH;++i)
  {
   cout<<array[j][i]<<" ";
  }
  cout<<"\n";
 }
 

}

void initial(){
 for (int j=0;j<HEIGHT;++j)
 {
  for (int i=0;i<WIDTH;++i)
  {
   array[j][i]=' ';
  }
 }
}

void drawPoint(int x,int y){

 array[y][x]='*';

}

void line(int x1,int y1,int x2,int y2){

 int x,y;
 int dx = x2 - x1;  
 int dy = y2 - y1;  
 int ix = abs(dx);  
 int iy = abs(dy);  
 int inc = max(ix, iy);  
 int plotx = x1;  
 int ploty = y1; 

 x = y = 0;  
 for(int  I = 0; I <= inc ; I++)  
 {  
  x += ix;  
  y += iy;  
  if( x > inc)  
  {  
   x -= inc;  
   plotx += sign(dx);  
  }  
  if( y > inc )  
  {  
   y -= inc;  
   ploty += sign(dy);  
  }  
  drawPoint(plotx, ploty);
  //그리는 함수 ( plotx, ploty); 

 }
}

int main(){

 initial();

 //line( 0,0,10,10 );

 show();


 return 0;
}



http://withwani.springnote.com/pages/159993

브레슨햄 알고리즘


컴퓨터 화면에 선을 빠르게 그리는 방법 중에 하나가 브레슨햄(Bresenhan) 알고리듬이 있습니다. 실수 나누셈을 사용하는 직선 공식보다 정수 계산만을 하는 브레슽핸 알고리듬이 매우 빠르죠.

이번에 임데디드 포럼에 그래픽 관련 문서를 만들면서 브레슨햄 선긋기 알고리듬을 정리해 보았습니다. 포럼에는 동영상까지 올렸으므로 관심있는 분은 방문해 보시기 바랍니다.

브레슨햄(Bresenham)알고리듬

직선의 공식을 사용하여 머릿 속으로 그래프를 그려 보면, 무수히 많은 점을 생각할 수 있읍니다만, 컴퓨터 그래픽에서는 스크린 좌표가 모두 정수이므로, 복잡하고 계산을 느리게 만드는 실수 계산을 정수 계산 만으로도 구현할 수 없을까하는 생각에서 만들어진 것이 브레슨햄 알고리듬입니다.

 

직선의 공식을 이용하여 계산된 좌료값이 소주점 이하 몇개의 자리로 된 실수값을 어렵게 구했다고 하더라도 컴퓨터화면에 출력할 때에는 소수점이하를 모두 버림한단든지 반올림해서 정수로 만들게 됩니다. 이렇게 버려지는 소수점 이하의 복잡한 계산을 브레슨햄 공식을 이용하여 없애 보도록 하겠습니다.

*** 이하의 설명은 dx 가 dy 보다 큰 경우일 때 입니다. ***

사용자 삽입 이미지

 

 

컴퓨터 화면에 직선을 긋기위해 이미 (xi, yi) 좌표에 점을 찍었습니다. 브레슨햄의 기본 원리는 선의 공식에 따라 다음 좌표값을 구하는 것이 아니라 현재 점의 위치에 대해서 어느 좌표에 다음 점을 찍을 지를 판단하는 알고리듬입니다.

 

그림에서 (xi,yi)의 다음 점의 위치는 녹색점(xi+1, yi+1) 보다는 빨강색점(xi+1, yi) 가 실제 점에 가깝습니다. 그렇다면 여기서 녹색점과 빨강색점에 대해 실제 직선의 위치와의 차이 d1, d2를 구해 보겠습니다.

 

d1, d2를 구하는 이유는, d1 < d2 라면 실제 y 점이 yi에 가깝다는 얘기가 되고, yi 에 점을 찍으면 됩니다. 반대로 d1 > d2 라면 yi+1에 점을 찍으면 되기 때문입니다.

 

 

 

즉, 0 < d1-d2 이면 yi+1 에, 0 > d1-d2 이면 yi 에 점을 찍으면되므로 (1) d1 과 d2의 차, 특히 (2) 차이값이 양수인지, 음수인지를 구하면 되겠습니다.

 

사용자 삽입 이미지



d1 = y -yi

여기서 y=m(xi+1) +b 이므로,

d1 = m(xi+1) +b -yi

d2 는,

 

d2 = (yi+1) -y
   = yi +1 -( m(xi+1)+b)
   = yi -m(xi +1) -b +1

두 거리의 차이를 구해 보겠습니다.

 

d1 - d2 = m(xi+1) +b -yi -(yi -m(xi +1) -b +1)
        = m(xi+1) +b -yi -yi +m(xi+1) +b -1
        = 2 m(xi+1) -2yi +2b -1

 

m 은 기울기를 dy/dx 이므로,

 

  d1 - d2 = 2(dy/dx)(xi+1) -2yi +2b -1

 

여기서 다음 점을 찾기 위해서는 두 거리의 차이가 궁굼한 것이 아니라 두 차이에 대한 부호, 즉 양수인지 음수인지만이 필요하므로 정수 나눗셈이 있는 부분을 양편에 dx를 곱해서 없애겠습니다.

 

dx(d1-d2) = 2dy(xi+1) -2dxyi +2dxb -dx
          = 2dyxi +2dy -2dxyi +2dxb -dx

다시 이 공식에서 변수 부분인 xi 또는 yi 가 들어간 부분과 한번 계산되면 다시 계사할 필요가 없는 부분으로 정리해 보겠습니다. 그리고 부호값 만을 생각할 수 있는 변수 pi 로 정리해 보겠습니다.

 

dx(d1 - d2) = pi = 2dyxi +2dy -2dxyi +2dxb -dx
            = 2dyxi -2dxyi +2dy +2dxb -dx
            = 2dyxi -2dxyi +2dy +dx(2b -1)

상수부분인 2dy +dx(2b-1)를 C 로 대치하면,

 

pi = 2dyxi -2dxyi +C   <--- 공식 1

가 됩니다.

 

우리가 이 알고리듬을 이용해서 선을 긋게 되면, 루프를 이용하게 될 것이고, 이전에 계산된 pi 값을 이번 계산에 대입하고 적용할 수 있습니다.

그러므로 다음 pi 값인 pi+1 값을 아래와 같이 구할 수 있습니다.

 

pi+1 = 2dyxi+1 -2dxyi+1 +C

이전 p 값을 계속 참조하여 계산 하므로 pi 와 pi+1 값의 차를 구하겠습니다.

 

pi+1 - pi= 2dyxi+1 -2dxyi+1 +C - 2dyxi +2dxyi -C
        = 2dy(xi+1-xi) - 2dx(yi+1-yi)

여기서 xi+1 와 xi는 서로 이웃하는 점이므로 xi+1 - xi는 1입니다.

그러므로 아래와 같이 정리할 수 있습니다.

 

pi+1 - pi= 2dy - 2dx(yi+1-yi)

이제 pi+1 값만 구한다면,

pi+1 = pi + 2dy - 2dx(yi+1-yi)

아직까지 복잡하게 보이지만 역시 스크린 좌표는 정수이고 yi+1와 yi 의 차이가 0 또는 1이라는 점을 상기한다면,

  • 계산된 pi 값이 양수라면 d1이 더 크므로 다음 점은 현재의 yi 보다 1 만큼 크게되므로,

    pi+1 = pi + 2dy - 2dx

    가 되며,
  • pi 값이 음수라면 d1이 더 작으므로 yi 값과 같아지므로 yi+1 - yi 는 0이 되므로,

    pi+1 = pi + 2dy

    값이 됩니다.
사용자 삽입 이미지





여기서 계산된 pi+1은 다음 루프의 pi 값이 되므로 이를 루프에서 계속 계산되고 다음 계산에 대입된다면 처음 p0 값을 구하고 점을 찍고 다음 pi 값으로 대입하면서 점 위치를 찾아 점을 찍으면 됩니다.

 

p0 구하기

p0값을 구하기 위해 공식 1 에 처음 좌표 (x1, y1)을 대입하고, 다음 예상 좌표를 (x1+1, y1+1/2)로 생각하고 p0을 구합니다..

 

p(x1, y1) = 2dyx1 -2dxy1 +C

p(x1+1, y1+1/2)= 2dy(xi+1) -2dx(yi+1/2) +C

p0  = p(x1+1, y1+1/2) - p(x1, y1)
    = 2dy(xi+1) -2dx(yi+1/2) +C - ( 2dyx1 -2dxy1 +C)
    = 2dyx1 +2dy -2dxy1 -dx -2dyx1 +2dxy1 +C -C
    = 2dy(x1-x1) +2dy -2dx(y1-y1) -dx
    = 2dy -dx

p0 을 구하기 위해 x1 의 다음 좌표는 당연히 1 을 증가한 x1+1 이 되겠지만 , y1 축의 값은 y1 이 될지 y1+1이 될지 모르므로 확률 상의 경우를 1/2로 보고 계산한 것입니다.

 

선을 긋기 전에 필요한 상수 값

  • 최초의 p0 을 구합니다.
  • pi 의 부호 값에 따라 아래의 2가지 값이 필요합니다.
    • 2(dy -dx)
    • 2dy

이후 선을 긋는 루프에서

  • 계산된 p 값이 양수이면,
    • y 좌표값을 1 증가하고,
    • p 값에 2(dy-dx) 값을 더합니다.
  • 음수 이면,
    • p 값에 2dy 만 더합니다.
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>        // abs
          
          #include <unistd.h>        // open/close
          #include <fcntl.h>         // O_RDWR
          #include <sys/ioctl.h>     // ioctl
          #include <sys/mman.h>      // mmap PROT_
          #include <linux/fb.h>
          
          int   screen_width;
          int   screen_height;
          unsigned short *fb_mapped;
          
                                   
          void  dot( int x, int y)
          {
             unsigned short *ptr;
          
             ptr   = fb_mapped + screen_width * y + x;
             *ptr  = 0xffff;
          }
          
          void  line( int x1, int y1, int x2, int y2)
          {        
             int      dx, dy;
             int      p_value;
             int      inc_2dy;
             int      inc_2dydx;
             int      inc_value;
             int      ndx;
                             
             dx       = abs( x2 -x1);
             dy       = abs( y2 -y1);
             
             
             if ( dy <= dx)
             {
                inc_2dy     = 2 * dy;
                inc_2dydx   = 2 * ( dy - dx);
                
                if ( x2 < x1)
                {
                   ndx   = x1;
                   x1    = x2;
                   x2    = ndx;
                   
                   ndx   = y1;
                   y1    = y2;
                   y2    = ndx;
                }
                if ( y1 < y2)  inc_value   = 1;
                else           inc_value   = -1;
                   
                dot( x1, y1);
                p_value  = 2 * dy - dx;    
                for (ndx = x1; ndx < x2; ndx++)
                {
                   if ( 0 > p_value)    p_value  += inc_2dy;
                   else
                   {
                      p_value  += inc_2dydx;
                      y1       += inc_value;
                   }
                   dot( ndx, y1);
                }
             }
             else
             {
                inc_2dy     = 2 * dx;
                inc_2dydx   = 2 * ( dx - dy);
                
                if ( y2 < y1)
                {
                   ndx   = y1;
                   y1    = y2;
                   y2    = ndx;
                   
                   ndx   = x1;
                   x1    = x2;
                   x2    = ndx;
                }
                if ( x1 < x2)  inc_value   = 1;
                else           inc_value   = -1;
                   
                dot( x1, y1);
                p_value  = 2 * dx - dy;    
                for (ndx = y1; ndx < y2; ndx++)
                {
                   if ( 0 > p_value)    p_value  += inc_2dy;
                   else
                   {
                      p_value  += inc_2dydx;
                      x1       += inc_value;
                   }
                   dot( x1, ndx);
                }
                
             }
             
          }  
          
          
          int   main( int argc, char **argv)
          {
             int      fb_fd;
             struct   fb_var_screeninfo  fbvar;
             struct   fb_fix_screeninfo  fbfix;
             int      bytes_per_line;
             int      mem_size;
          
             if ( access( "/dev/fb", F_OK))
             {
                printf( "프레임 버퍼 장치가 없습니다.\n");
                return 0;
             }
          
             if ( 0 > ( fb_fd = open( "/dev/fb", O_RDWR)))
             {
                printf( "프레임 버퍼에 접근할 수 없습니다.\n");
                return 0;
          
             }
          
             if ( ioctl( fb_fd, FBIOGET_VSCREENINFO, &fbvar))
             {
                printf( "FBIOGET_VSCREENINFO를 실행하지 못했습니다.\n");
                return 0;
             }
             if ( ioctl( fb_fd, FBIOGET_FSCREENINFO, &fbfix))
             {
                printf( "FBIOGET_FSCREENINFO 실행하지 못했습니다.\n");
                return 0;
             }
          
             screen_width   = fbvar.xres;                    // 스크린의 픽셀 폭
             screen_height  = fbvar.yres;                    // 스크린의 픽셀 높이
             bytes_per_line = fbfix.line_length;             // 한개 라인 당 바이트 개수
          
             mem_size       = bytes_per_line * screen_height;
          
             fb_mapped      = ( unsigned short *)mmap( 0,
                                                    mem_size,
                                                    PROT_READ|PROT_WRITE,
                                                    MAP_SHARED,
                                                    fb_fd,
                                                    0);
          
             
             if ( 5 != argc)
             {
                printf( "사용방법: $]./sample x1 y1 x2 y2 \n");
             }
             else
             {
                line( atoi( argv[1]), atoi( argv[2]), atoi( argv[3]), atoi(argv[4]));
             }
          
             munmap( fb_mapped, mem_size);
             close( fb_fd);
          
             return 0;
          }
          

void bs_BresenhamLine(vector2i s, vector2i e, CImage* img, COLORREF color)
{
 vector2i vStart = s;
 vector2i vEnd = e;
 int dx = vEnd.x-vStart.x;
 int dy = vEnd.y-vStart.y;
 int stepx = 1;
 int stepy = 1;
 if(dx<0)
 {
  dx = -dx;
  stepx = -1;
 }

 if(dy<0)
 {
  dy = -dy;
  stepy = -1;
 }

 int x = vStart.x;
 int y = vStart.y;

 int eps = 0;

 if(dx>dy)
 {
  do 
  {
   //m_vLinelist[m_nLineSize++] = vector2f((float)x,(float)y);
   img->SetPixel(x,y,color);
   if(dx==0)
    break;
   if((eps+=dy) << 1 >= dx)
   {
    y += stepy;
    eps -= dx;
   }
  } while((x+=stepx)!=vEnd.x);
 }
 else
 {
  do
  {
   //m_vLinelist[m_nLineSize++] = vector2f((float)x,(float)y);
   img->SetPixel(x,y,color);
   if(dy==0)
    break;
   if((eps+=dx) << 1 >= dy)
   {
    x += stepx;
    eps -= dy;
   }
  } while((y+=stepy)!=vEnd.y);
 }
}

 
 



브레슨햄 알고리즘  프로그래밍이야기 

2007/03/26 11:08

복사http://blog.naver.com/bbosasi8/110015833947



Bresenham Algorithm 

간단히 말해 선그리는 알고리즘이다. 

(Side Note. 1965년에 발표됐단다 ㅡㅡ; 짱오래뎄네...) 

그냥... 

y = mx + b 
(m은 기울기 y/x, b는 y축을 통과하는 점) 

이렇게 for로 x쭉 돌리면 나온다. 

근데 문제는 기울기에 나누기 and x곱하기 게다가 실수 ㅡㅡ; 

느릴것이 자명하다. 

그래서 나온것이 이 알고리즘이다. 

(브레젠햄, 브레슨햄, 브렌센햄 뭐 다양하게 불리는데 별로 관심없고...) 

간단한 pseudo code로 표현해보자면. 

1. 에러항(error term) 변수를 하나 만들어 0을 집어 넣는다. 

    int errterm = 0; 

2. x와 y의 길이값을 가져온다. 
    int delta_x = x2-x1; // 단, x2>=x1 
    int delta_y = y2-y1; // 단, y2>=y1 

3. delta_x의 절반값을 들고있는다. 
    int half_x = delta_x/2; // 소수점이하는 버린다. 

4. x에 대해 x++씩 루프를 돌리면서 ... 
    y길이를 에러항에 더해주고... 
    에러항이 half_x보다 크다면 y++시켜준다. 

        for( ;x1<=x2;x1++) 
        { 
                errterm += delta_y; 
                 
                if ( errterm > halfx ) 
                { 
                        errterm -= delta_x; 
                        y1++; 
                } 
        } 

나누기, 곱하기~ 이놈들을 없앴다. ^^ 

으흐흐... 

어디선가 긁은 더 깔끔한한 코드 

#define max( x, y) (((x) > (y)) ? (x) : (y)) // 큰수 찾는거 당연히 아시겠줘?  
 
#define abs( x ) (((x) > 0) ? -(x) : (x)) // 절대값.  
 
#define sign( x ) ((x) > 0 ? 1 : ((x) == 0 ? 0: (-1))) // 양수:1, 0, 음:-1  
 
 
두점 ( x, y ) (x2, y2)  
 
dx = x2 - x1;  
 
dy = y2 - y1;  
 
 
ix = abs(dx);  
 
iy = abs(dy);  
 
inc = max(ix, iy);  
 
 
plotx = x1;  
 
ploty = y1;  
 
x = y = 0;  
 
 
for( I = 0; I <= inc ; I++)  
 
{  
 
x += ix;  
 
y += iy;  
 
 
if( x > inc)  
 
{  
 
x -= inc;  
 
plotx += sign(dx);  
 
}  
 
if( y > inc )  
 
{  
 
y -= inc;  
 
ploty += sign(dy);  
 
}  
 
그리는 함수 ( plotx, ploty);  
 

반응형
반응형

복사http://jmpabu.blog.me/70069397777


프로그래밍에 있어서는 기하는

사실적으로 쉬운 부분이다.

그러나 대부분(?)의 인간들은 기하에 대한 문제를

어렵게 생각한다. 물론 나도 마찬가지이다.

기하는 여러 경우로 나눠서 생각해보아야 하기 때문이다.

그러면 우선적으로 기본부터 알고가자.

 

========== 다각현의 면적 ===========

수올을 한다면 대부분은 알고있을 것이다.

다각형의 각 꼭지점의 좌표가 시계방향순으로 했을경우에

(x1,y1), (x2,y2), ... , (xn,yn)이라 하자. (-> n각형)

(혹은 반시계방향도 괜찮다. 또, 삼각형일때는 순서는 상간없다.)

면적 S는 다음과 같이 구한다.

이를 흔히 사선식이라 부른다.

증명은 알아서 해보길 바란다.

 

====== 시계 및 반시계 방향 확인 ======

어느 세 점, (x1,y1), (x2,y2) (x3,y3), 이 있다하자.

이때 이 세 점을 순서대로 이어서 선을 그을 때 이 선이

시계방향으로 돌아가는가, 반시계방향으로 돌아가는가를 아는 것 이다.

 

위의 사선식을 이용하면 쉬게 구할 수 있다.

S = 1/2 |x| 라 해보자. (이 경우에서는 n=3일 때이다.)

i) x<0 ; 이는 시계방향을 의미이다.

ii) x=0; 이는 일직선 상에 세 점이 놓여있음을 의미한다.

iii) x>0; 이는 반시계방향을 의미한다.

증명은 역시 알아서 해보길 바란다.

 

========= 선분 교차 =========

선분교차의 여부에 관한것은 내가 이 블로그에 올려놨으니 그 설명으로도 충분히 이해가 가길 바란다.

 

=========== 점의 위치 ==========

어떤 점 (x0,y0) 이 있다 해보자.

그리도 n각형의 도형 (x1,y1) ~ (xn,yn)있다 하자. (n≥3)

그럴때 (x0,y0)이 위의 도형안에 있는지,

도형 위에 있는지, 또 도형 밖에 있는지를 판별 해 보려고 한다.

 

점이 도형위에 있는지를 판별하는것은 문제가 되지 않는다.

임의의 한 변과 주어진 점으로 사선식을 돌렸을때 0이 나와야하며

점의 좌표범위가 (xi,yi), (x(i+1),y(i+1))의 내부에 위치하기만 한다면

선분위에 그 좌표가 있는셈이다. (물론 방법은 조금 달라도 된다.)

 

그럼 나머지의 경우를 알아보자.

방법은 간단하다.

(x0,y0)에서 오른쪽으로 직선을 그어보자. ((x0,y0) - (∞,y0) 연결)

그 선분과 도형과의 교점갯수를 세어봤을때

짝수이면 점은 도형 바깥에 위치하는 것이며

홀수이면 점은 도형 안쪽에 위치하게 되는 셈이다.

 

셀 때에는 그저 각 선분마다 그 반직선과 만나면 갯수를 증가시켜주면 된다.

그러나 교점을 셀 때에는 어떤 경우는 세어야 하며

어떠한 경우는 세지 말아야 하는 경우가 생기게 된다.

다음 그림을 봐보자.

 

1,3번과 같은 경우는 만나지 않은것으로,

2,4번과 같은 경우는 1번 만난것으로 체크를 해 쥐야 한다.

그러므로

위와같은 경우에서 첫줄일 경우에만 한번 체크해 주면 되겠다.

반응형
반응형

 

블로그 이미지

3DMP engines

3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc.. 


결론적으로 이것은   인 결과 즉 사원수3개의 곱으로(또는 p 가 w=0 인 벡터여도 상관없다) 나온 결과들을 

행렬로 옮겨놓은것이다






이하내용은  지금은 알수 없는 어디선가 퍼온자료



쿼터니언은 복소수의 확장으로 i, j, k 3개의 허수와 w, x, y, z 4개의 실수부로 이루어져 있다.

즉 하나의 스칼라와 3개의 벡터 ==> 4개의 구성 요소로 이루어진 복소수를 말한다.

허수 i, j, k는 i * i = -1의 성질을 가진다.

 = w + xi + yj + zk
 

= sq + vq

 

 = (sq , vq)

 

 = [ w , (x, y, z) ]

여기서 w는 스칼라 v = (x, y, z)는 벡터이다.

쿼터니언 크기  ||q|| = Norm(q) = sqrt(w+ x2 + y2 + z2)

단위 쿼터니언 성질  w+ x2 + y2 + z= 1

단위 쿼터니언은 (x, y, z)요소를 임의의 축, w요소를 회전 각도로 하여 4차원 공간에 표현 할 수 있다.

그림으로 간단하게 표현 하면 벡터 축 A를 중심으로 회전하는 θ는

 

사원수를 이용한 벡터 회전 변환

벡터 p를 사원수 q로 회전할 때 공식과 행렬에 대한 변환은 다음과 같다.

 

 =

|
|
|
|
|
|

1 - 2Y2 - 2Z2

2XY + 2ZW

2XZ - 2YW

2XY - 2ZW

1 - 2X2 - 2Z2

2YZ + 2XW

2XZ + 2YW

2YZ - 2XW

1 - 2X2 - 2Y2

|
|
|
|
|
|

 

쿼트니언을 행렬 변환하는 함수

//-----------------------------------------------------------------------------

//예전 다이렉트X 버전에 d3dmath.cpp 파일에 있는 소스이다.

//-----------------------------------------------------------------------------

VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z, FLOAT w )

{

    FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;

    FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;

    FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;

 

    mat._11 = 1 - 2 * ( yy + zz );

    mat._12 =    2 * ( xy - wz );

    mat._13 =    2 * ( xz + wy );

 

    mat._21 =    2 * ( xy + wz );

    mat._22 = 1 - 2 * ( xx + zz );

    mat._23 =    2 * ( yz - wx );

 

    mat._31 =    2 * ( xz - wy );

    mat._32 =    2 * ( yz + wx );

    mat._33 = 1 - 2 * ( xx + yy );

 

    mat._14 = mat._24 = mat._34 = 0.0f;

    mat._41 = mat._42 = mat._43 = 0.0f;

    mat._44 = 1.0f;

}

 

행열을 쿼트니언으로 변환하는 함수

VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, D3DMATRIX& mat )

{

    if( mat._11 + mat._22 + mat._33 > 0.0f )

    {

        FLOAT s = (FLOAT)sqrt( mat._11 + mat._22 + mat._33 + mat._44 );

 

        x = (mat._23-mat._32) / (2*s);

        y = (mat._31-mat._13) / (2*s);

        z = (mat._12-mat._21) / (2*s);

        w = 0.5f * s;

    }

    else

    {

 

 

    }

    FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;

    FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;

    FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;

 

    mat._11 = 1 - 2 * ( yy + zz );

    mat._12 =    2 * ( xy - wz );

    mat._13 =    2 * ( xz + wy );

 

    mat._21 =    2 * ( xy + wz );

    mat._22 = 1 - 2 * ( xx + zz );

    mat._23 =    2 * ( yz - wx );

 

    mat._31 =    2 * ( xz - wy );

    mat._32 =    2 * ( yz + wx );

    mat._33 = 1 - 2 * ( xx + yy );

 

    mat._14 = mat._24 = mat._34 = 0.0f;

    mat._41 = mat._42 = mat._43 = 0.0f;

    mat._44 = 1.0f;

}

 

 

 

반응형
반응형

블로그 이미지

3DMP engines

3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..




[평행이동 타원과 선분의 교차판정]

 

 



 

* 설명 : 두 점을 지나는 직선의 y 값을 평행이동 타원의 방정식에 대입하여 x 에 대해 정리하면

           직선과 타원의 교차되는 해를 구할 수 있으며 이 범위가 선분의 범위에 포함된다면 교차된것

           올린 글중 

 





 

 

 

 

 

반응형
반응형


첨부파일 : squ-curve.ppt






http://ko.wikipedia.org/wiki/%ED%83%80%EC%9B%90





타원

위키백과, 우리 모두의 백과사전.
두 점 F1과 F2를 초점으로 갖는 타원.
원뿔을 평면으로 잘라 얻은 타원.

타원(楕圓)이란 평면 위의 두 정점으로부터의 거리의 합이 일정한 점의 집합으로 만들어지는 곡선을 이르는 기하학 용어이다. 타원을 정의하는 기준이 되는 두 정점은 타원의 초점(focus)으로 불린다. 타원 상에서 두 개의 초점으로부터의 거리가 같은 두 점을 잇는 선분을 단축(짧은 축)이라고 하며, 두 개의 초점으로부터의 거리의 차가 최대인 두점을 잇는 선분을 타원의 장축(긴 축)이라고 한다. 또한, 이 두 선분의 반을 짧은반지름(semiminor axis), 긴반지름(semimajor axis)이라고 한다.

[편집]
두 초점이 가까울 수록 타원은
 에 가까워지며, 두개의 초점이 일치했을 때의 타원은 원이 된다. 그 때문에 원은 타원의 특수한 경우라고 생각할 수도 있다.타원의 성질

[편집]타원의 작도

위의 정의를 따르면 두 개의 초점에 실을 고정해, 실을 팽팽하게 유지하면서 필기구를 실에 걸쳐서 움직여서 그릴 수 있다. 이 외, 타원 컴퍼스, 타원 템플릿등을 사용하여 작도할 수 있다.

[편집]타원의 방정식

2차원 직교좌표계에서 원점 O가 타원의 장축과 단축의 교점이며, 각 축이 x축이나 y축과 일치할 때의 타원의 방정식은 다음과 같이 간단히 표현된다.

\frac{x^{2}}{a^{2}} + \frac{y^{2}}{b^{2}} = 1

장축이 x축과 일치할 때, 2 a는 타원의 장축의 길이, 2 b는 단축의 길이가 된다. 같은 타원을 호도각에 따른 매개변수 t로 나타내면 다음과 같다.

x = a\,\cos t
y = b\,\sin t
0 \leq t < 2\pi

x축으로 α만큼, y축으로 β만큼 평행이동한 타원의 방정식은 다음과 같다.

\frac{(x-\alpha)^{2}}{a^{2}} + \frac{(y-\beta)^{2}}{b^{2}} = 1

[편집]타원의 넓이

타원의 긴반지름이 a이고 짧은반지름이 b인 타원의 넓이는 \pi ab 이다.

[편집]이심률

 이 부분의 본문은 이심률입니다.

타원의 찌그러진 정도를 나타내는 이심률  E=\frac {e} {a} 는 다음과 같이 정의된다.

E = \sqrt{1 - \frac{b^2}{a^2}}

은 이심률이 0인 경우이고, 이심률이 작을수록 원에 가깝다.

[편집]타원의 성질

한 초점에서 출발한 빛이 진행하다가 타원의 어느 한점을 만나면 이때 빛은 페르마의 최소 시간 원리를 따르므로 타원에서 반사되고 그 후 빛은 타원의 다른 초점을 지난다.

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

쿼터니언<->행렬 변환 함수 소스  (0) 2012.11.02
[2D] 평행이동 타원과 선분의 교차판정  (0) 2012.11.02
원과 선분의 충돌  (0) 2012.11.02
[2D] 두 선분의 교차판정  (0) 2012.11.02
NDC 공간이란  (0) 2012.11.02
반응형

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

[2D] 평행이동 타원과 선분의 교차판정  (0) 2012.11.02
타원 그리기  (0) 2012.11.02
[2D] 두 선분의 교차판정  (0) 2012.11.02
NDC 공간이란  (0) 2012.11.02
베지어 곡선(Bezier Curve) 유도와 설명  (1) 2012.11.02
반응형

일본 사이트의 내용인데 구글 번역기로 번역한것
일어 번연은 그럭저럭 괜찮군... ㅋ
 
http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm
 
§ Algorithm §


☆ 더 쉽게 - 선 교차 판정 - ☆

여기에서는 선분 교차 판정의 정석이라 할 방법을 소개하고 있습니다.
선분과 직선 간과 소중한 정의입니다.

직선은 한 2 점을지나는선이고
선분은 한 2 점을연결하는선이다.

교차 판정에 대한 점 A, B, C, D, 선분 AB와 선분 CD의 교차를 생각하고 있습니다. 먼저 '선 교차 판정'의 전통적인

"교차점을 찾아 그 교차점이 2 개의 세그먼트의 범위에 있는지 조사한다"

라는 생각을 다른 해석으로 바꿉니다.
2 선이 교차하고있다는 것은

"점 A, B를 지나는 직선이 선분 CD와 교차하며
점 C, D를 지나는 직선이 선분 AB와 교차하고있다 "


로 해석할 수 있습니다. 그래서 선과 선의 교차점은 다음과 같이 확인합니다.

"선을 경계로 선분을 구성하는 2 가지 사항이
직선에 양쪽에 존재할 때, 직선과 선분은 교차한다 "


그런 다음 그 점이 직선에 대해 어느 편에있는지를 묻는 방법을 알아보겠습니다.
y = ax + b라는 직선 =를 부동로 대체
y> ax + b, y <ax + b라는 영역을 나타내는식이 있었다면, 이들 3 개식이 그려진 도형 영역은 다음과 같이 나타낼 수 있습니다.

여기서 2 개의 식을 왼쪽에 移項하여

y - ax - b> 0
y - ax - b <0

로 할 수 있습니다. 있는 점이 직선에 대해 어느 편에 있는지 필요하다면 직선의 방정식에 그 문제에 관해서 (X, Y)를 할당하고 결과 얻어진 값이 양수인지 음수인지에 따라 알 수 있습니다. 양의 경우 한 지점은 직선의 위쪽에 음수이면 한 지점은 직선의 아래 부분에 위치한다는 것을 알 수 있습니다. 직선의 양쪽 (위쪽과 아래쪽)에 점이 있으면 교차하기 때문에, 직선과 선분의 교차 판정을 위해서는 선분을 구성하는 2 개의 점을 직선의 방정식에 대입하여 얻은 값 부호가 서로 다른 (혹은 0) 여부를 조사하면 좋은 것입니다. 다른 경우에 (서로를 곱한 <0) 교차하고 있다고 판정할 수 있습니다.
이것을 구체적으로 식 화해보십시오.
점 A, B의 좌표를 A (x1, y1), B (x2, y2) 로,이 2 가지를 지나는 직선과
점 C, D의 좌표, C (x3, y3), D (x4, y4) 을 잇는 선분을 생각합니다.
점 A (x1, y1), B (x2, y2)를 지나는 직선 AB의 방정식은

y = x * (y1 - y2) / (x1 - x2) + y1 - x1 * (y1 - y2) / (x1 - x2)

로 나타낼 수 있습니다. 나눗셈은 0으로 나누기 또는 오버플로가 무서워 위해 피하기 때문에, 양변에 (x1 - x2)를 걸고 다음과 같이 변형합니다.

y * (x1 - x2) = x * (y1 - y2) + y1 * (x1 - x2) - x1 * (y1 - y2)

이것을 더욱 단순화하고, 왼쪽에 수집합니다.

(x1 - x2) * (y - y1) + (y1 - y2) * (x1 - x) = 0

이것은 점 A (x1, y1), B (x2, y2)를 지나는 직선의 방정식입니다.

이제이 방정식에 점 C (x3, y3), D (x4, y4)을 할당하고 그 부호를 검사하여 직선과 선분의 교차 판정을 할 수 있습니다.
점 C를 할당
tc = (x1 - x2) * (y3 - y1) + (y1 - y2) * (x1 - x3)
점 D를 할당
td = (x1 - x2) * (y4 - y1) + (y1 - y2) * (x1 - x4)

교차 = 2 개의 식의 부호가 다르다는 것을 수식으로 표현하면,

tc * td <0

과 같습니다 다음 코드로 판정 가능합니다. 시저하면 1 줄은 모르지만,
생각 자체는 One Line입니다.

'구조
Private Type POINT x As Double
    y As Double
End Type

'좌표 p1, p2을 지나는 직선과 좌표 p3, p4을 잇는 선이 교차하는지 확인
Private Function intersect (p1 As POINT, p2 As POINT, P3 As POINT, p4 As POINT) as Boolean

    If (((p1.x - p2.x) * (p3.y - p1.y) + (p1.y - p2.y) * (p1.x - p3. x)) * _ ((p1.x - p2.x) * (p4.y - p1.y) + (p1.y - p2.y) * (p1.x - p4.x))> 0 #) Then
        '교차하지 않는
        intersect = False
        Exit Function
    End If
    '교차
    intersect = True
End Function

그리고, 선분 AB와 직선 CD에 대해서도 같은 조사를 사용하여

ta = (x3 - x4) * (y1 - y3) + (y3 - y4) * (x3 - x1)
tb = (x3 - x4) * (y2 - y3) + (y3 - y4) * (x3 - x2)

ta * tb <0

위와 함께, 2 가지 조건 판정하는 경우, 2 개의 선분의 교차 판정을 할 수 있습니다.

'구조
Private Type POINT x As Double
    y As Double
End Type

'좌표 p1, p2를 잇는 선과 좌표 p3, p4을 잇는 선이 교차하는지 확인
'그러나 선이 겹치는 경우 ( 3 점, 4 점이 일직선상에있다), "교차하고 있지 않다"라고 판정합니다.
Private Function intersection (p1 As POINT, p2 As POINT, P3 As POINT, p4 As POINT) as Boolean
    
    If (((p1.x - p2.x) * (p3.y - p1.y) + (p1.y - p2.y) * (p1.x - p3.x)) * _ ((p1.x - p2.x) * (p4.y - p1.y) + (p1.y - p2.y) * (p1 x - p4.x)) "0 #) Then
        If (((p3.x - p4.x) * (p1.y - p3.y) + (p3.y - p4.y) * (p3.x - p1.x)) * _ ((p3.x - p4.x) * (p2.y - p3.y) + (p3.y - p4.y) * (p3.x - p2.x)) " 0 #) Then
            intersection = True
            Exit Function
        End If
    End If
    intersection = False

End Function

이 판정은 선분들이 겹치는 경우 (3 점 또는 4 점이 일직선상에있다), "교차하고 있지 않다"라고 판정합니다. 이것을 "교차한다"고 판정하고 싶은 경우에 대해서는더 빠르고 - 선 교차 판정 -를 참조하십시오. 위의 알고리즘만으로는이를 판정하는 것은 조금 어렵습니다.


(곱셈에 대한 오버플로 및 정수와 부동 소수점)

위 코드는 부동 소수점 연산에서 실시하고 있지만 실제로이 작업을 Windows 그리기 등에 사용하는 경우에는 정수 계산만으로 가능하며, 부동 소수점 대신 Long 정수를 사용하는 것이 빠르게 처리할 수 있기 때문에, 그 쪽이 좋을지도 모릅니다. 만약, 판정하려는 선의 점이 엄청나게 큰 경우, 곱셈에 대한 오버플로가 우려되기 때문에 전체 규모 자체를 작게하여 부동 소수점 계산을 할 필요가 있습니다. 그럴 때 선언하는 변수를 변경하면 유효한이 계산 방법은 아주 편리 뛰어나다고 생각합니다.

아래의 예제에서는 정수 버전을 사용하고 있습니다.


(참고로)

대부분의 참고서이 교차 판정을

"점 A, B를 지나는 직선과 반점 C의 위치 관계에 관하여, ABC 순서별로 점이 시계 방향 또는 시계 반대 방향으로 위치하고있는가라는 것을 알고있다"

와 같이 기술하고 설명하고 있다고 생각합니다. 위의 설명은이 방법을 증명 형식에 가서 보았습니다.


(참조)

'알고리즘 C 제 3 권;
野平 코헤이, 별 군수, 사토 Drug, 타구치 동쪽 공역
현대 과학사

'알고리즘과 데이터 구조』
강촌 준 아키라, 上坂 吉則, 아사 세종 바다, 아리사 마코토, 니시 무라 슌스케
実教出版


(샘플 프로그램의 동작 확인)

기종PC - 9821V13S
OSWindows95
개발 도구Visual Basic Ver.4.0
업데이트 :00/07/22

다운로드 easyCross.lzh(2.86KB)

Visual Basic Ver.5.0, Ver.6.0 잘 작동한다고 생각합니다.
또한,이 코너에 게재되는 프로그램 코드 및 프로그램 파일로 인해 발생하는 손해 등에 대해서 책임을 질 수 없습니다. 

★이 선의 교차는 다양한 작업에 사용할 수 있다고 생각합니다. 본 소스 문서 배포 전재는 금지 입니다만 게재되는 프로그램 코드 및 프로그램 파일은 각자의 책임하에 자유롭게 배포달라고해도됩니다. 그 때, 본 사이트를 소개해 주시면 대단히 기쁩니다.


Algorithm 인덱스 화면


http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/IntersectionEX.htm

 

'構造体
Private Type POINT
    x As Double
    y As Double
End Type

'座標 p1,p2 を結ぶ線分と座標 p3,p4 を結ぶ線分が交差しているかを調べる
'ただし、線分が重なっている場合(3点,4点が一直線上にある)、「交差している」、と判定します。
Private Function intersectionEX(p1 As POINT, p2 As POINT, _ 
                               p3 As POINT, p4 As POINT) As Boolean
    'x座標によるチェック
    If (p1.x >= p2.x) Then
        If ((p1.x < p3.x And p1.x < p4.x) Or (p2.x > p3.x And p2.x > p4.x)) Then
            intersectionEX = False: Exit Function
        End If
    Else
        If ((p2.x < p3.x And p2.x < p4.x) Or (p1.x > p3.x And p1.x > p4.x)) Then
            intersectionEX = False: Exit Function
        End If
    End If
    'y座標によるチェック
    If (p1.y >= p2.y) Then
        If ((p1.y < p3.y And p1.y < p4.y) Or (p2.y > p3.y And p2.y > p4.y)) Then
            intersectionEX = False: Exit Function
        End If
    Else
        If ((p2.y < p3.y And p2.y < p4.y) Or (p1.y > p3.y And p1.y > p4.y)) Then
            intersectionEX = False: Exit Function
        End If
    End If
    
    If (((p1.x - p2.x) * (p3.y - p1.y) + (p1.y - p2.y) * (p1.x - p3.x)) * _
        ((p1.x - p2.x) * (p4.y - p1.y) + (p1.y - p2.y) * (p1.x - p4.x)) > 0#) Then
        intersectionEX = False: Exit Function
    End If
    If (((p3.x - p4.x) * (p1.y - p3.y) + (p3.y - p4.y) * (p3.x - p1.x)) * _
        ((p3.x - p4.x) * (p2.y - p3.y) + (p3.y - p4.y) * (p3.x - p2.x)) > 0#) Then
        intersectionEX = False: Exit Function
    End If
    intersectionEX = True

End Function

반응형
반응형

  • ttp://smilewjp.springnote.com/pages/1753430

  • 투영(Projection)

  • 시야 영역을 양끝 모서리점이(-1,-1,-1)과 (1,1,1)의 좌표를 가지는 단위 정육면체로 변환하는것. 이러한 단위 정육면체를 정규 시야 영역이라고 한다. 대표적인 두가지 투영 방법으로 직교투영(orthographic projection)과 원근 투영(perspective projection)이 있다.
    직교 투영에서 시야 영역은 보통 직사각형 상자 모양이고, 직교 투영에 의해 이러한 시야 볼륨은 단위 정육면체로 변환된다. 직교 투영의 주된 특징은 평행선이 변환 후에도 평행을 유지한다는 것이다. 이 변환은 평행 이동과 크기 변환의 조합으로 표현된다.
    원극투영은 물체가 카메라에서 멀이질수록 투영한 후에 더 작게 보인다. 또한 평생선은 수평선에서 한 점으로 수렴할 수 도 있다. 그러므로 원근 투영변환은 인간이 물체의 크기를 인지하는 방법을 흉내낸 것이라고 할 수 있다.
    직교투영과 원근 투영 변환은 모두 4*4 행렬로 구성될 수 있으며, 변환후에 모델은 (NDC)정규화된 장치 좌표계에 놓여있다라고 한다.
  •  


     

    - 정규 좌표계(NDCS : Normalized Device Coordinate System, 정규화 장치 좌표계)
       * 정규화(normalization)란? : 어떤 값을 1을 기준으로 상대적으로 표시하는 행위
       * 절단 좌표계의 동차 좌표(x,y,z,w)를 3차원 좌표(x/w, y/w, z/w, 1)로 변환하는 원근분할을 가한 좌표 -> 2D 정규 좌표(소수점 정밀도)

    반응형
    반응형



    베지어 곡선

     

    http://kin.naver.com/open100/detail.nhn?d1id=11&dirId=1113&docId=234193&qb=67Kg7KeA7Ja0IOqzoeyEoA==&enc=utf8&section=kin&rank=2&search_sort=0&spq=0&pid=gkyGCz331yVssc%2B5Lg8ssv--496937&sid=Tby37L6VvE0AACnTDDU

     

    1. 수학적으로 N차 베지어 곡선은 다음과 같이 정의된다.

     

    t가 0에서 1까지일때, 벡터 B_N이 그리는 궤적이 베지어 곡선이다.

    벡터 p_k 는 조정점(control point)이고, N C k는 조합, N!/k!/(N-k)!을 의미한다.

     

    어도브사에서 정한 ps 규약 중의 하나인 3차 베지어 곡선의 경우, 다음과 같이 요약할 수 있다.

     

    (편의상 B, p의 벡터 기호는 생략한 것임)

     

    2. 베지어 곡선의 성질은 여러가지가 있는데, 대표적으로

     

    1) 시작점:t=0일 때, p_0점

    2) 끝점:t=1일 때, p_N점

    3) 시작점에서 접선은 p_0, p_1의 변위와 평행

    4) 끝점에서 접선은 p_N-1, p_N의 변위와 평행

    5) 언제나 조정점들의 convex hull안에 들어간다.

    6) 조정점들 중 여러 개를 같은 좌표로 설정하면, 그 부분에서 convex hull에 점점 가까워진다. 즉, 곡률이 더 심해진다.

     

    3. 역사

    수학적으로 예전에 알려진 곡선이지만, 피에르 베지어(Pierre Bézier)가 1960년대에 자동차 모델, 르노를 CAD로 디자인 할 때, 사용했는데, 그의 이름이 붙었다.

     

     


     

    http://seirion.com/130

     

    3차 베지어 커브 일반식 유도

    혹자는 왜 하필이면 3차 베지어 커브이냐 ... 라고 궁금증을 가질 수도 있지만,
    대부분의 폰트는 3차 이하의 베지어 커브들로 구성된다는 점,
    3차 베지어 커브이면 원에 가까이 근사할 수 있다는 점 등이 그 이유일 것이다.
    실제로 베지어 커브로는 완벽한 원을 만들 수 없다.

    따지고 보면 1차 베지어 커브(사실은 직선)로도 원하는 모양을 만들 수 있긴 하다.
    물론 이건 매우 비효율적이다. 어차피 픽셀로 표현되는 컴퓨터 나라에서 곡선이란 게 무의미 할 수도 있다.
    아무튼 그건 그거고 ...

    3차 베지어 커브의 일반식을 유도하기 위한 조건은 다음과 같다.
    1. 컨트롤 포인트는 4개이다. (P0P1P2 and P3)
    2. 곡선은 첫번째 포인트와 마지막 포인트를 지난다.
    3. 곡선의 첫 지점에서의 기울기는 P0 과 P을 이은 직선의 기울기의 3배이다.
    4. 곡선의 마지막 지점에서의 기울기는 P2 와 P을 이은 직선의 기울기의 3배이다.

     


    *원본에 내용을 덧붙인다,

    4. 곡선의 마지막 지점에서의 기울기는 P2  P3 을 이은 직선의 기울기의 3배이다.

     3배가 되는 이유는

     에서 N=3, 일경우 이것은 3차 방정식형태로 전계되며 (1-t)^3 에 관한 계수들은

    파스칼의 삼각형( 이항계수: n개 중에서 k개를 뽑을 수 있는 개수) 에 의하여 3이 곱해진다

    2차일때 1,2,1 이 곱해지듯 전개되는 두번째와 세번째 항에 3에 곱해짐으로

    이항계수는 다음과 같다.

     {n \choose k} = \frac{n!}{k!(n-k)!} \quad \mbox{if } n\geq k\geq 0  \qquad \mbox{(1)}

     {n \choose k} = 0 \quad \mbox{if } k<0 \mbox{ or } k>n


    {n \choose k}    =nCkC(n,k)

    ex)  {7 \choose 3} = \frac{7\cdot 6 \cdot 5}{3\cdot 2\cdot 1} = 35

     

     

    파스칼의 삼각형은 수학에서 이항계수를 삼각형 모양의 기하학적 형태로 배열한 것이다. 이것은 블레즈 파스칼에 의해 이름 붙여졌으나 이미 수세기 전에 다른 사람들에게서 연구된 것이다.


    Pascal triangle.svg

     

     

    파스칼 삼각형의 응용

    파스칼의 삼각형은 이항 전개에서 계수들의 값을 계산하는 데에 사용된다. 예를 들어

    (x + 1)^2 = 1 \cdot x^2 + 2 \cdot x + 1

    라는 식에서, 각 계수의 값인 1, 2, 1은 파스칼의 삼각형의 3번째 줄에 대응된다.

    일반적으로,

    (x + y)^n = a_0 x^n + a_1 x^{n-1} y^1 + a_2 x^{n-2} y^2 + \cdots + a_n y^n

    와 같은 전개식에서, a_i = {n \choose i} 가 성립한다. 즉, ai는 파스칼의 삼각형의 (n+1) 번째

    줄의 (i+1) 번째 값과 대응된다.


     

     

     

     

    위 사실에 근거하여,
    3차 식을 다음과 같이 u에 대한 3차 식으로 두고,

    사용자 삽입 이미지






    이놈을 매트릭스로 표현하면,

    사용자 삽입 이미지







    즉, 

    사용자 삽입 이미지






    그리고 미분한 식은 다음과 같다.

    사용자 삽입 이미지






    위 조건 1,2,3,4 를 적용하여 보면,

    [식 1.1]

    사용자 삽입 이미지



     

    사용자 삽입 이미지



     

    사용자 삽입 이미지



     

    사용자 삽입 이미지






     

    사용자 삽입 이미지

    이 식에서 

    사용자 삽입 이미지

    로 치환하면, 다음과 같다.

    사용자 삽입 이미지




    조건 1,2,3,4 로부터 유도된 식으로부터 

    사용자 삽입 이미지


     

    사용자 삽입 이미지

    를 구할 수 있고, 값은 다음과 같다.

    사용자 삽입 이미지
    사용자 삽입 이미지






     

    *원본에 덧붙인다.
    결론적으로 ([계수행렬][t])^T * [P] 로써 베지어 곡선이 표현되며,

    계수 행렬을 구하면 핵심적인 것이 정리된다,

    이 계수 행렬은 [식 1.1] 들의 P 들로 풀이되는Pn 들을 P0~3 까지 서로 연립하여 풀면 Pn 들에 붙는

     Mb 같은 계수행렬 형태로 정리할 수 있게 된다

    한가지 힌트는 Mb 행렬중 가장 오른쪽 열이 P0에 대하여 풀어 나온 나온 계수가 된다.

    마찬가지로 3 열이 P0 의 계수는 -3, P1 의 계수는 3 이다.


     

    사용자 삽입 이미지

    라고 치환하면,

    사용자 삽입 이미지

    이렇게 되고, 

    고로, 

    사용자 삽입 이미지

    다음을 통해서 b(u) 를 구할 수 있다.


    *원본에 덧붙인다.

    결과적으로 계수행렬  Mb^T 와 U 를 곱하여  (1-t)^3 즉 3차에 관한 항들로 전계가 되고

    이것이 P 와 곱해짐으로써 베지어 곡선을 만들 수 있게 된다.

    Tip : 3차식=3차곡선= N=4= N-1 곡선,  점이 4개면 3차 곡선 형태가 된다





    이제 다 끝났다.

    사용자 삽입 이미지



    이었으므로, 다음과 같은 일반항이 도출된다.

    사용자 삽입 이미지








    references : 
    http://en.wikipedia.org/wiki/B%C3%A9zier_curve
    Interactive Computer Graphics 2nd Edition (Addison Wesley) p434-436


     

     

     

    Bézier curves


    Written by Paul Bourke
    Original: April 1989, Updated: December 1996

     

    이 문서는 베지어 곡선이라는 특수한 곡선에 대한 수학적인 설명을 담고 있습니다. 이 곡선의 이름은, 1970년대 Renault car를 디자인하는 과정에서 이 곡선을 사용했던 Pierre Bézier라는 프랑스 엔지니어의 이름을 따서 만들어졌습니다. 그때부터 이 곡선은 식자 산업(typesetting industry)에서 절대적인 우위를 점하게 되었고, 특히 Adobe Postscript, 폰트 제품 등에서 널리 사용되었습니다.

    3차원 공간에 있는 N+1개의 조절점(control point) pk (k=0,1,...,N)를 생각해봅시다. 베지어 parametric 곡선 공식은 다음과 같습니다.

    B(u)는 서로 다른 위치에 있는(discrete) N개의 조절점에 의해 얻어지는 곡선을 구하기 위한 연속함수입니다. u=0이면 첫번째 조절점(k=0)에, u=1이면 마지막 조절점(k=N)에 도달합니다. 아래는 N=4, 즉 조절점이 4개인 경우의 곡선 모습입니다.
    역자 주 : 첫번째 조절점이 시작점, 마지막 조절점이 끝점이라고 생각하시면 쉽겠죠? ^_^ 
    그리고, N개의 조절점이 아니라 N+1의 조절점이라고 해야 하는 듯. 
    나중에 나오지만, 조절점의 위치가 모두 각각 다를 필요는 없습니다.

    주의점:

    • 이 베지어 곡선은, 조절점 중 처음과 끝 점을 빼고는 보통 어느 조절점과도 만나지 않습니다. 공식을 사용하면 B(0) = P0 이고 B(1) = PN 이 되겠지요.

    • 곡선은, 항상 조절점으로 이루어진 다각형 안에 들어가게 됩니다. 곡선이 조절점들 사이에서 크게 벗어나거나 하는 일은 없습니다.

    • 조절점이 P0 하나뿐이라면, 즉 N=0 이라면 모든 u에 대해 B(u) = P0 입니다. (역자 주 : u는 0이상 1 이하의 실수)

    • 조절점이 P0 , P1 두개뿐이라면, 즉 N=1이라면 이 공식은 두 점 사이를 잇는 선분을 만들어냅니다.


    • 라는 부분은 blending 함수라고 하는데, 이 부분에서 조절점들을 blend해서 곡선을 생성하기 때문입니다.

    • blending 함수는 조절점의 갯수보다 차수가 하나 낮은 다항함수입니다. 예를 들어, 3개의 조절점이 있다면 베지어 곡선은 포물선을 그리고, 4개의 조절점으로는 3차곡선을 얻게 됩니다.

    • 첫번째 조절점의 위치와 마지막 조절점의 위치가 같을 경우 폐곡선이 생깁니다. 이때 처음의 두 조절점 사이의 접선(tangent)과 끝의 두 조절점의 접선이 같을 경우, first order continuity가 가능합니다. (역자 주 : P0 - P1 간의 기울기와 PN-1 - PN 간의 기울기가 같을 경우..라고 보시면 되겠습니다. first order continuity는, 두 곡선의 (1계)도함수가 같은, 즉 접선의 기울기가 서로 같은 상태를 의미합니다.) 

    • 비슷한 위치에 여러 조절점이 있을 경우, 그쪽으로 베지어 곡선을 "당기는" 정도가 증가합니다.

    • 조절점의 갯수가 많아지면, 좀더 높은 차수의 식과, 많은 횟수의 팩토리얼 값을 계산해야 합니다. 그래서 보통 긴 곡선을 만들 때는, 그 곡선을 다시 여러 곡선으로 작게 쪼개는 방법을 씁니다. 이렇게 하면, 전체적인 모습에 변화를 주지 않고도 곡선의 부분적인 형태를 쉽게 바꿀 수 있는 효과도 얻게 됩니다. 물론 곡선이 첫번째 조절점에서 시작해서 마지막 조절점에서 끝나기 때문에, (나눠진) 곡선 조각들을 이어붙이기는 쉽습니다. 또한 베지어 곡선에서는 마지막 점에서의 접선이 마지막 두 조절점을 이은 선과 같기 때문에, (나누어진 곡선들의) 첫번째 조절점의 기울기도 맞출 수 있습니다. 
      Second order continuity는 보통 불가능합니다. (역자 주 : Second order continuity는, 이계도함수의 값이 같을 때의 상태입니다. 즉, 곡선의 변화율이 같다는 뜻입니다.) 

    • 조절점이 2개인 특수한 경우(직선)을 제외하고는, 한 베지어 곡선에 평행한 다른 베지어 곡선을 유도(derive)해내는 것은 불가능한 것으로 알려져 있습니다.

    • 베지어 곡선으로 원을 완벽하게 표현할 수는 없습니다.

    • coincident parallel curves나 직선인 베지어 곡선의 경우를 제외하고는, 한 베지어 곡선에 평행한 베지어 곡선을 만드는 것은 불가능합니다.

    • 조절점이 3개일 경우는 공식이 다음과 같이 정리됩니다 : 

      B(u) = P0 * ( 1 - u ) 2 + P1 * 2 * u ( 1 - u ) + P2 u2

    • 조절점이 4개일 경우는 공식이 다음과 같이 정리됩니다 : 

      B(u) = P0 * ( 1 - u )3 + P1 * 3 * u * ( 1 - u )2 + P2 * 3 * u2 * ( 1 - u ) + P3 * u3

    베지어 곡선은 굉장히 안정적인 형태를 만들고, 계산하기도 쉽기 때문에 널리 쓰이고 있습니다. 이런 형태의 베지어 곡선 말고도 조금 다른 모습을 만들어 내는, 또다른 베지어 곡선 공식이 있습니다. 대체로 모습은 비슷하지만, 곡선이 각 조절점을 모두 통과한다는 점이 다릅니다. Spline 곡선을 참조하세요.


    예제

    분홍색 선이 조절점들을 이은 선이고, 회색 선이 베지어 곡선입니다.

    베지어 곡선을 표현하는 다항식의 차수는 조절점의 갯수보다 하나 낮기 때문에, 조절점이 세 개인 이 경우에는 2차곡선이 만들어집니다. 두 곡선의 조절점의 모양이 대칭을 이루면, 곡선 또한 항상 대칭입니다.

    곡선은 항상 끝점을 지나며, 처음의 두 점을 이은 선에 접하고 끝의 두 점을 이은 선에도 접합니다. 이 성질로 인해, first order continuity를 유지하면서 여러 베지어 곡선을 이을 수 있게 됩니다.

    곡선은 항상 조절점들로 이루어진 볼록다각형(convex hull) 안에 있게 됩니다. 그래서 곡선은 "안정적이고", 엉뚱하게 튀어나가는 일이 없습니다.

    시작점과 끝점을 갖게 했을때 곡선이 생깁니다. 시작점과 끝점의 접선(tangents)이 일치할 경우 곡선은 first order continuity를 유지하면서 닫히게 됩니다. 또, 조절점을 한 곳에 여러번 지정하게 되면, 그 쪽으로 곡선이 쏠리게 됩니다.


    C source

    typedef struct XYZ

    {

        double x;

        double y;

        double z;

    }XYZ;

    /*

    조절점이 3개인 베지어 곡선 예제

    mu는 0(곡선의 시작)부터 1(곡선의 끝) 사이의 값을 가질 수 있습니다.

    */

    XYZ Bezier3(XYZ p1,XYZ p2,XYZ p3,double mu)

    {

        double mum1,mum12,mu2;

        XYZ p;

        mu2 = mu * mu;

        mum1 = 1 - mu;

        mum12 = mum1 * mum1;

        p.x = p1.x * mum12 + 2 * p2.x * mum1 * mu + p3.x * mu2;

        p.y = p1.y * mum12 + 2 * p2.y * mum1 * mu + p3.y * mu2;

        p.z = p1.z * mum12 + 2 * p2.z * mum1 * mu + p3.z * mu2;

        return(p);

    }

    /*

    조절점이 4개인 베지어 곡선 예제

    mu는 0(곡선의 시작)부터 1(곡선의 끝) 사이의 값을 가질 수 있습니다.

    */

    XYZ Bezier4(XYZ p1,XYZ p2,XYZ p3,XYZ p4,double mu)

    {

        double mum1,mum13,mu3;

        XYZ p;

        mum1 = 1 - mu;

        mum13 = mum1 * mum1 * mum1;

        mu3 = mu * mu * mu;

        p.x = mum13*p1.x + 3*mu*mum1*mum1*p2.x + 3*mu*mu*mum1*p3.x + mu3*p4.x;

        p.y = mum13*p1.y + 3*mu*mum1*mum1*p2.y + 3*mu*mu*mum1*p3.y + mu3*p4.y;

        p.z = mum13*p1.z + 3*mu*mum1*mum1*p2.z + 3*mu*mu*mum1*p3.z + mu3*p4.z;

        return(p);

    }

    /*

    일반적인 베지어 곡선 예제

    조절점의 갯수는 n+1개가 됩니다.

    0 <= mu < 1 *중요!* 마지막 조절점은 계산하지 않습니다.

    */

    XYZ Bezier(XYZ *p,int n,double mu)

    {

        int k,kn,nn,nkn;

        double blend,muk,munk;

        XYZ b = {0.0,0.0,0.0};

        muk = 1;

        munk = pow(1-mu,(double)n);

        for (k=0;k<=n;k++)

        {

            nn = n;

            kn = k;

            nkn = n - k;

            blend = muk * munk;

            muk *= mu;

            munk /= (1-mu);

            while (nn >= 1) {

                blend *= nn;

                nn--;

                if (kn > 1) {

                    blend /= (double)kn;

                kn--;

                }

                if (nkn > 1) {

                    blend /= (double)nkn;

                    nkn--;

                }

            }

            b.x += p[k].x * blend;

            b.y += p[k].y * blend;

            b.z += p[k].z * blend;

        }

        return(b);

    }


    • FAQ
      > 1. SpLines 코드 - 코드를 이해하기 위한, 간단한 테스트
      > 프로그램이 있습니다. 정말 괜찮게 구현해놓았네요. 질문이 하나 있습니다:
      > 어떻게 동적인 결과(dynamic resolution)를 얻을 수 있을까요?
      > 2. Bezier 코드에서 - 어떻게 이 코드를 쓰는지에 대한 예제가 없네요.. 
      > 세 함수 모두 곡선을 만드는 대신, 단지 점 하나만을 리턴하네요. 
      > 게다가 double형 인자인 mu( 0 < mu <1) 는 뭐죠?
      
      함수를 호출할 때는, 0부터 1 사이의 범위에서 mu값을 바꾸면서 함수들을
      호출하세요. mu의 값을 증가시킴에 따라, 곡선 위에서 (곡선 방향으로) 이동하는 
      점들을 얻게 됩니다. 그러므로 mu에 0.5를 넣는다면, 전체 곡선(길이)의 딱 중간에
      있는 점을 함수가 리턴하겠지요. 하나 예를 들어볼게요.
      
         #define NSTEPS 100
         int ncontrolpoints=0;
         XYZ p,*controlpoints;
         
         ... 이곳에 조절점 배열과, 데이터들을 만들고 읽는 루틴이 들어가겠지요.
      
         for (i=0;i%lt;NSTEPS;i++) {
            p = Bezier(controlpoints,ncontrolpoints,i/(double)N));
      
            .... 이제 p 변수를 이용하세요. 예를 들어, 화면에 찍는다거나 등등.
      
         }
      
      spline 코드가 호출되는 방식도, 이와 같습니다.

    출처 : http://eunchul.com/Algorithms/BezierCurves/BezierCurves.htm

     

     


     

    베지어 곡선뒤에 숨겨진 수학원리 #

    좋습니다. 가장먼저 짚고 넘어가야할 것은 번스타인(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)
    

    이렇게 분해해놓은 공식만있으면 수학공식정리를 하지 않아도 됩니다! 이제 베지어 곡선뒤에 숨은 간단한 수학을 건너뛰었습니다. 이들을 가지고 프로그램을 논하도록 하죠!


    베지어 곡선

    번스타인(Bernstein) 정리 공식들 

    1 = t + ( 1 - t ) 
    ▒ 0 ≤ t ≤ 1 

    2차 베지어 곡선이라면 양변에 제곱 
    3차 베지어 곡선이라면 양변에 세제곱 
    ... 

    2차 베지어 곡선 

    1^2 = t^2 + 2 * t * ( 1 - t) + ( 1 - t ) * ( 1 - t )

    3차(cubic) 베지어 곡선 

    1^3 = t * t * t + 3 * t * t * (1 - t) + 3 * t * (1 - t) * (1 - t) + (1 - t) * (1 - t) * (1 - t)

    4차(quartic) 베지어 곡선 

    1^4 = t * t * t * t + 4 * t * t * t * (1 - t) + 6 * t * t * (1 - t) * (1 - t) + 4 * t * (1 - x) * (1 - t) * (1 - t) + (1 - t) * (1 - t) * (1 - t) * (1 - t)

    제어점은 각 식에 대해서 곱의 합으로 분리했을때 곱의 갯수이고 
    각 제어점들을 각 곱에 곱해줌으로써 값들은 베지어 곡선을 이루게 된다. 

    2차 베지어 곡선의 예제 코드 

    public double B1(double t) 

      return t*t; 

    public double B2(double t) 

      return 2 * t * (1 - t); 

    public double B3(double t) 

      return (1 - t) * (1 - t); 

    ... 

      double x, y; 
      double detailBias = 1.0 / 50.0; 
      double count = 0; 

      do 

        x = pt0].X * B1(count) + pt[1?.X * B2(count) + pt[2].X * B3(count); 
        y = pt0].Y * B1(count) + pt[1?.Y * B2(count) + pt[2].Y * B3(count); 

        image.SetPixel?((int)x, (int)y, Color.Black); 

        count += detailBias; 

      } while (count <= 1); 

    출처 : http://www.synch3d.com/wiki/moin/moin.cgi/_ba_a3_c1_f6_be_ee_20_b0_ee_bc_b1

    반응형
    반응형

    블로그 이미지

    3DMP engines

    3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..


    Herimit Curve

     





    에르미트 곡선을 3차 다항식으로부터 도출 하여, 곡선 임의의 한 점에서의 근사적 좌표 프레임을 얻어오는

    과정 까지를 진행하겠습니다

     

    먼저 기호들을 살펴보자 아래의 그림과 같다

    P0, p1 은 각각 점이고 Q0은 곡선을 뜻한다 이때 Q0 ~ Qn 까지 생성 될 수 있다( P0~Pn 에 의하여.. )

    P'0 과  P'1 은 각 점에서의 접선벡터(속도벡터)를 뜻한다

    일반적으로

     

        Q(t) = ( x(t),y(t),z(t) )

     

    로 표현 할 수 있다

     또한 이것의 1차 미분은

        Q'(t) = ( x'(t),y'(t),z'(t) )

     

    이다, 즉 각 성분을 미분한다 이때의 인자는 t 이므로 t 에 대해서 미분하지만 아래설명에서 t 와 u 를 혼용해서

    쓰는데, 개의치 말고 t,u 모두 그냥 실수 범위라고 생각 하면 되겠다

     

    * 일반적인 3차방정식으로부터 에르미트 곡선 공식의 유도식은 다음가 같다

     

     

     

    원래의 Q 와 Q' 의 식으로 0,1 인자를 이용한 고정된 값을 도출 하는 것이 포인트이다

    도출된 값들을 다시 원래의 식에 대입하여 a,b 에 대해 정리 한 후.... 

     

     

    * 아래 내용은 어떻게 저 a,b 가 나왔는지에 대한 풀이이다...

     

     

     

    구한 상수 값들 ( a,b,c,D ) 을 원래의 3차 다항식에 대입하여 푼다

     

     

     

     

     

    이렇게 푼 것을 행렬의 형태로 맞추기 위해 식을 각 포인트( 2개의 점과 2개의 접선) 를 기준으로 식을 다시

    정리한다

     

     

     

     

     

     

     

    여기까지다 에르미트 곡선의 도출 과정이다

     

     

     

    이제는 근사적 좌표계를 어떻게 구할 껏인가에 대한 과정이 되겠다

     

    먼저 r(t) 곡선에 대해 생각하면

     

    r(t)를 한번 미분하면 속도벡터 v(t) 이고 v(t) 를 한번더 미분하면 a(t) 가속도 벡터를 구할 수 있게 된다

    (단, 단위원의 경우)

     

     

     

     

    위의 식을 따라가보면 알 수 있는 것은 속도 벡터가 일정한 상수값으로 나올때 가속도 벡터와 속도 벡터의

     

    내적은 0 즉 수직이라는 말이 된다

    (여기서 유추해 볼 수 있는 것은 이 둘을 외적하면 up 벡터를 구할 수있다는 것)

     

    예를 들어보자 PI/4 일경우를 기준으로 어떤 벡터가 나오는지를 확인해보자

     

     

     

    그림에서 잘 설명 되어 있으니 , 별 다른 설명은 하지않겠다 , 다만 sin 미분하면 cos , cos 미분하면 - sin 이 된다

     

     

     

    이부분이 실질적인 근사적인 좌표프레임을 구하는 부분이다

     

    위의 과정을 이해했다면 마지막 과정을 대강 어느정도 이해할 수 있을 것이다

     

    근사적이기 때문에 완전한 가속도 벡터가 될 수 없다

     

    가속도벡터를 제대로 구하고 싶다면 벡터 미분을 참고하여야 한다

     

    근사적으로 구하면 속도에서 좀 이득을 볼 수있을 것이다

     

     

    Copyright : 송 정 헌

     


    반응형

    '수학 (Mathematics) > 3D수학' 카테고리의 다른 글

    NDC 공간이란  (0) 2012.11.02
    베지어 곡선(Bezier Curve) 유도와 설명  (1) 2012.11.02
    두 벡터 사이의 각  (0) 2012.11.02
    벡터 미적분, 접선과 가속도 - 공간 곡선  (0) 2012.11.02
    두직선의 교점  (0) 2012.11.02
    반응형

    http://egohim.blog.me/70012169260



    vector의 cross product를 사용하면 될 것 같습니다. 

    먼저 두 벡터 사이의 각도는 사실 0~180밖에 나올수 없지만, 0~360가 나오도록 한다면 기준이 있어야할 것입니다. 

    기준1. vector a(기준)에서 vector b까지의 
    기준2. 시계 방향(기준) 혹은 시계 반대방향(기준) 

    위의 기준은 cross product의 순서로 정할 수 있는 것 같네요. 
    vector a에서 vector b로의 각도가 [0,180]이면 
    vector a와 vector b이 cross product의 z값은 0과 같거나 크고 
    vector a에서 vector b로의 각도가 (180,360) 또는 (-180,0) 이면 
    vector a와 vector b이 cross product의 z값은 0보다 작을 것입니다. 



    vector a=(ax, ay, az) 
    vector b=(bx, by, bz) 
    일 때 cross product(axb)의 z-component는 -ay bx + ax by이므로 

    아래와 같이 하면 가능하겠네요. 


    float cosAng1 = DotProduct(vector1, vector2); 

    return (vector1.y*vector2.x + vector1.x*vector2.y > 0.0f) ? (float)(acos(cosAng1)) : - (float)(acos(cosAng1)); 


    실제로 곱하기 계산도 한번 줄었네요.(dot product-> 곱하기 3번 ---> 곱하기 2번)

    반응형
    반응형

    원문 http://pinkwink.kr/197

     


    google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 
    본 자료는 국립 창원대학교 메카트로닉스 공학부 학생을 대상으로 한 공업수학 수업 자료입니다. 본 자료는 수업의 교재인 공업수학I 개정3판 (고형준 외, 도서출판 텍스트북스) 의 내용을 재구성한 것으로 수업보조 자료 이외의 목적이 없음을 알립니다.




    곡선운동

    위치벡터를 한번 미분하면 속도벡터가 됩니다. 속도벡터를 한번 미분하면 가속도 벡터가 되구요.


    속도의 크기를 의미하는 속력은 곡선의 길이를 구하듯이 계산하면 됩니다.


    이때 만약 크기(속력)가 일정한 속도벡터가 있었다면, 위 과정처럼 내적을 이용한 풀이를 응용해보면 속도성분과 가속도성분이 서로 수직이라는 것을 알 수 있습니다.

     
    즉, 위치벡터의 미분치인 속도벡터에 가속도벡터가 수직하면서, 본래의 위치벡터와 방향이 반대(구심가속도)라는 것을 알 수 있는것이지요.


    물론, 위치벡터를 직접 두번 미분해보면 위에서처럼 알 수 있습니다. (단, 크기가 일정할때 말이지요..) 이를 구심가속도벡터라고 부릅니다.

     
    위에서처럼 초기 높이가 s0이고 초기속도가 위와 같은 포물선운동을 하는 물체의 경우 , 만약 그 물체자체에는 추진력이 없고 외부의 힘이 없다면, 작용하는 힘은 중력만 존재할 것입니다.

     
    이를 적분하면 당연히 속도가 될텐데요. 이때 초기치를 대입하고 다시 풀어보면


    위와 같을 것이고 이때 얻은 속도를 다시 적분해서 위치벡터를 찾을 수 있습니다. 단, 위 식을 보실때 적분인자가 시간 t라는 걸 기억하셔야합니다.

     
    그러면, 위에서처럼 x,,y쪽 성분을 구할 수 있는것이지요.


    google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 




    google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 


    곡률과 가속도의 접선 가속도 벡터 및 법선 가속도 벡터

    단위접선벡터를 이야기하는 것은 이미 지난번에 했었는데요.


    이를 이용하면 곡률을 정의할 수 있습니다.

     
    위 그림과 수식들을 보시면, 속도벡터와 가속도벡터들을 찾고 있고, 그 와중에 곡률을 정의하고 있구요.

     
    만들어진 가속도벡터에서 위치벡터와 수직한방향의 접선가속도벡터와 법선가속도벡터성분을 정의내릴수있습니다.


    즉, 접선가속도 성분은 속도와 가속도벡터의 내적으로, 법선가속도 성분은 외적으로 찾을 수 있다는 것을 알 수 있습니다.

     
    접선과 법선으로 이루어진 평면의 수직한 방향의 벡터를 종법선벡터라고 하는데요 이는 당연히 외적으로 구할 수 있겠죠. 

    반응형
    반응형

    http://www.gisdeveloper.co.kr/15


    두 선의 교차점 구하기 
    이 글은 두 선분의 교차점을 구하는 알고리즘이 작업에 필요해서 작성해둔 글이다. 참고로, 예전에 두선분의 교차점을 구하는 것 자체가 쉬울 것으로 생각하고 흔히 생각하는 기울기, y 절편을 이용하여 접근하려고 하였다. 이는 상당히 비효율적 방법이였고 조금 더 효율적인 방법으로 접근하였다. 

    먼저 직선의 방정식으로써, 기울기와 절편으로 나타내지 말고, t 매개변수를 이용해 나타내면 다음과 같다.


    P1과 P2는 직선의 시작점과 끝점을 나타내며, t의 범위는 0에서 1까지이다. (P1, P2에서 1, 2는 아래첨자로 생각하기 바란다)

    선의 식을 알았으니, 이제 두선의 교점을 구해보는 것으로 응용해보자. 먼저 아래 그림을 보자.


    Line1은 P1과 P2로 이루어져 있으며, Line2는 P3와 P4로 이루어져 있다. 두개의 라인을 식으로 표현해보면 다음과 같다.


    이미 알겠지만, t와 s는 0에서 1부터의 값이며, 두선의 교점은 두선의 공통된 값이므로 P(t)와 P(s)는 같으므로 위의 2개의 식은 아래의 1개의 식으로 나타낼 수 있다.


    다시 위의 식을 x, y로 분리해보면 아래와 같은 두개의 식들로 분리된다.


    위의 식을 t와 s에 대해서 정리를 해보면 다음과 같다.


    즉, 위의 t와 s는 두선이 서로 만날때의 값이므로, 최종적으로 두선의 교점은 다음과 같이 나타낼 수 있다.


    위의 x, y가 우리가 구하고자하는 두 직선의 교점이다. 

    마지막으로 t와 s에 대해 정리해 보도록 하자.

    s와 t의 값이 0과 1 사이를 벗어나는 경우, 두 선은 교차하지 않는다고 판정해야 한다. 그리고 s와 t를 구하는 공식에서 분모가 0인 경우 두 선은 평행하다는 의미이므로 교점은 존재하지 않다. 분모와 분자 모두 0인 경우 두 선은 동일한 선이다.

    아래의 코드는 위의 설명을 토대로 작성하였다.
    bool GetIntersectPoint(const POINT& AP1, const POINT& AP2, 
                           const POINT& BP1, const POINT& BP2, POINT* IP) 
    {
        double t;
        double s; 
        double under = (BP2.y-BP1.y)*(AP2.x-AP1.x)-(BP2.x-BP1.x)*(AP2.y-AP1.y);
        if(under==0) return false;
    
        double _t = (BP2.x-BP1.x)*(AP1.y-BP1.y) - (BP2.y-BP1.y)*(AP1.x-BP1.x);
        double _s = (AP2.x-AP1.x)*(AP1.y-BP1.y) - (AP2.y-AP1.y)*(AP1.x-BP1.x); 
    
        t = _t/under;
        s = _s/under; 
    
        if(t<0.0 || t>1.0 || s<0.0 || s>1.0) return false;
        if(_t==0 && _s==0) return false; 
    
        IP->x = AP1.x + t * (double)(AP2.x-AP1.x);
        IP->y = AP1.y + t * (double)(AP2.y-AP1.y);
    
        return true;
    }

    반응형

    '수학 (Mathematics) > 3D수학' 카테고리의 다른 글

    두 벡터 사이의 각  (0) 2012.11.02
    벡터 미적분, 접선과 가속도 - 공간 곡선  (0) 2012.11.02
    사각형 무게중심  (0) 2012.11.02
    벡터의 내적과 외적  (0) 2012.11.02
    한 축에 대한 기저 생성  (0) 2012.11.02
    반응형


     

     http://blog.daum.net/anil-gifted/12850152


            

     

     

    1. 한개의 사각형을 두개의 삼각형으로 나누어 세 중선을 통해 각 삼각형의 교점을 찾는다. 선분을 연결한다.

    2. 1과 같이 다른 삼각형에도 교점을 표시한다.그리고 선분연결

    3. 이게 바로 사각형의 무게  중심점이 된다.

     

     

    각 꼭지점에서 마주보는 변의 중점으로 선을 그엇을 때 만나는 점입니다.
    좌표(x1,y1)-(x2,y2)-(x3,y3)으로 표현된 경우에는 ((x1+x2+x3)/3. (y1+y2+y3)/3)으로 간단하게 계산할 수도 있습니다.

    특징은 중학교 수학책을 참고하시고...

    갑자기 궁금해져서 사각형의 무게중심을 구하는 방법을 찾아봤습니다.


    오른쪽 그림과 같이 사각형을 두 개의 삼각형으로 쪼갭니다. 
    (물론 서로 마주보는 두 꼭지점을 연결해야죠)

    그러면 삼각형 둘로 나뉘는데, 
    각각 삼각형의 무게중심을 구합니다.

    왼쪽에 있는 삼각형을 A, 오른쪽을 B라고 하면 오른쪽과 같은 그림이 나오게 됩니다. GA는 A의 무게중심, GB는 B의 무게중심입니다.
    다음은 GA-GB를 잇는 선분을 면적의 역수로 내분한 점을 찾으면 됩니다.

    즉, A의 면적이 4B의 면적이 1이라고 하면 GA- GB를 1:4로 내분한 점이 사각형의 무게중심이 됩니다. (4:1이 아닙니다. 그렇게 되면 큰 삼각형 쪽으로 중심이 잔뜩 쏠릴 겁니다)

    반응형
    반응형

    http://sayzy.blog.me/70080729572



    벡터의 내적

     

    내적의 특성

    ▣ 만약 두 벡터가 UㆍV = 0 라면, U와 V는 직각이다.
    ▣ 만약 두 벡터가 UㆍV > 0 라면, 두 벡터 간의 각도는 90도 보다 작다.
    ▣ 만약 두 벡터가 UㆍV < 0 라면, 두 벡터 간의 각도는 90도 보다 크다.
     

    가장 중요한 것은 두 벡터의 내적은 그 결과가 항상 스칼라라는 것입니다. 이 때문에 스칼라 적이라고도 하며 점곱 이라고도 불립니다.

     

    공간상에 임의의 두 벡터 A, B가 있을때..


     

    두 벡터 사이의 각 구하기

    우리는 위의 공식을 이용하여 두 벡터간의 각을 알아낼수가 있습니다.

    위 식이 성립됩니다.

    코싸인 세타 값을  M이라고 한다면..

      라는 라디안 값을 얻을 수 있습니다.

     

    투영 벡터

    우리는 여기서 어느 한 면에서의 점(G)와 원 사이의 거리를 알고 싶습니다.

    그러려면 B_P의 투영 벡터인 X벡터의 스칼라 값을 구하여야 됩니다.

    원점에서부터 오는 벡터 P가 있습니다.

    그리고 마찬가지로 원점에서부터 오는 벡터 B가 있습니다.

    B_P는 B벡터 - P벡터를 한 벡터입니다.

    벡터 X의 길이를 s라 하면 s =  가 됩니다.

    B_P벡터와 점(G)의 노말 벡터인 N과 내적을 하게 된다면...

    내적 값은 N은 길이가 1이므로 이것도 역시  가 되게 됩니다.

    결과를 보면 X의 스칼라 값 s와 N의 내적 값이 같다는걸 보게 됩니다.

    따라서 길이가 1인 벡터 N과 B_P의 내적값은 X벡터의 스칼라 값인 길이가 됩니다.

    여기에  x N벡터를 하면 크기와 방향을 가지는 투영 벡터인 X벡터가 나오게 됩니다.

     

    투영벡터에 관한 정보는 아래 사이트에서 보고 글을 올린 것이니 이해가 안되시면 링크를 따라가셔서 보시면 됩니다.

    http://wibler.egloos.com/3574643

     

    벡터의 외적

     

    공간상에 임의의 두 벡터 A, B가 있을때..

    벡터의 내적이 두 벡터간의 사잇각을 나타내는 스칼라임에 비하여 벡터의 외적은 두 벡터에 모두 수직한

    벡터를 결과 값으로 받는다는 점 때문에 크로스곱 또는 벡터적이라고도 합니다.

    벡터 A와 B를 포함하는 평면에는 수직인 두개의 방향인 위쪽과 아랫쪽이 있습니다.

     

    위 그림과 같이 오른손 법칙이나 왼손 법칙으로 두 벡터의 외적 벡터인 z 방향을 알아 낼수가 있습니다.

    반응형
    반응형

    임의의 한 축 r

     

    1. r의 최소 성분을 찾아 0 으로 만든다

     

    2. 나머지 두개의 성분을 교체한 후 이들의 첫번째 성분을 음수로 만든다

     ( 0 이 아닌 두개 중 어떤 것이든 음수가 될 수 있다 )

     

    3. 이렇게 나온 s 는 r 과 수직인 벡터가 나온다

     

    4 t = r X s  로 cross 벡터를 구한다   X : 외적

    반응형
    반응형

    ** 간단하고 안전한 방향전환 행렬 구하기 **
    copyrightⓒ Gamza

     


    두개의 단위 방향벡터가 주어지고 한 벡터를 다른 벡터로 회전하는 행렬을 구하는 문제는 게임에 종종 등장하곤 합니다.
    그런데 문제는 이것이 참 구하기도 까다롭고 수치적으로 불안정 해지는등...여러모로 사용하기가 까다롭다는 것입니다.
    만약 입력이 달랑 단위 방향벡터 두개가 아니라 두개의 완전한 좌표축으로 주어진다면 문제는 정말로 간단해집니다.

    이 글은 두개의 좌표축이 주어지고 한 좌표축을 다른 좌표축으로 변환하는 회전행렬을 보.여.드리 위한 글입니다.

    문 제
    세개의 단위벡터로 표현되는 좌표축이 두개 있다.
    A : Vside, Vup, Vdir
    B : Vside, Vup, Vdir
    Vsideside vector(일반적으로 x축)
    Vupup vector(일반적으로 y축)
    Vdirdirection vector(일반적으로 z축)
    좌표축 A를 B가되도록 회전시키는 회전 행렬을 구하라. 
    정 답
    구하고자 하는 회전 행렬을 M 이라 하면,
    B.Vside=A.Vsidex M
    B.Vup=A.Vupx M
    B.Vdir=A.Vdirx M
    행렬로 간단히 표현하면...
    B = A x M
    A,B: 각행이 Vside, Vup, Vdir인 3x3행렬
    M을 구하면...
    M = inverse(A) x B = transpos(A) x B

    뭐...계산이랄것이 하나도 없죠....그래서 보여드린다고 했던겁니다...ㅡ.ㅡ;;;
    너무 간단해서 허탈하기까지...
    어쨌든 입력이 달랑 단위 방향벡터 두개인 경우....Up vector만 적당히 잡아줄수 있으면, 이 방법을 써서 간단하고도 안전하게 완벽한 회전 행렬을 구할수 있습니다.

    반응형

    '수학 (Mathematics) > 3D수학' 카테고리의 다른 글

    벡터의 내적과 외적  (0) 2012.11.02
    한 축에 대한 기저 생성  (0) 2012.11.02
    점과 직선/반직선/선분과의 거리  (0) 2012.11.02
    선형변환 (Linear Transformations)  (0) 2012.11.02
    동차 좌표  (0) 2012.11.02
    반응형

    출처: http://www.gamza.net

     

    copyrightⓒ playUs [2003년 04월 19일]

     

    1. 정사영(투영) 벡터

     


     
     
    벡터A를 벡터B에 투영한 벡터[?]는 다음과 같이 표현됩니다.
    [?] = ( 벡터A를 벡터B에 투영한 길이 ) N 
    (N : B방향 단위벡터)
    벡터A를 벡터B에 투영한 길이는 내적을 이용하면 구할 수 있고....
    ( 벡터A를 벡터B에 투영한 길이 ) = |A|cos@ = A • B / |B|
    또, B방향 단위벡터는 N은 아래처럼 구해지니....
    N = B / |B|
    결국 벡터A를 벡터B에 투영한 벡터[?]를 다시 표현하면 아래와 같이 됩니다.
    [?] = (A•B/|B|) (B/|B|) = ((A • B)/(|B|*|B|)) B = ((A•B)/(B•B)) B

    2. 점과 직선과의 거리
    점과 직선의 수직거리는 점에서 직선에 내린 수선(벡터H)의 크기입니다.
     

     
    P : 거리를 알고 싶은 점
    Lorg : 직선상의 임의의 한점
    Ldir : 직선의 방향벡터
     
     
    이때 벡터H는 아래그림과 같이 구할수 있죠.

     
    Pprj : 벡터(P-Lorg)를 Ldir에 투영한 벡터

    Pprj는 벡터(P-Lorg)를 Ldir에 투영한 투영벡터입니다.
    저 위의 투영벡터 공식을 적용해보면...
    Pprj = (((P-Lorg)•Ldir)/(Ldir•Ldir)) Ldir
    최종적으로 벡터 H를 정리하면 다음과 같이 됩니다.
    H = (P-Lorg) - Pprj = (P-Lorg) - (((P-Lorg)•Ldir)/(Ldir•Ldir)) Ldir
    식은 길지만 따져보면 상당히 값싼 연산임을 알수 있습니다.
    무엇보다도 이 식의 최대 장점은 단위벡터가 필요없다는 것입니다.
    벡터를 정규화할 필요가 없으니 보기보다는 훨씬 값싼 연산이라 할수 있죠.

    3. 점과 반직선과의 거리
     

     
    P : 거리를 알고 싶은 점
    Lorg : 반직선의 시작점
    Ldir : 반직선의 방향벡터

    위 그림에서 보듯, 점이 반직선의 시작점보다 뒤쪽(Ldir방향기준)에 있을 경우에 점과 반직선의 거리는 그냥 |P-Lorg|로 구해집니다.

    4. 점과 선분과의 거리
    벡터A를 벡터B에 투영한 벡터Aprj는 벡터B에 스칼라 값 ((A • B)/(|B|*|B|))을 곱한 벡터입니다.
    따라서 계수가 되는 ((A • B)/(|B|*|B|)) 의 크기에 따라 아래와 같이 구분될 수 있습니다.
     
     

     
     
     
    이것을 이용하면 다음 그림과 같이 점(P)과 선분(S0,S1)의 거리를 구할수 있습니다.
     

    P : 거리를 알고 싶은 점
    S0,S1 : 선분을 이루는 두점
    V1 : S0에서 P를 향하는 벡터
    V2 : S0에서 S1을 향하는 벡터

    사실 점과 반직선의 거리는 위에서 세번째 경우를 두번째 경우로 대치시킨것 뿐입니다.
     

    반응형
    반응형

    <선형대수학 개념이해 보충자료 1>

    선형변환 (Linear Transformations)

    Sang-Gu Lee, Sungkyunkwan Univ., Korea

     

      선형변환 개념의 시각적 이해를 위한  Flash tools, Animations, JAVA Applets 모음집입니다.

     (이에 보태어 행렬식의 기하학적 의미등도 추가 하였습니다.)

    christmas.gif

      아래는 는 선형변환의 이미지가 아닙니다. 왜냐하면 선형변환은 선(line)을 선(line)으로 보낸답니다.

         

      아래에서 선형변환을 만지고  느껴봅시다.

    • SWF 1(LT), 평면상에서 x 축에 대한 대칭 이동이라는 선형변환의 행렬 표현
    • SWF 2(LT), 평면상에서 y 축에 대한 대칭 이동이라는 선형변환의 행렬 표현
    • SWF 3(LT), 평면상에서 원점에 대한 대칭 이동이라는 선형변환의 행렬 표현

     

    • SWF 4(LT), 평면상에서 직선 y = x 에 대한 대칭 이동이라는 선형변환의 행렬 표현
    • SWF 5(LT), 평면상에서 상자를 늘리기, 줄이기, 확대, 밀기에 대응하는 선형변환의 행렬 표현

     

    • SWF 6(LT-Movie) with , 단위원에 대한 행렬 A 에 의한 선형변환의 이미지 (또는 행렬의 대각화)
    • SWF Image (LT3D), 단위 Cube에 대한 3차 행렬 A에 의한 선형변환의 이미지<3차원>

     

    SWF 6(LT-Movie) with , Image(LT3D),

     

    • SWF 7(Volume),  행렬식의 기하학적 의미 <3차원 경우는 부피, 2차원의 경우 면적>입니다.
      •  

     

      (ii) Understanding of Concepts

    * Matrices of L.T.

     

    <Appedix>

    반응형
    반응형

    1.

    *출처 OpenGL로 배우는 컴퓨터 그래픽스 주우석/한빛미디어

     

     

    동차 좌표란 개념이 왜 생겼나?

     

    V =     a*Vx + b * Vy + c * Vz    ->    Vector V 

    P = r + a*Vx + b * Vy + c * Vz    ->    Vertex P 

     

    원점 r 에 관한 정보를 제외 시켜버리면 벡터 V 와 정점 P 는 모두 ( a, b, c ) 이므로

    이 둘을 구분할수 없다. 이러한 불편을 해소시키기 위한것이 동차 좌표 개념이다.

    이는 3차원 좌표를 3개의 요소로 표시할것이 아니라 차원을 하나 높여 4개의 요소로 표현하자는

    것이다.

     

    * 여기서 r 은 임의 위치에서 원점 을 가르키는 벡터다. 즉 원점이라 할수 있다.

     

    =  a * Vx + b * Vy  + c * Vz + 0 * r       ->      Vector V 는 ( a, b, c, 0 )

    P = a * Vx + b * Vy  + c * Vz + 1 * r       ->        Vertex P 는 ( a, b, c, 1 )

     

    즉 마지막 요소 가 0 이면 Vector를 나타내고,

    마지막 요소가 1이면 정점을 의미 하도록 한것이다.

     

    이렇게 함으로써 Vector와 정점을 동일한 방법으로 표현할수 있다.

     

     

     

     

     

    좀더 쉽게 접근하기 위해 차수를 내려 2차원 평면의 예를 들어보자.

    2차원 평면상의 점 ( 1, 2 ) 를 동차 좌표로 표시하면 ( 1, 2, 1 ) 이 된다.

    이는 3차원으로 말하면 Z 축으로 높이 1 의 위치에 있는 점에 해당된다.

     

    엄밀히 말해 2차원 평면상의 점을 3차원 공간 상의 직선에 사상( mapping ) 시킨 것이 동차 좌표다.

    다시 말해 원점에서 출발해 ( 1, 2, 1 )를 통과하는 모든 3차원 좌표가 동일한 2차원 좌표 ( 1, 2) 를

    의미한다.

     

    즉 ( 1, 2, 1 ) =  ( 3, 6, 3 ) = ( 4, 8, 4 ) 이 된다.

     

    따라서 동차 좌표의 마지막 요소로 앞 요소를 나눈 값이 실제 3차원 좌표가 된다.

     

    같은 맥락에서 만일 3차원 동차 좌표를 4차원 ( x, y, z, w ) 좌표로 표시되면 3차원 실제 좌표는

    ( x / w, y / w, z / w )가 된다. 즉 ( 1, 2, 4, 1 ) = ( 2, 4, 8, 2 ) = ( 5, 10, 20, 5 ) 이며

    w = 0 일 경우 그 자체가 Vector ( x, y, z ) 를 나타낸다.

     

     

    2.동차좌표계(Homogeneous Coordinates) 간단한 정리

     

    좌표계 차원을 n 이라 할때, n개로 이루어진 좌표 만으로는

    표현할 수 없는 요소가 있으며 그 한계를 극복하기 위해

    n + 1로 표현한 좌표계를 동차 좌표계 (Homogeneous Coordinates) 라 한다.         

     

    - n + 1 좌표계에서는 논리상으로 어떤 무한대에 해당하는 좌표 영역이 있을때

    특정 점 nx / 0 을 통해 어떤 점을 무한대로 표현할 수도 있다.

     

    - Perspective Projection 할 시에 n 차원의 좌표계는 모니터 좌표계로 변환이

    되며, 이 경우 거리 축의 거리에 따라 특정 위치의 Vertices는 크기 및 위치가

    연산 되어 져야 하며 이때 사용되는 것이 동차좌표계 (Homogeneous Coordinates)의

    w 다. 즉, 각각의 n 차원 좌표들을 w로 나누어 적용시킨다.


    반응형
    반응형

    아핀 공간

    위키백과, 우리 모두의 백과사전.
    (아핀공간에서 넘어옴)

    수학에서 아핀공간(affine space)은 유클리드 공간 아핀기하학적 성질들을 일반화해서 만들어지는 구조이다. 아핀공간에서는 점에서 점을 빼서 벡터를 얻거나 점에 벡터를 더해 다른 점을 얻을 수는 있지만 원점이 없으므로 점과 점을 더할 수는 없다. 1차원 아핀공간은 아핀직선(affine line)이라고 한다.

    물리적 공간(상대론 이전의 의미에서)은 아핀공간일 뿐만 아니라 계량구조, 좀 더 구체적으로 말하면 등각구조를 갖고 있다.

    [편집]정의

    아핀공간은 벡터공간 정칙적으로 작용하는 집합이다. 즉, 이는 벡터공간의 주동차공간이다.

    이를 풀어서 말하면, S가 집합이고 V가 벡터공간이라 하자. 이때 함수

    \Theta : S \times S \to V : (a, b) \mapsto \Theta(a, b).

    를 생각하고, 그 함수값 Θ(a,b)를 a - b로 적어서 벡터 b에서 벡터 a를 빼는 것으로 보자. 이때 이 함수가 다음의 두 조건을 만족하면 S를 아핀공간이라 한다:

    1. S의 임의의 원소 b에 대해 Θb: S → V, Θb(a) = a - b는 전단사함수이고,
    2. S의 임의의 원소 a,b,c에 대해 (a-b) + (b-c) = a-c이다.

     

     

     



    볼록 집합

    유클리드 공간에 속하는 집합 A에 대해, 그 안의 임의의 두 점을 골랐을 때 둘을 연결하는 선분이 A에 포함될 경우, A를 볼록 집합(convex set)이라 한다. 예를 들어 속이 찬 은 볼록 집합이지만, 안쪽에 구멍이 있거나 초승달처럼 오목하게 들어간 부분이 있을 경우 볼록 집합이 아니다.

    볼록 집합은 구간 개념의 임의 차원에 대한 일반화로 볼 수 있다. 구간은 1차원에서의 볼록 집합이며, 임의 차원의 볼록 집합을 1차원에 임의 방향으로 투영하더라도 그 상은 구간이 된다.


    이동: 둘러보기찾기
    볼록 집합.
    볼록 집합이 아닌 예.
     

     

    반응형
    반응형

     

     

    기저(basis)와 좌표계(coordinate system), 고유값(eigenvalue)과 고유벡터(eigenvector)

     


     
    >> 기저(basis)와 좌표계(coordinate system)
     
    선형대수에서 기저(basis)라 함은 임의의 벡터공간 V에 대해서 어떤 벡터집합 S가 서로 “1차독립”이면서 벡터공간 V를 “생성”하면 벡터집합 S를 벡터공간 V의 기저라고 합니다.
     
    사실 위의 기저에 대한 정의는 지극히 수학교과서적인 정의이죠. 기저에 대한 모든 의미가 다 담겨있기는 하지만 이런 딱딱한 정의 내용을 보고 해당 정의가 의미하는 모든 것을 집어내기에는 어지간한 수학적 감각이 있지 않다면 어려울 것으로 생각됩니다. 물론 질문자 분께서도 같은 이유로 인해서 좀 더 쉽게 이해할 수 있는 방법에 대해 질문을 했을 것으로 생각됩니다.
     
    이런 엄밀하고 딱딱한 정의에서 벗어나 기존에 우리가 주로 활용하면서 익숙해져 있는 직각좌표계를 가지고 선형대수에서의 기저에 대한 이해를 할 수 있도록 설명을 한번 해 보고자 합니다. 물론 이런 느슨하고 부드러운 설명들은 수학적인 허점을 드러낼 수 있으므로 대충의 감과 이해를 얻고자 하는데 그 목적이 있으며, 이 이해를 바탕으로 다시 한번 엄밀한 정의를 검토함으로써, 해당 정의가 의미하는 바를 좀 더 깊이 있게 이해할 수 있도록 하면 되겠습니다.
     
    우선 우리에게 익숙한 2D 직교좌표계를 떠올려 보죠. 두 좌표축을 각각 x, y라고 하고 이 x, y 좌표 평면위의 모든 점에 대해서 x, y에 대한 좌표값 (a, b)로 표현할 수 있다는 것을 배워왔습니다. 여기서 x, y 좌표 평면위의 모든 점을 나타내어 주는 좌표값들은 수의 순서 짝으로써 벡터로 해석될 수 있습니다. 그리고 이 각각의 좌표축을 나타내는 두 단위벡터를 다음과 같이 생각할 수 있겠죠.
     
    v1 = (1, 0)
    v2 = (0, 1)
     
    여기서는 좌표축을 나타내는 기준벡터로써 길이가 1인 단위벡터를 사용했지만 벡터의 길이는 크게 중요하지 않습니다. 다만 길이가 0이 아닌 벡터이면 충분하다는 사실을 1차독립, 1차결합 등이 무엇을 의미하는지 아신다면 이해하실 겁니다. (1차독립과 1차결합은 기저를 이해하는데 중요한 개념이므로 이에 대한 이해가 없으시다면 먼저 교재를 통해서 이에 대한 이해를 구하시는 것이 좋겠습니다.)
     
    위의 두 벡터 v1, v2는 서로 1차독립이면서 동시에 1차결합을 통해서 2D 직교좌표계의 모든 점을 표현할 수 있는 벡터공간을 생성함을 알 수 있습니다. 따라서 위의 두 벡터의 집합 S = {v1, v2}는 2D 직교좌표계의 벡터공간 V를 생성하는 기저라고 할 수 있습니다.
     
    마찬가지로 3D 직교좌표계에 대해서 각각의 좌표축에 대한 단위벡터는 아래와 같습니다.
     
    v1 = (1, 0, 0)
    v2 = (0, 1, 0)
    v3 = (0, 0, 1)
     
    그리고 이 벡터들의 집합 S = {v1, v2, v3}는 3D 직교좌표계의 벡터 공간을 생성하는 기저라고 할 수 있습니다. 이해를 돕기 위해서 실제 예를 하나 들자면, 3D 직교좌표계 내의 한 점(벡터) (2, 5, 7)을 기저들의 일차결합으로 나타내면 아래와 같이 되겠죠.
     
    2 (1, 0, 0) + 5 (0, 1, 0) + 7 (0, 0, 1) = (2, 5, 7)
     
    그리고 3D 직교좌표계 내의 모든 점들은 위와 같이 기저 S를 사용한 1차결합으로 표현할 수 있으며, 따라서 집합 S는 3D 직교좌표계의 벡터 공간을 생성하는 기저라 할 수 있습니다.
     
    이제 기저와 좌표계에 대해서 조금 이해가 되셨는지 모르겠네요. 선형대수를 공부하기 전까지 우리는 막연히 좌표계를 세우고 해당 좌표계 내에서의 모든 점들을 수의 순서 짝으로 표현 하는 방법에 대해서 배웁니다. 그리고 이 개념들이 선형대수를 배우면서 좌표계는 각 좌표축을 대표하는 벡터들을 기저로 하는 벡터공간이며, 이 공간내의 모든 점들은 수의 순서 짝으로써 벡터로 해석될 수 있으며, 해당 벡터들은 기저 벡터들의 일차결합으로 표현할 수 있다는 사실을 이해하게 됩니다.
     
    그리고 이러한 사실들을 일반화함으로써, 기하학적으로 구상화할 수 없는 4차원 이상의 고차원에 대한 벡터에 대해서도 똑같이 적용할 수 있는 여러 벡터 연산들의 성질들을 연구할 수 있게 됩니다. 그리고 이런 수학적인 정리와 증명들은 각종 이공계의 여러 분야에서 상상 이상의 응용력을 발휘하며 인류 사회의 발전에 막대한 공헌을 한다고 할 수 있겠습니다.
     
    사실 위에서는 직관적인 이해를 돕기 위해서 2D, 3D의 직교좌표계라는 벡터공간의 특수한 경우로만 설명을 했지만, 선형대수를 조금 더 공부하시다 보면 일반화에 의한 차원의 확장이라든지, 또는 직교좌표계는 직교기저들이 이루는 벡터공간으로써 일반적인 벡터공간의 특수한 한 경우에 불과하다는 점 등을 이해하게 되실 겁니다. 다만, 여러 응용분야에 있어서 정규직교기저에 의한 벡터공간은 특히 유용하게 사용되는 경우가 많으므로, 정규직교기저에 대한 성질이 더 중요하게 다루어지기도 합니다.
     
    간단하게 실례를 든다면, 물리학에서 운동의 법칙을 배울 때, 처음에는 일차원 운동으로 개념을 잡습니다. 하지만 2, 3차원 혹은 그 이상의 차원으로 이 운동의 법칙을 확장하는 것은 의외로 쉽습니다. 그것을 가능하게 해주는 것이 바로 벡터공간에 대한 수학적 연구의 결과입니다. 그리고 혹시 컴퓨터 3D 게임을 하시는지는 모르겠지만, 선형대수에서의 3차원 정규직교기저에 대한 연구 결과의 응용 없이는 컴퓨터의 3D 그래픽스라는 분야 자체가 존재할 수 없습니다. 이것은 제가 3D 프로그래머로써 현업에서 응용을 하고 있기에 장담할 수 있습니다. 선형대수가 없는 3D 그래픽 소프트웨어 개발은 상상조차 할 수 없습니다.
     
    설명이 많이 부족하기는 하지만 위에서 언급한 2/3 차원 직교좌표계가 어떻게 벡터공간으로 대응이 되는지에 대한 이해를 바탕으로 다시 한번 교재의 정의를 살펴봄으로써 기저에 대한 이해 및 기저와 좌표계 사이의 관계에 대한 이해를 구하시면 도움이 되실 것이라 생각합니다.
     
     
    >> 고유값(eigenvalue)과 고유벡터(eigenvector)
     
    고유값과 고유벡터에 대한 정의는 그리 어려운 것이 아닙니다만, 기저를 설명할 때 언급했던 것처럼 정의만 보고 고유값과 고유벡터가 도대체 뭔지 이해를 하는 것이 쉽지만은 않죠. 하지만 선형대수에 있어서 고유값과 고유벡터에 대한 이해는 상당히 중요합니다. 아마 질문자 분께서 이 고유값과 고유벡터에 대한 내용을 제대로 이해하신다면, 벡터에 선형변환을 가하는 선형 연산자로써의 행렬이라는 존재에 대해서 조금 더 깊이 이해할 수 있는 계기가 될 수 있을 것입니다.
     
    다만, 걱정되는 것은 저의 짧은 지식에 의한 설명으로 제대로 의미 전달이 가능할 것인가가 문제라면 문제겠죠. 어쨌든 시작해 보도록 하겠습니다. 고유값, 고유벡터에 대한 교과서적인 정의는 다음과 같습니다.
     
    A가 행렬이고 같은 차원의 벡터 x에 대해서 Ax = λx를 만족하면, 스칼라 λ를 행렬 A의 고유값이라 하고, 벡터 x를 스칼라 λ에 대응하는 행렬 A의 고유벡터라고 한다.
     
    고유값과 고유벡터에 대한 정확한 이해를 위해서 먼저 고유값과 고유벡터의 기하학적인 성질을 설명을 드리자면, 행렬 A가 어떤 벡터 x에 선형변환을 가하는 선형연산자일 때, 즉 회전변환과 확대/축소 변환을 가하는 연산자일 때, 해당 벡터 x에 대해서 회전변환은 가하지 않고 확대/축소 변환만을 가한다면 이 벡터 x는 A의 고유벡터가 된다는 뜻입니다. 그리고 이런 경우 확대/축소의 양을 나타내는 스칼라를 따로 분리할 수 있게 되는데 이 스칼라 값이 고유값 λ가 된다는 의미입니다.
     
    이해를 돕기 위해서 실제 계산을 한번 해 보겠습니다. 예를 들어서 확대연산자의 표준 행렬이라고 할 수 있는 다음 행렬에 아무 벡터나 곱해보면 위에서 보았던 Ax = λx를 만족한다는 것을 쉽게 알 수 있습니다.
     

     


    위의 행렬에서는 결국 (1, 0)과 (0, 1) 두 개의 고유벡터가 존재하며 이들 각각에 대응되는 고유값은 k가 된다는 것을 알 수 있습니다. 여기서 자세한 계산 과정을 적지는 않겠습니다. 계산은 책을 보고 훈련을 통해서 익히면 그만입니다. 이해가 없는 계산은 아무짝에 쓸모없는 소모전에 불과 하므로 여기서는 이해에 중점을 맞출 것이며 될 수 있으면 구체적인 계산은 피하도록 하겠습니다. 위의 행렬로 직접 한번 고유값과 고유벡터를 계산해 보시고 결과를 확인해 보세요.
     
    자, 이쯤 왔으면 뭔가 딱 느껴지는 것이 있어야 합니다. 위의 행렬은 어떤 벡터이든지 Ax = λx를 만족하는 변환을 가합니다. 그리고 이러한 벡터들은 고유벡터인 (1, 0), (0, 1) 두 벡터의 선형결합에 의해 표현될 수 있습니다. 그리고 이 두 고유벡터는 일반적으로 생각하는 2차원의 정규직교기저벡터와 정확하게 일치합니다.
     
    우리는 고유값과 고유벡터의 기하학적 성질을 알 고 있으므로, 위 형태의 행렬이 2차원 정규직교기저가 생성하는 벡터 공간에서 확대/축소 연산을 가하는 표준 행렬이라는 것을 쉽게 알 수 있습니다. 그리고 이쯤에서 어떤 행렬 A가 있을 때, 그 행렬로부터 힘들게 계산해서 구해내는 고유값과 고유벡터가 어떤 의미인지를 어느 정도는 이해할 수 있을 것이라 생각합니다.
     
    설명을 계속해 보겠습니다. 여기서 부터는 잘 따라오셔야 합니다. 일반적으로 우리가 머릿속에 그리는 2차원 직교좌표계에서의 벡터들에게 선형연산을 가하는 어떤 행렬 A가 있을 때, 이 행렬 A가 위에서 본 확대/축소 행렬의 형태가 아닌 이상, 그 행렬이 2차원 정규직교기저가 만드는 벡터공간 내에서는 확대/축소 뿐 아니라 회전변환까지도 가하게 됩니다. 즉, 이것은 이 행렬 A가 2차원 정규직교기저의 벡터 공간에서는 벡터들에게 어떤 변환을 가할지 계산하기가 복잡하다는 의미가 됩니다. 단순히 확대/축소 변환만 가하는 행렬과 확대/축소 및 회전변환까지 가하는 행렬 중 어느 행렬이 더 이해하기 쉽고 계산하기 쉬우며 더 나아가 어떤 문제 해결에 응용하기 쉬운지는 이견의 여지가 없을 것입니다.
     
    이제 어느 정도 결론에 도달해 가는 것 같습니다. 이제 우리는 어떤 선형연산자로써의 행렬이 있을 때, 이 행렬로부터 고유값과 고유벡터를 계산해 냄으로써, 이 행렬이 벡터에 가하는 변환을 고유벡터들이 기저를 이루는 고유공간에서의 변환으로 해석함으로써, 회전 변환은 배제하고 확대/축소 변환만으로 이해하고 응용할 수 있게 되었습니다.
     
    확실한 이해를 위해서 구체적인 예를 한 가지만 들어 보겠습니다. 다음과 같은 행렬 A가 있습니다.

     
    위 행렬 A의 고유벡터는 v1 = (1, 1), v2 = (-1, 1) 이고, 고유값은 λ1 = 3, λ2 = -1입니다. 그러면 이 행렬 A가 벡터 x = (x1, x2) 에 변환을 가할 때, 이 변환을 고유벡터 v1, v2가 기저를 이루어 생성하는 고유벡터 공간에서 이해를 하면, v1 방향으로는 3배, v2 방향으로는 -1배한 벡터들의 합으로 변환이 가해진다는 것을 알 수 있습니다.
     
    위 설명이 사실인지 직접 계산을 통해서 이해를 해 보죠.

     

     
    위의 풀이 과정으로 x = (2, 3) 인 경우를 계산해 보면 Ax = (8, 7) 이 나온다는 것을 알 수 있습니다. 그리고 이것은 실제 Ax를 행렬 계산으로 계산했을 때 구해지는 값이기도 하다는 것을 확인해 보시기 바랍니다. 그리고 이것을 그림으로 나타내면 아래 그림과 같습니다.

     

     

     

     
    위 그림을 보시면 보다 더 명확하게 이해가 가실 겁니다. 즉, 행렬 A가 벡터 x에 가하는 변환을 행렬 A의 고유벡터들이 기저를 이루어서 생성되는 고유공간에서 이해를 하면, 고유 벡터들의 확대/축소 연산만을 가지고도 이 변환을 이해할 수 있게 된다는 것입니다. 이것이 원래의 직교기저가 생성하는 벡터 공간에서의 변환을 이해하는 것 보다 훨씬 쉽다는 것을 그림을 통해서 이해해 보시기 바랍니다. 그리고 이러한 결과로 인해서 고유값과 고유벡터의 개념은 이공계 분야에서 상당히 중요한 응용에 사용되는 경우가 아주 아주 많습니다.
     
    자, 이제 어느 정도 이해가 되셨으리라 생각합니다. 항상 느끼는 거지만, 수학이란 학문은 수식을 제외하고 말로만 설명을 하려면 상당히 힘들죠. 하지만 바꾸어 말하면 수식으로만 설명이 된 내용들은 탁월한 감각이 있지 않은 사람들이 보기에는 쉽게 이해하기가 힘들다는 것도 분명한 사실입니다. 저 역시도 후자에 속하는 한 사람으로써 고유값과 고유벡터를 이해하는데 애를 먹었던 기억이 있습니다.
     
    짧은 지식으로, 그리고 말로 수학을 설명 하느라 핵심 내용이 어느 정도로 잘 전달되었는지 모르겠지만, 그래도 어렴풋이나마 이해를 하셨다면 여기서의 이해를 잘 떠올리면서 다시 한번 교재의 정의들과 응용에 활용되는 예제들을 풀어 보시기 바랍니다. 분명 이전에 잘 모르고 공식으로만 풀어내던 고유값과 고유벡터에 대해 새로운 눈을 뜨게 되실 것이라 생각합니다. 아울러 아까도 잠깐 업급 했지만, 선형연산자로써의 행렬을 바라보는 눈도 이전 보다는 한층 더 발전된 시각으로 바로 볼 수 있게 되었기를 바래봅니다.
     
    그럼 행운을 빕니다.

     

     

    참고]

    NAVER 지식인


    반응형

    '수학 (Mathematics) > 3D수학' 카테고리의 다른 글

    동차 좌표  (0) 2012.11.02
    아핀공간과 볼록집합  (0) 2012.11.02
    IntersectTriangle 분석  (0) 2012.11.02
    픽킹 ( 광선과 오브젝트 충돌판정 )  (0) 2012.11.02
    3D 기하학  (0) 2012.11.02
    반응형

    출처: http://www.gamza.net

     

    copyrightⓒ 김성수 [2002년 05월 26일]

     

    이글은 D3D의 Pick예제에 나와있는 IntersectTriangle에 관한 설명입니다. 이 함수가 하는일이나 사용법에 대해선 예제에 잘 나와있기때문에 이런것을 설명하지는 않습니다. 이글의 목적은 함수 자체가 어떤 원리로 동작을 하는지를 이해하는것이죠.

    IntersectTriangle은 단순히 소스분석만해서는 도저히 이해를 할 수 없습니다.
    가뜩이나 벡터연산이 복잡해 머리가 아픈데, 수학적인 레벨에서 최적화를 해놓았으니 더욱 암호처럼 보일수 밖에....
    그럼 IntersectTriangle의 동작원리에 대해 하나씩 알아보겠습니다.

    1. 삼각형 점포함 테스트
    IntersectTriangle이 반직선과 삼각형의 교차판정을 하는방법은 2차원적으로 해석될수 있습니다.
    반직선과 삼각형 평면의 교점이 삼각형에 포함되는지를 검사하는것이죠.
    그런데 특별한 사정때문에 이전에 제가 썼던 글에 있는 점포함테스트를 사용하지 않습니다.
    약간은 특이한 방법을 쓰게되죠.


     
     
    그림을 보시면 벡터가 세개 나옵니다. OA,OB는 고정된 벡터이고 OP는 임의의 벡터입니다.
    임의의 벡터 OP를 벡터 OA,OB를 가지고 표현해 봅시다.
    OP = u * OA + v * OB ( u,v는 임의의 실수 )
    벡터의 영역문제에서 자주본 꼴이죠? (생각이안나는 사람은..정석을 뒤져봅시다)
    u와 v에 제약을 가하면 점P는 특정한 영역을 표현하게 됩니다.
    옴옴...뭘하려는지 알겠다고요?
    그렇습니다. u,v에 어떤 조건을 붙여서 P가 삼각형 OAB영역을 표현하도록 하려는겁니다.
    P가 OAB영역을 표현하기위한 조건은, 삼각형의 변(①②③)에대해 각각 하나씩 있습니다.
    ① : 0 ≤ u
    ② : 0 ≤ v
    ③ : u + v ≤ 1
    이 조건들은 알아서덜 증명을... (①②번 조건은 말이 필요없고...③번조건은 직선 AB가 t*OA + (1-t)*OB 임을 이용)
    위조건을 만족하는 u,v에 대해 P가 표현하는 영역은 삼각형 OAB입니다.
    점 P가 삼각형 OAB에 포함되는지를 검사하는것은 u,v가 위조건을 만족하는지를 검사하는것과 같다는 얘기.
    IntersectTriangle이 출력하는 u,v가 지금껏 이야기해온 u,v입니다. 반직선과 삼각형 평면의 교점이 P, 삼각형의 각 꼭지점이 O,A,B인 셈이죠. 따라서 반직선과 삼각형의 교차판정은 코드중에 다음처럼 나타납니다.
        if( *u < 0.0f || *u > det )
            return FALSE;
        if( *v < 0.0f || *u + *v > det )
            return FALSE;
    
    Picking일 경우 IntersectTriangle이 출력하는 u,v를 사용하면 마우스의 3차원 위치와 카메라와의 거리를 쉽게 구할수 있습니다.
    마우스의 3차원좌표 = v0 + u * ( v1 - v0 ) + v * ( v2 - v0 )
    카메라와의 거리 = |마우스의 3차원좌표-orig|

    2. 벡터분해
    문제는 OP를 OA,OB로 표현하는것. 다시말해 u,v값을 어떻게 구하는가 하는것입니다.
    이제 OP를 OA,OB로 분해하는법을 생각해봅시다.

     
     
    왼쪽그림을 보면 v = |Ob| / |OB| 임을 쉽게 알 수 있죠?
    이때 벡터 OB와 Ob를 OA에 수직인 벡터 nA에 투영을 한것이 오른쪽 그림입니다.
    보다시피 한쌍의 닮은꼴 삼각형이...... 옴옴...그냥 아래식을 주욱 읽으시면 걍 이해가....
    (도데체 그림때문에 설명할게 없잖아!...ㅡ.ㅡ;;)
    v = |Ob|/|OB| = |Ob||nA|cosθ/|OB||nA|cosθ = Ob•nA/OB•nA
    여기서 벡터 Ob와 OP는 법선 nA에 대해 같은 정사영을 갖습니다.
    Ob•nA = OP•nA
    v = Ob•nA/OB•nA = OP•nA/OB•nA
    같은 방법으로 u를 표현하면..
    u = OP•nB/OA•nB
    이제 법선과 내적값을 구하는일만 남았군요.

    3. 내적값(OP•N)과 법선(N)
    실제로 IntersectTriangle은 공간상의 반직선과 평면의 교점(P)을 구하지 않고 u,v값을 계산해 냅니다.
    교점이 없이도 OP•N 값을 알아내는 방법이 있기때문인데요, 바라보는 방향에 비책이 숨어 있습니다
     

     
     
    왼쪽그림은 IntersectTriangle의 입력들을 그려놓은것입니다. 오른쪽 그림은 이것을 dir과 평행한 방향으로 바라본 그림이고요.
    그림에 표시된 법선(N)은 V0,V2를 포함하고 바라보는 방향과 평행한 평면의 법선벡터입니다.
    이때, 점 P와 orig는 이 벡터(N)에대해 '같은 정사영'을 갖는 점들임을 알수 있습니다. 즉 다음이 성립한다는 말이죠.
    (orig-V0)•N == (P-V0)•N
    N을 법선으로 하는 평면은 V0,V2,(V0+dir)을 포함하는 평면이고(dir과 평행한 방향으로 바라봤으므로),
    따라서 법선 N은 다음과같이 구해집니다.
    N = dir ⅹ ( V2 - V0 )
    연산자 'ⅹ' 가 외적인건 아시죠?
    이제 모든값을 알았으니 정리를 좀 해볼까요?
    u = tvec • ( dir ⅹ e2 ) / e1 • ( dir ⅹ e2 )
    음...갑자기 이상한것들이 튀어나와서 죄송. 식을 쓰다보니 점점 길어지는것 같아서... 
    앞으로는 아래와 같은 정의를 사용하도록 하겠습니다.
    e1 = V1 - V0
    e2 = V2 - V0
    tvec = orig - V0
    이제야 소스의 다음부분에 대한 설명이 끝났군요.
    D3DXVec3Cross( &pvec, &dir, &edge2 );
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );
    *u = D3DXVec3Dot( &tvec, &pvec );
    FLOAT fInvDet = 1.0f / det;
    *u *= fInvDet;
    
    사실 여기까지가 설명의 끝입니다.
    나머지는 최적회일 뿐이죠.

    4. 최적화
    u를 구한것과 같은 방법으로 v를 구해 봅시다.
    v = tvec • ( e1 ⅹ dir ) / e2 • ( e1 ⅹ dir )
    여기에 약간의 수학적성질을 적용해보면 재미있는 사실을 알게됩니다.
    A•(BⅹC) = B•(CⅹA) = C•(AⅹB)
    이것을 이용해서 v의 분모부분을 변형해볼까요?
    e2 • ( e1 ⅹ dir ) = e1 • ( dir ⅹ e2 )
    오호...잘보니 v,u의 분모부분이 같은넘이었군요!
    분자부분도 같은방법으로 변형시켜보면 소스코드가 이해가 되실겁니다.
    (이것두 역시 최적화. 나중에 t 를 계산할때 외적결과를 또 써먹으려고 변형을 해 놓은거죠. )
    이것으로 다음소스에 대한 설명이 끝났습니다.
    D3DXVec3Cross( &qvec, &tvec, &edge1 );
    *v = D3DXVec3Dot( &dir, &qvec );
    *v *= fInvDet;
    
    IntersectTriangle은 연산을 수행하는 도중 판정결과를 알 수 있다면 바로 리턴하는 방식으로, 필요없는 연산이 일어나지 않도록 구성되어있습니다.
    그중 하나가 첫번째 나온 비교문입니다. 
        if( det < 0.0001f )
            return FALSE;
    
    이 비교문은 코딩 차원에서 본다면 0으로 나누는 에러방지와 det값과 u,v값의 비교를 쉽게해주는 역할을 합니다만, 수학적으로 보면 이코드의 또다른면을 볼 수 있게됩니다.
    이 조건이 참이되는 경우를 생각해 보도록 합시다. det값은 법선벡터 N과 변벡터 e1의 내적값입니다.
    이값이 0이면 삼각형은 dir과 평행한 평면에 존재하는것 입니다. 만약 이 값이 0보다 작으면 삼각형이 뒤집어져 있는경우죠.
     
     
     

     
     
    여기서 잠깐!
    D3D8.1 버젼부터는 det에 절대값을 취함으로써 뒤집어진 면도 교차라고 판정하도록 되어있습니다.
    사실 이전 버젼의 예제들은 det값을 그대로 사용해서, IntersectTriangle함수가 반직선과 삼각형의 교차판정뿐 아니라 뒤집어진 삼각형이 아닌지까지 검사하도록 만들어져 있었던겁니다.
    이것을 함수의 목적에 맞도록 수정했다고나 할까요?
    하지만 det에 절대값을 취하는 부분만 없애면 '별도의 연산없이' 뒤집어진 삼각형을 검사해낼 수 있다는것을 꼭 알아두시길...

    5. t : orig와 P 의 거리
    소스에대한 의문들이 풀리셨나 모르겠습니다. 근데 교차판정과는 전혀 상관없는 코드가 하나 더있네염. 안그래두 엄청시리 길어졌는데...그렇다고 안하고 놔두자니 영 찜찜...
    다음은 아직 설명하지 않은 '유일한' 코드입니다.
        *t = D3DXVec3Dot( &edge2, &qvec );
        *t *= fInvDet;
    
    우선 설명을 하기전에 t와 det를 적당히 변형하도록 하겠습니다.
    ( 각종 연산결과들을 최대한 재사용하려고 변형해 놓은거라서 변형하지 않고는 설명이 넘 어렵습니다. )
    det = e1 • ( dir ⅹ e2 ) = dir • ( e2 ⅹ e1 )
    t = e2 • ( tvec ⅹ e1 ) = tvec • ( e1 ⅹ e2 ) = -tvec • ( e2 ⅹ e1 )
    ( ∵ AⅹB = -BⅹA )
    공식을 보고 있자니 원래 문제를 e1,e2를 포함하는 평면과 평행한 방향으로 다시 보고싶어집니다.
    (삼각형을 옆에서 바라봤으니 삼각형은 선분으로 보입니다.)
     
     

     
     
    우리가 구하고자 하는 t는 dir을 단위로하는 시점에서 교점까지의 거리입니다.
    |P-orig| = t * |dir|
    ∴ t = |P-orig|/|dir| = |P-orig||N|cosθ/|dir||N|cosθ = (P-orig)•N / dir•N
    (여기서 N = e2 ⅹ e1 )
    근데 N에 대해서 벡터 P-orig 와 -tvec이 같은 정사영을 갖습니다. 따라서...
    (P-orig)•N == (-tvec)•N
    ∴ t = (P-orig)•N / dir•N = (-tvec)•N / dir•N

    우~~~아~~~~~정말로 길군요.
    말로 설명하면 금방될것을....황금같은 주말에 이틀동안 집에 틀어밖혀서 이것만 써댔네염.....T.T...
    이것으로 소스가 완전히 이해되셨기를 바랍니다.
    이해가 안되신다면 질문주세염.
    거럼...오늘 프랑스전.... 2:1 에 5000원 걸었는데......
    '한국승'에 걸었답니다. 코리아팀 파이팅! o(^O^)O
    - 참고소스 DX8 -
    //-----------------------------------------------------------------------------
    // Name: IntersectTriangle()
    // Desc: Given a ray origin (orig) and direction (dir), and three vertices of
    //       of a triangle, this function returns TRUE and the interpolated texture
    //       coordinates if the ray intersects the triangle
    //-----------------------------------------------------------------------------
    BOOL CMyD3DApplication::IntersectTriangle( const D3DXVECTOR3& orig,
                                           const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                           D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                           FLOAT* t, FLOAT* u, FLOAT* v )
    {
        // Find vectors for two edges sharing vert0
        D3DXVECTOR3 edge1 = v1 - v0;
        D3DXVECTOR3 edge2 = v2 - v0;
    
        // Begin calculating determinant - also used to calculate U parameter
        D3DXVECTOR3 pvec;
        D3DXVec3Cross( &pvec, &dir, &edge2 );
    
        // If determinant is near zero, ray lies in plane of triangle
        FLOAT det = D3DXVec3Dot( &edge1, &pvec );
    
        D3DXVECTOR3 tvec;
        if( det > 0 )
        {
            tvec = orig - v0;
        }
        else
        {
            tvec = v0 - orig;
            det = -det;
        }
    
        if( det < 0.0001f )
            return FALSE;
    
        // Calculate U parameter and test bounds
        *u = D3DXVec3Dot( &tvec, &pvec );
        if( *u < 0.0f || *u > det )
            return FALSE;
    
        // Prepare to test V parameter
        D3DXVECTOR3 qvec;
        D3DXVec3Cross( &qvec, &tvec, &edge1 );
    
        // Calculate V parameter and test bounds
        *v = D3DXVec3Dot( &dir, &qvec );
        if( *v < 0.0f || *u + *v > det )
            return FALSE;
    
        // Calculate t, scale parameters, ray intersects triangle
        *t = D3DXVec3Dot( &edge2, &qvec );
        FLOAT fInvDet = 1.0f / det;
        *t *= fInvDet;
        *u *= fInvDet;
        *v *= fInvDet;
    
        return TRUE;
    }

    반응형
    반응형

    픽킹 ( 광선과 오브젝트 충돌판정 )


    http://blog.naver.com/zeowing/90082924441


    copyrightⓒ 김성수 [2002년 05월 21일]

    BLACK&WHITE 같은 마우스를 만들려면 마우스의 2D위치를 3D공간좌표로 변환하는것이 필요해집니다. 등장하는 '신의손'이 실제 공간좌표를 갖기때문이죠. 이것은 상당히 효과만점인 반면, 물체를 Pick할줄만 알면 아주 간단하게 끝나는 아주 쉬운 기법입니다.
    D3D의 Pick예제를 보면 물체를 picking하는 기법이 깔끔하게 나와있으니 그걸 그대로 사용하도록 하겠습니다.
    2D마우스 좌표를 3D좌표로 변환하는 순서는 다음과 같습니다.
    (1) 마우스 좌표를 가지고 공간상에 반직선을 만든다. (언프로젝션)
    (2) 반직선과 교차하는 폴리곤중 가장 가까운것을 택한다. ( picking )
    (3) 직선과 폴리곤의 교점을 구한다.( == 3D마우스 좌표 )

    1. 언프로젝션
    우선 마우스 좌표에 해당하는 3D점을 하나 구합니다.
    ( 아래식이 이해가 안되시는 분들은 '언프로젝션 ( Unprojection )' 과 그것에 링크된문서들을 꼭 읽어보세요. 안읽어보셔도 당장 써먹는데야 지장이 없겠지만....배워서 남주는거 아니니깐요.)

     
     m_pd3dDevice->GetViewport(&vp);
     m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );
     GetCursorPos( &ptCursor );
     ScreenToClient( m_hWnd, &ptCursor );
     v.x = ((  (((ptCursor.x-vp.X)*2.0f/vp.Width ) - 1.0f)) - matProjection._31 ) / matProjection._11;
     v.y = ((- (((ptCursor.y-vp.Y)*2.0f/vp.Height) - 1.0f)) - matProjection._32 ) / matProjection._22;
     v.z =  1.0f;

    언프로젝션하는 부분을 주의하세요. D3D예제에 있는대로 하시면 안될경우가 있습니다.
    ( 투영행렬에 클리핑행렬이 포함된것 같은경우 )
    ...
    이제 카메라 좌표와 구해진 점을 잇는 반직선을 만들면 되죠,

            m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
            D3DXMatrixInverse( &m, NULL, &matView );
            vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
            vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
            vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
            vPickRayOrig.x = m._41;
            vPickRayOrig.y = m._42;
            vPickRayOrig.z = m._43;

    2. Picking
    D3D예제를 보시면 IntersectTriangle 함수를 사용해서 위에서 구한 반직선이 삼각형에 교차하는지를 검사해서 Pick를 수행하게 됩니다.
    근디 우리가 해야할건...그중에서 카메라에 젤 가까운넘을 골라내는겁니다.
    거럼 ...어떤넘이 카메라에 가장 가까운 넘인가???

    BOOL CMyD3DApplication::IntersectTriangle( const D3DXVECTOR3& orig,
                                           const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                           D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                           FLOAT* t, FLOAT* u, FLOAT* v )

    IntersectTriangle함수의 6번째 인자(t) 는 출력용 인자입니다. 폴리곤과 반직선의 교점이 카메라에서 얼마나 떨어져 있는지를 알려주죠.
    다시말하면....교차가 발견될때마다 출력된 t 값을 조사해서...젤 작은넘을 유지하도록 하면 됩니다.
    t가 제일 작은 폴리곤이 실제로 picking된 폴리곤이죠.

    3. 3D마우스 좌표계산
    최종적인 3D좌표는 반직선과 IntersectTriangle함수의 출력으로 얻어진 t값으로부터 다음과 같이 구해집니다.

    3D마우스 좌표 = vPickRayOrig + vPickRayDir * t ;



    자...끝났습니다.

    참....마우스가 화면상의 어떤것도 선택하고 있지 않을경우를 별도 처리 해야한다는 것을 잊지마세요.
    아무것도 선택되지 않았다면 '카메라로부터의 기본거리'를 적용하는 것이 가장 자연스러울듯 합니다.

    t = 기본거리 / D3DXVec3Length( vPickRayDir ) ;


    이렇게 처리하면 되죠.

    이거...응용할데가 많겠죠?
    레벨편집기라던가, RPG, 전략시뮬같은데서도 유용하게 쓰일듯...

    펌 http://www.gamza.net/









    [출처] [Direct3D] 픽킹(Picking) - 지형 픽킹|작성자 dovcat

     

     

     

     

     

     

     

    소스 코드

     

     FLOAT PointX;
     FLOAT PointY;

     // 뷰 포트 정보를 받아옵니다.
     D3DVIEWPORT9 ViewPortInfo;
     mDevice->GetViewport(&ViewPortInfo);

     // 프로젝션 매트릭스를 얻어옵니다.
     D3DXMATRIX Proj;
     mDevice->GetTransform(D3DTS_PROJECTION, &Proj);
      
     // 마우스 포인트를 투영창의 좌표로 변환합니다.
     PointX = (2.0f * LOWORD(lParam) / ViewPortInfo.Width - 1.0f) / Proj(0, 0);
     PointY = (-2.0f * HIWORD(lParam) / ViewPortInfo.Height + 1.0f) / Proj(1, 1);

     // 투영창의 좌표로 변환된 포인트를 가지고 광선을 생성합니다.
     RAY Ray;
     Ray.origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
     Ray.dir  = D3DXVECTOR3(PointX, PointY, 1.0f);

     // 뷰 매트릭스를 얻어옵니다.
     D3DXMATRIX View;
     mDevice->GetTransform(D3DTS_VIEW, &View);

     // 뷰 매트릭스의 역행렬을 구합니다.
     D3DXMATRIX ViewInverse;
     D3DXMatrixInverse(&ViewInverse, 0, &View);

     // 포인트를 월드 스페이스의 좌표로 변환합니다.
     D3DXVec3TransformCoord(&Ray.origin, &Ray.origin, &ViewInverse);
     D3DXVec3TransformNormal(&Ray.dir, &Ray.dir, &ViewInverse);
     D3DXVec3Normalize(&Ray.dir, &Ray.dir);

     

    그리고 이 놈으로 광선과 지형(삼각형(face))의 교차를 검사하세요.

    D3DXIntersectTri()

    Direct3D에서 제공하는 제 입장에선 아주 강력한 함수로군요.

    광선과 평면식의 조합을 어쩌구저쩌구 해서 교차 테스트릴 해도 마음대로 성공하지 못했는데...

    이 녀석 하나로 코드도 줄고 테스트도 한 번에 되더군요... 흑흑....


     

     

    한가지 덧붙이자면 월드까지 간 형태에서 로컬좌표까지 내려가 충돌판정을 할 수 있는데

     

    이는 동일하게 광선을 로컬좌표까지 변환하여 충돌판정을 하면 된다

     

    윈도우좌표부터 로컬좌표까지 어느좌표에서의 충돌판정이 좋다라기보다는 각 상황에 맞게 최적의 좌표에서 충돌판정하는 것이

     

    최적이라 할 수 있겠다

     

     

     

    IntersectTriangle 의 좀 더 자세한 설명을 감자닷넷에서 퍼왔다,

     

     

    1. 삼각형 점포함 테스트
    IntersectTriangle이 반직선과 삼각형의 교차판정을 하는방법은 2차원적으로 해석될수 있습니다.
    반직선과 삼각형 평면의 교점이 삼각형에 포함되는지를 검사하는것이죠.
    그런데 특별한 사정때문에 이전에 제가 썼던 글에 있는 점포함테스트를 사용하지 않습니다.
    약간은 특이한 방법을 쓰게되죠.

    그림을 보시면 벡터가 세개 나옵니다. OA,OB는 고정된 벡터이고 OP는 임의의 벡터입니다.
    임의의 벡터 OP를 벡터 OA,OB를 가지고 표현해 봅시다.

    OP = u * OA + v * OB   ( u,v는 임의의 실수 )

    벡터의 영역문제에서 자주본 꼴이죠? (생각이안나는 사람은..정석을 뒤져봅시다)
    u와 v에 제약을 가하면 점P는 특정한 영역을 표현하게 됩니다.
    옴옴...뭘하려는지 알겠다고요?
    그렇습니다. u,v에 어떤 조건을 붙여서 P가 삼각형 OAB영역을 표현하도록 하려는겁니다.
    P가 OAB영역을 표현하기위한 조건은, 삼각형의 변(①②③)에대해 각각 하나씩 있습니다.
    ① :     0 ≤ u
    ② :     0 ≤ v
    ③ : u + v ≤ 1
    이 조건들은 알아서덜 증명을... (①②번 조건은 말이 필요없고...③번조건은 직선 AB가 t*OA + (1-t)*OB 임을 이용)
    위조건을 만족하는 u,v에 대해 P가 표현하는 영역은 삼각형 OAB입니다.
    점 P가 삼각형 OAB에 포함되는지를 검사하는것은 u,v가 위조건을 만족하는지를 검사하는것과 같다는 얘기.
    IntersectTriangle이 출력하는 u,v가 지금껏 이야기해온 u,v입니다. 반직선과 삼각형 평면의 교점이 P, 삼각형의 각 꼭지점이 O,A,B인 셈이죠. 따라서 반직선과 삼각형의 교차판정은 코드중에 다음처럼 나타납니다.

        if( *u < 0.0f || *u > det )
            return FALSE;
        if( *v < 0.0f || *u + *v > det )
            return FALSE;
    

    Picking일 경우 IntersectTriangle이 출력하는 u,v를 사용하면 마우스의 3차원 위치와 카메라와의 거리를 쉽게 구할수 있습니다.

    마우스의 3차원좌표 = v0 + u * ( v1 - v0 ) + v * ( v2 - v0 )
    카메라와의 거리 = |마우스의 3차원좌표-orig|
     
     
     
    p.s 좀더 자세한 설명은 다음에...

    반응형
    반응형

    반응형
    반응형

    감자닷넷 주인장께서 홈페이지 리뉴얼을 하셨드라고요 다시 올립니다~

     

     

    http://www.gamza.net/

     

     

     

    반사벡터


     

    전반사는 물체가 충돌하여 튕겨나갈때 라던가, 빛의 반사, 당구공등의 구현에 사용되는데, 이것은 벡터를 가지고 생각해보면 생각보다 매우 간단하게 구현됨을 알수 있습니다. 


    전반사

    전반사는 입사벡터와 반사벡터의 크기가 동일하고, 입사각과 반사각이 같은 것을 말합니다.




    여기서 우리가 풀고자 하는 문제는 충돌면의 법선벡터(N)와 입사벡터(D)만을 가지고 반사벡터([?])를 만들고자 하는것입니다.
    그림을 보고 머리를 굴려봅시다.


    negDprj : 벡터-D를 법선N에 투영한 벡터

    위에나오는 직각삼각형은 모두 '합동'입니다.
    따라서 [?]는 벡터negDprj를 두배로 한 벡터와 벡터D의 더한 벡터임을 알 수 있습니다.

    [?] = 2 negDprj + D

    여기에 투영벡터공식(negDprj)을 적용하면.....

    [?] = ( 2 * (-D•N)/(N•N) ) N + D

    만약 법선 벡터 N이 단위벡터라고 가정하고 정리하면...

    [?] = ( 2 * (-D•N) ) N + D

     


     

     

     

    미끄러짐 벡터


     

     

    충돌시엔 보통 미끄러짐 처리를 하게 됩니다. 이럴때 사용하는 미끄러짐 벡터를 구하는 법을 알아보도록 하겠습니다.

    충돌시 속도벡터는 다음과 같이 충돌면에 수직인 성분과 평행인 성분으로 분리됩니다.
    여기서 수직성분은 없애고 수평성분에 해당하는 이동을 하는것이 여기서 구현하고자 하는 '미끄러짐'입니다.

    자, 이제 문제는 물체의 속도벡터(V)와 충돌면의 법선벡터(N)로부터 속도벡터의 수평성분을 구하는 것으로 정리되었습니다.
    그런데 여기서 V의 수직성분이라 함은....V를 N에 투영한 벡터(Vprj)를 말합니다.
    따라서 투영벡터공식을 적용해서 Vprj를 구하면...
    Vprj = ( (V•N)/(N•N) ) N
    V를 알고, V의 수직성분을 알게되었으니 우리의 목표인 V의 수평성분은 아래와 같이 구해집니다.
    속도벡터의 수평성분 = V - Vprj = V - ( (V•N)/(N•N) ) N
    만약 법선 벡터 N이 단위벡터라고 가정하고 정리하면...
    속도벡터의 수평성분 = V - (V•N) N
     
     
     
     
     

    반응형
    반응형

    ■ 3D Engine

    new RHW(Reciprocal Homogeneous W)란? < 김성완 - 2001년 7월 23일 >

    "W는 Homogeneous coordinates의 네번째 성분이고 homogeneous coordinates 는 우리말로 동치 좌표라고 합니다. 일반적으로 3차원 좌표변환 행렬로 4*4 행렬을 사용하는데.. 그렇게 되면 버텍스 좌표계 값은 (x,y,z,1)로 사용합니다. "

    Realtime Dynamic Level of Detail Terrain rendering with ROAM

    번역 : 이봉식 - 2000년 4월 20일 >
    원문 : By Bryan Turner Gamasutra April 03, 2000

    "▶ Introduction to Terrain Visualization
    ▶ Explanation of Patch Class 
    ▶ Roam Engine Qualifiers"

    Picking < 김성완 - 2000년 3월 25일 >

    "D3D IM 에서 화면상의 객체를 마우스로 선택하는걸 Picking이라고 하는데... 
    화면상의 마우스 좌표값에 대응되는 삼차원 물체를 찾아내는 거죠."

    거울 효과 < 김성완 - 2000년 3월 25일 >

    "물체가 바닥에 반사되는 효과는 보통 그 물체를 뒤집어서 반사되는 것 처럼 보이도록 하나 더 그립니다."

    T&L 가속에 대해서 < 김성완 - 2000년 3월 20일 >

    "제대로 T&L가속이 이루어 지려면 Vertex 데이타가 비디오 램에 있어야 합니다."

    3D Programming 관련 서적 소개 < 김성완 - 2000년 2월 22일 >

    "3차원 그래픽 프로그래밍을 공부하려면 책 한두권으로 되는게 아니라 여러권을 공부해야합니다."

    *** g-Matrix3D Engine version 0.1 < 김성완 - 2000년 1월 24일 >

    "g-Matrix 3D는 Win32 기반의 본격적인 3차원 엔진을 염두에 두고 개발중인 3차원 엔진으로 Software, OpenGL, Direct3D를 모두 지원 합니다."

    D3DVERTEX, D3DLVERTEX, D3DTLVERTEX < 김성완 - 2000년 1월 24일 >

    "Direct3D의 경우 3차원 게임 개발자들이 선택적으로 모듈을 사용할 수 있도록, 세가지의 꼭지점 데이타 형식을 지원합니다."

    OpenGL과 Direct3D < 김성완 >

    "1. OpenGL과 D3D의 선택 < 1999년 12월 3일 >
    2. OpenGL과 D3D의 파이프라인 비교 < 2000년 1월 12일 >"

    DirectX 7.0의 Direct3DX < 김성완 - 2000년 1월 10일>

    "DirectX 7.0으로 버전업 되면서 가장 큰 변화를 겪은 Component가 아마 Direct3D Immediate Mode 일 겁니다."

    3차원 엔진 < 김성완 >

    "1. 상용 3차원 엔진 < 1999년 12월 21일 >
    2. D3d와 OpenGL은 3차원 엔진이 아니다. < 1998년 12월 28일 >
    3. 국내에서는 3D 엔진 안 만드는가?? < 1998년 1월 3일 >"

    [강좌] Quaternion < 김성완 >

    " 1. 복소수와 쿼터니온 그리고 회전 < 1999년 6월 24일 >
    2. 쿼터니온의 유래와 Angular displacement < 1999년 7월 13일 >
    3. 단위 쿼터니온과 임의축 회전의 대응 < 1999년 11월 11일 >"

    Blade의 Projection shadow < 조기용 >

    "1. Blade의 Omni라이트 구현법 < 1999년 6월 25일 >
    2. Projection Shadow < 1999년 11월 9일 >"

    회전 공식 증명 < 김성완 - 1999년 10월 21일 >

    "증명방법은 두가지를 보통 접하는데..
    한가지는 기하학적인 방법이고, 다른 하나는 대수적인 방법입니다."

    Quake VS Blade < 조기용 - 1999년 6월 24일 >

    "퀘이크3에선 BSP를 끝까지 고집하는 덕에 정적 LightMap과 그림자가 아예 없는데 반해, Blade에서 Project shadow라는 최첨단 기술로 빛과 그림자 처리를 동적으로 처리했어요."

    Opengl을 겜에 적용할때... < 김성완 - 1999년 7월 19일 >

    " 윈도우즈 시스템에 기본적으로 설치된 OpenGL 은 소프트웨어 드라이버로 구성된 OpenGL이라서 3차원 가속기와는 일단 무관합니다."

    OpenglㆍDirectxㆍGlide < 조기용 - 1999년 7월 10일 >

    "하나의 랜더러만을 고집하면서 퍼포먼스를 높이려는건... 
    하루하루가 급변하는 현시점에선 자신의 무덤을 파는 행위라고 볼수있죠."

    게임제작에 있어 매우 중요한 요소 < 조기용 - 1999년 7월 8일 >

    "3차원 게임에선 이상할 정도로 모두 약속이라도 한듯...
    FOV(field of view)를 90도 이상으로 하는데... 
    이점이 바로 프로그래머의 고정관념이라는게 바로 제 주장이예요."

    3차원 게임에서의 자료구조 < 조기용 >

    "1. 3차원 게임에서의 자료 구조에 대해 < 1999년 7월 2일 >
    2. 동적인 자료 구조에 대해 < 1999년 7월 2일 >"

    D3dIM vs D3dRM < 김성완 - 1999년 6월 30일 >

    "Immediate mode는 2차원 스크린상에 그려질 삼차원 물체를 최종적으로 삼각폴리곤 단위로 직접 다 처리해 주어야 하는 모드이고, Retained Mode는 삼차원 물체의 지오 메트리정보와 에니메이션 정보만 넘겨주면 알아서 해주는 모드입니다."

    맥워리어3의 그림자 처리방법 < 조기용 - 1999년 6월 24일 >

    "S 버텍스값으로 64x64비트맵에 단색으로 랜더링해요.
    그 비트맵을 blur 를 해 주고, 그렇게 blur된 비트맵을 로보트 발바닥에 4각페이스로 랜더링 하면 돼요."

    Euler Angles < 김성완 - 1999년 6월 23일 >

    "Euler Angles는 3차원 공간에서 물체가 취할 수 있는 방향을 나타내는데 사용되는 세개의 각도 값의 조합을 말합니다."

    광원 효과 < 김성완 - 1999년 6월 21일 >

    "광원효과는 광원을 움직이거나 밝기를 변화시키는 걸 말합니다."

    Quake3 범프 매핑 취소 < 김성완 - 1998년 10월 19일 >

    "PC GAMER 1998.11월호에 독점기사로 퀘이크3의 전모가 실렸더군요."

    인텔의 katmai < 김성완 - 1998년 9월 14일 >

    "인텔도 1998년 4/4분기에 발표 예정인 katmai에 3차원 처리 명령어를 추가할 예정"

    Portal 렌더링 엔진 소스 < 김성완 - 1998년 7월 25일 >

    "Zen이라는 엔진의 링크가 등록되었는데.. 
    소스가 완전히 공개되어 있습니다."

    메시아의 3차원 모델 처리 < 김성완 - 1998년 7월 6일 >

    "'메시아' 에 사용된 기법으로 모델의 폴리곤 수를 거리나 주변 배경의 조건에 따라 유연하게 변화시킨다고 하는 군요. "

    듀크 뉴켐 3D 엔진 개발자는.. < 김성완 - 1998년 1월 26일 >

    "켄 실버맨이라는 미국 고등학생으로 겐의 래버린스 라는 울펜스타인 3D 형식의 게임을 쉐어로 발표했던 친굽니다."

    반응형
    반응형

    ** [강좌] ** [강좌] Quaternion **Quaternion **

    copyrightⓒ 김성완(kaswan) [1999년 11월 11일]

    3. 단위 쿼터니온과 임의축 회전의 대응

    전에 우리는 임의의 벡터 'r' 을 Angular displacement 시킨 결과가 Rr = (cosΘ)r+(1-cosΘ)n(n.r)
    +(sinΘ)n×r 이 된다는 것을 알았다. 
    더 전에 임의의 복소수에 단위 복소수를 곱한게 결국 임의의 복소수를 복소 평면상에서 회전시키는 것이랑 같다는 것도 알았다.

    그렇다면 임의의 쿼터니온에 단위 쿼터니온을 곱한 것은 3차원 공간에서의 회전에 대응될 것인가...? 
    답은 거의 그렇다이다.(곱하는 방법이 조금 특이함)

    쿼터니온 q = w + xi + yj + zk 가 있을때, 
    w는 스칼라 성분으로 나머지는 벡터 성분으로 볼 수 있다.
    즉, q = (s, V) 라고 간단히 적을 수 있다. 
    이때 물론 s = w 이고 V = xi + yj + zk 이다.

    복소수에 공액 복소수가 있듯이 쿼터니온에도 공액 쿼터니온이 있다.
    복소수 c = a + bi 의 공액복소수가 c~ = a - bi 로 정의되고..
    복소수의 크기 |c| = √(cc~) = √(a²+ b²)로 정의 되듯이.. 
    쿼터니온의 경우, 공액쿼터니온은 q~ = (s, -V) 로 정의되고, 쿼터니온의 크기도 마찬가지로 qq~ = s²+ |V|²= |q|² 로 정의된다.
    그러므로 단위 쿼터니온은 qq~ = 1 인 쿼터니온이다.

    이제 우리의 목표인 Angular displacement와 대등되는 결과가 나오려면.. 
    p = (0, r)처럼 벡터성분만 있는 순수 쿼터니온에 qpq~ 처럼 단위쿼터니온과 그의 공액쿼터니온을 앞뒤로 곱해준다.
    그러면 qpq~ = (0, (s²- V.V)r + 2V(V.r) + 2 sV x r) 가 되고, q 는 단위쿼터니온이므로 q = (cosΘ,sinΘn), |n| = 1 라고 둘 수 있다.
    즉, s = cosΘ, V = sinΘn 이라는 얘기다. 
    cos²Θ+ sin²Θ= 1 이므로 말된다.

    좌우지간 이걸 위식에 대입하면..

    qpq~ = (0, (cos²Θ- sin²Θ)r + 2sin²Θn(n.r) + 2cosΘsinΘn x r)
        = (0, cos2Θr + (1 - cos2Θ)n(n.r) + sin2Θn x r) 이 된다.

    이걸 저번에 구해두었던 
    Rr = (cosΘ)r + (1 - cosΘ)n(n.r) + (sinΘ) n x r 과 비교해보자. 
    Θ에 2가 곱해진것 외에는 동일한 결과가 나왔다. 
    이건 다시말하면 벡터 r을 Angular displacement (Θ, n)으로 회전 시키는 것은 Angular displacement를 쿼터니온 공간으로 옮겨와서 단위쿼터니온 q = (cos(Θ/2), sin(Θ/2)n) 로 표시하고 쿼터니온 (0,r) 에다 다음과 같은 계산을 하는 것이다.

    q(0,r)q~

    결론적으로 말하면 3차원 공간에서 (Θ, n)으로 표시되는 임의 회전축 n에 대한 회전은 쿼터니온 공간(일종의 4차원 공간)의 단위 쿼터니온 (cos(Θ/2), sin(Θ/2)n) 과 같다는 것이다.
    2차원 평면에서 Θ만큼 회전 한 것이..

    결국 복소평면의 단위복소수 (cosΘ, sinΘ) 에 대응되는 것과 흡사한 결과인 것이다.

    그럼 이런 유용한 쿼터니온을 구체적으로 어떻게 활용하는 지는 다음에...

    반응형

    + Recent posts