Computer Graphics

Chapter 05. 정점 배열과 3차원 도형 그리기

CodeJB 2021. 5. 28. 21:09

큐브, 각 정점 번호가 적혀있음

#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <iostream>

#define _WINDOW_WIDTH 800
#define _WINDOW_HEIGHT 800

GLfloat MyVertices[8][3] = {{-0.25,-0.25,0.25},{-0.25,0.25,0.25},{0.25,0.25,0.25},
{0.25,-0.25,0.25},{-0.25,-0.25,-0.25},{-0.25,0.25,-0.25},
{0.25,0.25,-0.25},{0.25,-0.25,-0.25}}; 
//정육면체의 8개의 정점 3차원 좌표(꼭지점)
//순서대로 0부터 7번의 번호가 매겨질 것이다.(밑에서)

GLfloat MyColor[8][3] = {{0.2,0.2,0.2},{1.0,0.0,0.0},{1.0,1.0,0.0},
{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,0.0,1.0},
{1.0,1.0,1.0},{0.0,1.0,1.0}};
//각 정점마다 색깔

void MyDisplay(){
    glClear(GL_COLOR_BUFFER_BIT);
    
    int VertexList[6][4] = {{0,3,2,1},{2,3,7,6},{7,4,5,6},{1,2,6,5},{0,3,7,4},{0,4,5,1}};
    //각 정점에 번호를 매기고 그 번호에 따라 면을 지정함
    
    for(int i = 0; i < 6; i++){
        int index0 = VertexList[i][0];//6번 돌면서 각 정점 번호에 모두 접근하여 값을 할당한다.
        int index1 = VertexList[i][1];
        int index2 = VertexList[i][2];
        int index3 = VertexList[i][3];
        
        glBegin(GL_POLYGON);
        	//정점 번호가 0번이면 {-0.25,-0.25,0.25}가 들어갈 것이다.
            //이렇게 모든 정점 번호들을 할당시켜준다.
            
            glColor3fv(MyColor[index0]); glVertex3fv(MyVertices[index0]);
            glColor3fv(MyColor[index1]); glVertex3fv(MyVertices[index1]);
            glColor3fv(MyColor[index2]); glVertex3fv(MyVertices[index2]);
            glColor3fv(MyColor[index3]); glVertex3fv(MyVertices[index3]);
        glEnd();
    }
    glFlush();
}

void MyReshape(int width, int height){
    glViewport(0, 0, width, height);
    GLfloat f_w = (GLfloat)width / (GLfloat)_WINDOW_WIDTH;
    GLfloat f_h = (GLfloat)height / (GLfloat)_WINDOW_HEIGHT;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0*f_w, 1.0*f_w, -1.0*f_h, 1.0*f_h, -2, 2);
    gluLookAt(0.5, 0.5, 1, 0, 0, 0, 0, 1, 0); //보는 각도 조절
    //위치를 약간 오른쪽으로 틀고 보고자 하는 객체를 바라보도록(0,0,0)지정
    //카메라의 머리는 y축방향으로 위쪽을 보도록함. 일반적으로 (0,1,0)을 씀.(0,1,0)이 아니면 카메라를
    //돌려서 사용하는거나 마찬가지니까 그럴일이 별로 없으니..
    //gluPerspective로 구현할 수 있지만 이 내용은 나중에 하므로
    //일단 gluLookAt으로 대용함
}

int main(int argc, char ** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
    glutCreateWindow("Cube Drawing");
    
    //콜백함수
    glutDisplayFunc(MyDisplay);
    glutReshapeFunc(MyReshape);
    
    glutMainLoop();
}

 


void WINAPI glColor3fv( const GLfloat *v);
//인자 설명 : 
//빨강, 녹색, 및 파랑 값을 포함하는 배열에 대한 포인터이다. 따라서, 배열값을 인자로 넘겨주어 컬러를 지정할 수 있다.

void glVertex3fv( const GLfloat *v);
//인자 설명 :
//한 정점에 대한 3차원 좌표 배열에 대한 포인터이다.

void WINAPI gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,
GLdouble centerx,GLdouble centery,GLdouble centerz,
GLdouble upx,GLdouble upy,GLdouble upz
);
//View Transform Matrix를 정의하는 함수
//시점 좌표계를 정의하는 함수로, (eyeX, eyeY, eyeZ)에 있는 카메라가 (centerX, centerY, cneterZ)에 있는 
  초점을 바라보는 것이다.
