블로그 이미지
래머
오늘도 열심히 개발하는 개발자입니다.

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2019. 3. 21. 18:12 기타


y^2 = b^2 * (1 - (x^2 / a^2))

posted by 래머
2018. 9. 20. 14:50 기타

크롬 : 개발자도구가 열린상태에서 새로고침을 꾹 누르면 나오는 메뉴에서 캐시비움 가능

오페라 : 도구 -> 설정 -> 고급설정 -> 검색 데이터 지우기 에서 삭제

파이어폭스 : Shift + 새로고침


posted by 래머
2018. 6. 2. 07:19 기타


 



           --------------------------------------------

           16비트 컬러의 이펙트 필터 소개와 그 알고리즘

           --------------------------------------------


                                                           전석환 (INGRAM)


요즘 16비트 게임이 러쉬합니다. 16비트의 구조적/운용적 난점에도 불구하고 많은

개발사들이 16비트를 선택하는데는 나름대로 이유가 있습니다. 그 어쩔 수 없는

이유중에 하나인 "16비트 모드만이 누릴수 있는 이펙트-Alpha Blend, 광원효과-"

에 대해 완벽 분석을 해보겠습니다.


아래에 부연되는 모든 연산작업은 각각 RGB별 배열로 작성하여 구현되므로 속도상

에 커다란 영향을 주지 않습니다. 참고로 하나의 효과를 구현 하기에 소요되는 배

열의 크기는 배열1[32][32], 배열2[64][64]로 long 형 선언시 20 K byte입니다.


약간의 소스도 준비되어 있으니 개념을 이해하시기 어렵지 않을겁니다.



1. Color Dodge


    응용분야 : 빛 계열(전격계 포함)의 효과 및 마법에 가장 적합한 효과입니다.


    알고리즘 : 표현되는 결과물(Dodge)을 위해 필요한 자재를 바탕색(BG)과 덧색

               (SPR)으로 나누었을때 RGB별 공통되는 연산식은 ...


                        Dodge=(BG*MAXDAC)/(MAXDAC-SPR)


               입니다. 이는 바탕색의 DAC가 높으면 높을수록 Dodge 본연의 색상

               이 나와주는 것이며 또한 반대로 바탕색이 어두우면 어두울수록 D

               odge 효과가 약해진다는 것을 살펴볼 수 있습니다. 또한 Dodge 로

               강렬한 표현을 하려면 배경과 마찬가지로 SPR 의 전체적인 밝기가

               높아야만 원래 추구하는 이미지를 전달하게 됩니다.


               주의할점은 Dodge 의 표현상 원래 SPR의 섬세한 이미지 전달을 불

               가능하다는 것입니다. ( SPR 이미지의 심한 왜곡 )



2. Lighten


    응용분야 : SPRITE, 원래의 색상이 필요한 -색의 왜곡없는- 다중 투명 효과.


    알고리즘 : 일단 알고리즘은 상당히 간단합니다. RGB 별로 BG, SPR 중 큰 DAC

               값을 취하면 그 값이 바로 Lighten 을 구현하는 값이 됩니다.


                        Lighten = max ( BG, SPR )


               이 Lighten 효과는 Table을 필요로 하지 않기 때문에 속도상에 약

               간의 이점을 가지게 됩니다. 다른 효과들과는 달리 색상의 왜곡이

               전혀 없으므로 원래 SPR 에 가장 근접한 이미지를 전달할 수가 있

               다는 장점도 있습니다. 하지만 알고리즘상의 문제점으로 BG 의 밝

               기에 따라 생략되는 부분도 있을 수 있어 실제 SPR 이미지의 크기

               중 많은 부분이 축소/생략 되는 경향또한 있습니다.



3. Screen


    응용분야 : 연기같이 부드럽고-Soft touch- 연한 소재의 효과로 적합합니다.

               (굴뚝에서 피어나는 연기따위...)


    알고리즘 : Lighten의 개량형이라 생각하면 됩니다. 연산식을 살펴보면 ...


                        TempSum=(MAXDAC-max(BG,SPR))/MAXDAC*min(BG,SPR)

                        Screen=max(BG,SPR)+TempSum


               다시 말하면 Lighten은 자신(SPR)의 색상을 과장하지 않지만 Scr

               een 은 어느정도 (어느정도라지만 일정한 왜곡률을 위한 계산식이

               있다) 자신의 색상을 높여서 표현하기 때문에 원래 이미지의 축소

               /생략되는 부분이 없어,실제 구현되는 이미지의 영역도 Lighten보

               다 넓습니다.


4. Dodge-Screen


    응용분야 : 불 계통의 모든 효과와 화염계 마법 모두.


    알고리즘 : 불을 표현하는 Effect를 위해 Dodge와 Screen 을 보완하여 결합한

               효과입니다. Dodge로 일단 BG 쪽의 색 왜곡을 심화하고 그뒤에 Do

               dge 효과로 왜곡된 메인 이미지들을 Screen 방식을 이용해 밝은색

               위주로 깨끗하게 정렬합니다. 쉽게 설명드리자면 Dodge 로 BG쪽을

               끌어당긴 다음 Screen으로 한번 더 Effect 를 먹인것과 다를 바가

               없습니다.(하지만 효과를 재차 반복할 수는 없는 관계로 Table 을

               작성하여 단 한번에 구현합니다.)


5. Screen-Dodge


    응용분야 : Dodge의 특성상 BG의 왜곡 심도를 결정함에 있어 BG가 제로에 가까

               운 수 혹은 제로일때 왜곡이 불가능한 것을 보완한 필터 로써 완벽

               히 검은색의 BG에서도 Dodge가 구현. (플레이 스테이션에서 사용되

               는 Dodge 필터 구현과 동일 )


    알고리즘 : 위 5번항과 마찬가지이나 구현 순서만 바뀌면 됩니다. 일단 Screen

               효과로 BG를 끌어 올린다음 Dodge로 왜곡을 심화합니다.5번항이 구

               현됐다면 아주 쉬운 CASE입니다.


6. Dodge-Burn


    응용분야 : 불에 타 시커멓게 그을린 듯한 효과, 굴뚝 연기.


    알고리즘 : Color Dodge 효과를 정 반대로 응용한 효과로 Dodge와는 달리 SPR

               색상이 높을 수록 BG 색상을 어둡게 왜곡합니다. 반대로 SPR 색상

               이 낮을 수록 BG 본연의 색상이 표현되게 왜곡을 약화합니다.


                DodgeBurn = (BG*(MAXDAC-SPR))/MAXDAC;


               색의 왜곡을 심화하려면 ( MAXDAC-SPR )과 (MAXDAC), 분자 분모부

               를 제곱 연산합니다.( 경험으로 볼때 3제곱 연산이 적당하다 )



7. Different


    응용분야 : 암흑 마법 발동이나 독, 마비등의 Effect 응용 가능.


    알고리즘 : BG 와 SPR 색상의 편차를 고스란히 대입하는 간단한 알고리즘.


                        Different=(max(BG,SPR)-min(BG,SPR))


               이를 이용하여 텍스쳐 형식으로 캐릭터에게 독립적인 표현이 가능

               하므로 상태 이상시 캐릭터 Status 표현으로도 응용할 수 있습니다.



 ==========================================================================



(주1) 위의 모든 공식은 실제 게임에서 쓰일 때에는 사전에 RGB 테이블[*][*]로

     선연산하여 사용하도록 합니다. ( 그렇지 않고, Pixel 한번 처리할때마다

     RealTime으로 연산하면서 구현한다면 치명적인 과부하가 발생합니다. )


     15비트 컬러의 경우, Color Dodge를 예로 든다면 Dodge[32][32]의 배열을

     준비 한 후,


     for ( long bg=0 ; bg<32 ; bg++ ) {

         for ( long spr=0 ; spr<32 ; spr++ ) {

            Dodge[bg][spr]=(long)((bg*32)/(32.0-spr));

        }

    }


    (주) 분모측의 32.0으로 소수점을 표현한 이유는 컴파일적인 문제로 Floating

         연산을 위한 것입니다.


    실제 구현은,


    BG와 SPR에 대해 15비트 R,G,B 값을 구해서 사전에 만들어 놓았던 테이블을

    참조, 구현하도록 합니다.


    아래는 간단한 예문입니다.


    long d,e;

    WORD r,g,b;


    d = dest[0];//배경 버퍼 dest 에서 BG Pixel 을 구해서 d 에 저장.

    e = data[0];//SPR Pixel 을 구해서 e 에 저장.


    r=Dodge[(d&0x7c00)>>10][(e&0x7c00)>>10];//사전에 만들어 놓을 테이블 참조.

    g=Dodge[(d&0x03e0)>>5][(e&0x03e0)>>5];

    b=Dodge[d&0x001f][e&0x001f];


    dest[0]=(WORD)((r<<10)|(g<<5)|(b));//완성된 색을 배경 버퍼로 전송.


    이상입니다.


 (주2) 위에 구현된 모든 이펙트 필터를 한마디로 표현한다면 왜곡과 생략이라

       할 수 있습니다. 즉 Sprite 에 의해서 표현되어지는 것이 아니라 '스프

       라이트에 의해서 왜곡되어지는 배경'이 이펙트 스프라이트에 대한 정의

       라 할 수 있습니다. ( 이해가 가시나요? )


 (주3) 사족을 하나 달겠습니다. 위의 모든 정보들은 인터넷에서 파오거나,

       어디서 보고 들은 것들이 아닙니다. 그야말로 순전히 수많은 시행착오

       를 겪은 끝에 구현하게 된 것들입니다. 열심히 더 업그레이드 해주십

       시요. 여러분들이 더 열심히 해 주실수록 우리 게임계의 미래는 밝아

       집니다. 지켜 보겠습니다.


 (주4) 이 모든것을 가능하게 곁에서 도와준 남영이와 늘 옆에서 날카로운

       지적으로 날 땀흘리게 했던 응용수학의 달인 경일에게 감사와 영광을...



                                                    1997. 12. 27. INGRAM





