과제로 했었던 OpenGL로 놀이동산 만들기!
앞에 올렸던 대부분의 OpenGL 코드를 망라한 것이라 보면 된다.
다른 놀이기구는 거의 문제 없지만
롤러코스터의 경우에는 찌그러... 졌다기 보다 움직임이 부자연스럽다.
많은 분들이 참고용으로 보셨으면 하는 마음에 올린다.
#include<stdio.h> #include<Windows.h> #include<GL\glut.h> #include<GL\GLAUX.H> #include<math.h> #define GL_PI 3.1415f GLfloat xRot = 0.0f; //x방향 회전 각도 GLfloat yRot = 0.0f; //y방향 회전 각도 GLfloat xStat = 0.0f; //x방향 위치값 GLfloat yStat = 0.0f; //y방향 위치값 GLfloat zStat = 0.0f; //z방향 위치값 GLfloat vikingRot = 10.0f; //바이킹 회전 각도 GLfloat vikingAcc = 10.0f; //바이킹 가속도 boolean sig = false; //바이킹 가속도 부호 GLfloat hurriRot = 0.0f; //허리케인 링 회전 각도 int ovalA = 630; //롤러코스터 타원 장축 a값 int ovalB = 450; //롤러코스터 타원 단축 b값 GLfloat rolx = (GLfloat)ovalA; //롤러코스터 x값 int rol4 = 4; //롤러코스터 4분면 값 GLfloat bend=10.0f; //끝의 휜 부분 속도 조절 GLfloat bendrotate = 0.0f; //끝의 휜 부분 각도 조절 bool iCull = TRUE; bool iOutline = FALSE; bool iDepth = TRUE; GLfloat amb [] = {0.3f, 0.3f, 0.3f, 1.0f}; GLfloat dif [] = {0.8f, 0.8f, 0.8f, 1.0f}; GLfloat lightpos[] = {0.0f, 500.0f, -600.0f, 1.0f}; AUX_RGBImageRec *grasstex; GLuint texID; void ovalFunc(GLfloat x, int split, GLfloat out[3]) { /* function ovalFunc() 타원의 현재 x값과 몇사분면인지 split을 입력받아 좌표가 x이고 사분면 값이 split 일 때, out에 점 위치를 나타내줌. x : y, z 좌표를 구하고 싶은 x 값. split : 현재 몇 사분면인지를 나타내는 값. out : x좌표 입력으로 x, y, z값을 구한 값을 반환하는 변수. */ GLfloat divide = 180.0f; out[0] = x; out[1] = ovalB * sqrt((1-x*x/(ovalA*ovalA))); switch(split) //사분면마다 부호가 달라짐 { case 1: out[2] = 100 + 50 * cos((GL_PI/divide)*x); break; case 2 : out[0] = -out[0]; out[2] = 100 + 50 * cos((GL_PI/divide)*x); break; case 3 : out[0] = -out[0]; out[1] = -out[1]; out[2] = 100 + 50 * cos((GL_PI/divide)*x); break; case 4 : out[1] = -out[1]; out[2] = 100 + 50 * cos((GL_PI/divide)*x); break; default : out[0] = 0; out[1] = 0; out[2] = 0; break; } } void calcNormal(float v[3][3], float out[3]) { /* function calcNormal() 점 3개를 받아 해당 삼각형의 normal vector를 구하는 함수 v[3][3] : (x, y, z) 점 좌표 3개 out[3] : normal 벡터를 반환받을 벡터 3개 ※ glut함수를 쓰면 느리므로 직접 제작 */ float v1[3], v2[3], length; static const int x = 0; static const int y = 1; static const int z = 2; v1[x] = v[0][x]-v[1][x]; v1[y] = v[0][y]-v[1][y]; v1[z] = v[0][z]-v[1][z]; v2[x] = v[2][x]-v[1][x]; v2[y] = v[2][y]-v[1][y]; v2[z] = v[2][z]-v[1][z]; out[x] = v1[y]*v2[z] - v1[z]*v2[y]; out[y] = v1[z]*v2[x] - v1[x]*v2[z]; out[z] = v1[x]*v2[y] - v1[y]*v2[x]; length = (float)sqrt(out[x]*out[x] + out[y]*out[y]+out[z]*out[z]); if(length == 0.0f) length = 1.0f; out[x] /= length; out[y] /= length; out[z] /= length; } void createCylinder(GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat radius, GLfloat h) { /* function createCyliner() 원기둥의 중심 x,y,z좌표, 반지름, 높이를 받아 원기둥을 생성하는 함수(+z방향으로 원에서 늘어남) centerx : 원기둥 원의 중심 x좌표 centery : 원기둥 원의 중심 y좌표 centerz : 원기둥 원의 중심 z좌표 radius : 원기둥의 반지름 h : 원기둥의 높이 */ GLfloat x, y, angle; glBegin(GL_TRIANGLE_FAN); //원기둥의 윗면 glNormal3f(0.0f, 0.0f, -1.0f); glColor3ub(139, 69, 19); glVertex3f(centerx, centery, centerz); for(angle = 0.0f; angle < (2.0f*GL_PI); angle += (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(x, y, centerz); } glEnd(); glBegin(GL_QUAD_STRIP); //원기둥의 옆면 for(angle = 0.0f; angle < (2.0f*GL_PI); angle += (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(sin(angle), cos(angle), 0.0f); glVertex3f(x, y, centerz); glVertex3f(x, y, centerz + h); } glEnd(); glBegin(GL_TRIANGLE_FAN); //원기둥의 밑면 glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(centerx, centery, centerz + h); for(angle = (2.0f*GL_PI); angle > 0.0f; angle -= (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(x, y, centerz + h); } glEnd(); } void createShip(GLfloat x, GLfloat y, GLfloat z, GLfloat size) { /* function createShip() 중심 (x,y,z)로 부터 z축으로 길게 배 생성, 옆면 길이는 size * 2, 총 길이는 size * 4 x : x 좌표 y : y 좌표 z : z 좌표 size : 배 크기의 기본단위 */ float v[3][3]; float out[3]; glBegin(GL_TRIANGLES); glColor3f(0.65f, 0.16f, 0.16f); //바이킹 뒷 왼쪽 삼각형 v[0][0] = x-size; v[0][1] = y; v[0][2] = z-size; v[1][0] = x; v[1][1] = y; v[1][2] = z-2*size; v[2][0] = x; v[2][1] = y-size; v[2][2] = z-size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x-size, y, z-size); glVertex3f(x, y, z-2*size); glVertex3f(x, y-size, z-size); v[0][0] = x; v[0][1] = y-size; v[0][2] = z+size; v[1][0] = x; v[1][1] = y; v[1][2] = z-2*size; v[2][0] = x-size; v[2][1] = y; v[2][2] = z+size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x, y-size, z+size); //바이킹 앞 왼쪽 삼각형 glVertex3f(x, y, z+2*size); glVertex3f(x-size, y, z+size); glColor3f(0.65f, 0.16f, 0.16f); //바이킹 왼쪽 몸통 v[0][0] = x; v[0][1] = y-size; v[0][2] = z+size; v[1][0] = x-size; v[1][1] = y; v[1][2] = z-size; v[2][0] = x; v[2][1] = y-size; v[2][2] = z-size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x, y-size, z+size); glVertex3f(x-size, y, z-size); glVertex3f(x, y-size, z-size); v[0][0] = x-size; v[0][1] = y; v[0][2] = z-size; v[1][0] = x; v[1][1] = y-size; v[1][2] = z+size; v[2][0] = x-size; v[2][1] = y; v[2][2] = z+size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x-size, y, z-size); glVertex3f(x, y-size, z+size); glVertex3f(x-size, y, z+size); glColor3f(0.65f, 0.16f, 0.16f); //바이킹 뒷 오른쪽 삼각형 v[0][0] = x; v[0][1] = y; v[0][2] = z-2*size; v[1][0] = x+size; v[1][1] = y; v[1][2] = z-size; v[2][0] = x; v[2][1] = y-size; v[2][2] = z-size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x, y, z-2*size); glVertex3f(x+size, y, z-size); glVertex3f(x, y-size, z-size); v[0][0] = x; v[0][1] = y-size; v[0][2] = z+size; v[1][0] = x+size; v[1][1] = y; v[1][2] = z+size; v[2][0] = x; v[2][1] = y; v[2][2] = z+2*size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x, y-size, z+size); //바이킹 앞 오른쪽 삼각형 glVertex3f(x+size, y, z+size); glVertex3f(x, y, z+2*size); glColor3f(0.65f, 0.16f, 0.16f); //바이킹 오른쪽 몸통 v[0][0] = x+size; v[0][1] = y; v[0][2] = z-size; v[1][0] = x; v[1][1] = y-size; v[1][2] = z+size; v[2][0] = x; v[2][1] = y-size; v[2][2] = z-size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x+size, y, z-size); glVertex3f(x, y-size, z+size); glVertex3f(x, y-size, z-size); v[0][0] = x+size; v[0][1] = y; v[0][2] = z-size; v[1][0] = x+size; v[1][1] = y; v[1][2] = z+size; v[2][0] = x; v[2][1] = y-size; v[2][2] = z+size; calcNormal(v, out); glNormal3fv(out); glVertex3f(x+size, y, z-size); glVertex3f(x+size, y, z+size); glVertex3f(x, y-size, z+size); glEnd(); glBegin(GL_POLYGON); //바이킹 갑판 glColor3f(0.65f, 0.16f, 0.16f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x+size, y, z-size); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x, y, z-2*size); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x-size, y, z-size); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x-size, y, z+size); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x, y, z+2*size); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(x+size, y, z+size); glEnd(); } void createRing(GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat radius, GLfloat h, GLfloat thick) { /* function createRing() 링의 중심 x,y,z좌표, 반지름, 높이, 두께를 받아 링을 생성하는 함수 centerx : 링의 중심 x좌표 centery : 링의 중심 y좌표 centerz : 링의 중심 z좌표 radius : 링의 반지름 h : 링의 높이 thick : 링의 두께 */ GLfloat x, y, angle; glColor3ub(148, 0, 211); glBegin(GL_QUAD_STRIP); //링의 윗면 for(angle = (2.0f*GL_PI); angle > 0.0f; angle -= (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(x, y, centerz); x = centerx + (radius-thick)*sin(angle); y = centery + (radius-thick)*cos(angle); glVertex3f(x, y, centerz); } glEnd(); int color = 0; glBegin(GL_QUAD_STRIP); //링의 바깥쪽 옆면 for(angle = 0.0f; angle < (2.0f*GL_PI); angle += (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(sin(angle), cos(angle), 0.0f); glVertex3f(x, y, centerz); glVertex3f(x, y, centerz + h); color++; } glEnd(); glColor3ub(148, 0, 211); glBegin(GL_QUAD_STRIP); //링의 안쪽 옆면 for(angle = (2.0f*GL_PI); angle > 0.0f; angle -= (GL_PI/8.0f)) { x = centerx + (radius-thick)*sin(angle); y = centery + (radius-thick)*cos(angle); glNormal3f(-sin(angle), -cos(angle), 0.0f); glVertex3f(x, y, centerz); glVertex3f(x, y, centerz + h); } glEnd(); glBegin(GL_QUAD_STRIP); //원기둥의 밑면 for(angle = 0.0f; angle < (2.0f*GL_PI); angle += (GL_PI/8.0f)) { x = centerx + radius*sin(angle); y = centery + radius*cos(angle); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(x, y, centerz+h); x = centerx + (radius-thick)*sin(angle); y = centery + (radius-thick)*cos(angle); glVertex3f(x, y, centerz+h); } glEnd(); } void createChair(GLfloat x, GLfloat y, GLfloat z, GLfloat thick, GLfloat width, GLfloat height) { /* function createChair() 의자 왼쪽 위 끝 x,y,z좌표, 등받이 높이, 앉는부분 길이를 받아 의자를 생성하는 함수 x : 의자 왼쪽 위 끝 x좌표 y : 의자 왼쪽 위 끝 y좌표 z : 의자 오른쪽 위 끝 z좌표 thick : 의자 두께 width : 의자 가로길이 height : 의자 세로길이 */ glColor3ub(0, 0, 0); glBegin(GL_QUADS); glNormal3f(-1.0f, 0.0f, 0.0f); //등받이 왼쪽 옆면 glVertex3f(x, y, z); glVertex3f(x, y+height, z); glVertex3f(x+thick, y+height, z); glVertex3f(x+thick, y, z); glNormal3f(0.0f, 0.0f, 1.0f); //등받이 앞면 glVertex3f(x+thick, y, z); glVertex3f(x+thick, y+height, z); glVertex3f(x+thick, y+height, z+width); glVertex3f(x+thick, y, z+width); glNormal3f(1.0f, 0.0f, 0.0f); //등받이 오른쪽 옆면 glVertex3f(x+thick, y, z+width); glVertex3f(x+thick, y+height, z+width); glVertex3f(x, y+height, z+width); glVertex3f(x, y, z+width); glNormal3f(0.0f, 0.0f, -1.0f); //등받이 뒷면 glVertex3f(x, y, z+width); glVertex3f(x, y+height+thick, z+width); glVertex3f(x, y+height+thick, z); glVertex3f(x, y, z); glNormal3f(0.0f, 1.0f, 0.0f); //등받이 윗면 glVertex3f(x, y, z); glVertex3f(x+thick, y, z); glVertex3f(x+thick, y, z+width); glVertex3f(x, y, z+width); glNormal3f(0.0f, 1.0f, 0.0f); //앉는 부분 윗면 glVertex3f(x, y+height, z); glVertex3f(x+height, y+height, z); glVertex3f(x+height, y+height, z+width); glVertex3f(x, y+height, z+width); glNormal3f(-1.0f, 0.0f, 0.0f); //앉는 부분 왼쪽 옆면 glVertex3f(x, y+height, z); glVertex3f(x, y+height+thick, z); glVertex3f(x+height, y+height+thick, z); glVertex3f(x+height, y+height, z); glNormal3f(0.0f, 0.0f, -1.0f); //앉는 부분 앞쪽 glVertex3f(x+height, y+height, z); glVertex3f(x+height, y+height+thick, z); glVertex3f(x+height, y+height+thick, z+width); glVertex3f(x+height, y+height, z+width); glNormal3f(1.0f, 0.0f, 0.0f); //앉는 부분 오른쪽 옆면 glVertex3f(x, y+height, z+width); glVertex3f(x+height, y+height, z+width); glVertex3f(x+height, y+height+thick, z+width); glVertex3f(x, y+height+thick, z+width); glNormal3f(0.0f, -1.0f, 0.0f); //앉는 부분 밑면 glVertex3f(x, y+height+thick, z); glVertex3f(x, y+height+thick, z+width); glVertex3f(x+height, y+height+thick, z+width); glVertex3f(x+height, y+height+thick, z); glEnd(); } void createHalfSphere(GLfloat x, GLfloat y, GLfloat z, GLfloat radius) { /* function createHalfSphere() 구의 중심 x, y, z 좌표를 받아 반구를 만드는 함수 x : 반구의 중심 x 좌표 y : 반구의 중심 y 좌표 z : 반구의 중심 z 좌표 raidus : 반구의 반지름 */ GLfloat angley; //y축 값을 구하기 위한 각도 GLfloat nexty; //다음 y축 값을 구하기 위한 각도 GLfloat anglex; //x, y축 값을 구하기 위한 각도 glColor3ub(136, 206, 250); //반구의 색 지정 glBegin(GL_QUAD_STRIP); for(angley = 0.0f; angley <= (0.5f*GL_PI); angley += ((0.5f*GL_PI)/8.0f)) //반구만 그려야 하므로 0.5곱함 { y = radius*sin(angley); //y축 값 계산 nexty = angley+((0.5f*GL_PI)/8.0f); //다음 angley값 저장 for(anglex = 0.0f; anglex < (2.0f*GL_PI); anglex += (GL_PI/8.0f)) { x = radius*cos(angley)*sin(anglex); z = radius*cos(angley)*cos(anglex); glNormal3f(-cos(angley)*sin(anglex), -sin(angley), -cos(angley)*cos(anglex)); //반구의 안쪽으로 normal 벡터 생성 glVertex3f(x, y, z); x = radius*cos(nexty)*sin(anglex); z = radius*cos(nexty)*cos(anglex); glNormal3f(-cos(nexty)*sin(anglex), -sin(nexty), -cos(nexty)*cos(anglex)); glVertex3f(x, radius*sin(nexty), z); } } glEnd(); } void createRail(GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat radius) { /* function createRail() 레일의 중심인 x, y, z값을 받아서 레일 반지름이 radius인 레일을 생성하는 함수. centerx : 레일의 중심 값 x centery : 레일의 중심 값 y centerz : 레일의 중심 값 z radius : 레일의 굵기(반지름 */ int column=0; //column 세주는 변수 GLfloat angle, x, y, z; //각도, x, y, z 좌표 GLfloat length; //변위 벡터 길이 GLfloat rotate; //변위 벡터 각도 GLfloat currout[3]; //현재 값 GLfloat nextout[3]; //다음 값 GLfloat dis[3]; //변위 벡터 for(int i = 1;i<=4;i++) //총 4사분면 { for(float j = 0;j<ovalA;j++) //x의 최대값은 ovalA { if(j == 0) //j==0일때는 currout도 구해줘야함 { ovalFunc(j, i, currout); } else //이 전의 nextout은 현재의 currout과 같음 { currout[0] = nextout[0]; currout[1] = nextout[1]; currout[2] = nextout[2]; } ovalFunc(j+1, i, nextout); //nextout 값 받아옴. dis[0] = nextout[0]-currout[0]; //변위 벡터 구함 dis[1] = nextout[1]-currout[1]; dis[2] = nextout[2]-currout[2]; length = (GLfloat)sqrtf(dis[0]*dis[0] + dis[1]*dis[1] + dis[2]*dis[2]); //변위 벡터의 길이 구함 if(length == 0) length = 1; //벡터 길이 0이라면 1로 dis[0] /= length; //단위 벡터로 바꿔줌 dis[1] /= length; dis[2] /= length; rotate = (GLfloat)asinf(dis[2])*180.0f/GL_PI; //해당 축으로 몇도 회전시켜야 하는지 구함 if(column % 60 == 10) //column을 60의 간격으로 만듦 { glPushMatrix(); glTranslated(currout[0], currout[2], currout[1]); //해당 레일로 좌표이동 glRotated(90.0f, 1.0f, 0.0f, 0.0f); //x축으로 90도 회전 createCylinder(0.0f, 0.0f, 18.0f, 5.0f, currout[2]); //cylinder 제작 glPopMatrix(); } glColor3ub(255, 0, 0); glPushMatrix(); glTranslated(currout[0], currout[2], currout[1]); glRotatef(rotate, dis[0], dis[2], dis[1]); glBegin(GL_QUAD_STRIP); for(angle = 0.0f; angle <= (2.0f*GL_PI); angle += (GL_PI/8.0f)) { x = radius*cos(angle)*dis[1]; //현재 x, y, z값 구함 y = radius*sin(angle); z = radius*cos(angle)*dis[0]; glNormal3f(cos(angle)*dis[1], sin(angle), cos(angle)*dis[0]); glVertex3f(x, y, z); x = dis[0]*length*2.0f + radius*cos(angle)*dis[1]; //다음 x, y, z값 구함(곡선이라 갈라지므로 길이 1.3배) y = dis[2]*length*2.0f + radius*sin(angle); z = dis[1]*length*2.0f + radius*cos(angle)*dis[0]; glNormal3f(cos(angle)*dis[1], sin(angle), cos(angle)*dis[0]); glVertex3f(x, y, z); } glEnd(); glPopMatrix(); column++; } } } void createCar(GLfloat x, GLfloat y, GLfloat z, GLfloat bump, GLfloat width, GLfloat height, GLfloat thick) { GLfloat halfw = width/2; glColor3ub(0, 0, 255); glBegin(GL_QUADS); glNormal3f(0.0f, -1.0f, 0.0f); //차의 바깥쪽 밑 부분 glVertex3f(x+halfw+bump, y, z-halfw); glVertex3f(x+halfw+bump, y, z+halfw); glVertex3f(x-halfw, y, z+halfw); glVertex3f(x-halfw, y, z-halfw); glNormal3f(0.0f, 0.0f, -1.0f); //차의 바깥 왼쪽 옆면 glVertex3f(x+halfw, y, z-halfw); glVertex3f(x-halfw, y, z-halfw); glVertex3f(x-halfw, y+height, z-halfw); glVertex3f(x+halfw, y+height, z-halfw); glNormal3f(-1.0f, 0.0f, 0.0f); //차의 바깥쪽 뒷면 glVertex3f(x-halfw, y, z-halfw); glVertex3f(x-halfw, y, z+halfw); glVertex3f(x-halfw, y+height, z+halfw); glVertex3f(x-halfw, y+height, z-halfw); glNormal3f(0.0f, 0.0f, 1.0f); //차의 바깥 오른쪽 옆면 glVertex3f(x-halfw, y, z+halfw); glVertex3f(x+halfw, y, z+halfw); glVertex3f(x+halfw, y+height, z+halfw); glVertex3f(x-halfw, y+height, z+halfw); glNormal3f(0.0f, 1.0f, 0.0f); //차의 바깥 위 왼쪽 윗면 glVertex3f(x-halfw, y+height, z-halfw); glVertex3f(x-halfw, y+height, z-halfw+thick); glVertex3f(x+halfw, y+height, z-halfw+thick); glVertex3f(x+halfw, y+height, z-halfw); glVertex3f(x-halfw, y+height, z+halfw); //차의 바깥 위 오른쪽 윗면 glVertex3f(x+halfw, y+height, z+halfw); glVertex3f(x+halfw, y+height, z+halfw-thick); glVertex3f(x-halfw, y+height, z+halfw-thick); glVertex3f(x-halfw, y+height, z-halfw+thick); //차의 바깥 위 뒤쪽 윗면 glVertex3f(x-halfw, y+height, z+halfw-thick); glVertex3f(x-halfw+thick, y+height, z+halfw-thick); glVertex3f(x-halfw+thick, y+height, z-halfw+thick); glNormal3f(sqrt(2.0f), sqrt(2.0f), 0.0f); //차의 범퍼 윗부분 glVertex3f(x+halfw, y+height, z-halfw); glVertex3f(x+halfw, y+height, z+halfw); glVertex3f(x+halfw+bump, y, z+halfw); glVertex3f(x+halfw+bump, y, z-halfw); glNormal3f(0.0f, 1.0f, 0.0f); //차의 안쪽 밑면 glVertex3f(x-halfw+thick, y+thick, z-halfw+thick); glVertex3f(x-halfw+thick, y+thick, z+halfw-thick); glVertex3f(x+halfw, y+thick, z+halfw-thick); glVertex3f(x+halfw, y+thick, z-halfw+thick); glNormal3f(1.0f, 0.0f, 0.0f); //차의 안쪽 뒷면 glVertex3f(x-halfw+thick, y+thick, z-halfw+thick); glVertex3f(x-halfw+thick, y+height, z-halfw+thick); glVertex3f(x-halfw+thick, y+height, z+halfw-thick); glVertex3f(x-halfw+thick, y+thick, z+halfw-thick); glNormal3f(-1.0f, 0.0f, 0.0f); //차의 안쪽 앞면 glVertex3f(x+halfw, y+thick, z-halfw+thick); glVertex3f(x+halfw, y+thick, z+halfw-thick); glVertex3f(x+halfw, y+height, z+halfw-thick); glVertex3f(x+halfw, y+height, z-halfw+thick); glNormal3f(0.0f, 0.0f, 1.0f); //차의 안 왼쪽 옆면 glVertex3f(x+halfw, y+thick, z-halfw+thick); glVertex3f(x+halfw, y+height, z-halfw+thick); glVertex3f(x-halfw+thick, y+height, z-halfw+thick); glVertex3f(x-halfw+thick, y+thick, z-halfw+thick); glNormal3f(0.0f, 0.0f, -1.0f); //차의 안 오른쪽 옆면 glVertex3f(x+halfw, y+thick, z+halfw-thick); glVertex3f(x-halfw+thick, y+thick, z+halfw-thick); glVertex3f(x-halfw+thick, y+height, z+halfw-thick); glVertex3f(x+halfw, y+height, z+halfw-thick); glEnd(); glBegin(GL_TRIANGLES); glNormal3f(0.0f, 0.0f, 1.0f); //차의 바깥 오른쪽 삼각형 glVertex3f(x+halfw, y, z+halfw); glVertex3f(x+halfw+bump, y, z+halfw); glVertex3f(x+halfw, y+height, z+halfw); glNormal3f(0.0f, 0.0f, -1.0f); //차의 바깥 왼쪽 삼각형 glVertex3f(x+halfw, y, z-halfw); glVertex3f(x+halfw, y+height, z-halfw); glVertex3f(x+halfw+bump, y, z-halfw); glEnd(); glPushMatrix(); glTranslatef(x, y, z); glRotatef(180.0f, 0.0f, 0.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); createChair(-halfw+thick, -40.0f, -halfw+thick, 10.0f, 30.0f, 30.0f); glPopMatrix(); glPushMatrix(); glTranslatef(x, y, z); glRotatef(180.0f, 0.0f, 0.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); createChair(-halfw+thick, -40.0f, 0.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glPushMatrix(); glTranslatef(x, y, z); glRotatef(180.0f, 0.0f, 0.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); createChair(thick, -40.0f, 0.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glPushMatrix(); glTranslatef(x, y, z); glRotatef(180.0f, 0.0f, 0.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); createChair(thick, -40.0f, -halfw+thick, 10.0f, 30.0f, 30.0f); glPopMatrix(); } void renderViking() { glPushMatrix(); //바이킹 왼쪽 앞 기둥 glRotatef(90.0f, 0.7f, 0.3f, 0.0f); createCylinder(5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //바이킹 왼쪽 앞 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, -0.3f, 0.0f); createCylinder(-5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //뒤쪽으로 이동 glTranslatef(0.0f, 0.0f, -120.f); glPushMatrix(); glPopMatrix(); //바이킹 오른쪽 뒷 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, 0.3f, 0.0f); createCylinder(5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //바이킹 왼쪽 뒷 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, -0.3f, 0.0f); createCylinder(-5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //바이킹 윗 기둥 createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 120.0f); glTranslated(0.0f, 0.0f, 60.0f); //바이킹 지탱 기둥 glRotatef(90.0f, 1.0f, 0.0f, 0.0f); glRotatef(vikingRot, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 130.0f); glPopMatrix(); //배 생성 glPushMatrix(); glTranslatef(0.0f, 180.0f, 440.0f); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); glRotatef(vikingRot, -1.0f, 0.0f, 0.0f); createShip(0.0f, -130.0f, 0.0f, 50.0f); } void renderHurricane() { glPopMatrix(); //허리케인 오른쪽 앞 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, 0.3f, 0.0f); createCylinder(5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //허리케인 왼쪽 앞 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, -0.3f, 0.0f); createCylinder(-5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //뒤쪽으로 이동 glTranslatef(0.0f, 0.0f, -200.f); glPushMatrix(); glPopMatrix(); //허리케인 오른쪽 뒷 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, 0.3f, 0.0f); createCylinder(5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //허리케인 왼쪽 뒷 기둥 glPushMatrix(); glRotatef(90.0f, 0.7f, -0.3f, 0.0f); createCylinder(-5.0f, 0.0f, 0.0f, 15.0f, 200.0f); glPopMatrix(); //허리케인 윗 기둥 createCylinder(0.0f, 0.0f, -15.0f, 15.0f, 230.0f); glTranslated(0.0f, 0.0f, 95.0f); //허리케인 지탱 기둥 glRotatef(90.0f, 1.0f, 0.0f, 0.0f); glRotatef(vikingRot, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 130.0f); glPushMatrix(); glTranslated(0.0f, 0.0f, 130.0f); //지탱기둥과 링사이 연결기둥 glRotated(90.0f, 1.0f, 0.0f, 0.0f); glRotated(hurriRot, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 10.0f, 30.0f); glRotated(90.0f, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 10.0f, 30.0f); glRotated(90.0f, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 10.0f, 30.0f); glRotated(90.0f, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 10.0f, 30.0f); glPopMatrix(); //링 생성 glTranslated(0.0f, 0.0f, 110.0f); glRotated(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 0.0f, 50, 30, 20); glRotated(90.0f, 1.0f, 0.0f, 0.0f); //8개의 의자 생성 createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); glRotated(45.0f, 0.0f, 1.0f, 0.0f); createChair(50.0f, 0.0f, -15.0f, 10, 30, 30); } void renderLetsTwist() { glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 25.0f, 300.0f); //바닥 지탱 기둥 glRotated(90.0f, 0.0f, 1.0f, 0.0f); glRotated(hurriRot, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, -50.0f, 25.0f, 200.0f); //바닥 지탱 기둥과 회전원기둥을 연결하는 기둥 glRotated(hurriRot, 0.0f, 0.0f, 1.0f); createCylinder(0.0f, 0.0f, 150.0f, 40.0f, 50.0f); //회전 원기둥 glTranslatef(0.0f, 0.0f, 175.0f); glRotated(90.0f, 0.0f, 1.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); //6개 기둥 중 1번째 기둥 glPushMatrix(); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //1번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); //6개 기둥 중 2번째 기둥 glPushMatrix(); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //2번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); glPushMatrix(); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //3번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); glPushMatrix(); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //4번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); glPushMatrix(); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //5번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); glPopMatrix(); glRotated(60.0f, 1.0f, 0.0f, 0.0f); createCylinder(0.0f, 0.0f, 0.0f, 15.0f, 150.0f); glRotatef(hurriRot, 0.0f, 0.0f, 1.0f); createRing(0.0f, 0.0f, 50.0f, 25.0f, 100.0f, 10.0f); //6번째 기둥의 돌아가는 링과 의자 2개 createChair(25.0f, -15.0f, 85.0f, 10.0f, 30.0f, 30.0f); createChair(25.0f, -15.0f, 120.0f, 10.0f, 30.0f, 30.0f); } void renderRollerCoaster() { GLfloat currout[3]; createRail(0.0f, 0.0f, 0.0f, 20.0f); //레일 생성 ovalFunc(rolx, rol4, currout); //움직일 경로 좌표 값 받아옴 glPushMatrix(); glTranslated(currout[0], currout[2]+15.0f, currout[1]); //차체 구현할 좌표로 translate if(rol4 == 4 || rol4 == 3) { glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //3, 4분면 곡선 차체 반대로 if(rol4 == 4) glRotatef(-bendrotate, 0.0f, 1.0f, 0.0f); //차체 회전 구현 else glRotatef(bendrotate, 0.0f, 1.0f, 0.0f); } else { if(rol4 == 2) glRotatef(-bendrotate, 0.0f, 1.0f, 0.0f); //차체 회전 구현 else glRotatef(bendrotate, 0.0f, 1.0f, 0.0f); } createCar(0.0f, 0.0f, 0.0f, 20.0f, 70.0f, 30.0f, 5.0f); //차체 생성 glPopMatrix(); } void RenderScene(void) { glShadeModel(GL_SMOOTH); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if(iCull) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if(iDepth) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if(iOutline) glPolygonMode(GL_BACK,GL_LINE); else glPolygonMode(GL_BACK,GL_FILL); glFrontFace(GL_CCW); glEnable(GL_TEXTURE_2D); grasstex = auxDIBImageLoad("brick.bmp"); glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, grasstex->sizeX, grasstex->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, grasstex->data); glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_AMBIENT, amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); glLightfv(GL_LIGHT0, GL_POSITION, lightpos); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glPushMatrix(); glPopMatrix(); glPushMatrix(); glTranslatef(xStat, yStat-10.0f, zStat-1000.f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glPushMatrix(); glPopMatrix(); //하늘 생성 glPushMatrix(); createHalfSphere(0.0f, 0.0f, 0.0f, 2000.0f); glPopMatrix(); //지면 생성 glPushMatrix(); glBindTexture(GL_TEXTURE_2D, texID); glColor3ub(255, 255, 255); glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f); glTexCoord2f(10.0f, 10.0f); glVertex3d(2000.0f, 0.0f, 2000.0f); glTexCoord2f(0.0f, 10.0f); glVertex3d(2000.0f, 0.0f, -2000.0f); glTexCoord2f(0.0f, 0.0f); glVertex3d(-2000.0f, 0.0f, -2000.0f); glTexCoord2f(10.0f, 0.0f); glVertex3d(-2000.0f, 0.0f, 2000.0f); glEnd(); glDisable(GL_TEXTURE_2D); glPopMatrix(); glPushMatrix(); glTranslatef(0.0f, 0.0f, -500.0f); renderRollerCoaster(); //롤러코스터 생성 glPopMatrix(); glPushMatrix(); glTranslatef(600.0f, 180.0f, 500.0f); glPushMatrix(); renderHurricane(); //허리케인 생성 glPopMatrix(); glPushMatrix(); glTranslatef(0.0f, 180.0f, 500.0f); renderViking(); //바이킹 생성 glPopMatrix(); glTranslatef(-600.0f, 250.0f, 500.0f); renderLetsTwist(); //렛츠 트위스트 생성 glPopMatrix(); glutSwapBuffers(); } void ProcessMenu(int value) { switch(value) { case 1: iDepth = !iDepth; break; case 2: iCull = !iCull; break; case 3: iOutline = !iOutline; break; } glutPostRedisplay(); } void KeyControl(int key, int x, int y) { if(key == GLUT_KEY_DOWN) xRot -= 5.0f; if(key == GLUT_KEY_UP) xRot += 5.0f; if(key == GLUT_KEY_RIGHT) yRot -= 5.0f; if(key == GLUT_KEY_LEFT) yRot += 5.0f; glutPostRedisplay(); } void myKeyboard(unsigned char key, int x, int y) { switch(key) { case 'W' : case 'w' : zStat += 10.0f; break; case 'S' : case 's' : zStat -= 10.0f; break; case 'Q' : case 'q' : xStat += 10.0f; break; case 'A' : case 'a' : xStat -= 10.0f; break; case 'E' : case 'e' : yStat += 10.0f; break; case 'D' : case 'd' : yStat -= 10.0f; break; case 'Z' : case 'z' : exit(0); break; } } void SetupRC(void) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } void ChangeSize(GLsizei w, GLsizei h) { GLfloat fAspect = (GLfloat)w/(GLfloat)h; glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0f, fAspect, 1.0f, 3000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void TimerFunc(int value) { glutPostRedisplay(); if(vikingAcc <= -10.0f) //바이킹 가속도의 부호가 바뀌는 지점 sig = true; if(vikingAcc >= 10.0f) sig = false; if(vikingRot != 0.0f) //0도일때는 가속도가 붙지 않는다. { if(sig) //부호에 따라 가속도 증가 및 감소 vikingAcc++; else vikingAcc--; } vikingRot += vikingAcc; //바이킹의 위치 계산 hurriRot += 5.0f; //5도 씩 회전 if(hurriRot >= 360.0f) //360도 이상이 될 때 0으로 초기화 hurriRot = 0; if(rol4 % 2 == 0) //2, 4사분면 { if(rolx >= (ovalA-100.0f)) //끝의 휜 부분에서 x 증가값 감소 { rolx-=bend; if(bend != 10.0f) bend+=0.5; } else rolx -= 10.0f; } else //1, 3사분면 { if(rolx >= (ovalA-100.0f)) //끝의 휜 부분에서 x 증가값 감소 { rolx+=bend; if(bend != 1.0f) bend-=0.5; } else rolx += 10.0f; } if(rolx >= (ovalA-260.0f)) //끝의 휜 부분에서 차체를 회전시킴 { if(rol4 % 2 == 0) { if(bendrotate != 0.0f) bendrotate -= 3.0; } else { if(bendrotate != 90.0f) bendrotate += 3.0; } } if(rolx > ovalA || rolx < 0.0f) { switch(rol4) { case 1: //1사분면 끝 rol4 = 4; rolx = (GLfloat)ovalA; bend = 5.0f; break; case 2: //2사분면 끝 rol4 = 1; rolx = 0.0f; bend = 10.0f; bendrotate = 0.0f; break; case 3: //3사분면 끝 rol4 = 2; rolx = (GLfloat)ovalA; bend = 5.0f; break; case 4: //4사분면 끝 rol4 = 3; rolx = 0.0f; bend = 10.0f; bendrotate = 0.0f; break; } } glutTimerFunc(100, TimerFunc, 1); } void main(void) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(400, 400); glutCreateWindow("BounceRectangle"); glutReshapeFunc(ChangeSize); glutTimerFunc(33,TimerFunc,1); glutSpecialFunc(KeyControl); glutKeyboardFunc(myKeyboard); glutDisplayFunc(RenderScene); glutCreateMenu(ProcessMenu); glutAddMenuEntry("깊이 테스트", 1); glutAddMenuEntry("은면 제거", 2); glutAddMenuEntry("뒷면 라인 그리기", 3); glutAttachMenu(GLUT_RIGHT_BUTTON); SetupRC(); glutMainLoop(); }
'Graphics > OpenGL' 카테고리의 다른 글
[OpenGL]간단한 나무 만들기 함수 (2) | 2014.07.05 |
---|---|
[OpenGL]반구 만들기 함수 (0) | 2014.07.05 |
[OpenGL]간단한 의자 만들기 함수 (0) | 2014.07.05 |
[OpenGL]간단한 링 만드는 함수 (0) | 2014.07.05 |
[OpenGL]간단한 배 만들기 함수 (5) | 2014.07.05 |