OpenGL

[OpenGL-5] Cube Control Program

zamezzz 2016. 11. 2. 23:19

안녕하세요.


다섯번째 포스팅입니다 ^^


오늘은 드디어 cube를 만들고, 여러 콜백함수를 통해 이를 제어하는 프로그램을 만들거에요.


먼저 간단하게 요구사항부터 정리해보고, 이 후에 프로그래밍을 진행해봅시다~


* 요구사항 *

5.1. Color cube 만들기

5.2. 키보드 콜백을 통한 cube 회전

5.3. 마우스 콜백을 통한 회전축 변환

5.4. GLSL 연결




  5.1 Color cube 만들기


먼저, Color cube를 만들어 봅시다.


지금까지 배운 개념을 활용한다면, cube를 만드는 것은 어렵지 않습니다!


다음 순서로 진행할 거에요.


  • cube 데이터 초기화 -> face 구성 -> cube 구성


가장 처음으로 실시할 것은 Cube의 데이터를 초기화 하는 것입니다.


Cube의 각 면은 아래 사진처럼 삼각형으로 구성되어 있습니다.


그렇다면 총 몇개의 Vertex 정보를 가져야 할까요?


cube는 6개의 면, 각 면은 2개의 삼각형, 각 삼각형은 3개의 점이 있어요.


즉 6 * 2 * 3 = 36으로 36개의 vertex 정보를 가져야 함을 알 수 있습니다.


const int Numvertices =  36으로 선언하면 되겠죠?


또한 GLSL에서 사용될 vec타입의 변수 2가지를 설정해주어야 합니다.


각 점의 위치 정보를 저장할 point4, 각 점의 색 정보를 저장할 color4 변수를 선언할게요.


typedef vec4 pointe4;

typedef vec4 color4;


여기서 각 정보는 4가지 값을 가져요.


위치는 XYZW 정보를 가지며, 색은 RGBA 정보를 가진답니다. (w는 원근, a는 투명도)


이해 가시죠? 그럼 샘플 데이터를 보며 보다 잘 이해 합시다!


아래와 같은 cube를 만든다고 가정합시다! 

각 point4와 color4는 다음과 같이 입력할 수 있겠죠?


point4 vertex_pos [8] = {

    point4( -0.5, -0.5,  0.5, 1.0 ),

    point4( -0.5,  0.5,  0.5, 1.0 ),

    point4(  0.5,  0.5,  0.5, 1.0 ),

    point4(  0.5, -0.5,  0.5, 1.0 ),

    point4( -0.5, -0.5, -0.5, 1.0 ),

    point4( -0.5,  0.5, -0.5, 1.0 ),

    point4(  0.5,  0.5, -0.5, 1.0 ),

    point4(  0.5, -0.5, -0.5, 1.0 )

};

 color4 vertex_colors[8] = {

    color4( 0.0, 0.0, 0.0, 1.0 ),  // black

    color4( 1.0, 0.0, 0.0, 1.0 ),  // red

    color4( 1.0, 1.0, 0.0, 1.0 ),  // yellow

    color4( 0.0, 1.0, 0.0, 1.0 ),  // green

    color4( 0.0, 0.0, 1.0, 1.0 ),  // blue

    color4( 1.0, 0.0, 1.0, 1.0 ),  // magenta

    color4( 1.0, 1.0, 1.0, 1.0 ),  // white

    color4( 0.0, 1.0, 1.0, 1.0 )   // cyan

};


이제 각 정보를 구성하였으니, 이를 조합하여 실제 면을 그려봅시다.


face를 구성하겠습니다. 이를 위해서 quad라는 함수를 만들건데요.


quad() 함수는 4가지 값을 입력받아서, 두 개의 삼각형을 만들어 하나의 face를 생성해주어요


int index = 0; 


void quad(int a, int b, int c, int d) {

    colors[Index] = vertex_colors[a]; points[Index] = vertex_pos[a]; Index++;

    colors[Index] = vertex_colors[b]; points[Index] = vertex_pos[b]; Index++;

    colors[Index] = vertex_colors[c]; points[Index] = vertex_pos[c]; Index++;


    colors[Index] = vertex_colors[a]; points[Index] = vertex_pos[a]; Index++;

    colors[Index] = vertex_colors[c]; points[Index] = vertex_pos[c]; Index++;

    colors[Index] = vertex_colors[d]; points[Index] = vertex_pos[d]; Index++;

}


두 개의 삼격형 △(abc)와 (acd)를 만들어 이를 하나의 면으로 만들어 주는 것이죠!


삼각형 순서는 위의 초록 face 그림을 참고해주세요.


이제 face를 구성하였으니, cube를 만들어 보아야죠?


총 12개의 삼각형을 만들어주면 되는 것입니다. 아래 그림과 함께 코드를 보면 이해가 잘 되요!


void colorcube() {

    quad( 1, 0, 3, 2 );

    quad( 2, 3, 7, 6 );

    quad( 3, 0, 4, 7 );

    quad( 6, 5, 1, 2 );

    quad( 4, 5, 6, 7 );

    quad( 5, 4, 0, 1 );

}


어떠한 순서로 quad가 생성되는지 보이시죠? 총 6개의 face 즉 12개의 삼각형으로 만들었어요.


숫자를 붙여두어서, 이해가 잘 되실거에요.


이렇게하면 끝입니다. cube만드는 것은 간단하죠 ?


이렇게 정의된 정보를 vertex glsl / fragment glsl로 보내주기만 하면 완성입니다.


cube라는 간단한 객체를 point 값과 color 값을 입력하여 만들어보았습니다.


glsl은 콜백함수까지 정리한 후 마지막에 보겠습니다!




  5.2 키보드 콜백을 통한 cube 회전