게제동 강좌란 

 

제   목    [PROG] 브렌슨헴 알고리즘 - 1 

 

작성자    김학규 (neolith) 

 작성일  03-13  조회수  2663  

 

  



 정영태   (viracoza)

[강좌] 브렌센헴 알고리즘 #1/3 - 직선         02/28 17:46   190 line


제가 이번에 안하던 짓을 하는 이유는

어느 분인가가 브렌센헴 알고리즘을 물어왔기

때문입니다. 다른 고수들 놔두고 왜하필

저한테 물었는지는 잘 모르겠으나, 이왕이면

강좌로 하는 것이 낫다고 생각해서 강좌의

형식을 빌어서 쓰는 것입니다.

그러므로 오늘부터 3회에 걸쳐

브렌센헴 알고리즘만을 강좌하기로 하겠습니다.

처음엔 직선, 다음엔 원, 그리고 타원 순으로요.


브렌센헴 알고리즘이 왜 필요한지는 굳이

쓰지 않겠습니다.

하지만 여러 사람들이 이 알고리즘에 손을

대지 않는 이유는 단지 이 알고리즘이

수학적 지식을 필요로 한다는 지레짐작

때문입니다.

사실 이 알고리즘은 아주 기초적인 수학능력

만 있으면 쉽게 이해할 수 있는 알고리즘입니다.

장점은 모두 아시다시피 속도가 빠르다는 것이고,

단점은 선의 질이 그다지 좋지 않다는 것입니다.

특히 이것은 직선보다 곡선에서 더 드러납니다.

이 브렌센헴 알고리즘을 보완한 알고리즘이

몇개 더 있지만 설명을 생략하겠습니다.


브렌센헴 알고리즘의 가장 핵심이 되는 것은

에러텀이라는 것입니다. 오차이지요.

무한대의 해상도를 갖는 CRT는

존재하지 않으므로 CRT에 선을 그리려면

어쩔 수 없이 오차가 생기기 마련입니다.

이 오차를 이용하는 것입니다.


이 오차가 어느 일정 한도 이상이 되면

점을 찍는 위치를 증가시킵니다.

이해를 돕기위해 좌표계는 컴퓨터가 아니라

일반적인 스퀘어 좌표계를 쓰겠습니다.


     │

    3│            ???

    2│      ???

    1│???

     └───────────

    0  1 2 3 4 5 6 7 8 9

     

위의 그림은 (1,1)【?(9,3)까지 선을 긋는

모습입니다. 당연히 매끈한 직선이 아니라

정수의 좌표를 갖는 점들의 집합이 되었죠.

설명을 돕기 위해 위의 좌표를 일반화하지

않았습니다. 그냥 가로가 x좌표고 세로가 y좌표

라고 해 두었습니다. 이것을 일반화시키면

설명이 복잡해지거든요.


자~ 이론 설명에 앞서, 선이 그려지는 과정부터

말씀드리죠.

우선 첫번째 점은 1,1에 찍습니다. 그 다음에

x좌표를 증가시킵니다. 그래서 에러텀을 살피고

만약 에러텀이 일정 한도 이하라면 그냥 넘어갑니다.

이렇게 진행하다가 보면 에러텀은 갈수록 커져가고,

나중에는 그 일정 한도라는 값을 넘어서게 됩니다.

그럼 y좌표를 증가시킵니다.

물론 y를 증가시켰으니 에러텀은 어느정도

줄어들겠죠. 에러텀에서 어느 값을 빼면 됩니다.

이 과정을 x좌표가 9가 될 때까지 반복하면 됩니다.

별로 어렵지 않게 이 방법이 실수의 가상좌표상의

점의 정수화와 거의 일치한다는 것을 증명할 수는

있지만 설명하기도 귀찮고, 또 설명한다고 해도

재미가 없어서 생략합니다. (흐-)


브렌센헴 알고리즘을 개략적으로 예를 들어 설명하자면,

그러니까... 무식한 예를 들죠.

만약 점이 0 아니면 1... 식의 정수값을 갖고,

그 증가율이 0.1이라면 어떻게 하겠습니까?

0.1, 0.2, 0.3, 0.4 까지는 그냥 0이라고 하고,

0.5부터 1이라고 하면 되겠죠?

그럼 이것을 아까의 과정으로 설명하죠.


우선 증가율이 0.1이므로...

처음 점은 0.

그 다음엔..

거기에 0.1을 더하면 0.1. 이것은 0.5보다 작으므로

오차는 0.1인채로 넘어가죠.

또 0.1을 더하면 0.2, 이것도 0.5보다 작으므로

오차는 0.2 ...

이런식으로 오차는 계속 늘어갑니다.

이러다가 0.5가 되는 순간 점의 값은 1로 뛰게 됩니다.

그럼 이제 오차는 -0.4가 되죠.

즉 에러에서 0.9를 뺀 것입니다.

이제 또 0.1을 더하면 -0.3으로 아직 0.5보다 작습니다.

또 더하고... 이렇게 하다가 보면 다시 에러텀은

0.5보다 커지고 점의 값은 또한번 증가하게 됩니다.


그렇다면 이것의 스케일을 좀 넓혀보죠.

왜냐하면 당연한 얘기지만 비록 곱셈 없이 덧셈뺄셈만

썼다지만 위의 것은 실수를 썼잖아요.

이것을 정수화 하기 위해선 약간의 연산을 해야 합니다.

그러기 위해선 아주 기초적인 미분식이 들어가는데...

생략하고 결론을 말하죠.

위의 것을 정수화 하고, 다음에 주어진 인수에 따라

재구성하면,


처음의 에러텀은 당연히 0이고,

증가율은 End_X - Start_X ... 즉 X의 변화량,

에러텀의 한계는 X의 변화량을 2로 나눈 값,

에러텀이 한계를 넘었을 때 빼주는 수는 Y의 변화량.


이렇게 됩니다.

그럼 방금 위의 인수를 바탕으로 알고리즘을 설명하면,


 "X의 값을 증가시킨 다음에 에러텀에 Delta_X를 더해준다.

 그 결과 에러텀이 Delta_X / 2 의 값보다 크거나 같으면

 Y의 값을 증가시키고 에러텀에선 Delta_Y를 빼준다.

 이 과정을 X가 선을 긋는 끝 좌표에 도달할 때까지 한다."

 

하나 주의해야 할 것은 위의 경우는 X의 기울기가 Y의

기울기보다 컸을 때의 얘기라는 것입니다.

만약 그 반대라면 진행 과정도 반대가 됩니다.


이해가 가시나요? 제딴엔 최대한 자세히 설명한 것입니다.

아래에 실제 소스를 싣죠.


void line2( int x1, int y1, int x2, int y2, char color )

{

  int x, y, temp;

  int delta_x, delta_y, half, error = 0;

  

  /* 한상 x2 >= x1, y2 > y1 이 되도록 한다. */

  if( x1 > x2 ){

    temp = x1;

    x1 = x2;

    x2 = temp;

   }

  if( y1 > y2 ){

    temp = y1;

    y1 = y2;

    y2 = temp;

   }

      

  /* x, y의 변화량을 구한다. */

  delta_x = x2 - x1;

  delta_y = y2 - y1;

  

  /* 처음 시작점을 찍는다. */

  put_pixel( x1, y1, color );


  /* 각 좌표의 기울에 따라 선을 긋는다. */

  if( delta_x > delta_y ){

    y = y1;

    half = (int)( delta_x / 2 );


    for( x = x1+1; x <= x2; x ++ ){

      error += delta_y;

      if( error > half ){

        y ++;

        error -= delta_x;

       }

      put_pixel( x, y, color );

     }

   } else {

    x = x1;

    half = (int)( delta_y / 2 );


    for( y = y1+1; y <= y2; y ++ ){

      error += delta_x;

      if( error > half ){

        x ++;

        error -= delta_y;

       }

      put_pixel( x, y, color );

     }

   }

}


이해가 가셨나 모르겠군요.

위의 예제는 Game13h에서 직접 실행할 수 있도록

만든 것입니다. 함수명을 line2()로 한 것도

Game13h하고 충돌하지 말라고 한 것입니다.

