레이블이 CG인 게시물을 표시합니다. 모든 게시물 표시
레이블이 CG인 게시물을 표시합니다. 모든 게시물 표시

2006년 5월 9일 화요일

[CG]2006.5.9. MS Research Asia - Harry Shum

. 오늘 소개한 논문 2편
Yin Li, Jian Sun, Chi-Keung Tang and Heung-Yeung Shum. Lazy Snapping. SIGGRAPH 2004. (ACM Transaction on Graphics)  (Video 19M)
http://research.microsoft.com/research/pubs/view.aspx?pubid=1266
http://research.microsoft.com/~jiansun/papers/LazySnapping_SIGGRAPH04.pdf
http://research.microsoft.com/~jiansun/videos/ImageCompletion_tiny.wmv

Jian Sun, Lu Yuan, Jiaya Jia and Heung-Yeung Shum. Image Completion with Structure Propagation. SIGGRAPH 2005 (Video 56M).
http://research.microsoft.com/~jiansun/papers/ImageCompletion_SIGGRAPH05.pdf

. 참석자
신성용, 좌경룡, 홍세준, 최성희, 한환수, 김진수 교수님을 포함한
10여명의 CS 교수님들과 터만홀을 가득 채운 학생들.

. 관련 분야
Signal processing, Image processing, Computer Vision, Computer Graphics

. MSRA 소개
1998년 베이징에 설립, 200여명의 researchers, 2,000명의 intern students.
거기 있는 유명한 사람들 : SGI 설립자, IBM Deepblue 설계자 등..
주로 computer Graphics관련 분야를 집중적으로 연구함.
(UI, Digital Media, Digital Entertainment, Networking and systems, searching and mining)
중국 학생이 70%이상, official language는 english
2005년 Siggraph에 9편, SIGIR에 12편이 실림.
(전체 논문의 10%에 해당하는 엄청난 양임.)
World's hottest lab 등으로 잡지에 소개됨.

. TTG(Technology Transfor Group) : Parachut group
  Research를 product로 바꿈.                                  

. Dr. Harry Shum
CMU Robotics 전공, 4년전 신성용 교수님초대로 KAIST 방문
Managing Director MSRA(1999~2006)

. Prior, Context and Interactive Computer Vision
  완전 자동이 아니라 약간 step back해서 User의 입력을 약간 받아서
  쉽게 feedback해주고 잘 해보자.

. IBM : Image Based Modeling

. Lazy Snapping
Just draw two lines
In line와 out line만 그리면 됨.
Red line : What you want
Blue line : What you don't want
Lazy : 부지런하게 모든 boundary를 그리지 않고 선만 대충 그음.
Interactive Graph Cut

Divide and Conquer : Input -> Coarse Boundary -> Refine Boundary
Stroke Drawing <-> Graph cut Algorithm
Graph cut problem -> Per-Pixel Graph cut 대신 Pre-segmentation first
Energy Minimization E(x) = E1(Xi) + lE2(Xi, Xj)
E1 : difference
E2 : Similarity

Noting new algorithm, Present New system.

. 논문 잘 쓰는 법
Write -> Intoducting, Abstract, Summary -> Title
Good title is short title => 2 words, end with ing

. Image completion
Small Missing : Pixel-level, PDE based
Large Missing : how?
Curve-based : BP(Belief propagation) Algorithm
Our Motivation : Missing salient structures, fill-in
Abstract window, curve - a few curves - human specify that.
Structures completion befor texture complete
Fragment-based Image completion, Image Repairing, object Removal

Node Energy, Coherence Energy => Dynamic Programming
Graph Labeling, discretize nodes
Decouple Image into two part

Multiple Intersecting Curves
Loopy Belief Propagation
Tour Into pictures도 쉽게 가능

사진을 2장 찍은 것이 아니라 object를 지우고 그 부분을 메꿈.
자세히 비교하면 이상할 수도 있지만 결과 사진만 보면 매우 그럴듯 함.
걸리적거리는 사람이나 물체를 깔끔하게 지워버릴 수 있다.
Boundary를 바꾸고 싶을 때 가리고 새로 그리기만 하면 된다.

. 감상
마치 무슨 마법이나 장난을 보는 것 같다.
이런 신기한 툴이라면 누구나 써보고 싶어할만한 것 같다.
연구자나 사용자 모두 직관적이고 매우 재미있어할 수 밖에 없겠다.

지겨운 algorithm이나 math가 이런 멋진 결과들을 가져오다니.


2006년 5월 2일 화요일

[CG]CG Term project 발표정리 - 2006.5.2

. 조원 : (주한별, Linda), (김지혜, 이춘석 tclab)
. Color2gray : Salience-Preserving color removal
  . gray로 바꾸면 intensity만 남아 안 보이게 되는 것이 있다.
  (Intensity가 같고 chrominance만 다른 경우)
  . Intensity를 희생하더라도 차이가 구분되게 한다.
  . Chrominance difference -> luminance
  . f(g) = sigma((i,j) in k, ((gi - gj) - dij)^2)
  . d : chrominance difference
  . f(g)를 minimize하는 g를 찾으면 된다.(optimization)
  . 색, 인지과학이용.(human visual sensitivity)

. 조원 : (김윤영 tclab)
. Feature Preserving Regular Remeshing
  . surface remeshing : 3D mesh를 remesh해서 다시 3D로 만듬.
  . mesh : polygon으로 정의된 연결 집합
  . Regular remeshing
  . Regular remesh : 모든 vertex가 같은 valence를 가짐.
  . Valence : vertex에 연결된 edge의 수
  . Connectivity가 좋다. 압축률이 좋다.
  . Goal : feature를 잘 보존하면서 remesh
  . Segmentation : 3D를 자름
  . Parameterization : 3D를 2D에 펼침 => feature preserving
  . least square conformal Map => regular remeshing

  . Parameterization
  . 각도 보존(Conformal map, angle-preserving)
  . 경위도 보존
  . 넓이 보존
  . Contribution - 기존방법의 단접 - 삼각형이 매우 찌그러짐.

