opengl공부하다가 계속 막히는 부분이 있어서 질문드립니다.
회전변환 때문인데요,
우선 제가 하려는게
예를 들면 삼각형을 그린다고 했을때
마우스 클릭으로 좌표를 3개 지정해서 삼각형을 그린다음에
glRotatef함수를 사용해서 원하는 각도만큼 도형을 회전시키려고 했습니다.
회전하는 것 자체는 문제가 없는데, 회전 한 이후에 마우스 클릭을 통해서 추가로
좌표를 지정해 사각형을 그렸을 때, 이 네번째 좌표가 제가 클릭한 좌표와 다르게 찍히네요
왜그런지 찾아보니까 glRotatef함수가 좌표들을 회전시키는게 아니라 모델좌표계 자체를 회전시켜서
전역좌표계와 모델좌표계가 일치하지 않아서 발생하는 문제인것 같은데요...
glIdentity나 glPush, Pop 등을 사용해서 어떻게 해야하는거 같은데
며칠동안 계속붙잡고있는데도 안됩니다ㅠㅡㅠ
전체 코드는 아래에 있습니다
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <glut.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#pragma warning(disable:C4996)
using namespace std;
GLfloat Vertex[200][2]; //정점좌표를 저장할 배열
GLint topleftx, toplefty; //마우스에 좌표를 저장할 변수 선언
GLint num = 0; //배열의 개수로 사용할 변수 선언
GLfloat mag; //확대를 위한 변수
GLfloat movx, movy; //평행이동을 위한 변수
GLfloat lot; //회전을 위한 변수
GLint t;
GLfloat Px, Py;//도형의 무게중심
void mouseclick(int button, int state, int x, int y) //마우스 좌클릭으로 좌표 지정
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
topleftx = x;
toplefty = y;
Vertex[num][0] = topleftx / 600.0;
Vertex[num][1] = (600 - toplefty) / 600.0;
num++;
}
glutPostRedisplay();
}
void display()
{
glViewport(0, 0, 600, 600);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
if (num <= 1) //입력된 좌표가 1개일 경우 점을 찍게하여 위치를 확인 가능하게 한다.
{
glBegin(GL_POINTS);
glVertex3f(Vertex[0][0], Vertex[0][1], 0);
glEnd();
glFlush();
}
else if (num == 2) //입력된 좌표가 2개일 경우 두 점을 직선으로하여 위치를 볼 수 있게 한다.
{
glBegin(GL_LINES);
for (int i = 0; i < num; i++)
{
glVertex3f(Vertex[i][0], Vertex[i][1], 0);
}
glEnd();
glFlush();
}
else if (num >= 3) //입력된 좌표가 3개이상일 경우 도형을 그린다
{
glBegin(GL_POLYGON);
for (int i = 0; i < num; i++)
{
glVertex3f(Vertex[i][0], Vertex[i][1], 0);
}
glEnd();
glFlush();
}
if (t == 1) //manify함수를 통해 바뀐 점들로 다시 도형을 그린다
{
glBegin(GL_POLYGON);
for (int k2 = 0; k2 < num; k2++)
{
glVertex3f(Vertex[k2][0], Vertex[k2][1], 0);
}
glEnd();
glFlush();
}
if (t == 2) //move함수를 통해 바뀐 점들로 다시 도형을 그린다
{
glBegin(GL_POLYGON);
for (int l2 = 0; l2 < num; l2++)
{
glVertex3f(Vertex[l2][0], Vertex[l2][1], 0);
}
glEnd();
glFlush();
}
if (t == 3)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(Px, Py, 0); //회전된 도형의 중심을 다시 원래 도형의 중심으로 이동
glRotatef(lot, 0, 0, 1); //도형을 입력된 각도 값만큼 회전
glTranslatef(-Px, -Py, 0); //도형의 중심을 원점으로 옮김
glBegin(GL_POLYGON);
for (int i = 0; i < 200; i++)
{
glVertex3f(Vertex[i][0], Vertex[i][1], 0);
}
glEnd();
glFlush();
}
if (t == 4)
glClear(GL_COLOR_BUFFER_BIT);
}
void magnify() //키보드 입력으로 확대
{
float sumx = 0; //무게중심의 x좌표 계산을 위한 변수설정
float sumy = 0; //무게중심의 y좌표 계산을 위한 변수설정
for (int k0 = 0; k0 < num; k0++)
{
sumx += Vertex[k0][0];
sumy += Vertex[k0][1];
}
Px = sumx / num;
Py = sumy / num;
for (int k1 = 0; k1 < num; k1++)
{
Vertex[k1][0] = Px + mag*(Vertex[k1][0] - Px); //원래의 점에서 확대됐을 때 점의 x좌표
Vertex[k1][1] = Py + mag*(Vertex[k1][1] - Py); //원래의 점에서 확대됐을 때 점의 y좌표
}
}
void move() //키보드 입력으로 평행이동
{
for (int l1 = 0; l1 < num; l1++)
{
Vertex[l1][0] += movx; //원래 점에서 평행이동 됐을때 점의 x좌표
Vertex[l1][1] += movy; //원래 점에서 평행이도 됐을때 점의 y좌표
}
}
void lotate() //키보드 입력으로 도형의 무게중심을 중심으로 회전
{
GLfloat sumx = 0;
GLfloat sumy = 0;
for (GLint k0 = 0; k0 < num; k0++)
{
sumx += Vertex[k0][0];
sumy += Vertex[k0][1];
}
Px = sumx / num;
Py = sumy / num;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(Px, Py, 0); //회전된 도형의 중심을 다시 원래 도형의 중심으로 이동
glRotatef(lot, 0, 0, 1); //도형을 입력된 각도 값만큼 회전
glTranslatef(-Px, -Py, 0); //도형의 중심을 원점으로 옮김
glBegin(GL_POLYGON);
for (int i = 0; i < num; i++)
{
glVertex3f(Vertex[i][0], Vertex[i][1], 0);
}
glEnd();
glFlush();
glPopMatrix();
}
void DoMenu(int value)
{
switch (value)
{
case 1:
cout << "몇 배 확대 : ";
cin >> mag;
magnify();
t = 1;
break;
case 2:
cout << "x축으로 : ";
cin >> movx;
cout << "y축으로 : ";
cin >> movy;
move();
t = 2;
break;
case 3:
cout << "몇 도 회전 : ";
cin >> lot;
lotate();
t = 3;
break;
case 4:
t = 4;
break;
case 5:
exit(0);
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("도와주세요");
glClearColor(1.0, 1.0, 1.0, 1.0);
glutCreateMenu(DoMenu);
glutAddMenuEntry("확대", 1);
glutAddMenuEntry("이동", 2);
glutAddMenuEntry("회전", 3);
glutAddMenuEntry("모두지우기", 4);
glutAddMenuEntry("종료", 5);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glutDisplayFunc(display);
glutMouseFunc(mouseclick);
glutMainLoop();
return 0;
}