하지만 점찍는 함수를 가진 어떠한 라이브러리에서도

사용하실 수 있습니다.

소스를 보시면 호출한 함수라곤 put_pixel()밖에

없다는 것을 알 수 있을 것입니다.

이 함수의 용도는 지정한 화면상의 위치에 정해진

색으로 점을 찍는 함수입니다.

그러니 이 함수만 만드신다면 어떤 스크린 모드에서도

사용하실 수 있습니다.

만약 기회가 난다면 브렌센헴 알고리즘?보완한

알고리즘을 올리도록 하고, 지금은 이것으로 끝냅니다.

다음엔 원 그리는 부분을 올리도록 하겠습니다.



                   - ID빌려쓰는 빈대 경민...



 

게제동 강좌란 

 

제   목    [PROG] 브렌슨헴 알고리즘 - 2 

 

작성자    김학규 (neolith) 

 작성일  03-13  조회수  1246  

 

  



 정영태   (viracoza)

[강좌] 브렌센헴 알고리즘 #2/3 - 원           03/01 14:52   198 line


저번 강좌에 이어 이번엔 브렌센헴 알고리즘으로

원을 그리는 방법을 살펴 보겠습니다.

아시는 분은 다 아시다시피 이 브렌센헴 알고리즘은

구현이 쉽고 빠른 대신에 그 질이 좋지 못하다는

단점을 갖고 있습니다.

이것은 직선보다 원이 더 심합니다.

특히 타원의 경우엔 별도의 보완책 없이 쓰면

더욱 엉망이 되고 맙니다.

또한 여기선 화면의 종횡비는 계산에 넣지

않기로 하겠습니다.

모두 아시다시피 그래픽 모드마다 화면의 종횡비는

조금씩 다릅니다. 오직 몇가지 모드만이 정사각형

픽셀을 제공하는데, 모드 12h가 대표적인 예이죠.

그래픽 종횡비 보정을 해야 그래픽 모드에 상관없이

제대로 된 원을 그릴 수 있으나,

이번 강좌에선 그 부분을 빼기로 하겠습니다.

물론 그 부분이 어려워서는 아닙니다.

하지만 이 강좌는 브렌센헴 알고리즘만을 설명하기

위한 강좌이므로 주제에서 벋어난 부분의 설명은

가능한 한 줄일 생각입니다.


브렌센헴의 알고리즘은 직선이든 원이든 

그 전개 과정은 거의 흡사합니다.

어차피 에러텀에 일정 수를 더하고 그것이

일정 한도가 될 때까지 진행하다가 다음 순간

y의 값이 증가하고...

실제 그 과정에 대한 설명은 전 강좌를 봐 주시기

바랍니다.

그럼 직선과 원이 뭐가 달라지느냐...

이제 그것을 설명할까 합니다.


우선 원은 모든 방향이 대칭이 됩니다.

원을 그릴 때는 기본 4방향 대칭을 이용합니다.

그러나 이럴 경우엔 약간의 문제가 생깁니다.

처음 45도는 제대로 그려지다가 나중엔

X의 좌표 변화율에 비해 Y좌표 변화율이

너무 커져서 점이 떨어지게 됩니다.

그래서 45도씩 그려서 그것을 다시 대칭시킵니다.

이것은 원이 모든 방향으로 대칭된다는

성질로 쉽게 증명이 됩니다.

그러니 실제론 원이라기 보다 곡선으로 이루어진

8각형이라고 하는 것이 낫겠군요.


실제로 원을 그릴 때는 45도 각도만 그리고

그것을 8방향으로 대칭 시킵니다.

그러니 기울기에 따라 그리는 루틴이 갈릴

필요도 없겠죠.

무조건 증가 성분만 있는 부분을 그린 다음에

8방향으로 대칭 시키면 되니까요.

그럼에도 불구하고 원을 그리는 알고리즘은

직선에 비해 신경써줘야 할 부분이 좀 있습니다.


우선 대칭이 되는 네 점을 나열해 보겠습니다.

만약 원점이 (0,0)이라면 임의의 원상의 점 (x,y)는

각각 (y,x), (x,-y), (y,-x), (-x,y), (-y,x), (-x,-y),

(-y,-x)와 대칭됩니다.

만약 원점이 (x0, y0)라면, 이것은 알고리즘에 의해

구해진 (x,y)에 대해,

(x0+x, y0+y), (x0+x, y0-y), (x0+y, y0+x),

(x0+y, y0-x), (x0-x, y0+y), (x0-y, y0+x),

(x0-x, y0-y), (x0-y, y0-x) 의 팔방향으로

대칭된 점들이 구해집니다.


이제 원을 그리는 알고리즘을 위해 실제

원의 방정식에서 각 점의 위치를 구하는 식을

분석해 보기로 하겠습니다.

설명을 쉽게 하기 위해 원점을 (0,0)이라고

하겠습니다. 실제로 이렇게 구해진 x,y는

위의 방법을 사용해 실제 점으로 환원할 수

있습니다. 반지름은 ratio라고 합니다.


우선 원상의 점중에 1/8만을 구합니다.

어느 방향을 하든 상관없지만 이왕이면

x는 증가, y는 감소하는 원의 우상단 부분을

사용합니다. 그럼 x는 0부터 시작해서 y까지

한다고 하면 됩니다.

왜냐하면 x와 y의 반지름에 관한 관계는

서로 동등하므로 만약 이 두값이 같다면 1/8의

지점에 도달한 것이기 때문입니다.

(이런 것까지 증명해줄 필요는 없겠죠?)

물론 y값도 상수가 아닙니다. 그러니 루프의

횟수는 처음부터 정해진 것이 아닙니다.

루프가 진행되어 감에 따라 일정한 규칙에

따라 y좌표도 감소하므로 대체로 처음 정한

y값보다 작은 횟수로 루프가 끝나기 마련입니다.


출발좌표가 (0, ratio)이므로 다음 점의 좌표는

(1, ratio) 이든가 (1, ratio-1)이 될 것입니다.

이 둘중에 어느것인지 판단하는 것은 전 강좌의

직선의 에러텀을 연상하십시요.

다음 점을 구하면 이것이 무엇이든간에 이론적인

원의 점에서 보면 오차가 있습니다.

이 오차의 절대값을 d라고 놓으면,


         d = |(x² + y²) - ratio²|


라는 식이 성립합니다.

이제 위에서 얘기한 (1, ratio)와 (1, ratio-1)

를 사용해 오차를 각각 구할 수 있습니다.

그럼 이 오차가 작은 경우가 우리가 구하고자

하는 점이겠죠?

편이상 (1, ratio)의 오차를 d(S₁),

(1, ratio-1)의 오차를 d(D₁)라고 놓겠습니다.

그럼 d(D₁) - d(S₁)의 값이 0보다 작으면

점이 감소한 것이고, 그렇지 않으면 점은 감소하지

않은 것입니다. 점이 감소했다면 그 오차에서

일정 값을 빼 줍니다. 이것은 전 강좌에서도

언급한 적이 있으니 설명은 생략합니다.

이런 과정을 x를 증가시켜가며 진행해서 원의

1/8의 정도를 그릴 때까지 반복합니다.

x가 언제 1/8지점까지 왔는가는 곧 설명합니다.


이정도 했으면 원 그리기 알고리즘의 대략적인

설명이 되었다고 생각합니다.

브렌센헴 알고리즘을 설명하기 위해 약간

바람을 잡은 셈이죠.

이제부터가 진짜 브렌센헴 알고리즘입니다.

위의 대략적인 이해가 끝났다면 스스로

브렌센헴 알고리즘의 구조를 머릿속에

떠올릴 수 있을 것입니다.

수학이 골치아프시다는 분은 그냥 아래 설명과

소스를 보십시요.

저도 수학과지만 수학은 무지 골치아픕니다.


원의 방정식에서 브렌센헴 알고리즘을

이끌어 내는 과정은 생략합니다.

솔직히 말하면 저도 하라면 헛갈려서

못해요. 유도식을 보고서야 할 수 있죠.

흐흐- 이해는 하지만 하라면 못하는 것...

이것이 우리나라 교육의 문제랄까?

얘기가 잠깐 옆으로 샜는데...

간단히 말씀드리죠.


우선 초기값으로 x, y, thres를 설정합니다.

여기서 thres는 에러텀 비슷한 것인데

아주 약간 다릅니다. 어떻게 다른가는

설명이 애매하니 생략합니다.(생략 투성이군...)

x의 초기값은 0, y의 초기값은 반지름, thres는

3에서 지름을 뺀 값으로 합니다.

그리고 루프를 시작하는데...

그 종결조건은 x가 y보다 커지는 경우입니다.

만약 thres가 0보다 작으면 thres를

6 + x * 4만큼 증가시킵니다. 그렇지 않다면

thres는 10 + (x - y) * 4만큼 증가시키고

y를 하나 감소시킵니다.

이렇게 하면 x와 y의 값이 모두 구해지므로

원점을 중심으로 8방향으로 점을 모두 찍습니다.