. 조원 : 공내진
. Fast bilateral filtering for the display of high-dynamic range
  . HDR : High-dynamic-range
  . device들보다 인간이 보는 contrast range가 훨씬 넓다.
  따라서 완벽하게 표현하지 못한다.
  . 선형으로 변환하면 대비가 분명하지 않다.
  . 영화가 너무 어두울 때
  . 밝은 것(오랜노출)부터 어두운 것(짧은 노출)순으로 16장을 찍고 합쳐서 만든다.
  . Tone reproduction problem : contrast를 잘 맞추기
  = Tone mapping operator 찾기
  . Anisotropic diffusion : 가까운 pixel의 영향을 더 많이 받음.
  . Bilateral filter : contrast를 잘 변환

  . bilateral : 쌍방의, 좌우 양측의
  . anisotropic : directionally dependent
  . have different characteristic in different direction
  . ex) polarising lens, polaroid sunglasses

  . isotropic : directionally independent
  . diffusion : spotaneous spreading of matter, heat or momentum

  . layes
  . base layer : operation을 함
  . Detail layer : 보존
  . Color layer : 안씀

  . Bilateral mask
  . f : 관심 pixel의 주변만 봄
  . g : edge에서는 intensity가 달라지는 속성을 이용,
         너무 intensity가 커지면 중단.

. 조원 : (최영남 AI, 김효실 GC), (양형진)
. A new voronoi based surface reconstruction algorithm
  . Laser scan으로 물체를 sampleing하여 point를 얻음.
  . Surface reconstruction : surface 위의 점을 sampling하고
  그것을 다시 construct해서 surface를 만듬.

  . Delaunay triangle : 점들을 이어 삼각형으로 만듬.
  . edge property : 어느 삼각형의 외접원도 그 세 점 외에 다른 점을 포함하지 않음.
  . http://www.ics.uci.edu/~eppstein/gina/delaunay.html

  . Mesh : simple element로 discretization

  . Voronoi diagram : R^d를 point로 cell로 나눔. (decomposition)
  . closest point에 의해 분할되는 공간

  . Medial Axis
  . voronoi diagram의 edge의 boundary
  . tree-like skeleton
  . continuous cousin of the Voronoi diagram
  . http://www.cs.utexas.edu/users/amenta/powercrust/tools.html#mat
 
  . Power crust
  . Medial axis transform을 이용한 3D surface reconstruction algorithm

  . Clakrson's hull
  . n-d Delaunay triangulation을 위한 Exact arighmetic을 해준다.

  . Geodesic distance와 euclidean distance가 다른 것을 구별하기 위해
  axis를 사용한다.

. Surface reconstruction algorithm
  . CGAL library 이용
  . Improve : handling sharp edge
  . Compression 해보기

. 조원 : 유상욱
. Realistic 3D face construction
  . Final fantasy : Model의 사진을 기반으로 만듬
  . 사진 + camera parameter
  . 3D face Model construction - 사용자가 feature point 추가가능
  . Image Texturing
  . Virtual Boundary
  . Matching
  . Embedding
  . Smoothing

. 조원 : 서원필(VR), 이용준
. Sequential Point trees
  . Point based rendering (삼각형이 아닌 point cloud를 이용하자.)
  . Inefficient when all vertices are rendered
  . Hole problem
  . Qsplat - Octree처럼 공간을 나눔
  . tree라서 array보다 느리다.
  . CPU + GPU를 모두 쓰므로 bottleneck이 있다.

. 조원 : 이지현
. Making paper craft toys from meshes using strip-based approximate unfolding
  . Paper craft
  . Unfolding : Mesh -> 전개도

  . 기존의 방법
  . Unrealistic to assemble
  . simplify-smoothness 보존
  . Triangle strip : 언제나 unfold가능, loop도 ㅣㅇㅆ을 수 있음.
  . Zonal region : 띠를 만듬.

. 조원 : (주현성, 이지원), (이정환 CG)
. Particle system
  . 20년이 넘어 이미 모두 상업화됨.
  . Research topic이 없음.
  . 최초의 motion blur 작품(streaks of lights)

. Digital Photography of flash and no-flash image pairs
  . flash : High-frequency, red-eye, harsh shadow
  . No-flash : Ambient illumination, noise
  . 동일한 카메라 위치에서 찍은 두 사진을 합성하고 장점만 취해 더 좋은 이미지를 얻는 다.

. Art-based rendering of fur, grass and trees

. Stanford computer Graphics Laboratory
http://www-graphics.stanford.edu/
-> Data archives
The digital michelangelo project의 일환으로 status scanner가 있어서
데이터가 많음 point set sample data를 얻을 수 있음.
Bunny, Lion, Happy Buddha, Dragon, Lucy 등이 있다.

2006년 4월 16일 일요일

[CG]오차누적 - rotation transformation

수학적으로는 360도 회전하는 것이나 5도씩 72번 회전하는 것이 같다.
하지만 numerical하게는 변수에 값을 누적하기 시작하면 오차가 매우 커진다.

5도씩 100번 회전하면 물체의 크기가 30%나 적어진다.
5도 회전할 때마다 오차가 0.3%있는 것이다.
또한 도형이 shearing되기 시작한다.
(shearing + scale down)

시뮬레이션)
#include "math.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
long double x0 = 100;
long double y0 = 100;
long double x = 0;
long double y = 0;
float theta = 5.0 * 3.141592 / 180.0;

for (int i = 0; i < 100; i++)
{
x0 = x + (x0 - x) * cos(theta) - (y0 - y) * sin(theta);
y0 = y + (y0 - y) * cos(theta) + (x0 - x) * sin(theta);

cout << "i : (x0, y0), d : " << i << ", " << x0 << ", " << y0 << ", " << sqrt(pow(x0, 2) + pow(y0, 2)) << endl;
}

cout << "theta : " << theta << endl;
cout << "cos(theta) : " << cos(theta) << endl;
cout << "sin(theta) : " << sin(theta) << endl;
cout << "sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) : " << sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) << endl;

return 0;
}

해결책 1)
. 원본과 transformation을 항상 저장한다.
- 복잡한 transformation을 했을 경우 모두 저장하기 힘들고 performance가 떨어진다.

가짜 해결책 2)
Rotation 각도를 크게 해서 한, 두 번만 한다.

가짜 해결책 3)
Rotation 각도를 작게 해서 잠시만 보여준다.

가짜 해결책 4)
Rotation과 함께 scale을 시도한다.

실패한 해결책 5)
변수를 double, long double 등으로 바꾼다.
(truncation error를 줄이려는 생각이었으나 실패.)

진짜 해결책)
사실은 vector, matrix 곱셈을 잘못한 것이다.
x0의 값이 바뀐 후 값이 y0의 계산에 이용되고 있다.
따라서 임시변수 2개를 만들어서 x0, y0값을 따로 저장해두고 계산이 끝난 후 복사해야 한다.
(혹은 먼저 값을 복사해두고 계산해야 한다.)

[OpenGL]Zoom in, out, pan 구현하기

방법 1)
glOrtho를 이용한다.
World coordinate에서 clipping할 영역을 지정하는 방법

