** 2012학년도 1학기 컴퓨터 그래픽스 과제.
중간 과제였는지 기말 과제였는지 기억이 안날 뿐더러 ...
이 코드가 제대로 동작하는 지에 대해 확신할 수가 없다.
3D 공간 개념이나 카메라 등을 제대로 이해하지 않고 되는대로 막 짠 코드라.. =_= 업벡터니 뭐니 이런 걸 2012학년도 2학기때 가서 아... 그랬구나! 라고 이해함. 근데 사실 지금도 잘 모르겠다. 꾸준한 공부가 필요해.
문제는 이랬던듯.
/* MEMO.
문제.
- spot light : 조명의 위치와 거리를 키보드로 조절할 수 있도록
- multi light : 2개의 조명을 동시 사용
- 재질 설정 : 금속성 재질과 돌멩이 재질간의 전환이 가능하도록
*/
재질 설정에 대한 코드는 아래에 있지 않은 모양이다. 외장하드를 뒤져봐야해ㄷㄷ
/*
*** 키보드 조작 참고.
F : 백색광 좌로 이동
G : 백색광 밑으로 이동
H : 백색광 우로 이동
T : 백색광 위로 이동
B : 백색광 가까이
V : 백색광 멀리
J : 청색광 좌로 이동
K : 청색광 밑으로 이동
L : 청색광 우로이동
I : 청색광 위로 이동
P : 청색광 가까이
O : 청색광 멀리
A : 줌 인
Z : 줌 아웃
*/
#include <Windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <gl\glut.h>
#include <cmath>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
// Zoom In/Out, Rotation, Color 를 위한 전역변수 선언
static int yRot = 0; // 좌우 회전 설정값
static int xRot = 0; // 상하 회전 설정값
static float zoom = 100.0f; // Zoom In/Out 설정값
// RGB 설정값
static float red = 0.0f;
static float blue = 0.0f;
static float green = 0.0f;
class Model_PLY
{
public:
int Model_PLY::Load(char *filename);
void Model_PLY::Draw();
float* Model_PLY::calculateNormal( float *coord1, float *coord2, float *coord3 );
Model_PLY();
float* Faces_Triangles;
float* Faces_Quads;
float* Vertex_Buffer;
float* Normals;
int TotalConnectedTriangles;
int TotalConnectedQuads;
int TotalConnectedPoints;
int TotalFaces;
};
// class Model_PLY
Model_PLY ply;
Model_PLY::Model_PLY()
{
}
float* Model_PLY::calculateNormal( float *coord1, float *coord2, float *coord3 )
{
/* calculate Vector1 and Vector2 */
float va[3], vb[3], vr[3], val;
va[0] = coord1[0] - coord2[0];
va[1] = coord1[1] - coord2[1];
va[2] = coord1[2] - coord2[2];
vb[0] = coord1[0] - coord3[0];
vb[1] = coord1[1] - coord3[1];
vb[2] = coord1[2] - coord3[2];
/* cross product */
vr[0] = va[1] * vb[2] - vb[1] * va[2];
vr[1] = vb[0] * va[2] - va[0] * vb[2];
vr[2] = va[0] * vb[1] - vb[0] * va[1];
/* normalization factor */
val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] );
float norm[3];
norm[0] = vr[0]/val;
norm[1] = vr[1]/val;
norm[2] = vr[2]/val;
return norm;
}
int Model_PLY::Load(char* filename)
{
this->TotalConnectedTriangles = 0;
this->TotalConnectedQuads = 0;
this->TotalConnectedPoints = 0;
char* pch = strstr(filename,".ply");
if (pch != NULL)
{
FILE* file = fopen(filename,"r");
fseek(file,0,SEEK_END);
long fileSize = ftell(file);
try
{
Vertex_Buffer = (float*) malloc (ftell(file));
}
catch (char* )
{
return -1;
}
if (Vertex_Buffer == NULL) return -1;
fseek(file,0,SEEK_SET);
Faces_Triangles = (float*) malloc(fileSize*sizeof(float));
Normals = (float*) malloc(fileSize*sizeof(float));
if (file)
{
int i = 0;
int temp = 0;
int quads_index = 0;
int triangle_index = 0;
int normal_index = 0;
char buffer[1000];
fgets(buffer,300,file); // ply
// READ HEADER
// -----------------
// Find number of vertexes
while ( strncmp( "element vertex", buffer,strlen("element vertex")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element vertex"));
sscanf(buffer,"%i", &this->TotalConnectedPoints);
// Find number of vertexes
fseek(file,0,SEEK_SET);
while ( strncmp( "element face", buffer,strlen("element face")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element face"));
sscanf(buffer,"%i", &this->TotalFaces);
// go to end_header
while ( strncmp( "end_header", buffer,strlen("end_header")) != 0 )
{
fgets(buffer,300,file); // format
}
//----------------------
// read verteces
i =0;
for (int iterator = 0; iterator < this->TotalConnectedPoints; iterator++)
{
fgets(buffer,300,file);
sscanf(buffer,"%f %f %f", &Vertex_Buffer[i], &Vertex_Buffer[i+1], &Vertex_Buffer[i+2]);
i += 3;
}
// read faces
i =0;
for (int iterator = 0; iterator < this->TotalFaces; iterator++)
{
fgets(buffer,300,file);
if (buffer[0] == '3')
{
int vertex1 = 0, vertex2 = 0, vertex3 = 0;
//sscanf(buffer,"%i%i%i\n", vertex1,vertex2,vertex3 );
buffer[0] = ' ';
sscanf(buffer,"%i%i%i", &vertex1,&vertex2,&vertex3 );
/*vertex1 -= 1;
vertex2 -= 1;
vertex3 -= 1;
*/
// vertex == punt van vertex lijst
// vertex_buffer -> xyz xyz xyz xyz
//printf("%f %f %f ", Vertex_Buffer[3*vertex1], Vertex_Buffer[3*vertex1+1], Vertex_Buffer[3*vertex1+2]);
Faces_Triangles[triangle_index] = Vertex_Buffer[3*vertex1];
Faces_Triangles[triangle_index+1] = Vertex_Buffer[3*vertex1+1];
Faces_Triangles[triangle_index+2] = Vertex_Buffer[3*vertex1+2];
Faces_Triangles[triangle_index+3] = Vertex_Buffer[3*vertex2];
Faces_Triangles[triangle_index+4] = Vertex_Buffer[3*vertex2+1];
Faces_Triangles[triangle_index+5] = Vertex_Buffer[3*vertex2+2];
Faces_Triangles[triangle_index+6] = Vertex_Buffer[3*vertex3];
Faces_Triangles[triangle_index+7] = Vertex_Buffer[3*vertex3+1];
Faces_Triangles[triangle_index+8] = Vertex_Buffer[3*vertex3+2];
float coord1[3] = { Faces_Triangles[triangle_index], Faces_Triangles[triangle_index+1],Faces_Triangles[triangle_index+2]};
float coord2[3] = {Faces_Triangles[triangle_index+3],Faces_Triangles[triangle_index+4],Faces_Triangles[triangle_index+5]};
float coord3[3] = {Faces_Triangles[triangle_index+6],Faces_Triangles[triangle_index+7],Faces_Triangles[triangle_index+8]};
float *norm = this->calculateNormal( coord1, coord2, coord3 );
Normals[normal_index] = norm[0];
Normals[normal_index+1] = norm[1];
Normals[normal_index+2] = norm[2];
Normals[normal_index+3] = norm[0];
Normals[normal_index+4] = norm[1];
Normals[normal_index+5] = norm[2];
Normals[normal_index+6] = norm[0];
Normals[normal_index+7] = norm[1];
Normals[normal_index+8] = norm[2];
normal_index += 9;
triangle_index += 9;
TotalConnectedTriangles += 3;
}
i += 3;
}
fclose(file);
}
else { printf("File can't be opened\n"); }
} else {
printf("File does not have a .PLY extension. ");
}
return 0;
}
void Model_PLY::Draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, Faces_Triangles);
glNormalPointer(GL_FLOAT, 0, Normals);
glDrawArrays(GL_TRIANGLES, 0, TotalConnectedTriangles);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
// 조명 위치 조정 변수 선언
static float light1_x = 1.0f;
static float light1_y = 1.0f;
static float light1_z = 0.48f;
static float light0_x = 0.0f;
static float light0_y = 0.0f;
static float light0_z = 0.48f;
void Display()
{
// Light 0 의 위치, 방향, 조명각
GLfloat Light0_Position[] = {light0_x, light0_y, light0_z, 1.0};
GLfloat Light0_Direction[] = {0, 0, -0.9};
GLfloat Light0_SpotAngle[] = {80.0};
// Light 1 의 위치, 방향 조명각
GLfloat Light1_Position[] = {light1_x, light1_y, light1_z, 2.0};
GLfloat Light1_Direction[] = {0, 0, -0.9};
GLfloat Light1_SpotAngle[] = {80.0};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glViewport(0, 0, 600, 600);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glPushMatrix();
gluPerspective(zoom, 1, 0.1, 100); //가시부피 및 시야각을 통한 Zoom In/Out 설정
gluLookAt(0, 0.05, 0.48, 0, 0, -0.8, 0.0, 1.0, 0.0); // 카메라 시점
glLightfv(GL_LIGHT0, GL_POSITION, Light0_Position);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, Light0_Direction);
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, Light0_SpotAngle);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 1.0);
glLightfv(GL_LIGHT1, GL_POSITION, Light1_Position);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, Light1_Direction);
glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF, Light1_SpotAngle);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 1.0);
glRotatef((GLfloat)xRot, 1.0, 0.0, 0.0); // 상하 회전
glRotatef((GLfloat)yRot, 0.0, 1.0, 0.0); // 좌우 회전
ply.Draw();
//glPopMatrix();
glutSwapBuffers();
glFlush();
}
void LightInit()
{
GLfloat light0_ambient[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light0_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light1_ambient[] = {0.0, 1.0, 1.0, 1.0};
GLfloat light1_diffuse[] = {0.0, 1.0, 1.0, 1.0};
GLfloat light1_specular[] = {0.0, 1.0, 1.0, 1.0};
GLfloat bunny_stone_ambient[] = {0.0, 0.0, 0.0, 1.0};
GLfloat bunny_stone_diffuse[] = {0.4, 0.4, 0.4, 1.0};
GLfloat bunny_stone_specular[] = {0.7, 0.7, 0.7, 1.0};
GLfloat bunny_stone_shininess[] = {20.0};
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST); // 깊이 버퍼 활성화
glEnable(GL_LIGHTING); // 조명 활성화
glEnable(GL_LIGHT0); // 0번 광원 활성화
glEnable(GL_LIGHT1); // 1번 광원 활성화
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, bunny_stone_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, bunny_stone_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, bunny_stone_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, bunny_stone_shininess);
}
void MyKeyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'a': //
if(zoom < 7.0f) // 시점(화면) 밖을 벗어나므로 값 제한
zoom = 7.0f;
zoom-=1.0f;
glutPostRedisplay();
break;
case 'z': //Zoom Out
if(zoom > 180.0f) // 시점에 의해 bunny가 상하반전 되지 않도록 값 제한
zoom = 180.0f;
zoom += 1.0f;
glutPostRedisplay();
break;
/////////////////////////////////////////////////
case 'j': // Light0 좌로 회전
light1_x -= 0.03;
// light1_y = sqrt(0.9529-(light1_x*light1_x));
glutPostRedisplay();
break;
case 'i':
light1_y += 0.03;
glutPostRedisplay();
break;
case 'k':
light1_y -= 0.03;
glutPostRedisplay();
break;
case 'l':
light1_x += 0.03;
// light1_y = abs(sqrt(0.9529-(light1_x*light1_x)));
glutPostRedisplay();
break;
case 'o':
light1_z -= 0.01;
glutPostRedisplay();
break;
case 'p':
light1_z += 0.01;
glutPostRedisplay();
break;
//////////////////////////////////////////////////////////////
case 'f': // Light1 좌로 회전
light0_x -= 0.03;
// light1_y = sqrt(0.9529-(light1_x*light1_x));
glutPostRedisplay();
break;
case 't':
light0_y += 0.03;
glutPostRedisplay();
break;
case 'g':
light0_y -= 0.03;
glutPostRedisplay();
break;
case 'h':
light0_x += 0.03;
// light1_y = abs(sqrt(0.9529-(light1_x*light1_x)));
glutPostRedisplay();
break;
case 'v':
light0_z -= 0.01;
glutPostRedisplay();
break;
case 'b':
light0_z += 0.01;
glutPostRedisplay();
break;
default:
break;
}
}
void MyKeyboard_S(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT: //Rotate to Left
yRot = (yRot+5) % 360;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT: //Rotate to Right
yRot = (yRot-5) % 360;
glutPostRedisplay();
break;
case GLUT_KEY_UP: //Rotate to Up
xRot = (xRot+5) % 360;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN: //Rotate to Down
xRot = (xRot-5) % 360;
glutPostRedisplay();
break;
default: // Default
break;
}
}
void ColorInit()
{
float RGB[3];
srand((unsigned int)time(NULL)); // rand() 초기화
// bunny 색상 랜덤 설정
for(int i=0; i<3; i++)
RGB[i] = (rand() % 255)+1;
// RGB 값을 0부터 1사이의 값으로 정규화
red = RGB[0] / 255;
green = RGB[1] / 255;
blue = RGB[2] / 255;
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glClearColor(1.0, 1.0, 1.0, 1.0);
ColorInit();
glutInitWindowSize(600, 600);
glutInitWindowPosition(30, 30);
glutCreateWindow("201033139_");
ply.Load("Stanford_Bunny.ply");
LightInit();
glutDisplayFunc( Display );
glutKeyboardFunc( MyKeyboard );
glutSpecialFunc( MyKeyboard_S );
glutMainLoop();
return 0;
}
재질 설정에 대한 부분은 아래 사이트를 참고하는 것이 좋을 것 같다.
재질에 적절히 맞는 값을 직접 테스트해보면서 찾는 노가다를 좀 줄일 수 있다. 사실 이것도 잘 이해하면 그다지 문제 될 부분은 아니지만... ㅠㅠ
http://devernay.free.fr/cours/opengl/materials.html
'스터디' 카테고리의 다른 글
Unity3D :: Time.timeScale (0) | 2013.10.06 |
---|---|
안드로이드 (0) | 2013.09.23 |
중간고사 대비 관련해서 이것저것 남겨두는 포스팅. (0) | 2013.04.21 |
Direct3D :: 시야각 설정을 통한 카메라 Zoom In/Out (0) | 2013.03.23 |
Direct3D :: 간단한 슈팅 게임 맛보기로 구현하기. (0) | 2013.03.14 |