//(upX, upY, upZ)는 카메라 상향 벡터이다.

 

sideVector는 UpVector와 ForwardVector의 외적이다. 두 벡터의 곱은, 두 벡터가 이루는 평면에 수직인 벡터를 만든다.

3차원 Cube그리기 함수 : drawCube

#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <iostream>

#define _WINDOW_WIDTH 1200
#define _WINDOW_HEIGHT 1200

//GLfloat MyVertices[8][3] = {{-0.25,-0.25,0.25},{-0.25,0.25,0.25},{0.25,0.25,0.25},{0.25,-0.25,0.25},{-0.25,-0.25,-0.25},{-0.25,0.25,-0.25},{0.25,0.25,-0.25},{0.25,-0.25,-0.25}}; //3차원 공간 상의 각 정점, 너비가 0.5인 큐브
GLfloat defaultCube[8][3] = {{-0.5,-0.5,0.5},{-0.5,0.5,0.5},{0.5,0.5,0.5},{0.5,-0.5,0.5},{-0.5,-0.5,-0.5},{-0.5,0.5,-0.5},{0.5,0.5,-0.5},{0.5,-0.5,-0.5}}; //3차원 공간 상의 각 정점, 너비가 1인 큐브

GLfloat MyColor[8][3] = {{0.2,0.2,0.2},{1.0,0.0,0.0},{1.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,0.0,1.0},{1.0,1.0,1.0},{0.0,1.0,1.0}};
//각 정점마다 색깔

void drawCube(GLfloat size, GLfloat x, GLfloat y, GLfloat z){
    //defaultCube를 이용해서 새로운 큐브를 만듬
    GLfloat MyCube[8][3];
    for(int i = 0; i < 8; i++){
        MyCube[i][0] = size * defaultCube[i][0] + x; //크기가 늘어난 상태로. 이동
        MyCube[i][1] = size * defaultCube[i][1] + y; // 0은 x축 1은 y축 z는 z축
        MyCube[i][2] = size * defaultCube[i][2] + z;
    }
    
    int index[6][4] = {{0,3,2,1},{2,3,7,6},{7,4,5,6},{1,2,6,5},{0,3,7,4},{0,4,5,1}};
    
    for(int i = 0; i < 6; i++){
        int index0 = index[i][0];
        int index1 = index[i][1];
        int index2 = index[i][2];
        int index3 = index[i][3];
        glBegin(GL_POLYGON);
            glColor3fv(MyColor[index0]); glVertex3fv(MyCube[index0]);
            glColor3fv(MyColor[index1]); glVertex3fv(MyCube[index1]);
            glColor3fv(MyColor[index2]); glVertex3fv(MyCube[index2]);
            glColor3fv(MyColor[index3]); glVertex3fv(MyCube[index3]);
        glEnd();
    }
}
void MyDisplay(){
    glClear(GL_COLOR_BUFFER_BIT);
    //원근감은 표현이 안돼있지만 좌표상에는 잘 찍히는 것을 볼 수 있다.
    drawCube(0.1, 0, 0,0);
    drawCube(0.1, 0.8,0,0);
    drawCube(0.1, 0 , 0.8,0);
    drawCube(0.1, 0 , 0,0.8);
    drawCube(0.1,0.8,0.8,0.8);  
    glFlush();
}

void MyReshape(int width, int height){
    glViewport(0, 0, width, height);
    GLfloat f_w = (GLfloat)width / (GLfloat)_WINDOW_WIDTH;
    GLfloat f_h = (GLfloat)height / (GLfloat)_WINDOW_HEIGHT;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0*f_w, 1.0*f_w, -1.0*f_h, 1.0*f_h, -2, 2);
    gluLookAt(0.5, 0.5, 1, 0, 0, 0, 0, 1, 0);
}

int main(int argc, char ** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB); //이중 버퍼링을 위해 이중버퍼 사용
    glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
    glutCreateWindow("Cube Drawing");
    
    //콜백함수
    glutDisplayFunc(MyDisplay);
    glutReshapeFunc(MyReshape);
    
    glutMainLoop();
}

출처 : https://huiyu.tistory.com/entry/gluLookAt%ED%95%A8%EC%88%98