int g_screenX = 800; // 화면의 가로 크기
int g_screenY = 600; // 화면의 세로 크기
float g_zoomFactor = 1;
float g_panningX = 0;
float g_panningY = 0;
float g_worldLeft = - g_screenX / 2.0 * g_zoomFactor + g_panningX;
float g_worldRight = g_screenX / 2.0 * g_zoomFactor + g_panningX;
float g_worldBottom = - g_screenY / 2.0 * g_zoomFactor + g_panningY;
float g_worldTop = g_screenY / 2.0 * g_zoomFactor + g_panningY;

void setCamera()
{
g_worldLeft = - g_screenX / 2 * g_zoomFactor + g_panningX;
g_worldRight = g_screenX / 2 * g_zoomFactor + g_panningX;
g_worldBottom = - g_screenY / 2 * g_zoomFactor + g_panningY;
g_worldTop = g_screenY / 2* g_zoomFactor + g_panningY;

glOrtho(g_worldLeft, g_worldRight, g_worldBottom, g_worldTop, -1, 1);
}

// 좌표 계산을 함
void calculateGLcoordinate(const int x, const int y, GLfloat* retX, GLfloat* retY)
{
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

// openGL window coordinate는 system의 window coordinates와 반대이므로
// y좌표를 얻으려면 viewport[3] - y를 해야 한다.
// grid처리를 위해 gridWidth로 나눈 나머지 값을 버리고 다시 곱한다.
*retX = floorf((static_cast<float>(x) * (g_worldRight - g_worldLeft) / g_screenX  + g_worldLeft) / gridWidth) * gridWidth;
*retY = floorf((static_cast<float>(viewport[3] - y) * (g_worldTop - g_worldBottom) / g_screenY  + g_worldBottom) / gridWidth) * gridWidth;

//cout << "x : " << x << endl;
//cout << "y : " << y << endl;
//cout << "*retX : " << *retX << endl;
//cout << "*retY : " << *retY << endl;
}

방법 2)
glPerspective, glFrustum 등을 이용
Camera를 조절.
- 어떻게 하는 지 잘 모르겠음.

방법 3)
glScale, glTranslate를 이용한다.
Model Matrix를 고치는 방법.

방법 4)
glVertex에 입력하는 물체의 좌표를 직접 고친다.

주의)
이 방법이 모든 Model, view matrix에 적용되게 해야 한다.
. 화면에 그릴 때 (OpenGL이 지원)
. pick 할 때 (OpenGL이 지원)
. 화면에 입력할 때 (직접 고쳐야 함.)

2006년 4월 7일 금요일

[Algorithm] Ellipse Drawing

문제) Modify Midpoint circle drawing algorithm to draw Ellipses

타원의 방정식)
  . (x^2 / a^2) + (y^2 / b^2) = 1
  . (b^2 * x^2) + (a^2 * y^2) = (b^2 * a^2)

  . (b^2 * x^2) + (a^2 * y^2) - (b^2 * a^2)
  (음수이면 타원의 외부, 양수이면 타원의 내부, 0이면 타원 위의 점)

  . EllipseError(xi, yi) = abs((b^2 * xi^2) + (a^2 * yi^2) - (b^2 * a^2))

방법)
. 1사분면(quadrant)에 대해 계산하고 4-way symmetry를 이용하여 2,3,4분면에 그린다.
. 1사분면에서 tangent line의 slope는 항상 음수
. tangent line의 slope가 -1보다 큰 곳과 작은 곳을 나누어 계산한다.

구현) Pseudo code(Algol 코드와 유사함)
Procedure PlotEllipse(CX, CY, XRadius, YRadius : Integer);
var X, Y, XChange, YChange, EllipseError, TwoASquare, TwoBSquare, StoppingX, stoppingY : Integer;
begin
  { CX : 타원의 중심의 X좌표 }
  { CY : 타원의 중심의 Y좌표 }
  TwoASquare := 2 * XRadius * XRadius; { 제곱을 미리 계산 }
  TwoBSquare := 2 * YRadius * YRadius;

  { 동 -> 북 }
  X:= XRadius;
  Y:= 0;
  XChange := YRadius*YRadius*(1-2*XRadius);
  YChange := XRadius*XRadius;
  EllipseError := 0;
  StoppingX := TwoBSquare*XRadius
  StoppingY := 0;

  while(StoppingX >= StoppingY) do {1st set of points, y'>-1}
      begin
          Plot4EllipsePoints(X,Y);
          ++Y;
          StoppingY := StoppingY + TwoASquare;
          EllipseError := EllipseError + YChange;
          YChange := YChange + TwoASquare;
          if ((2*EllipseError + XChange) > 0) then
              begin
                  --X;
                  StoppingX := StoppingX - TwoBSquare;
                  EllipseError := EllipseError + XChange;
                  XChange := XChange + TwoBSquare
              end
      end;

  { 북 -> 동 }
  X := 0;
  Y := YRadius;
  XChange := YRadius*YRadius;
  YChange := XRadius*XRadius*(1-2*YRadius);
  EllipseError := 0;
  StoppingX := 0;
  while (StoppingX <= StoppingY) do {2nd set of points, y' < -1}
      begin
          Plot4EllipsePoints(X,Y); {subroutine appears later}
          ++X;
          StoppingX := StoppingX + TwoBSquare;
          EllipseError := EllipseError + Xchange;
          XChange := XChange + TwoBSquare;
          if ((2*EllipseError + YChange) > 0) then
              begin
                  --Y;
                  StoppingY := StoppingY - TwoASquare;
                  EllipseError := EllipseError + YChange;
                  YChange := YChange + TwoASquare
              end
      end
end; {procedure PlotEllipse}

{ 4-way symmetry point draw }
procedure Plot4EllipsePoints(X, Y : integer)
begin
  display(CX+X,CY+Y); {point in quadrant 1}
  display(CX-X,CY+Y); {point in quadrant 2}
  display(CX-X,CY-Y); {point in quadrant 3}
  display(CX+X,CY-Y); {point in quadrant 4}
end; {procedure Plot4EllipsePoints}

참고)
Jerry R. Van Aken, An Efficient Ellipse-Drawing Algorithm, IEEE Computer Graphics & Applications, September 1984, pp.24~35
A Fast Bresenham Type Algorithm For Drawing Ellipses : http://homepage.smc.edu/kennedy_john/BELIPSE.PDF



[Algorithm]Anti-aliasing Lines

. Aliasing(Jagged or blocky pattern), artifact, black and white noise
  . Line뿐만 아니라 texture에서도 많이 나옴
  . 계단현상(stairecase)
  . raster effect
  . small object : 작은 물체는 안 그려진다.
  . Texture : pixel보다 얇은 texture는 안 그려진다.

. Anti-aliasing : removing data at too high a freequency to represent
  . 완벽하게는 안되고 최대한 잘해보자.
  . 두께를 가지는 line으로 생각함.
  . 각 rectangle(pixel)과 두께를 가지는 line의 면적비를 intensity로 줌
  . intensity adjusing along to line
   . 대각선으로 그려진 라인이 sqrt(2)배 더 길므로 그만큼 더 밝게 해주자.

방식)
. Supersampling(Postfiltering)
  . Increasing resolution - hardware이용, 계산량 증가
