void display()
{
//깊이 버퍼를 사용하여 DEPTH TEST를 활성화 -> 은면 제거
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//시점 설정. 초기 값은 camPos[0] = 0.1, camPos[1] = 0.1, camPos[2] = 0.1
gluLookAt(camPos[0], camPos[1], camPos[2],0.1, 0.0, 0.0, 1.0, 1.5, 0.0);
//scale값을 변수로 받아 줌인 줌아웃을 수행
glScalef(scale, scale, scale);
//WireSphere 함수를 사용하여 태양 생성
glBindTexture(GL_TEXTURE_2D, planet_texture[0]);
glTexCoord2f(0.2f, 0.5f);
glColor3f(sun_color[0], sun_color[1], sun_color[2]);
glutWireSphere(1, 20, 20);
glColor3f(1, 1, 0);
glutWireSphere(0.8, 20, 20);
glColor3f(1, 1, 1);
glutSolidSphere(0.6, 20, 20);
//수성
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, planet_texture[1]);
glColor3f(mercury_color[0], mercury_color[1], mercury_color[2]);
glRotatef(mercury_year, 0.0, 1.0, 0.0);
glTranslatef(1.5, 0.0, 0.0);
glRotatef(day, 0.0, 1.0, 0.0);
glutWireSphere(0.1, 10, 8);
glLoadIdentity();
glPopMatrix();
//금성
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, planet_texture[2]);
glColor3f(venus_color[0], venus_color[1], venus_color[2]);
glRotatef(venus_year, 0.0, 1.0, 0.0);
glTranslatef(2.5, 0.0, 0.0);
glRotatef(day, 0.0, 1.0, 0.0);
glutWireSphere(0.25, 10, 8);
glLoadIdentity();
glPopMatrix();
//지구
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, planet_texture[3]);
glColor3f(earth_color[0], earth_color[1], earth_color[2]);
glRotatef(earth_year, 0.0, 1.0, 0.0);
glTranslatef(3.5, 0.0, 0.0);
glRotatef(day, 0.0, 1.0, 0.0);
glutWireSphere(0.25, 10, 8);
glColor3f(0.254902, 0.411765, 0.882353);
glRotatef(earth_year, 0.0, 1.0, 0.0);
glRotatef(day, 0.0, 1.0, 0.0);
glutWireSphere(0.20, 10, 8);
//달
glBindTexture(GL_TEXTURE_2D, planet_texture[9]);
glRotatef(moon, 0.0, 1.0, 0.0);
glTranslatef(0.5, 0.0, 0.0);
glColor3f(1, 1, 0.878431);
glutWireSphere(0.06, 10, 8); //달
glLoadIdentity();
glPopMatrix();
//화성
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, planet_texture[4]);
glColor3f(mars_color[0], mars_color[1], mars_color[2]);
glRotatef(mars_year, 0.0, 1.0, 0.0);
glTranslatef(4.5, 0.0, 0.0);
glRotatef(day, 0.0, 1.0, 0.0);
glutWireSphere(0.125, 10, 8);
glLoadIdentity();
glPopMatrix();
.........
glDisable(GL_DEPTH_TEST);
glutSwapBuffers();
}

//행성의 공전을 수행하는 TimerFunc 함수
void timerFunc(int value) {
//자전. 모든 행성의 자전은 day로 똑같은 값을 갖도록 함
day = fmodf(day + 1, 360);
glutPostRedisplay();
// 행성 공전 구현
//주어진 공전 비율에 따른 공전 구현
//실수값의 나머지 연산은 fmodf를 사용
mercury_year = fmodf(mercury_year + 0.5, 360);
venus_year = fmodf(venus_year + 1.2, 360);
earth_year = fmodf(earth_year + 2, 360);
mars_year = fmodf(mars_year + 3.8, 360);
moon = fmodf(moon + 0.14, 360);
jupyter_year = fmodf(jupyter_year + 1.5, 360);
saturn_year = fmodf(saturn_year + 1.0, 360);
uranus_year = fmodf(uranus_year + 0.7, 360);
neptune_year = fmodf(neptune_year + 0.5, 360);
glutPostRedisplay();
glutTimerFunc(RotateTime, timerFunc, 1);
}
//키보드 입력에 따른 공전 속도 조절 함수
void Keyboard(unsigned char key, int x, int y)
{
switch (key)
{
//스페이스 바 입력 시 모든 행성의 공전 멈춤
//만약 이미 멈춤 상태라면, 스페이스바 재입력 시 공전 재개
case 32:
if (RotateTime == 0)
RotateTime = 45;
else
RotateTime = 0;
glutTimerFunc(RotateTime, timerFunc, 1); // 타이머 콜백
break;
//+ 입력 시 RotateTime의 값을 감소시켜, 공전 속도가 빨라지게 함
//0 이하로 내려가지 않게 하기 위한 조건문
case '+':
if (RotateTime > 5)
RotateTime -= 5;
printf("%d", RotateTime);
break;
//- 입력 시 RotateTime의 값을 증가시켜 공전 속도가 느려지게 함
//100 이상으로 올라가지 않도록 제어
case '-':
if (RotateTime < 100)
RotateTime += 5;
printf("%d", RotateTime);
break;
}
glutPostRedisplay();
}
//방향키 등 특수 키에 대한 이벤트 처리
void Special(int key, int x, int y)
{
float rotation = 0.1;
//왼쪽 방향키
if (key == GLUT_KEY_LEFT)
{
//camPos[2] -> z값을 변경시켜, 회전을 구현
camPos[2] -= rotation;
if (camPos[2] < -5.0) // 최소값을 벗어나는 경우
camPos[2] = -5.0;
}
//오른쪽 방향키
if (key == GLUT_KEY_RIGHT)
{
//camPos[2] -> z값을 증가시켜 회전을 구현
camPos[2] += rotation;
if (camPos[2] > 5.0) // 최대값을 벗어나는 경우
camPos[2] = 5.0;
}
//위쪽 방향키
else if (key == GLUT_KEY_UP)
{
//스케일을 증가시켜, 줌인을 구현
if (scale < 3)
scale += 0.1f;
}
//아래쪽 방향키
else if (key == GLUT_KEY_DOWN)
{
//스케일을 감소시켜, 줌인을 구현. 최소값은 0.1
if (scale > 0.1)
scale -= 0.1f;
}
glutPostRedisplay();
}


