General/Graphics / Vision

[컴퓨터그래픽스] 스탠드 그리기

croute 2010. 10. 19. 00:43

glu 파일에는 3d 물체를 그리는 함수들이 여럿있다.
이 함수들을 이용해서 스탠드를 그리려고 한다.

먼저 오브젝트 포인터가 필요해서 선언해주자.
GLUquadricObj  *qobj;  

그리고 요놈들도 있어야 되니까. 선언해주고 설정한다.
qobj = gluNewQuadric(); //  Quadric 객체 속성 설정 함수
gluQuadricDrawStyle(qobj, GLU_LINE); // 포인터랑 속성을 설정해줄 인자를 넘긴다.
 
여기서 잠깐 gluQuadricDrawStyle() 함수에 대해 알아보자.
gluQuadricDrawStyle() 함수 원형 -
void gluQuadricDrawStyle(GLUquadricObj *obj, GLenum drawStyle); 
첫번째 인자 : Quadric에 대해 속성을 설정해줄 포인터 변수.
두번째 인자 : GLU_FILL | FLU_LINE | GLU_SILHOUETTE | GLU_POINT 
GLU_LINE   Wire frame
GLU_FILL  Solid
GLU_POINT   point(점)
GLU_SILHOUETTE   외부모서리(선)만 그림



자 이제 할거 했으니,
여러 3D 물체를 그리는 함수들을 알아보자.

실린더
gluCylinder(포인터 변수, baseRadius, topRadius, Height, slices, stacks);
             
glutWireSphere(radius, slices, stack);
glutSolidSphere(radius, slices, stack);

원뿔
glutWireCone(base, height, slices, stacks);
glutSolidCone(base, height, slices, stacks);

: slices - wire 도형에서 세로로 그어지는 wire
: stacks - wire 도형에서 가로로 쌓이는 wire

토러스(이거 뭐랄까..... 도넛같이 생긴 그런거..)
glutWireTorus(innerRadius, outterRadius, sides, rings);
glutSolidTorus(innerRadius, outterRadius, sides, rings);

주전자
glutWireTeapot(size);             
glutSolidTeapot(size); 




그리려는 목표는 이런 모양의 스탠드이다.

뭐... 그림판으로 그려서 폼새가 안나긴 하지만... ㅡㅡ;;;;;

우선 세가지의 부분으로 나누었다.
윗부분, 몸통부분, 바닥부분.

몸통부터 그려보자.
void draw_body()
{
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder(qobj, 100, 100, 300, 20, 20); // 실린더. 스탠드의 body.
}

자 이렇게 몸통부분을 그렸다. 지금은 뭐 그냥 외형만 비슷하게 하려는 거라.








뚜껑의 구멍난 갓 부분을 그려보자.
원뿔을 이용할수도 있지만, 실린더를 이용해 윗부분의 너비를 작게해서 그렸다.
void draw_top()
{
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder( qobj, 50, 300, 300, 20, 20);  // 실린더, 위와 아래의 너비가 다름, 갓 부분.
}














마지막으로 밑의 받침대는 토러스로 그려보았다.
위의 실린더는 여러 선언들이 필요하지만, 토러스는 숫자들만 있으면 되니깐.
void draw_bottom()
{
glutWireTorus(100, 200, 20,20); // (inner, outter, side, ring)
}    





자 이제 합쳐보자.

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
glPushMatrix();  
glRotatef(theta, 0.0, 1.0, 0.0);
glColor3f (1.0, 0.0, 1.0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_body();
glPopMatrix();
glPushMatrix();
glTranslated(0, 250, 0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_top();
glPopMatrix();

glPushMatrix();
glTranslated(0, -300, 0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_bottom();
glPopMatrix();

glFlush();
glutSwapBuffers();
}   

여기가 중요하다.
실제로 각 객체들을 출력해 줄때는,

glPushMatrix();를 해주고, 그 객체 그리기가 끝나면
glPopMatrix();를 해주어야 한다.
안 그러면 Rotation한 거나, Translation한거, Scaling한게, 다음 그릴 객체에까지 영향을 미친다.

중요한 포인트 또 하나는 푸시, 팝을 하고 나면, 객체는 처음 위치에 똑같이 그려진다는 것이다.
그래서 로테이트를 하고 트랜슬레이트를 해서 위치를 옮겨주어야 한다.

아래 실제 전체 코드가 있다. 
// include 되있는 것중 안써도 되는것도 있다. 이런거 저런거 수업시간에 하던거 연결해서 하느라...

- 전체코드 -
#include <glut.h>
#include <glu.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>

// 포인터변수필요
GLUquadricObj  *qobj;

void draw_body()
{
qobj = gluNewQuadric();

gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder(qobj, 100, 100, 300, 20, 20); // 실린더. 스탠드의 body.
}

void draw_top()
{
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder( qobj, 50, 300, 300, 20, 20);  // 실린더, 위와 아래의 너비가 다름, 갓 부분.
//실린더( baseRadius, topRadius, height, slices, statck )
}

void draw_bottom()
{
glutWireTorus(100, 200, 20,20); // (inner, outter, side, ring)
}

//void draw_teapot()
//{
// glutWireTeapot(50);
//}

//=====================================
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
glPushMatrix();  
glRotatef(theta, 0.0, 1.0, 0.0);
glColor3f (1.0, 0.0, 1.0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_body();
glPopMatrix();
glPushMatrix();
glTranslated(0, 250, 0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_top();
glPopMatrix();

glPushMatrix();
glTranslated(0, -300, 0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_bottom();
glPopMatrix();

/*
glPushMatrix();
glTranslated(400, 200, 0);
glRotatef(90, 1.0, 0.0, 0.0);
draw_teapot();
glPopMatrix();
*/

glFlush();
glutSwapBuffers();
}

void init(void)
{
glEnable(GL_DEPTH_TEST);
   
glClearColor(0.0,0.8,1.0,0.0);   
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-500.0, 700.0, -500.0, 700.0, 0.0, 1000.0);

gluLookAt(200, 200, 200,
0, 0, 0,
0, 1, 0);
}

int main(int argc , char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow(" 3D Objects");
init();
glutDisplayFunc(display);
//glutIdleFunc(rotate);
glutMainLoop();
return 0;
}


↑ 요렇게 해서 그리면 ↓ 이런 결과물이 나온다.