. Area Sampling(Prefiltering)
  . intensity를 0~1사이의 gray scale로 넣자.
  . Box filter(Unweighted filter)
  . Cone filter(Weighted filter)
   . 같은 크기의 area라도 line의 center에 가까우면 weight를 더 준다.
   . Box filter는 Cone filter의 special case
   . Intensity functions f(D,t)
     . t : Line의 width
     . D : Line center로부터 pixel center까지의 거리
     . V : Vertical한 거리
     . D = v * cos(theta) = v dx / sqrt(dx^2+dy^2)
   . 그 점뿐만 아니라 그 위, 아래 점도 계산한다.

. Stochastic Sampling

2006년 4월 6일 목요일

[Algorhtim]Curve fitting, Interpolation, Apporoximation

. Curve fitting
  . Interpolation : 모든 control point를 지나야 함.
  control point가 많으면 noisy해짐(oscillatory feature)
  Lagrange, Hermite, Cubic spline, B-spline, piece-wise method
  참고) Numerical Analysis
  . Approximation : 모든 control point를 지날 필요 없음.
  control point가 많아도 smooth하다.


 

[CG Algorhtim]Midpoint circle algorithm

. 방법 1 : 원의 방정식에서 x값을 증가시키면서 y를 구하자.
  . 문제점
  . x가 원의 가장 왼쪽, 오른쪽 근처에서 원 위의 점들이 듬성듬성 찍힌다.
  . sqrt() 함수를 써야 한다. (느리다.)
  . y = yc +-sqrt(r^2-(x-xc)^2)

. 방법 2 : Polar coordinate를 이용하자.
  . 듬성듬성찍히는 문제를 해결
  . sin(), cos() 함수를 써야 한다. (느리다.) 
  . x = xc + rcos(theta)
  . y = yc + rsin(theta)

. 방법 3
  . 8-way symmetry를 이용하자.(x축 대칭, y축 대칭, y=x 대칭)
  2 x 2 x 2 = 8, 1/8, 45도만 계산하면 된다.
  . 북~북서쪽의 45도를 계산하자.(듬성듬성하지 않게)
  . Midpoint line algorithm을 응용하자.

void MidpointCircle ( int radius, int value )
{
  int   x, y;
  float d;

  x = 0;
  y = radius;
  d = 5.0 / 4 - radius;
  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) {
        d = d + x * 2.0 + 3;
  ++x;
     }
     else {
        d = d + (x - y) * 2.0 + 5;
  ++x;
  --y;
     }
     CirclePoints ( x, y, value );
  }
}

. 방법 4
  . floating point 연산을 없애자

void MidpointCircle (int radius, int value )
{
  int x, y;
  int d;

  x = 0;
  y = radius;
  d = 1 - radius;
  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) {
        d = d + x * 2 + 3;
  ++x;
     }
     else {
        d += (x - y) * 2 + 5;
  ++x;
  --y;
     }
     CirclePoints ( x, y, value );
  }
}

. 방법 5
  . loop 내의 곱셈을 없애자.
  . Second Order Differences
  . Key idea: Just as we calculate x and y incrementally, we can also calculate deltaE and deltaSE incrementally
caseE:
  deltaEold = 2xp + 3
  deltaEnew = 2xp + 5
  deltaDeltaE  = 2
  deltaDeltaSE = ( 2(xp - 1) - 2yp + 5 ) - ( 2xp - 2yp + 5 )
               = 2
caseSE:
  deltaDeltaE  = (2xp + 5) - (2xp + 3)
               = 2
  deltaDeltaSE = ( 2(xp + 1) - 2(yp - 1) + 5 ) - ( 2xp - 2yp - 5 )
               = 4

Starting out:
  deltaEstart = 2 * 0 + 3 = 3
  deltaSEstart = 2 * 0 - 2 * R + 5
                  = 5 - 2R

void MidpointCircle ( int radius, int value )
{                  
  int     x, y, d, deltaE, deltaSE;

  x       = 0;
  y       = radius;
  d       = 1 - radius;
  deltaE  = 3;
  deltaSE = 5 - radius * 2;

  CirclePoints ( x, y, value );
 
  while ( y > x ) {
     if ( d < 0 ) { /* Select E */
        d       += deltaE;
  deltaE  += 2;
  deltaSE += 2;
  x       ++;
     }
     else {         /* Select SE */
        d       += deltaSE;
  deltaE  += 2;
  deltaSE += 4;
  x       ++;
  y       ++;
     }
     CirclePoints ( x, y, value );
  }
}

참고)
http://www.cs.umbc.edu/~rheingan/435/pages/res/gen-3.Circles-single-page-0.html

Midpoint Circle Algorithm
Implicit Equation
  f(x,y) = x^2 + y^2 - R^2
     f(x,y) > 0  =>  point outside circle
     f(x,y) < 0  =>  point inside circle

Midpoint Criteria
  f(M) = f(xp+1, yp - 1/2)
       = (xp + 1)^2 + (yp - 1/2)^2 - R^2

  d >= 0 choose SE
       next M: +1 in x, -1 in y

  d <  0 choose E
       next M: +1 in x

Book keeping
  deltaE  = dnew - dold
          = f(xp + 2, yp - 1/2) - f(xp+1, yp - 1/2)
  = 2xp + 3

  deltaSE = f(xp + 2, yp - 3/2) - f(xp+1, yp - 1/2)
      = 2xp - 2yp + 5

  dstart   = f(x0 + 1, y0 - 1/2) = f(1, R - 1/2)
        = 5/4 - R

void CirclePoints (float x, float y, int value)
{
  WritePixel (  x,  y, value );
  WritePixel (  y,  x, value );
  WritePixel (  y, -x, value );
  WritePixel (  x, -y, value );
  WritePixel ( -x, -y, value );
  WritePixel ( -y, -x, value );
  WritePixel ( -y,  x, value );
  WritePixel ( -x,  y, value );
}

2006년 4월 1일 토요일

[CG]circular arc 그리기