여기까지가 루프이며, 이제 x를 증가시키면 되죠.


하나 예외적인 상황이 있는데,

반지름이 0인 경우죠. 이럴 경우엔 점 하나만을 찍은

채 함수를 종결합니다.

자, 아래 소스가 있습니다.


void circle2( int x0, int y0, word ratio, byte color )

{

   int x, y, thres;


   if( ratio == 0 ){

     put_pixel( x0, y0, color );

     return;

    }


   y = ratio;

   thres = 3 - (ratio + ratio);


   for( x = 0; x < y; x ++ ){

     if( thres < 0 )

       thres += 6 + (x << 2);

      else{

       thres += 10 + ((x - y) << 2);

       y --;

      }


     put_pixel( x0+x, y0+y, color ); put_pixel( x0+y, y0+x, color );

     put_pixel( x0-x, y0+y, color ); put_pixel( x0-y, y0+x, color );

     put_pixel( x0+x, y0-y, color ); put_pixel( x0+y, y0-x, color );

     put_pixel( x0-x, y0-y, color ); put_pixel( x0-y, y0-x, color );

    }

}


전번 강좌와 마찬가지로 점찍는 함수를 갖춘 다른 모든

프로그램에서 사용이 가능합니다.

이번에도 어제처럼 날림으로 강좌를 끝냈는데,

이유는(핑계는) 전산학도나 수학도를 위한 공식 유도가

아니라 브렌센헴 알고리즘이 이렇다 싶은 정도만

얘기하고 실제로 컴퓨터로 옮기는 것만을 설명하는 것이

이 강좌의 목적이기 때문입니다.

아마 다음 강좌인 타원 그리기 알고리즘은 더욱 날림이

될 것입니다. 원 그리기보다 배는 복잡하니까요.

그리고 제가 브렌센헴 알고리즘을 공부하기 시작한 것도

그렇게 오래되지 않았으니 강좌에서 틀린 부분도 있을

것입니다. 만약 그렇다면 아주 마음 놓고 씹어주세요.

언제든 칼맞을 준비가 되어 있습니다. (헤-)

그럼 조금이라도 도움이 되었기를...



                      - ID빌려쓰는 빈대 경민...



 

게제동 강좌란 

 

제   목    [PROG] 브렌슨헴 알고리즘 - 3 

 

작성자    김학규 (neolith) 

 작성일  03-13  조회수  1233  

 

  



 정영태   (viracoza)

[강좌] 브렌센헴 알고리즘 #3/3 - 타원         03/02 21:39   184 line


안녕하세요?

제가 개강 때문에 좀 바빠서 강좌가

늦어졌습니다. 원래 계획으론 하루에

하나씩 3일에 다 끝낼려고 했는데...

이번엔 브리슨헴 알고리즘 강좌

마지막인 타원 그리기입니다.

하나 미리 얘기해 둘 것은,

비록 여기에 브렌센헴 알고리즘의

강좌라지만 이 타원 그리기 알고리즘은

브렌센헴 알고리즘이 아닙니다.

실제 그 구현을 보면 브렌센헴 알고리즘과

유사하지만 어느 참고서적에서도 이것을

브렌센헴 알고리즘이라고 하지 않습니다.

하지만 연관관계도 있고, 그 구현면에서도

유사하니까 이 강좌에선 같은 계열에서

취급하는 것입니다.

이점 착오 없으시기 바랍니다.


척 보기에도 알 수 있듯이, 타원의 방정식은

원의 방정식보다 어렵습니다.

그리고 속도도 더 늦고요.

하지만 약간 변형을 하면 상당히 빠른 속도를

낼 수도 있습니다. 이 알고리즘의 이름은

모르겠지만 구현 방법면에선 할 하드베르그의

알고리즘과 유사하므로 그쪽 계통이 아닌가

생각됩니다. 속도는 무척 빠르지만

여기서는 다루지 않겠습니다.

만약 얘기를 하자면 원그리기까지

또다시 거슬러 올라가야 하기 때문입니다.


타원은 원의 경우와는 달리 4방향이 대칭됩니다.

그리고 단순 증가방식만을 쓰지 않습니다.

타원의 경우엔 선그리기처럼 45도를

기점으로 그 기울기(?)가 다르므로 구현할 때도

이 두경우를 나누어서 해 주어야 합니다.

그러니 실제론 4분의 1만을 그리고 나머지는

대칭으로 찍으면 되고, 또 이 1/4도 두가지로

나누어서 그려야 합니다.


이 알고리즘을 위한 설명은 따로 존재하지 않고

앞에서 한 설명을 바탕으로 유도식만을

보입니다. 실력이 있는 분들은 이해하실 수 있을

것입니다. 만약 이해가 안된다면 다른 참고서적들을

참고하세요. 아마 많은 그래픽 서적에서 이것을

다루고 있을 것입니다.


유도식이 긴 관계로 초기항과 결과만을 쓰기로

하겠습니다.

우선 타운의 방정식이


  (x0 - x)?  (y0 - y)?

  ────  - ────  = 1

     a?         b?


이라는 것은 후진 중학교 안나온 이상 다 아는

사실. 이것을 약간 변형시켜서,


  b?x? + a?y?- a?b? = 0

  

이라고 놓고 이것을 앞의 방법을 통해 d를 구하면


  d = b?(x+1)?+a?(y-1/2)?-a?b?

  

이고, 각각 d₁,d₂, d₃... 에 대해 

d₂- d₁, d₃- d₂... 등을 구하면


 d₂- d₁= -2a²y₁

 d₃- d₂= -2a²y₂

 .

 .

 .

 

이다. 이것은 기울기, 즉 dy/dx가 -1 이상일

때이고, 만약 기 이하라면


 d₂- d₁= -2a²y₁+ a²

 .

 .

 

으로 바뀝니다.

또한 생각해 줘야 할 것이 한두개 더 있지만

설명을 생략하기로 합니다.


이렇게 생각해 줘야 할 경우가 두가지인데다가

그 성격이 다르기 때문에 타원을 그리는 데엔

크게 나누어 두개의 다른 루프를 돌려야 합니다.

게다가 루프 내에서 당연히 판단 루프가

들어가죠. 총 4가지의 다른 상황을 처리하는

함수로 타원 그리는 함수는 구성되어 있습니다.


대략적으로 설명한대다가 알고리즘을 구현하기

위해 충분한 자료를 다 제시하지 못했습니다.

이유는 앞서 말했듯이 알고리즘 자체에

대한 강좌라기 보다는 소개와 실제 그 소스를

공개하는 데에 그 목적을 두기 때문입니다.


void ellipse2( int x0, int y0, word a0, word b0, byte color )

{

  int x = 0, y = b0;

  long a = a0, b = b0;

  long a_squ = a * a;

  long two_a_squ = a_squ << 1;

  long b_squ = b * b;

  long two_b_squ = b_squ << 1;

  long d, dx, dy;


  d = b_squ - a_squ*b + (a_squ >> 2);

  dx = 0;

  dy = two_a_squ * b;


  while( dx < dy ){

    put_pixel( x0+x, y0+y, color );

    put_pixel( x0-x, y0+y, color );

    put_pixel( x0+x, y0-y, color );

    put_pixel( x0-x, y0-y, color );

    if( d > 0 ){

      y --;

      dy -= two_a_squ;

      d -= dy;

     }

    x ++;

    dx += two_b_squ;

    d += b_squ + dx;

   }


  d += ( 3*(a_squ - b_squ)/2 - (dx+dy)/2 );


  while( y >= 0 ){

    put_pixel( x0+x, y0+y, color );

    put_pixel( x0-x, y0+y, color );

    put_pixel( x0+x, y0-y, color );

    put_pixel( x0-x, y0-y, color );

    if( d < 0 ){

      x ++;

      dx += two_b_squ;

      d += dx;

     }

    y --;

    dy -= two_a_squ;

    d += a_squ - dy;

   }

}


앞의 두 강좌와 마찬가지로 점찍는 기능을 가진 다른

모든 프로그램에서 실행이 됩니다.

아마 설명이 그다지 잘 되지 못했을테고,

게다가 알고리즘 구현에 필요한 것을 전부

설명하지 못했기 때문에 설명 자체만으로 프로그램을

짤 수는 없을 것입니다. 설명이 미흡하다고 생각하면

다른 참고서적을 살피고, 실력이 있으시다면

소스와 앞에서 설명한 몇가지 자료만으로 직접 분석해

보시기 바랍니다.


미흡한 강좌, 끝까지 봐 주신 여러분께 감사드립니다.

한번 그래픽 이론을 알고 싶다고 생각하고 보신

분들은 실망이 크시겠지만 그냥 한번 어떤 것인가

맛만 보겠다고 생각하시고 강좌를 보신 분들은

약간 도음이 되셨을 것입니다.


요즘 게임들이 테크닉 위주로 많이 나가는데,

이제는 테크닉보다 탄탄한 자료 구조와 이론을

바탕으로 그곳의 위에 화려한 테크닉의 옷을

입힌 알찬 게임이 많이 나왔으면 좋겠습니다.