간단하게 space bar를 통한 회전 on / off 가능하다록 구현해보겠습니다.


개념은 매우 간단합니다. bool 변수를 사용하여 true / false 설정을 해주면 되니까요 ^^


bool start = false


기본 디폴트 값은 정지상태로 선언을 하겠습니다.


keyboard 콜백함수는 아래와 같이 구현했어요. 크고 복잡한 기능이 아니기에 매우 간단하죠

void Keyboard(unsigned char KeyPressed,int X,int Y)  //keyboard callback

{

switch(KeyPressed)

{

case 32://space = start/stop

if(start==false) {

start=true

printf("Play!\n");

}

else{

start=false

printf("Stop!\n");

}

break;

}


이제 마우스 콜백 함수까지 작성 후 idel 함수를 통해 제어하겠습니다~~


  5.3 마우스 콜백을 통한 회전축 변환


마지막 기능은 마우스 콜백을 통한 회전축 변환입니다.


마우스 콜백도 간단하게 각 버튼 클릭시 x, y, z축으로 각각 변환되도록 해보겠습니다.


왼쪽 버튼 : axis=0 (x축)

가운데 버튼 : axis=1 (y축)

오른쪽 버튼 : axis=2 (z축)


이런 식으로 정리한 후 구현하겠습니다!


void mouse(int button, int state, int x, int y)//mouser callback

{

if(state == GLUT_DOWN){

switch(button){

case GLUT_LEFT_BUTTON://Left button = x axis

axis=0;

break;

case GLUT_MIDDLE_BUTTON://Middle button = y axis

axis=1;

break;

case GLUT_RIGHT_BUTTON://Right button = z axis

axis=2;

break;

}

}

} 


음... 각 버튼 클릭 시 axis 변환이 되도록 구성하였습니다.


그럼 이제 mouse / keyboard 버튼이 각각 눌려졌을 때 어떤 값을 가지는지 정의가 완료됐어요.


idle() 함수를 하나 만들어서 이것들이 실제 작동되도록 해 볼까요


코드 먼저 보시고, 한줄 씩 알아봅시다 


void idle() {

if(start==true){

if(axis==0){ //x axis

Ltime[0] += 0.003;

}

else if(axis==1){ //y axis

Ltime[1] +=0.003;

}


else if(axis==2){ //z axis

Ltime[2] +=0.003;


}

} 


먼저 start 상태인지 확인합니다. (space bar로 제어하였었죠?)


그리고 x축, y축, z축일 조건문을 넣어주고 각 조건에 따라 회전이 되도록하면 끝입니다.


매우 간단하죠? 하나 더 할 것이 있어요.


여기서 생성된 Ltime 값이 어디서 정의될까요? 이를 정의할 rotation martix를 만들어야 해요


앞서 포스팅에서 각 transformation에 대해서 정리한 것 기억하시나요?


그 중 rotation을 참고하시면 됩니다~~ 코드는 아래와 같습니다.


localx = mat4(

  vec4(1.0,0.0,0.0, 0.0),

  vec4(0.0, cos(Ltime[0]), sin(Ltime[0]), 0.0),

  vec4(0.0, -sin(Ltime[0]), cos(Ltime[0]), 0.0),

  vec4(0.0, 0.0,0.0, 1.0)

);


localy = ...


localz = ...


localrot = localx * localy * localz

glUniformMatrix4fv(uLocal, 1, false, localrot);


어떠신가요? x축 회전 matrix식에... 그 값을 Ltime으로 설정한 것입니다.


마찬가지로 localy, localz 구현하시면 됩니다!!


그리고 전체 회전 값을 localrot라는 변수로 정의하시고, 


glsl로 보낼 명령어를 입력하시면 됩니다! (uLocal로 사용됩니다)


이렇게 하면 회전축 변환 또한 완성입니다~


  5.4 GLSL 연결


지금까지 모든 date를 구성하였습니다. 이전 포스팅에서 정리한 것과 같이 이러한 내용들을


glsl로 연결하여 직접 우리 눈에 보이도록 해야 합니다. !


vertex glsl -> fragment glsl -> view 이렇게 생각하시면 될거에요.


각 GLSL은 아래와 같습니다. 주석 참고하셔서 이해하시면 될 것 같아요!


* vertex glsl

#version 410

in  vec4 vPosition;

in  vec4 vColor;

out vec4 color;


uniform float uMode; //local mode or global mode

uniform mat4 uLocal; //local rotation matrix


void main()

{

mat4 rotation = mat4(1.0); //initialization


rotation = uLocal; //set the rotation matrix

gl_Position = rotation * vPosition;

//set the Position with rotation

    color = vColor; //set the cube color

}


* fragment glsl

#version 410 core


in  vec4 color;

out vec4 fColor;


void main(){

    fColor = color;                      //set color

}


in 이 해당 쉐이더로 들어오는 변수이고, out은 밖으로 나가는 변수에요.


순서는 위에 말한 것과 같습니다~





이러한 과정으로 구현하면 처음 목표였던 Cube Control Program을 만들 수 있습니다.


핵심 부분 코드만 작성하였고, 중간중간에 연결고리가 빠진 사항이 있는데요...


잘 따라하시면 문제 없이 다들 만드실 수 있을거에요.


모르는 부분이 있으면 언제든지 댓글 주시구요!


긴글 읽어주셔서 감사합니다.

반응형

'OpenGL' 카테고리의 다른 글

[OpenGL-7] Projection Matix  (0) 2016.12.31
[OpenGL-6] Model View Matrix  (2) 2016.11.13
[OpenGL-4] Callback and Transformation  (0) 2016.10.30
[OpenGL-3] GLSL이란  (0) 2016.10.24
[OpenGL-2] OpenGL 시작하기  (3) 2016.10.20