. (x1, y1), (x2, y2), (x3, y3) 세점이 주어졌을 때
(x1, y1) -> (x2, y2) -> (x3, y3)를 차례로 지나는 arc를 그린다.
. 점을 지나는 순서를 지켜야 한다는 사실이 중요하다. 그렇게 해야 unique하게 arc가 결정된다.
. 두 점과 원의 중심이 주어지는 경우에는 arc가 unique하게 결정되지 않고 시계방향과 반시계방향의 2개가 나온다.

// theta들은 360 degree(not radian)

// 두 각이 입력되었을 때 같은 각인지 검사한다.
bool isEqualDegree(const int theta1, const int theta2)
{
int diff = (theta1 - theta2) % 360;

if (diff == 0)
return true;

return false;
}

int arcDirectionTest(const int theta1, const int theta2, const int theta3)
{
// 시계방향으로 돌아야 할지, 반시계방향으로 돌아야 할지 test
// direction = 1 : 반시계방향
// direction = -1 : 시계방향
int direction = 1;

for (int theta_i = theta1; theta_i < 360 + theta1; theta_i++)
{
if (isEqualDegree(theta_i, theta3)) {
// theta2를 theta3보다 먼저 지나게 그려야 하므로
// 방향을 바꾸자.
direction = -1;
break;
}

if (isEqualDegree(theta_i, theta2)) {
// theta2를 theta3보다 먼저 지나고 있으므로 방향 유지
break;
}
}

return direction;
}

// arc 그리기
direction = arcDirectionTest(theta1, theta2, theta3);
int theta_i = theta1;

while(1)
{
if (theta_i >= 180) {
theta_i = -179;
}

if (theta_i <= -180) {
theta_i = 180
}
// -179 <= theta_i <= 180

glVertex3f(x0 + r * cos(theta_i) , y0 + r * sin(theta_i), 0);

if (isEqualDegree(theta_i, theta3))
break;

theta_i += direction
}

[CG]외접원 - Circumscribed Circle

외접원 구하기

// (x1, y1), (x2, y2), (x3, y3) 삼각형의 세 꼭지점
// (x0, y0) - 외접원의 중심
// r - 외접원의 반지름

void circumscribedCircle(const float x1, const float y1, const float x2, const float y2, const float x3, const float y3, float* x0, float* y0, float r)
{
// (x1, y1), (x2, y2), (x3, y3) 세 점 중 2개 이상이 같거나
// 세 점이 일직선 상에 있으면 안된다.

// divide by 0 조건도 피해야 한다.
// 1. y1 - y2 = 0
// 2. y1 - y2 = 0
// 3. (x1 - x3 - (y1 - y3) * (x1 - x2) / (y1 - y2)) = 0
// 4. x1 - x2 = 0

*x0 = (pow(y1, 2) + pow(x1, 2) - pow(y3, 2) - pow(x3, 2) - (y1 - y3) * (pow(y1, 2) + pow(x1, 2) - pow(y2, 2) - pow(x2, 2)) / (y1 - y2)) / 2 / (x1 - x3 - (y1 - y3) * (x1 - x2) / (y1 - y2));
*y0 = (pow(y1, 2) + pow(x1, 2) - pow(y2, 2) - pow(x2, 2) - 2 * x0 * (x1 - x2)) / (y1 - y2) / 2;
*r = sqrt(pow(x3 - x0, 2) + pow(y3 - y0, 2));
}

Atan2 - Arc tangent

atan2(y, x);
좌표상 원점(0, 0)을 기준으로 (x, y)가 x축가 이루는 각 theta를 구해준다.
x-y coordinate를 polar coordinate로 바꿀 때나 원을 그릴 때 사용한다.

. atan(x) 대신 atan2(y, x)를 쓰는 이유
x가 0일 때 분모가 0이 되므로 atan(x)로는 모든 각을 계산할 수가 없다.

(x, y)
. 1사분면일때 : 0 ~ Pi/2 (0 ~ 1.5708)
. 2사분면일때 : Pi/2 ~ Pi (0 ~ 3.14159)
. 3사분면일때 : -Pi ~ -Pi/2 (-3.14159 ~ -1.5708)
. 4사분면일때 : -Pi/2 ~ 0 (-1.5708 ~ 0)
. (x, y)가 원점을 기준으로 반시계방향으로 돌 때
atan2(y, x)의 값은 2사분면에서 3사분면으로 넘어가는 순간 -2Pi가 되고
나머지 구간에서는 항상 증가한다.

. atan2(y, x) 컴파일시 에러가 날때
. 오버로드된 함수에 대한 호출이 모호합니다.
=> y, x의 type을 float나 double로 통일해준다.
int type으로 하거나 float, double을 섞으면 안된다.

. 예제 프로그램
#include
#include
using namespace std;

void print(int x, int y)
{
cout << "atan2(" << y << ", " << x << ") : " << atan2(y, x) << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
print(0, 0); // 0
print(10, 0); // 0
print(10, 10); // Pi/4
print(0, 10); // Pi/2
print(-10, 10); // 3*Pi/4
print(-10, 0); // Pi
print(-10, -10); // -3*Pi/4
print(0, -10); // -Pi/2
print(10, -10); // -Pi/4

return 0;
}

. radian(0~Pi)을 degree(0~180)로 바꾸기
0 -> 0
Pi/4 -> 45
Pi/2 -> 90
Pi -> 180

즉) radian * 180 / Pi = degree

OpenGL - Tessellation

nonconvex polygon을 triangles로 break down하여
convex polygons(Tessellation)으로 만든다.

. Nonconvex polygon
. concave - 180도 이상의 각이 있음.
. complex - hole 같은 것이 있음.

. Contour(외곽선)
. convec, concave polygon의 경우 1개 이상있음.
. hole 1개당 contour 1개가 추가됨.
. Nested Contour - holes 안에 holes가 있음.

. OpenGL에서 Polygon을 그릴 때 convex가 아닌 경우(concave) 모양이 이상하게 그려질 수가 있다.
. OpenGL은 performance를 위해 입력이 convex임을 가정하기 때문이다. 따라서 tessellation을 해서 concave를 convex 여러개로 나눈다.

예제)
void CALLBACK tessVertexCallback(GLvoid *vertex)
{
GLdouble *ptr;
ptr = (GLdouble *) vertex;
glVertex3dv((GLdouble *) ptr);
// glColor3dv((GLdouble *) ptr + 3);

cout << "vertex[0] : " << ptr[0] << endl;
cout << "vertex[1] : " << ptr[1] << endl;
cout << "vertex[2] : " << ptr[2] << endl;
}

void CALLBACK tessCombineCallback(GLdouble coords[3], GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **dataOut)
{
GLdouble *vertex;
vertex = new GLdouble[6];
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];