특히 3차원 게임에 관한 관심이 높아지는데

조금 아는 듯 싶다 하는 분들이 자신의 소스를

공개하길 꺼리는 것 같군요.

저도 좀 많이 배우고 싶은데...

아무쪼록 혹시나 3차원 그래픽 쪽으로 지식이

조금 있는 분께서 이 글을 읽으신다면

우리나라 게임의 발전을 위해서도

소스를 팍팍 공개하시고, 강좌도 하시면서

자신의 지식을 아낌없이 나누어 주시길 바랍니다.

그럼...



                   - ID빌려쓰는 빈대 경민...



덧붙이는 말 : 앞 강좌에서 '브렌센헴'이라는 발음을 썼는데,

             실은 '브리슨헴'이라는 발음이 맞습니다.

             그리고 강좌에 의문이 있으신 분은 메일 주세요.

             강좌와 직접 관계없는 질문도 상관 없습니다.



 

게제동 강좌란 

 

제   목    [PROG] 신기한 벡터의 내적과 외적 

 

작성자    이태경 (수퍼유저) 

 작성일  08-23  조회수  1013  

 

  



벡터의 내적과 외적, 법선벡터를 알자.



먼저 벡터의 내적과 외적을 알기전에 벡터에 대해 조금만 얘기하겠습니다.

당연히 수학적인 부분이지만 초등학생도 알수 있도록 쉽게....


1. 벡터


  2차원 좌표상에 점을 표시할때 일반적으로 x,y 두개의 좌표를 가지고

  화면의 점을 그린다. 이때 수학적으로 점이란 눈에 안보이는 것이지만

  점을 구성하는 좌표 성분으로 P(x,y)라고 지정한다.


  벡터란 원점을 기준으로한 점이라고 생각하면 쉽게 설명할 수 있을 것

  이다. V(x,y)를 표시할때 결국 (0,0)에서 (x,y)의 방향을 가르키는

  말이며 v(2,2)와 v(3,3)은 결국 크기만 다르지 같은 방향을 가르키고

  있다.



2. 단위 벡터의 특성


  단위 벡터란 크기가 1인 벡터를 얘기한다.


  0 에서 1까지의 실수는 아무리 곱해서 절대로 1을 넘지 않는다.

  이 특성이 단위 벡터에서도 나타난다.

  단위 벡터끼리 곱하는 연산은 1000만번을 한다하더라도 단위 벡터다.

  사실 위의 예기는 아주 중요한 얘기이며 이 간단한 사실만으로

  연산을 아주 간소화 할수 있다.

  

  그럼, 단위 벡터는 어떻게 만드는가?

  v(1,1)와 v(2,2)는 크기가 다르지만 방향을 같다고 했다.

  두 벡터를 크기는 무시하고 오직 방향만 계산하고 싶다고 할때

  단위 벡터를 만든다. 결국 크기는 1이니까..


  같은수에다 같은수를 나누어 보라..

  예를 들어 8 / 8 = 1, 7676 / 7676 = 1

  역시 1이다.


  단위 벡터도 이렇게 구한다.


  벡터 v(x,y)가 있을때 벡터의 크기는 sqrt(x*x + y*y)이다.

  그럼, 이걸로 나누면 땡이다.


  v = sqrt(x*x + y*y);

  vx /= v ;

  vy /= v ;


  이제 벡터의 크기를 구해보자..


  크기 = sqrt(x*x + y*y)는 1이 나와야 한다.

  

  이것은 영어로 Normalize라고 한다.


3. 벡터의 내적


  이제 좀 어려운 부분을 얘기 하겠습니다.

  벡터의 내적은 꼴도보기 싫은 수학정석에 나와 있습니다.

  영어로 DotProduct 혹은 inner-Product, Scalar-Product라고 하더군요..

 벡터의 내적 공식은 두 벡터가 있을때 두 벡터 사이의 각도를

  구하는 공식이죠..


  그럼..  꼴도보기 싫은 수학정석에


  cos(theta) = a*b / |a|*|b| 라고 되어 있습니다.


  (참고) *는 곱셈이 아니고 . 이지만... 표기할게 없어서..


  공식이 어떻게 나왔나고 묻지는 마세요.. 책에 그렇게 되어 있기에..


  위 공식에서 만일 a와 b가 단위 벡터라면 |a|*|b|는 1이겠지요..


  그럼.. cos(theta)= a*b로 간략화 營윱求?


  a*b 벡터의 연산은 성분끼리 곱하면 됩니다.


  cos(theta) = a_x*b_x + a_y*b_y ;


  (예)


  float a_x, a_y, b_x, b_y;

  float v, costheta, theta;


  a_x = 1.0;    a_y = 3.0;

  b_x = 3.0;    b_y = 1.0;


  // 먼저 단위 벡터로 만든다.

  v = sqrt(a_x * a_x + a_y * a_y);

  a_x /= v;

  a_y /= v;

  v = sqrt(b_x * b_x + b_y * b_y);

  b_x /= v;

  b_y /= v;

  

  theta = a_x*b_x + a_y*b_y ;

  costheta = cos(theta);


  음.. 이제 costheta를 구했다면 황당한 값이 나옵니다.


  이걸가지고 어떻게 하란 말야..


  cos(theta) = rad 라고 했을때


  theta = acos(rad) 이렇게 역으로 구할수 笭윱求?


  그럼 위의 프로그램에 더 첨가합니다.


  theta = acos(costheta);


  결국 우리가 바라는 벡터 사이의 각이 나왔습니다.


  신기하져?


  (참고) 라디안 값

  일반적으로 sin, cos, tan 함수에서 sin(theta) = rad 일

  theta = asin(rad) 이렇게 역함수가 존재 합니다.

  tan는 atan 흔히들 아크 함수라고 하져..


  그리고 각도를 얘기할때 0~360도 얘기하는 것은 Degrees 값이라고

  하며 수학에서는 보통 Radian 값을 씁니다.


  0에서 180까지의 Degree 값을 얘기할때 라디안 값은

  0에서 3.141592(즉 PI) 값까지 나오지요..


  180 : 3.141592 = degree : rad  이렇게 되지요..


  rad = degree * 3.141592654f / 180 ;

  degree = rad * 180 / 3.141592654f ;


 

  그럼. 다시 벡터를 얘기합니다.


  theta = acos(costheta); 에서 나온 값은 라디안 값이므로

  degree = theta* 180 / 3.141592654f ;


  해보면 일반적인 각도가 나옵니다.


4. 벡터의 외적


   벡터의 외적이 꼴도 보기 싫은 고등학교 수학 정석에 있었는지는

   잘 모르겠네요.. 뒷장까지 본적이 없어서.. 


   벡터의 외적은 그럼 무엇일까요? 벡터 사이의 각이 아닌

   반대 방향 각을 구하는 공식일까요? 아닙니다.

   벡터의 내적과는 성격이 좀 다릅니다.

   벡터의 내적은 결국 라디안 실수 값이 나오지만

   외적을 구하는 공식은 그냥 벡터가 하나 더 생깁니다.


   두개의 벡터가 있을 기준점에 수직으로 못을 하나 꽂으면

   못 방향으로 벡터가 하나 생깁니다. 두 벡터에 수직인 벡터

   가 하나 더 생기는 셈이지요..

   영어로 CrossProduct라고 하져..


   그림으로 설명하면 더 쉬운데... 쩝..


   v1(x,y,z)와 v2(x,y,z)가 있을 (0,0,0)을 출발점으로 한 위로

   우뚝선 벡터 n(x,y,z)가 하나 더 생긴단 말이져..


   두벡터에 수직인 벡터는 사실 두게 있습니다.

   위아래...


   보통 시계 방향이냐 반시계 방향이나 따라서 한가지만 뽑아냅니다.


   다음은 내적을 구하는 연산입니다.

   외우지는 마세요.. 그냥 베껴 쓰면 되니깐...^^;


   n_x = v1_y * v2_z - v1_z * v2_y;

   n_y = v1_z * v2_x - v1_x * v2_z;

   n_z = v1_x * v2_y - v1_y * v2_x;


   주의 하실점은 반드시 벡터를 단위벡터로 만들고 하세용..