//마우스 이벤트
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
// 클릭한 위치를 정규화한다.
GLfloat normalizedX = (2.0 * x) / glutGet(GLUT_WINDOW_WIDTH) - 1.0;
GLfloat normalizedY = 1.0 - (2.0 * y) / glutGet(GLUT_WINDOW_HEIGHT);
GLfloat normalizedZ = 0.0;
//계산한 클릭 위치 좌표를 clickedPosition에 저장
clickedPosition[0] = normalizedX;
clickedPosition[1] = normalizedY;
clickedPosition[2] = normalizedZ;
// 클릭한 위치와 태양 사이의 거리 계산
GLfloat distance = sqrt(pow(sunPosition[0] - clickedPosition[0], 2) +
pow(sunPosition[1] - clickedPosition[1], 2) +
pow(sunPosition[2] - clickedPosition[2], 2));
printf("Distance sun-planet: %.2f\n", distance);
//태양의 색 변경
if (distance >= 0 && distance < 0.1)
{
//변경되는 rgb값은 랜텀으로 생성되는 0~1사이의 값을 사용
sun_color[0] = (GLfloat)rand() / RAND_MAX;
sun_color[1] = (GLfloat)rand() / RAND_MAX;
sun_color[2] = (GLfloat)rand() / RAND_MAX;
}
//수성의 색 변경
else if (distance >= 0.1&& distance < 0.2)
{
mercury_color[0] = (GLfloat)rand() / RAND_MAX;
mercury_color[1] = (GLfloat)rand() / RAND_MAX;
mercury_color[2] = (GLfloat)rand() / RAND_MAX;
}
//금성의 색 변경
else if (distance >= 0.20 && distance < 0.3)
{
venus_color[0] = (GLfloat)rand() / RAND_MAX;
venus_color[1] = (GLfloat)rand() / RAND_MAX;
venus_color[2] = (GLfloat)rand() / RAND_MAX;
}
//지구의 색 변경
else if (distance >= 0.3 && distance < 0.4)
{
earth_color[0] = (GLfloat)rand() / RAND_MAX;
earth_color[1] = (GLfloat)rand() / RAND_MAX;
earth_color[2] = (GLfloat)rand() / RAND_MAX;
}
//화성의 색 변경
else if (distance >= 0.4 && distance < 0.5)
{
mars_color[0] = (GLfloat)rand() / RAND_MAX;
mars_color[1] = (GLfloat)rand() / RAND_MAX;
mars_color[2] = (GLfloat)rand() / RAND_MAX;
}
//목성의 색 변경
else if (distance >= 0.55&& distance < 0.65)
{
jupyter_color[0] = (GLfloat)rand() / RAND_MAX;
jupyter_color[1] = (GLfloat)rand() / RAND_MAX;
jupyter_color[2] = (GLfloat)rand() / RAND_MAX;
}
//토성의 색 변경
else if (distance >= 0.65 && distance < 0.8)
{
saturn_color[0] = (GLfloat)rand() / RAND_MAX;
saturn_color[1] = (GLfloat)rand() / RAND_MAX;
saturn_color[2] = (GLfloat)rand() / RAND_MAX;
}
//천왕성의 색 변경
else if (distance >= 0.8 && distance < 0.9)
{
uranus_color[0] = (GLfloat)rand() / RAND_MAX;
uranus_color[1] = (GLfloat)rand() / RAND_MAX;
uranus_color[2] = (GLfloat)rand() / RAND_MAX;
}
//해왕성의 색 변경
else if (distance >= 0.90 && distance < 1.05)
{
neptune_color[0] = (GLfloat)rand() / RAND_MAX;
neptune_color[1] = (GLfloat)rand() / RAND_MAX;
neptune_color[2] = (GLfloat)rand() / RAND_MAX;
}
glutPostRedisplay();
}
}

void sub_menu_view(int value)
{
switch (value)
{
//VIEW를 선택하였을 때 camPos[] 값을 변경하여 각 선택에 따른 시점을 구현
case 1:
camPos[0] = 0.1f;
camPos[1] = 0.1f;
camPos[2] = 0.0f;
printf("TOP VIEW\n");
break;
case 2:
printf("FRONT VIEW\n");
camPos[0] = 0.0f;
camPos[1] = 0.0f;
camPos[2] = 0.0f;
break;
case 3:
camPos[0] = 0.1f;
camPos[1] = 0.1f;
camPos[2] = -5.0f;
printf("LEFT VIEW\n");
break;
case 4:
//camPos[]값을 랜덤으로 생성 -> 랜덤한 시점의 view
printf("RANDOM VIEW\n");
srand(time(NULL));
for (int i = 0; i < 3; i++)
{
camPos[i] = ((double)rand() / RAND_MAX) * 2.0 - 1.0;
}
printf("%f %f %f\n", camPos[0], camPos[1], camPos[2]);
break;
case 5:
camPos[0] = 0.1f;
camPos[1] = 0.1f;
camPos[2] = 0.1f;
printf("INITIAL VIEW\n");
break;
}
glutPostRedisplay();
}