for (int i = 3; i < 6; i++)
{
// vertex에 color 값을 주지 않았다면
// 메모리 오류가 난다.
// 그 때는 vertex[i] = 0; 이라고 적당히 적어주자.
vertex[i] = weight[0] * vertex_data[0][i] +
weight[1] * vertex_data[1][i] +
weight[2] * vertex_data[2][i] +
weight[3] * vertex_data[3][i];
}
*dataOut = vertex;

}

void CALLBACK tessError(GLenum error)
{
const GLubyte* szError = gluErrorString(error);

cerr << "tessError : " << szError << endl;
}

GLUtesselator *tobj;
tobj = gluNewTess();
gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(__stdcall*) ())&tessVertexCallback);
gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(__stdcall*) ())&tessCombineCallback);
gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(__stdcall*) ())&glBegin);
gluTessCallback(tobj, GLU_TESS_END, (GLvoid(__stdcall*) ())&glEnd);
gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid(__stdcall*) ())&tessError);

gluTessBeginPolygon(tobj, NULL);
gluTessBeginContour(tobj);

for(적절히 i의 loop를 돌면 됨)
{
gluTessVertex(tobj, polygon2[i], polygon2[i]);
++i;
}

gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
gluDeleteTess(tobj);

delete polygon2를 지움.

. 아무 것도 찍지 않을 때.
. 값을 잘 넣었는 지 확인
. error callback을 등록
. callback들에서 어느 vertex를 이용해 나눴는 지 출력해본다.

. combine callback을 등록하지 않을 때 나는 에러 메시지
: Need combine callback

. combine callback이 불리는 경우 오목한 정도가 심해서 나누려면 새로운 vertex가 필요할 때

. callback 함수 type casting
. Visual Studio 2003 .NET의 경우 위 처럼 적어줘야 한다.
책에서 다른 방식으로 적는 경우가 있는 데, 컴파일 에러(타입 오류)가 난다.

. callback 함수는 일반  function이거나 state member function 이어야만 한다.
  non-static member function일 때는 callback으로 등록할 수 없다.
  따라서 global variable 등을 동원하는 다른 꽁수를 써야 한다.

참고)
OpenGL Super Bible P.508
http://www.flipcode.com/articles/article_tesselating.shtml
http://www.songho.ca/opengl/gl_tessellation.html

2006년 3월 30일 목요일

Escherization

. M.C. Escher (Maurits Cornelis Escher)
Dutch graphic artist. 책 'Godel, escher, bach, '미학 오디세이'에 나오는 화가.

. Tessellation
동일한 모양을 이용해 틈이나 포개짐 없이 평면이나 공간을 완전하게 덮는 것

. Escherization
Escher의 그림처럼 plane을 tessellation해서 tiling함.
source S가 있을 때 최대한 적게 바꿔서 tiling되는 T로 만들어 붙이기.
http://www.cgl.uwaterloo.ca/~csk/projects/escherization/

. isohedral
. dihedral Escherization
. tiling two different shapes
. Aperiodic Escherization
. period가 없음.
. Non-Euclidean Escherization
. Escher의 작품
. Sky and water

2006년 3월 21일 화요일

MFC OpenGL Cube 그리기 + Maya Control 기능

. MDI는 복잡하므로 SDI로 할 것.
. seperate window로 화면을 2개로 나눌 것.
. viewport를 2개 저장해 놓고 2D, 3D image를 잘 찍을 것.
. OpenGL을 2개 띄울 수 있는 지 찾아 볼 것.

. MSDN -> Search
키워드 : SDI MFC Opengl
CUBE Sample : Demonstrates an OpenGL Application

. 클래스 뷰 -> CCubeView -> 마우스 오른쪽 -> 속성
-> WM_MOUSEMOVE -> OnMouseMove

. 추가할 멤버변수
CCubeView Class의
float m_fPosX;
float m_fPosY;
float m_fZoom;
float m_fRotX;
float m_fRotY;
float m_fLastX;
float m_fLastY;
(Wizard를 안 써도 class view에 잘 추가된다.)

. 멤버함수 수정
OnMouseMove(UINT nFlags, CPoint point)
{
int diffX = (int)(point.x - m_fLastX);
int diffY = (int)(point.y - m_fLastY);
m_fLastX = (float)point.x;
m_fLastY = (float)point.y;

// Left mouse button
if (nFlags & MK_LBUTTON)
{
m_fRotX += (float)0.5f * diffY;

if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
{
m_fRotX = 0.0f;
}

m_fRotY += (float)0.5f * diffX;

if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
{
m_fRotY = 0.0f;
}
}

// Right mouse button
else if (nFlags & MK_RBUTTON)
{
m_fZoom -= (float)0.1f * diffY;
}

// Middle mouse button
else if (nFlags & MK_MBUTTON)
{
m_fPosX += (float)0.05f * diffX;
m_fPosY -= (float)0.05f * diffY;
}

OnDraw(NULL);
// 위 내용을 추가

// 원래 내용 유지
}

. 생성자에서 맴버 변수를 모두 0으로 초기화

. Cubeview.h 파일에서
CubeView class 형식 재정의 에러가 날 때.
-> 첫 줄에 #pragma once 라고 적는다.

. pan (축의 방향으로 카메라만 움직이는 것)

. Visual Studio - solution > project보다 상위 개념, solution이 project를 포함한다.

. 단축키를 만들어서 그것을 누르면 가장 기본좌표(0,0,0) + 기본 카메라 뷰로 돌아오는 기능을 넣는 다.

. panning
. 도형과 카메라가 이루는 vector를 먼저 구한다.
적당한 up vector를 정한다.
위 두 vector를 cross product하면 left, right로 panning 할 수 있다.
up vector 방향을 이용하면 up, down으로 panning 할 수 있다.

. pan과 translate는 다르다.

. 리소스 뷰
-> Menu -> IDR_MAINFRAME - 메뉴를 추가한다.
-> Menu 이름에서 마우스 오른쪽을 클릭하면 이벤트 처리기를 추가할 수 있다.
-> Menu이름\tCtrl+Y(&O) : \t를 누르면 탭으로 적절한 간격으로 벌어지고 &를 누르면
-> Accelerator -> IDR_MAINFRAME - 추가한 메뉴 ID에 대해 키를 넣는 다.
예) ctrl + Y : Redo
ctrl + Z : Undo

. toolbar에 새로운 dialog 추가하기
. 프로젝트명.rc -> Dialog -> IDD_DIALOGBAR를 추가한다.
. 적당히 버튼들을 추가한다.
. 동적으로 위의 dialog를 추가한다.
. 그림 그리는 곳에서 마우스 오른쪽 클릭 -> 클래스 추가
. MainFrm.h의 include에 새로 만든 header를 추가