5. 법선 벡터


   법선 벡터는 3D 그래픽 프로그래밍에서 흔히 노말 벡터라고 합니다.

   3차원 상에 점(vertex)가 3개가 있다고 합시다.

   그럼.. 3개의 버텍스 사이에 면이 생깁니다. 일종의 평면이지요..

   이 노말 벡터는 의 앞뒤를 가르키는 벡터입니다.


   면을 앞 뒤를 구분하는 이유는 바로 연산량과 관계 있습니다. 구와 같은

   물체를 안쪽면까지 그린다면 엄청 느려지겠지요.. 그래서 뒷쪽 면은

   연산에서 제외 시켜 버립니다. 이것은 Cull_face 혹은 Cull_mode라고 하져..


   또한 노말 벡터는 라이트와 밀접한 관련이 있습니다. 무슨 말인가 하면

   당구를 생각합시다. 공을 한쪽 벽에 튀길때 들어 오는 각하고 나오는 각하고

   같습니다.

                                

   (그림)                     법선n

                               |

                         i     |     .o

                           .   |   .

                             . | .

                    -------------------------당구벽

    당구공이 벽과 부딪혀서 들어갈때 각은 법선과 당구공 방향 벡터와 내적으로

    구할수 있습니다. 결국 이 내적의 두배의 각도로 튕켜져 나옵니다.


    들어가는 공의 방향 벡터가 i라고 하고

    법선을 n, 튕겨져 나올 방향 벡터가 o라고 했을때


    o = 2(i*n)n - i; 란 벡터 공식이 나옵니다.

    (이것도 어떻게 나왔나고 뭍지 마세요..그냥 책에 있음)


    식이 좀 어렵죠..


    c/c++로 풀이하면..


    //  여기서 쓰인 벡터는 노말 벡터로 미리 만들어 줘야 합니다.


    //  일단 i 벡터의 방향을 뒤 집고..

    i_x = -i_x;

    i_y = -i_y;


    rad = 2 * ( n_x * i_x + n_y * i_y );

    o_x = rad * n_x - i_x;

    o_y = rad * n_y - i_y;


    이것도 신기하져.. 이걸 잘 응용하면 당구 겜도 만들어요..


    (공하고 부딪힐때는 공끼리 부짖히는 점을 법선 벡터로 두면..)


    잠시 삼천포로 빠졌군요..

  결국 빛을 표면에 뿌릴때 반사되는 각도를 계산하기 위해서 필요한거져..



    위의 예제는 2개의 벡터를 가지고 예기 했지만 3D 그래픽에서는

    버텍스가 3개입니다. 그럼.. 점 하나를 기준으로 (0,0,0)으로

    이동 시켜 버려면 2개만 가지고 위의 외적으로 노말을 구할 수 있습니다.


    다음은 노말벡터을 구하는 예제입니다.

    물론 연산에 들어가지전 단위 벡터로 만드는 건 잊지 마세요

   

    v1[0] = v0[0] - v1[0];

    v1[1] = v0[1] - v1[1];

    v1[2] = v0[2] - v1[2];

    v2[0] = v1[0] - v2[0];

    v2[1] = v1[1] - v2[1];

    v2[2] = v1[2] - v2[2];


    result[0] = v1[1] * v2[2] - v1[2] * v2[1];

    result[1] = v1[2] * v2[0] - v1[0] * v2[2];

    result[2] = v1[0] * v2[1] - v1[1] * v2[0];


    대충 아시겟져...

    이것만 알면 3D 그래픽에 꼭 핵심적인 벡터 연산은 아신겁니다.



    추신: 벡터는 참 신기하져? 도강이라도 하세요..


    iMusicSoft 주임 연구원 이태경 ( 저 대전 살아요..)



 

게제동 강좌란 

 

제   목    [PROG/초보] WAV CHUNK에 대한 이야기... ^^; 

 

작성자    박한규 (어셈블리) 

 작성일  12-22  조회수  291  

 

  



강좌 (3)에서 WAV에대한 이야기를 하였다.


제가 미처 빼먹은 부분이 있어 추가하고자 한다.


바로 청크라는 부분인데... 본 강좌는 여러가지의 WAV파일이 아닌


Window PCM포맷을 사용한다는 전제하여 강좌를 하여 청크라는 것을


빼먹게 되어 사과의 문을 쓰겠습니다.


보통 흔히 사용하는 WAV파일 포맷들이 Window PCM을 많이 사용하고 있습니다.

(필자 역시 그 포맷을 즐겨 사용합니다.)


보통 MP3화일을 WAV파일로 Decoding을 하여 얻는 파일 포맷이 바로


Window PCM포맷입니다.


현재 강좌를 꾸준히 보셨던 독자들께서는 이런 포맷들에 대해서는


그렇게 신경을 안쓰시고, 44바이트 건너뛰면 곧바로 data청크를 만날수가 있습니다.


하지만, 제게 청크에 대한 질문을 하셨던 내용은 다음 사항이 많았습니다.


"어떤 WAV파일은 읽어지고, 어떤 WAV는 읽어 지지 않습니다."

"이건 확실히 mmio를 이용한 청크 검색별로 읽어 가야하지 않을까요?"


오호...이런 질문 메일이 음청나게 많더군여...T_T;


네에 제게 질문을 주셨던 분들의 말이 맞습니다.


WAV파일의 포맷 종류가 매우 다양하기 때문입니다.


"참고로 COOL EDITOR라는 사운드 프로그램을 사용해보시길..."


제가 알고 있는 사운드 파이 포맷은 한 5가지 정도입니다.


그 중에서 일반적으로 널리 쓰이는 Window PCM 포맷을 초점을 맞추어


강좌를 써나간 겁니다. 다시 한번 이점에 대해서 양해를...


[WAV FILE FORMAT]

1. Window PCM

2. Window ADPCM

3. IMA ADPCM

4. ACM Wave

5. Mu/Law Wave


이렇게 다섯가지 입니다.


여기서 위 5가지의 포맷은 그렇게 크기 바뀌지 않습니다.


Window PCM에서 보았던 청크들중에서 한가지가 더 추가 한 것뿐입니다.


바로 "fact"라는 청크인데여...


이 청크에 대한 의미는 정확히 저도 잘 모르겠습니다.


그런데 한가지 저 청크를 조심스럽게 간단히 스킵을 하구...


읽게 되니까...사운드는 제대로 나오더군여... ^^;


그리고, ADPCM같은 경우의 포맷은 주로, 동영상 제작에 사용되는


사운드 포맷으로 널리 알려져 있는 포맷이기도 합니다.


압축된 포맷이죠...그래서 이 포맷은 일반 WAV포맷과 별다른 내용은


없지만, 그냥 데이터 필터링을 하지않구 그냥 출력하게되면,


치지익 하는 굉음이 나오게됩니다.


그리고, WAV파일을 재생하기 위한 필수 기본조건은 정확한 헤더를 얻는


방법을 아는것이라고 생각됩니다.


사운드를 재생하기에 앞서 재생하기 위한 충분한 정보가 제공되어야


하니깐여...^^;


ADPCM포맷의 WAV파일의 데이터 청크 내용은 저도 잘 모르겠습니다. ^^;


아~~~ 강좌 (3)에서는 조회수가 떨어질거라구 예상했었는데..흑흑...


역시나...너무 내용이 빈약 했던것 같군여...^^;


ADPCM이외의 포맷은 강좌 (4)에서 다루도록 하겠습니다.


그리고, 이쁘장한 재생기 프로그램 소스를 제공 해드리겠습니다.


좀 강좌 (4)의 내용은 음청나게 길어질듯...^^;


즐거운 시간 되십시여...^^;



 

 

'기타' 카테고리의 다른 글

타원의 방정식  (0) 2019.03.21
브라우저 새로고침  (0) 2018.09.20
파일질라 FTP 서버구축하기  (0) 2015.11.10
은행별 swift 코드 정보  (0) 2014.06.03
[본문스크랩] 캐릭터 애니매이션 2 - 스티칭애니 SMD  (0) 2014.05.04
posted by 래머
2015. 11. 10. 06:17 기타

업무상 FTP서버를 자주 사용합니다.

몇개의 FTP서버를 이용해 봤지만 파일질라서버가 가장 단순하고 파워풀한것 같습니다.

아래는 파일질라 FTP서버를 구축하는 방법에 대해서 설명해봤습니다.


먼저 FTP서버 설치 파일을 다운로드 받습니다.

공식적인 경로를 통해서 받으셔도 되지만 버전이 다를 수 있어 설명에 차이가 있을 수 있습니다.


파일질라설치파일


파일질라서버.zip


다운로드 받은 파일을 적당한 곳에 압축을 풉니다. 내용물을 보시면 아래와 같습니다.



FileZilla_Server-0_9_41.exe 가 서버 설치파일입니다. 위에 있는 FileZilla_server.exe는 서버 실행파일인데 유니코드 관련 패치가 되어 있는 버전입니다. 나중에 FTP서버에서 한글을 지원하기 위해서 필요합니다.


일단 설치 파일을 설치 합니다.


설치 과정은 그냥 Next를 주구장창 해주시면 됩니다.


서버 설치가 완료되었다면 FTP서비스가 자동으로 시작되게 됩니다. 유니코드 패치된 버전으로 교체하기 위해서 서비스를 멈추어야 합니다.

아래 그림에 보여지는 것처럼 프로그램 그룹으로 가서 Stop FileZilla Server를 통해서 서버를 멈출 수 있습니다.



만일 저방법으로 서버가 멈춰지지 않으면 직접 서비스항목에서 멈출 수 있습니다.

이제 파일질라서버가 설치된 폴더로 가서 아까 위에 압축풀었던  FileZilla_server.exe 파일을 덮어쓰기 해줍니다.

그런다음 다시 파일질라 서버를 재가동 합니다. 파일그룹에서 Start Filezilla Server로 재가동하시거나 아래 그림처럼 서비스에서 직접 가동할 수 있습니다.



