2006년 4월 1일 토요일

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

댓글 없음:

댓글 쓰기