. 현재 solution 파일이 있는 경로 : $(SolutionDir)
(include시 유용하게 쓰인다.)
속성 -> C/c++ -> 일반 -> 추가 포함 디렉터리 -> $(SolutionDir)

참고)
http://www.codeguru.com/cpp/g-m/opengl/openfaq/article.php/c10975__2/

2006년 3월 19일 일요일

CSG, ASV

CSG : Constructive Solid Geometry
ASV : Alternating Sum of Volumes

. 구글 검색어 : CSG tree alternating sum
-> http://www.citidel.org/?op=getobj&identifier=oai:ACMDL:articles.267754

. 관련 논문
K. Tang and T. Woo. Algorithmic aspects of alternating sum of volumes. Part 1: Data structure and difference operation. CAD, 23(5):357- 366, 1991. (Citation)

K. Tang and T. Woo. Algorithmic aspects of alternating sum of volumes. Part 2: Nonconvergence and its remedy. CAD, 23(6):435- 443, 1991. (Citation)
-> http://portal.acm.org/citation.cfm?id=124974
-> Display Format -> ACM Ref ->
-> http://dx.doi.org/10.1016/0010-4485(91)90011-K
-> PDF (700 K)

2006년 2월 14일 화요일

CG - Texture

Texture라는 것은 상당히 특이한 기법인 것 같다.
요즘 웹게시판이나 GUI에서 말하는 skin과 꽤 비슷하다.
일단 기하학적인 물체의 모양을 모두 그린 후 질감을 입히는 것이다.

음악으로 말하자면 midi와 비슷하다.
midi 방식은 거시적인 파장만 저장한 후 각 악기의 음을 녹음해서
음색을 입히는 방식이다. (악보 + 음색이라고 볼 수 있다.)

음색, texture 같은 기법들은 인간의 인식에 의해 사용되는 추상적인 모델을 이용한 손실 decomposition이라고 할 수 있겠다.

아무튼 상당히 훌륭한 생각이다. 일반적으로 같은 물체는 같은 질감을 가지니까.

. decal - 전사인쇄 방식
프라모델(plastic model)을 만들 때도 쓰인다. 판박이라고도 부른다.
일단 종이나 어떤 표현에 물감 등을 묻힌 후 그것을 입체 도형에 입히는 기법.

2006년 1월 25일 수요일

Bezier curve

. Bezier가 parametric curve를 만듬.
. control points가 magnetic처럼 curve를 잡아당김
. order : control point의 갯수
. degree : control point의 갯수 - 1
. order 2 : straight
. order 3 : quadratic curve
. order 4 : cubic
. 점이 5개 이상이면 control이 잘 안 되므로 힘들어서 잘 안 쓰임.
(심하게 oscillation함)

. Continuity
. Bezier curves를 여러개 놓고 생각
. None : 두 선이 not meet
. C0-Positional : Meet(share a common endpoint)
. C1-Tangent : same tangent at the breakpoint
. C2-Curvature : same tangent at the breakpoint, same rate of change

. OpenGL
. Control points를 정하고 그것들을 이용해서 bezier curve를 grid로 나누어 중간 vertecies n개를 계산하고 모두 이어서 출력
. Bezier surface도 같은 방식으로 가능.

. Bezier curve -> B-spline -> NURBS 로 발전된다.

참고)
Open Superbible, ch.10.
http://en.wikipedia.org/wiki/B%C3%A9zier_curve

Visual Studio .NET MFC + OpenGL

1. Create Project
File -> New -> Project -> Visual C++ Projects -> MFC Application
Project Name : oglMFCDialog
Application Type -> Dialog based -> Finish Button

2. Create the Control
Solution Explorer tabl -> Resource View(top right view들 중에 있음)
-> oglMFCDialog.rc -> Dialog -> IDD_OGLMFCDIALOG_DIALOG

View -> Toolbox -> Picture Control -> Drag하여 dialog window에 drop
(resize accordingly)
(사각형의 가장자리를 선택해야 선택이되고 사각형의 내부를 누르면 선택이 안되므로 주의)

Properties window (bottom right)
-> Behavior -> Visible -> False
-> ID -> (IDC_STATIC -> IDC_OPENGL로 바꿈)
(Visible을 true로 하면 이것이 OpenGL에서 그린것을 가려버리므로 false로 함)

3. Add the OpenGL Class
Class view -> oglMFCDialog + mouse right click -> Add Class
-> Add class wizard -> Generic C++ class -> Open button
Class name: COpenGLControl
Base class: CWnd
Access: public
Check Virtual destructor
Finish Button

OpenGLControl.h, OpenGLControl.cpp가 생성됨
afxwin.h가 include되고 cpp에 h가 include됨
class declaration과 definition이 됨.(이제 채워 넣으면 됨)

4. Add libraries
Class view -> oglMFCDialog + mouse right click -> Property
-> Linker -> Input -> opengl32.lib glu32.lib
(lib파일 사이에는 공백을 한 칸만 넣을 것)

5. Add member varible
#include
#include

class COpenGLControl : public CWnd
{
public:
/******************/
/* PUBLIC MEMBERS */
/******************/
// Timer
UINT_PTR m_unpTimer;

private:
/*******************/
/* PRIVATE MEMBERS */
/*******************/
// Window information
CWnd *hWnd;
HDC hdc;
HGLRC hrc;
int m_nPixelFormat;
CRect m_rect;
CRect m_oldWindow;
CRect m_originalRect;

6. Add the oglCreate Function
Class view -> COpenGLControl + mouse right -> Add -> Add function
void oglCreate(CRect rect, CWnd *parent);

7. Add the OnPaint()
Properties -> Messages button(Mouse hovering하면 bubble에 설명이 나옴, lightning bolt(번개) 아이콘 옆에 있음)
-> WM_PAINT -> "OnPaint"

COpenGLControl에 afx_msg void OnPaint() member function이 생긴다.

void COpenGLControl::OnPaint()
{
//CPaintDC dc(this); // device context for painting
ValidateRect(NULL);
}

8. Add the OnCreate()
Properties -> Messages button(Mouse hovering하면 bubble에 설명이 나옴, lightning bolt(번개) 아이콘 옆에 있음)
-> WM_CREATE -> "OnCreate"

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;

oglInitialize();

return 0;
}

9. Add oglInitialize()
Class view -> COpenGLControl + mouse right -> Add -> Add function
void oglCreate(void);