윈도우 트레이 영역에 보시면 아래 그림에 표시해놓은것처럼 서버 인터페이스 아이콘이 보입니다. 더블 클릭해서 파일질라 서버 인터페이스를 오픈 합니다.




파일질라 서버 인터페이스의 모습입니다.

매우 단촐한 구성이네요.

FTP클라이언트가 서버에 접속하기 위해서 계정이 필요합니다.

계정등록을 해보겠습니다.

아래 그림에 표시해놓은 사람모양 아이콘을 눌러줍니다.



그럼 아래 그림처럼 UI가 오픈되는데요.

오른쪽에 보시면 Users라고 등록된 계정의 목록이 나옵니다.

아래에 Add버튼을 눌러서 새로운 계정을 추가 할 수 있습니다.


Add버튼을 누르면 아래 그림처림 계정등록창이 나오는데 입력영역에 ID를 입력하시고 OK를 눌러줍니다.


계정이 추가 되었습니다. Users목록에 새로 추가된 계정(test)가 보이네요.

test를 선택하시고 왼쪽의 General항목을 눌러 줍니다.

몇개의 체크박스와 입력박스가 있는데

계정에 비번을 적용하실거면 Password항목에 체크를 해주시고 바로 오른편의 입력박스에 비번을 입력해줍니다.


다음으로 해당 FTP계정이 사용할 폴더를 지정해줘야 합니다.

왼쪽 Page영역의  Shared folders 를 눌러 보시면 아래 그림과 같은 모습을 볼 수 있습니다.

그림에 표시해놓은 Add버튼을 눌러서 공유 폴더를 추가 할 수 있습니다.

사용하실 폴더를 선택하고 확인을 해주세요.


선택한 폴더가 추가된 것을 볼 수 있습니다.

표시해놓은 files영역을 보시면 여러개의 체크 박스가 있는걸 볼 수 있습니다.

Shares folders에 있는 폴더를 선택하고 해당 폴더에 대한 권한을 지정할 수 있는 기능입니다.

Read, Write는 파일 읽기 및 쓰기 가능

Delete는 파일 지우기 가능

Append 는 파일 수정가능

디렉토리 항목에 있는

Create, Delete는 디렉토리(폴더) 생성 삭제 가능

List는 디렉토리 조회가능

+Subdirs는 디렉토리의 하위디렉토리까지 조회가능

하다는 의미입니다.

적절한 권한을 선택해주시고 OK버튼을 눌러주시면 됩니다.



설정이 성공적이라면 아래 그림과 같은 메시지를 볼 수 있습니다.


기본적으로 FTP서버는 21번 22번 포트를 사용하고 있습니다. 하지만 보안을 생각한다면 포트를 변경해주시는게 좋겠습니다.

툴바영역의 톱니 모양 아이콘을 눌러서 서버 옵션설정창에 진입할 수 있습니다.




옵션 설정창의 모습입니다.

가장위의 제너럴 셋팅 항목을 선택하시고 Listen On these ports에 원하시는 적당한 포트명을 기입합니다.

1 ~ 65535까지 입력가능하네요. OK를 눌러 주시면 옵션 변경이 완료됩니다.


이로서 서버에 대한 설정은 마무리 되었습니다. 더많은 기능들이 있는데 위정도까지만 설정하셔도 사용하는데 별다른 불편은 없을 겁니다.


이제 테스트를 해볼차례입니다.

아래 그림은 FTP클라이언트로 유명한 파일질라 FTP클라이언트의 모습입니다.

다양한 경로를 통해서 다운로드 할 수 있으니 검색을 통해서 다운로드 받으시기 바랍니다.

설치하고 실행하시면 아래 그림과 같은 화면을 볼 수 있습니다.

상단의 툴바 영역에 호스트, 사용자면, 비밀번호, 포트등을 입력할 수 있는 공간이 보입니다.

호스트에는 FTP서버의 주소를 입력해줍니다.

사용자명과 비밀번호에는 아까 위에서 만들었던 계정을 입력해주시면 도고

포트는 역시 위에서 설정한 포트를 입력 후 빠른 연결 버튼을 눌러 서버에 접속 할 수 있습니다.


아래는 서버 접속에 성공한 모습입니다.

그림에 보시면 빈디렉터리 목록이라는 영역이 보일겁니다. 위의 계정에서 설정한 공유폴더의 내용물이 표시되는 공간입니다.

여기에 파일을 업로드 하시거나 다운로드 할 수 있습니다.

이상 간단한 설명을 마칩니다.

posted by 래머
2014. 6. 3. 10:24 기타

한국씨티은행(CITIBANK KOREA)

주소: 39, DA-DONG, CHUNG-GU, SEOUL, KOREA

SWIFT CODE : CITIKRSX

ABA Code : 026009593


기업은행(INDUSTRIAL BANK OF KOREA)

주소 : EULJIRO 2-GAa, JUNG-GU, SEOUL, KOREA

SWIFT CODE : IBKOKRSE


농협(NATIONAL AGRICULTURAL COOPERATIVE FEDERATION=NH BANK)

주소 : 75, 1-KA, CHUNGJEONG-RO, JUNG-KU, SEOUL, KOREA

SWIFT CODE : NACFKRSEXXX


국민은행(KOOK MIN BANK)

주소 : 9-1, NAMDAEMUNRO-2GA, JUNG-GU, SEOUL, KOREA

SWIFT CODE  : CZNBKRSE


 

신한은행(SHIN HAN BANK)

주소 : 120, 2-GA, TAEPYUNG-RO, CHUNG-GU, SEOUL, KOREA

SWIFT CODE : SHBKKRSE


 

외환은행(KOREA EXCHANGE BANK)

주소 : 181, UL-JIRO 1-GA, JUNG-GU, SEOUL, KOREA

SWIFT CODE : KOEXKRSEXXX

 

 

우리은행(WOORI BANK)

주소 : 203, 1-GA, HOEHYEON-DONG, JUNG-GU, SEOUL, KOREA 

SWIFT CODE : HVBKKRSEXXX


하나은행(HANA BANK)

주소 : 101-1, 1KA EULJI-RO, CHUNG-KU, SEOUL, KOREA

SWIFT CODE : HNBNKRSE

 

  

부산은행(BUSAN BANK)

주소 : 830-38, BEOMOL 2-DONG, DONG-DU, BUSAN, KOREA

SWIFT CODE : PUSBKR2P

 


대구은행(DAEGU BANK)

주소 : 118, 2-GA, SUSUNG-DONG, SUSUNG-GU, TAEGU, KOREA

SWIFT CODE : DAEBKR22

 


우체국(KOREA POST OFFICE)

주소 : 21-1, CHUNGMURO 1-GA, JUNG-DU, SEOUL, KOREA

SWIFT CODE : SHBKKRSEKPO



posted by 래머
2014. 5. 4. 11:13 기타

출처 sharbong의 무한 삽질시작 | 샤르봉

원문 http://blog.naver.com/sharbong/100003379773

요즘 시도하는 것이 자꾸 날 실망시키는 관계로 우울함이 극상을 달리고있는 이때.

기분전환삼아서 캐릭터 애니매이션 2를 써본다.

 

첫번째 글에서 나는 본애니의 기본적인 방법에 관해서 이야기 했다.

그때 본애니에서는 스티칭 애니와 스키닝 애니  두개가 있다고 한 기억이 있다. ( 없나? )

뭐 하여간 오늘은 스티칭 애니의 대표적인 파일포멧인 SMD에 관해서 살짝 이야기 하겠다.

잠시 스티칭 애니에 관해서 살짝 이야기 하고 가겠다.

 

스티칭 애니는 점 하나에 본하나가 영향을 주는 형태를 말한다.

그때문에 관절부분이 애니때 접힌다면, 뽀족하게 될 소지가 높다.

하지만 버텍스하나에 매트릭스 하나이기에 속도는 빠르다.

(그림정보를 찾으려다 귀차니즘의 압박으로 그만두도록하자. 뭐 보는 사람이 있을지도 의문이니...)

 

참고로 SMD로 본애니를 공부했지만, 의외로 국내에서 SMD를 쓰는 사람과 회사들이 많다는거다.

( 뮤가 SMD로 만들었다....신기할 따름이다. )

SMD는 벨브사가 하프라이프 SDK를 공개하면서 같이 공개된 포멧이다.

( ...아닌가? 분명 벨브사가 만든것만은 분명하다. )

 

SMD의 장점은 군더더기가 없는 매우 명료한 정보들만 가지고 있다는 것이다.

그때문에 단점은 너무 군더더기가 없어서, 몇개가 있는지조차 가르쳐주지 않는다는거다.

( 본의 갯수라던가, 삼각형의 갯수등등... )

 

MOD파일을 보면 SMD말고 해더성 정보파일이 하나더 있는데, 그런식으로 관리하려고 뺀듯하다.

 

SMD의 자료구조는 크게 3부분으로 나뉜다.

본노드 / 스켈레톤 정보 / 매쉬 정보

 

이런 정보를 가지는 SMD는 두가지 포멧으로 나뉘어진다.

레퍼런스와 애니메이션.

 

레퍼런스에는 위의 3가지 자료구조를 모두 가지고 있다. 말그대로 레퍼런스로서 본과 본정보,

그리고 매쉬가 존재하는 것이다.

 

애니메이션은 위 3가지 정보중, 매쉬정보가 빠져있으며, 스켈레톤 정보가 프레임수만큼 나와있다.

여기서 살짝 smd를 보자.

 

version 1
nodes
  0 "Bip01"  -1
  1 "Bip01 Footsteps"   0
  2 "Bip01 Pelvis"   0
  3 "Bip01 L Leg"   2
  4 "Bip01 L Leg1"   3

  ....


skeleton
time 0
  0 0.000000 -0.000000 39.526119 0.000000 0.000000 -1.570795
  1 0.000000 0.000000 -39.332325 0.000000 0.000000 1.570795
  2 0.866404 0.000000 0.000000 -1.570795 -1.570796 0.000000
  3 -0.000005 0.000007 3.713254 0.002054 3.115505 -0.021473
  4 18.045723 -0.000000 -0.000000 0.000000 -0.000000 -0.121501

  .....


triangles
PLAYER_Chrome1.bmp
 20   6.2915   3.6852  58.7875   0.7828   0.5264   0.3317   0.0137   0.2611
 44   5.8005  -1.2928  62.2638   0.1754   0.2434   0.9539   0.0948   0.4558
 44   7.4334   2.4543  59.8983   0.1717   0.8248   0.5387   0.0317   0.3338
PLAYER_Chrome1.bmp
 19   3.9185   3.2071  51.5657   0.6297   0.6813  -0.3732  -0.1638   0.3040
 44   7.4334   2.4543  59.8983   0.1717   0.8248   0.5387   0.0317   0.3338
 44   8.0542   2.2868  54.9256   0.5291   0.7574  -0.3827  -0.0604   0.3564
PLAYER_Chrome1.bmp
 56  -7.4701   2.4393  59.9100  -0.2332   0.7523   0.6162   0.4673   0.3301
 56  -6.0121  -1.2665  62.3253  -0.1773   0.0557   0.9826   0.4038   0.4548
 20  -5.6520   1.8873  62.6681  -0.8312   0.0346   0.5549   0.3928   0.3307
 .....

 

이것이 바로 SMD의 파일구조다.

Nodes가 바로 본의 구조를 나타낸다.

 

  0               "Bip01"       -1

자신인덱스    본이름       부모인덱스

 

이런 형태로 본(트리)구조를 알려준다. 뭐 더이상 설명이 필요없을듯 하다.

 

다음은  skeleton


time 0   <- 레퍼런스라면 time 0 만 존재하지만 애니매이션이라면 애니 프레임수만큼 나올것이다.


  0                 0.000000 -0.000000 39.526119  0.000000 0.000000 -1.570795
자신인덱스    |-----부모의 상대위치------||-----오일러 X Y Z 회전----|

 

이 정보가 바로 실질적인 본의 매트릭스 정보를 말해준다.

1에서 이야기 했듯이 본노드는 부모로부터의 상대TM을 갖는다고 했다.

저정보들은 모두 부모로부터의 상대값만 가지고 있다. 위치도 회전도 말이다.

저 정보를 매트릭스화 할때 주의할점이 있다. 바로 곱하는 순서다.

저 정보를 매트릭스로 만드는 것을 잘 알고 있을것이다.

부모의 상대위치를 T라 하고 오일러 X Y Z는 각각 Rx RY Rz 라 할때 곱하는 순서는

Rx * Ry * Rz * T 순이다.

참고로 저 순서는 D3D에서의 순서다. OGL이라면 반대로 T * Rz * Ry * Rx 이다.

또한 오일러 회전의 각 축의 각도는 라디안 값이니 OGL이라면 다시 각도로 변환시켜야 할 것이다.

( OGL는 회전을 각도로 받고 D3D는 라디안 값으로 받는다. )

저렇게 해서 만들어지는 저 노드의 자기 TM이다.

부모가 있을때는 자기TM * 부모TM 순으로 곱해야 한다.

( 역시 OGL이라면 반대로 부모가 앞에 온다. )

 

이제 마지막 triangles


PLAYER_Chrome1.bmp  <- 이 삼각형이 사용하는 텍스쳐명이다.

 

아래 순서대로 삼각형을 구성한다.
 20   6.2915   3.6852  58.7875   0.7828   0.5264   0.3317   0.0137   0.2611
 44   5.8005  -1.2928  62.2638   0.1754   0.2434   0.9539   0.0948   0.4558
 44   7.4334   2.4543  59.8983   0.1717   0.8248   0.5387   0.0317   0.3338

자 이제 점정보를 보자.

 20                 6.2915   3.6852  58.7875   0.7828   0.5264   0.3317   0.0137   0.2611
영향본인덱스   버텍스 x y z                   노멀 x y z                    텍셀 u v

 

위에서 스티칭 애니는 하나의 본에 영향을 받는 구조라고 말했다.

버택스 하나가 본하나에 1:1 매칭된다는 것은 속도가 빠르다.

물론 스키닝 애니에 비해서일뿐이다. 순수 버택스 애니에 비하면 느릴수밖에 없다.

 

자 일단 SMD에 관해서 설명을 했다. SMD설명을 봐서 알겠지만, 처음에 말했듯이

뭐가 몇개있는지에 대한 정보가 전혀없다. 따라서 SMD를 읽어서 쓸때는 약간의

최적화가 필요하다.

첫번째가 텍스쳐, 같은 이름의 텍스쳐는 같은 텍스쳐인것이 당연하다.

두번째가 버텍스 인덱스화. 저래보여도 중복되는게 꽤 존재한다.

 

자 그럼 오늘은 여기까지.

보고 도움되는 사람이 있을지 의문이다. ( 보는 사람이 있는지도 의문이다. ㅡ.ㅡ )

그럼 오늘도 안녕히.

 

 

ps : 라이트맵이 싫어진다.




posted by 래머
2014. 5. 4. 11:11 기타



[본문스크랩] 하프라이프 mdl 파일포멧과 3d모델구조 낙서장

2007/01/05 08:35 수정 삭제

복사 http://blog.naver.com/choi98772/130013023537

전용뷰어 보기

첨부파일 (1)

출처 카페 > 게임 모델링 에 관한 모든것.. | 늘바나
원문 http://cafe.naver.com/moduser/461

하프라이프 mdl 파일포멧과 3d모델구조 설명




mdl파일구조.rar





posted by 래머
2014. 5. 4. 11:07 기타
출처 카페 > 게임 모델링 에 관한 모든것.. | 늘바나
원문 http://cafe.naver.com/moduser/75

SMD파일은 2개의 버전으로 구성 -> Reference , Animation file로 구성

 

공통구성data : bone의 node구성

Reference   : 0프레임의 bone position/rotation data triangle,

texture map data

Animation   : 모든 프레임의 bone position/rotation data

 

섹션별 구성

Header 

 Version 1 버전을 표시

 

Node tree 

뼈의 모든 본의 목록을 나타낸다.

부모가 없는 Objects는 부모의 ID가 1이다.

 

nodes

<ID> Bone Name <Parent ID>

end

 

Skeleton Pose

뼈 구조의 모든 본들의 position/rotation값들로 구성

Animation SMD는 매프레임마다 time블럭으로 저장

Reference SMD는 첫 프레임의 한 타임만 저장

 

Skeleton

Time 0

<ID><PosX><PosY><PosZ><RotX><RotY<RotZ>

<ID> ® Bone index,

<PosX><PosY><PosZ> ® 월드 좌표계에서의 위치값

<RotX><RotY<RotZ> ® Local Euler 라디안 회전값,부모의 local space의 회전값

Reference SMDs  이 프레임만 출력

Time 1

end

// Animation SMD 여기까지 출력

 

Triangle block

Triangles 리스트만 포함

 

Triangles

bitmapname.bmp

<Parent><PosX><PosY><PosZ><NormX><NormY><NormZ><TexU><TexV>

<Parent> ® vertex의 부모 bone의 ID번호

<PosX><PosY><PosZ>  ® 월드 좌표계에서의 vertex위치값

<NormX><NormY><NormZ> ® 스무싱을 위한  vertex normal vector

<TexU><TexV> ® vertex의 texture 좌표값

버텍스 3개씩 기록

 

nextBitmapName.bmp

새로운 triangle리스트 기록

..

end




posted by 래머
2014. 5. 4. 11:05 기타

퀘이크2 의 MD2파일을 로드하거라 압축된 PAK파일로 부터 MD2파일을 볼수 있게

해주는 프로그램이다.

출처 http://www.milkshape3d.com/




md2viewer14-choi98772.zip




posted by 래머
2014. 5. 4. 11:02 기타

하프라이프 게임에서 사용된 모델을(MDL파일) 보여주는 프로그램이다.

PAK으로 압축된 파일도 읽을수 있게 되어있다.

출처 : http://www.milkshape3d.com


hlmv125-choi98772.zip




posted by 래머
prev 1 next