void COpenGLControl::oglInitialize(void)
{
// Initial Setup:
//
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32, // bit depth
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16, // z-buffer depth
0, 0, 0, 0, 0, 0, 0,
};

// Get device context only once.
hdc = GetDC()->m_hDC;

// Pixel format.
m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, m_nPixelFormat, &pfd);

// Create the OpenGL Rendering Context.
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);

// Basic Setup:
//
// Set color to use when clearing the background.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);

// Turn on backface culling
glFrontFace(GL_CCW);
glCullFace(GL_BACK);

// Turn on depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

// Send draw request
OnDraw(NULL);
}

10. Add the OnDraw()
-> 일종의 Message function이지만 OnPaint()와 달리 Properties에서 추가하지 않고 Add -> Add function으로 추가함.

afx_msg void OnDraw(CDC *pDC);

void COpenGLControl::OnDraw(CDC *pDC)
{
// TODO: Camera controls.
}

11. Add OnTimer()
Properties -> Messages button(Mouse hovering하면 bubble에 설명이 나옴, lightning bolt(번개) 아이콘 옆에 있음)
-> WM_TIMER -> "OnTimer"

void COpenGLControl::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Draw OpenGL scene
// oglDrawScene();

// Swap buffers
SwapBuffers(hdc);

break;
}

default:
break;
}

CWnd::OnTimer(nIDEvent);
}

12. Add OnSize()
Properties -> Messages button(Mouse hovering하면 bubble에 설명이 나옴, lightning bolt(번개) 아이콘 옆에 있음)
-> WM_SIZE -> "OnSize"

void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

// Map the OpenGL coordinates.
glViewport(0, 0, cx, cy);

// Projection view
glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// Set our current view perspective
gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 2000.0f);

// Model view
glMatrixMode(GL_MODELVIEW);
}

13.
Class View -> CoglMEFDialogDlg + Mouse right -> Add -> Add function
private:
COpenGLControl m_oglWindow;

oglMFCDialogDlg.cpp::OnInitDialog()에 다음 내용 추가(retun 바로 앞에)

CRect rect;

// Get size and position of the picture control
GetDlgItem(IDC_OPENGL)->GetWindowRect(rect);

// Convert screen coordinates to client coordinates
ScreenToClient(rect);

// Create OpenGL Control window
m_oglWindow.oglCreate(rect, this);

// Setup the OpenGL Window's timer to render
m_oglWindow.m_unpTimer = m_oglWindow.SetTimer(1, 1, 0);


14. F5를 눌러 컴파일하면 됨, 그냥 까만 화면이 나옴

15, 16도 하면 화면이 나옴.
. 참고
http://www.codeguru.com/cpp/g-m/opengl/openfaq/article.php/c10975/

2006년 1월 20일 금요일

Visual Studio .NET 2003 + FLTK + OpenGL

. fltk 설치하기
. fltk-1.1.x-r.4721을 다운로드 받는 다.
. Visual Studio project directory 밑에 푼다.
. fltk-1.1.x-r4721\vcnet\fltk.sln을 연다.
. F5를 눌러 컴파일을 한다.


. fltk 사용하기
. Win32 Console application을 새로 만든다.

. Project -> Property -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded DLL(/MD)
. 위 설정을 빼먹었을 때 나는 에러
-------------------------------------
private: __thiscall
private:
__stdup
__stricmp
_exit
_free
.. 에 이미 정의되어 있습니다.
여러 번 정의된 기호가 있습니다.
-------------------------------------


. header file copy
fltk-1.1.x-r4721\FL을 현재 만드는 프로젝트 디렉토리로 복사한다.
(FL directory를 유지할 것)
(boost 같은 library도 같은 식으로 설정한다.)

. library file copy
fltk-1.1.x-r4721\lib\*.lib을 현재 만드는 프로젝트 디렉토리로 복사한다.

. stdafx.h에 추가할 내용
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.
#include >math.h<
#include >string<
#include >vector<
#include >fstream<

// FLTK
#include >FL/Fl.H<
#include >FL/Fl_Window.H<
#include >FL/Fl_Box.H<
#include >FL/Fl_Double_Window.H<
#include >FL/Fl_Menu_Bar.H<
#include >FL/fl_message.H<
#include >FL/Fl_Input.H<
#include >FL/Fl_Button.H<
#include >FL/Fl_Return_Button.H<
#include >FL/Fl_Text_Buffer.H<
#include >FL/Fl_Text_Editor.H<
#include >FL/fl_ask.H<
#include >FL/Fl_Group.H<
#include >FL/Fl_File_Chooser.H<

// FLTK + OpenGL
#include >FL/gl.h<
#include >FL/Fl_Gl_Window.H<
#include >Gl/glu.h<

. 프로젝트 -> 속성 -> 구성 속성 -> C/C++ -> 일반 -> 추가 포함 디렉터리
$(SolutionDir)
. 프로젝트 -> 속성 -> 구성 속성 -> C/C++ -> 미리 컴파일된 헤더
-> 미리 컴파일된 헤더 사용 안함
. 프로젝트 -> 속성 -> 구성 속성 -> 링커 -> 추가 종속성
-> fltkd.lib wsock32.lib comctl32.lib fltkgld.lib opengl32.lib glu32.lib
(debug mode일 때)

. Main source code 예제
// w라는 window를 찍고
// 메뉴 o와 opengl 창 g_mainWindow를 찍는 다.
(g_mainWindow라는 global variable을 통해
g_mainWindow->redraw() 같은 식으로 부르면
draw()가 호출되어 그려진다.)

int _tmain(int argc, _TCHAR* argv[])
{
Fl_Double_Window* w = new Fl_Double_Window(g_screenX + 60, g_screenY + 60, "MainMenuBar");
Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, g_screenY, 20);
o->menu(menu_);
g_mainWindow = new MyWindow1(0, 40, g_screenX - 20, g_screenY + 40, "CS580 PA1 - liyam, ilashman");

w->end();

w->show(argc, argv);

return Fl::run();
}

. 디버깅
console 창이 같이 뜨므로 printf() 등을 이용해서 값을 찍는 다.
debugger를 이용하여 stop point를 잡을 수도 있지만
event driven의 경우 너무 자주 stop될 수도 있다.

. 참고
GLUT와 FLTK가 같이 있을 때 FLTK가 event loop를 도는 편이 낫다.
GLUT도 evnet loop가 있지만
GLUT가 event loop를 돌게 해야 문제가 더 적다.
장점
. 창 속에 OpenGL창을 내장할 수 있다.
. 여러개의 OpenGL 창을 쉽게 관리할 수 있다.

. FLTK의 장점
MFC에 비해 사용법이 훨씬 단순하다.