'OpenGL'에 해당되는 글 10건
- 2010.06.06 :: Sphere에 Mapping 하는 소스예요~!
- 2009.11.12 :: 저번학기에 들은 그래픽스 과제중 하나.
- 2009.06.03 :: 개발중인 텀 과제...... 1
- 2009.04.21 :: 약속대로 OpenGL 실습과제(수업시간용)1 소스코드 공개.
- 2009.04.06 :: (최근 OpenGL실습레포트) 구현방법 공개. 2
- 2009.03.29 :: 실습과제 40%정도 진행된 스크린샷
- 2009.03.28 :: OpenGL 최근 실습과제 완성..
- 2009.03.20 :: 업데이트된 다양한 그리기
- 2009.03.17 :: 클릭 이벤트를 포함한 다양한 그리기.
- 2009.03.11 :: 다시 OpenGL 공부시작 첫단계;
심심해서 들어간 네이트에 아는 후배녀석이 물어보길래......뭐......
정보는 공유해라고 있는거니까요.....
구에다가 텍스쳐 매핑하는 소스인데 코드자체도 간단해서 보면 누구나 알수있을만하네요..
저도 예전에 필요해서 구해서 보고 코드작성에 도움을 받았던 코드인데 자료 오픈합니다~!
비쥬얼c 6.0으로 작성된 소스인데 아마도 2008에서 소스넣고 돌리셔도 될겁니다.
2010도 될듯........;;
로직만 참고하시고 쓰세요~!
덧 이소스를 작성한 사람은 제가 아니고, 저도 웹에서 얻었던 소스여서
원 소스 저작자가 삭제를 요청하시면 언제든지 삭제하겠습니다. ;
제가작성했던 소스는 다른여러가지가 너무많이 붙어있어서 올리기가 뭣해서......암튼....;;
2010.06.06...락페스티벌 다녀와서 기분좋은 상태에서 올리는 소스공유..
Glut를 이용해서 구현한 태양계 자전,공전 궤도의 시뮬레이션이다..
식겁했다.....
누군가 비슷한걸로 고민할거라생각하며 꼼수로 만든 소스코드를 공개한다..
돌려보려면 알아서 GLUT를 설치하길 바란다.
4-1학기(원래는 3-1학기) 그래픽스 과제로 개발중인 녀석이다...
일리히트 게임엔진과 Bullet 물리엔진을 사용했다.....
캐릭터는 그릴 재주가 없어 샘플 가져다쓰고....여러가지 효과는 일리히트를 조작하여 만들어냈다.
화면상으로는 볼순없지만 내부적 충돌처리도있어 이동에 대한 처리도 가능하고....뭐 그럴싸하다.
개인적으로 존경하는 존카멕 형님이 공개해주신 퀘이크 소스코드에서 추출한 BSP Loader, BSP CONVERTER를 적용시켰다. 그렇게라도 하지않으면 정말 느리다....;; 발로짯기때문이랄까...;; (발코..발코...)
Bullet Phsyx 물리엔진 붙여서 사용하고, Plane wave기능 적용시켜서 물효과주고..., 3인칭 카메라 매니저 작성해서 붙여서 따라다니는 카메라 구현했다...(디아블로시점이랄까)
예전의 약속대로 공개합니다.
기본적인 드로잉에 대한 코드가 구현되어있습니다.
소스코드 자체가 난잡하므로...(내공이 없어서....)
참고하실분은 알아서 잘 추려서 참고하세요..
각각의 구조체에는 좌표값을 위한변수, 로테이션을 위한 값, 그룹을 위한 할당값,
선택여부판단을 위한 Boolean 등이 들어있다.
이러한 객체를 관리하기위해 Vector를 이용하여 리스트를 구성하였다.
그러면 각각의 객체를 관리할수 있기때문이다.
드로우 에서는 두가지 펑션이 호출되게 해놓았는데,
하나는 오브젝트를 리스트를 돌면서 화면에 출력하는 것이고
하나는 마우스의 클릭&드래그를 통한 러버밴딩을 위한 출력을 위한 함수 두개를 호출.
다른 객체들을 그리는 부분은 모두들 쉽게 구현을 했으리라 생각한다. 하지만
많은 사람들이 glTranslatef 를 통한 중점 이동을 한후에 어떠한 문제가 발생했으리라 추측된다.
아마도 화면이 계속 밀리듯이 하다가 객체가 안보이는 현상이 생겼을것이다.
이는 매트릭스 모드의 복구가 이루어지지 않았기 떄문이다.
즉 무슨말인고 하니 , glTranslatef(0.5, 0.5, 0); 을 했다치면은 객체를 그린후
glTranslatef(-0.5, -0.5, 0) 를 해주어야 된다라는거다.
하지만 이짓을 상당히 귀찮은 짓이다.
그래서 glPushMatrix(); 를 통해서 현재 매트리스 상태를 저장하고 어떠한 작업을 한후에(중점 옮기기 라던지, 로테이션이라던지 이런것들) glPopMatrix()를 통해서
원래 상태로 되돌리면 위와같은 문제는 간단히 해결된다.
객체 변환의 기능의 경우 각각의 객체가 리스트르 통해서 따로관리되기에 각각의 값을 불러와서
그대로 로테이션, 해주고 출력하면 모든것이 해결된다. 단, 스케일의 변화같은경우에는 직접 객체를 그리기위한 반지름의 값, 혹은 사각형 등을 그리기위한 좌표값을 수정해서 저장해야만 반영이 되므로 이점을 유의하면 나머지도 무사히 구현가능하리라 생각한다.
러버벤딩을 이용한 처리의 경우에는, 마우스의 처음 클릭 값과, 마우스 버튼을 떼었을때의 경우를
생각해서 드로잉 하면되겠다. 이러면 별 문제가 발생하지않고 다 해결된다.
만약, 객체를 그렸는데 나타나지않는다면 이 경우를 의심해보자.
중심좌표를 이동할때 (마우스좌표값/화면축의 길이값)과 같이 적용했는지를 확인해보면 간단히 나온다.
무슨말인고하니 glOrthogo와 같이 투영값을 지정해줄시에 화면에 맵핑되는 값을 -1 ~ 1, 이런식으로 값을 지정하게되는데 거기게 맞는 값으로 매핑을 해주어야 윈도우 좌표계와 매핑되어 나오기 떄문이다. 즉 저값을 벗어나면 그냥 뷰의 화면에선 보이지않게된다. 이점을 잘 생각해보면 출력이 되지않는 경우를 제대로 할수있을것이다.
객체의 복사 붙이기 기능의 경우 역시 버퍼를 이용하면 단순하다.
어떠한 객체가 지정되면, 객체의 리스트의 정보에 셀렉트의 bool값이 true가 될것이고 이정보들을
컨트롤+c와같이 명령어를 먹이는순간 카피버퍼에리스트에 다 복사한다.
그리고 붙이기를 할때, 그 값을 해당하는 리스트에 다시 삽입하면 되는것이다. 그러면 화면에는
겹쳐져서 안보일지 몰라도 객체가 그려져 있을것이다.
잘라내기 역시 위와같으나, 버퍼에 옮김후에 원래 내용을 지워주면 해결된다.(간단한 문제임..)
드래그를 통한 객체이동의 경우 조금 귀찮은 방법을 사용해서 구현했다.
객체의 구조체에 처음에 그려진 좌표값이 있고, 드래그중에 이동될 x,y 변화값을 기록을 통해
드래그시에 이값을 참조하여 이동시켜 뿌리면 해결된다.
단 마우스 버튼을 떼는순간 이 값을 적용한 값을 좌표에 기록해주고, 그 이후 이 변화값을 0으로 해주면 말끔하게 드래그를 통한 객체 이동이 구현된다.
워낙 두서없이 글을 써서 정보를 얻을수 있으려나 모르겠지만, 한번쯤 디버깅을 해본 사람이라면
약간의 단서는 제공했으리라 생각된다.
아직 세부적인 기능을 다 구현하지 않았기에 개발 스크린샷만 공개한다.
개발이 완료되면, 세부적 기능을 어떻게 구현했는지와 소스코드를 올리겠다.(제출지난후에)
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
using namespace std;
// Define for Enum value
enum Drawtype {points, line, triangle, polygons};
#define vertexcnt vertice.size()
// Structure for Vertex Information
struct vertex
{
GLint x,y,z;
};
// Vertex Matrix Information
vector<vertex> vertice;
// Menu Type
int type = points;
// Wire information
bool wire=false;
// 동적으로 찍을수 있게 하기위한 창의 사이즈 값.
GLint width,height;
GLfloat thick=1.0f;
// 컬러 설정을 위한 값.
GLfloat r=0.5,g=0.5,b=0.5;
//---------------------------------------------------------------------------------------------
// 화면 렌더링펑션
void MyDisplay( ){
int cnt=0;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(r, g, b);
// 여기에서 드로잉
if(type == points)
{
glPointSize(thick);
for(cnt=0; cnt<vertexcnt; cnt++)
{
glBegin(GL_POINTS);
glVertex3f((GLfloat)vertice[cnt].x/width,(GLfloat)vertice[cnt].y/height,0.0);
glEnd();
}
}
else if(type == line)
{
glLineWidth(thick);
if(vertexcnt >1)
for(cnt=0; cnt<vertexcnt-1; cnt+=2)
{
glBegin(GL_LINES);
glVertex2f((GLfloat)vertice[cnt].x/width,(GLfloat)vertice[cnt].y/height);
glVertex2f((GLfloat)vertice[cnt+1].x/width,(GLfloat)vertice[cnt+1].y/height);
glEnd();
}
}
else if(type == triangle)
{
if(vertexcnt>2)
for(cnt=0; cnt<vertexcnt; cnt+=3)
{
if(!wire)
glBegin(GL_TRIANGLES);
else
glBegin(GL_LINE_LOOP);
if(cnt+2 < vertexcnt)
{
glVertex3f((GLfloat)vertice[cnt].x/width,(GLfloat)vertice[cnt].y/height,0.0);
glVertex3f((GLfloat)vertice[cnt+2].x/width,(GLfloat)vertice[cnt+2].y/height,0.0);
glVertex3f((GLfloat)vertice[cnt+1].x/width,(GLfloat)vertice[cnt+1].y/height,0.0);
}
glEnd();
}
}
else if(type == polygons)
{
if(wire)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_POLYGON);
for(cnt=0; cnt<vertexcnt; cnt++)
glVertex3f((GLfloat)vertice[cnt].x/width,(GLfloat)vertice[cnt].y/height,0.0);
glEnd();
}
glFlush( );
}
// 리사이징 이벤트
void MyReshape(int NewWidth, int NewHeight)
{
glViewport(0, 0, NewWidth, NewHeight);
width = NewWidth;
height = NewHeight;
printf("창사이즈 변경 : %d %d\n",NewWidth,NewHeight);
glMatrixMode(GL_PROJECTION); //투상행렬을 변환대상으로 설정
glLoadIdentity();
glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
}
// 키보드 일반키 이벤트
void keyboard(unsigned char pressed, int x, int y)
{
switch(pressed)
{
case 'w' :
if(wire)
wire = false;
else
wire = true;
break;
case ']':
thick += 0.15f;
break;
case '[' :
thick -= 0.15f;
break;
case 'q' :
case 'Q':
exit(0);
break;
case 'a':
r+=0.01;
break;
case 'z':
r-=0.01;
break;
case 's':
g+=0.01;
break;
case 'x':
g-=0.01;
break;
case 'd':
b+=0.01;
break;
case 'c':
b-=0.01;
break;
}
if(thick <= 0)
thick = 0;
if(thick >=5)
thick =5;
glutPostRedisplay();
}
// 마우스 클릭이벤트
void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y){
int cnt=0;
if(Button==GLUT_LEFT_BUTTON && State==GLUT_DOWN){
vertex temp;
temp.x=X;
temp.y=Y;
temp.z=0;
vertice.push_back(temp);
//vertexcnt = vertice.size();
printf("[%d] ( %d, %d, %d)\n",vertexcnt,X,Y,0);
}
glutPostRedisplay();
}
void MyMainMenu(int entryID){
if(entryID == 1)
{
vertice.clear();
system("cls");
}
if(entryID == 2)
exit(0); //프로그램 종료
glutPostRedisplay();
}
void MySubMenu(int entryID){
if(entryID == points)
type = points; // 점그리기
else if (entryID == line)
type = line; // 선그리기
else if (entryID == triangle)
type = triangle; // 삼각형
else if (entryID == polygons)
type = polygons; // 폴리곤
glutPostRedisplay();
}
void setup()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
}
int main(int argc, char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Mj's Report");
glClearColor (1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
// 서브메뉴등록
GLint MySubMenuID = glutCreateMenu(MySubMenu);
glutAddMenuEntry("Points", 0);
glutAddMenuEntry("Lines", 1);
glutAddMenuEntry("Triangle", 2);
glutAddMenuEntry("Polygones", 3);
// 메뉴등록
GLint MyMainMenuID = glutCreateMenu(MyMainMenu);
glutAddSubMenu("Drawing", MySubMenuID);
glutAddMenuEntry("Clear", 1);
glutAddMenuEntry("Exit", 2);
// 버튼에대한 메뉴등록
glutAttachMenu(GLUT_RIGHT_BUTTON);
// 드로잉 펑션 등록
glutDisplayFunc(MyDisplay);
setup();
// 마우스 클릭이벤트 콜백함수 등록
glutMouseFunc(MyMouseClick);
// 키보드 이벤트 콜백함수 등록
glutKeyboardFunc(keyboard);
// 리사이징 이벤트 콜백함수 등록
glutReshapeFunc(MyReshape); //reshape callback
glutMainLoop( );
return 0;
}
// 추가된기능
// [, ] 키를 이용한 굵기조절
// az sx dc 를 이용한 r,g,b 색상조정
// w키를 이용한 와이어프레임 렌더링 조정 기능 추가
// 라인모드일시에 쭉 이어지는게 아니라 한 쌍씩 되게끔 수정.
// STL의 벡터를 이용한 다중 버텍스정보입력
// 창의 사이즈 조절에 따른 확장기능
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <stdlib.h>
#include <stdio.h>
struct vertex
{
GLint x,y,z;
};
int vertexcnt=0;
struct vertex vertice[10000];
GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY;
int type = 0;
void MyDisplay( ){
int cnt=0;
glViewport(0, 0, 300, 300);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.5, 0.5, 0.5);
// 여기에서 드로잉
if(type == 0)
{
glPointSize(3.0f);
for(cnt=0; cnt<vertexcnt; cnt++)
{
glBegin(GL_POINTS);
glVertex3f((GLfloat)vertice[cnt].x/300,(GLfloat)vertice[cnt].y/300,0.0);
glEnd();
}
}
if(type == 1)
{
glLineWidth(1.0f);
if(vertexcnt >1)
for(cnt=0; cnt<vertexcnt-1; cnt++)
{
glBegin(GL_LINES);
glVertex2f((GLfloat)vertice[cnt].x/300,(GLfloat)vertice[cnt].y/300);
glVertex2f((GLfloat)vertice[cnt+1].x/300,(GLfloat)vertice[cnt+1].y/300);
glEnd();
}
}
if(type == 2)
{
if(vertexcnt>2)
for(cnt=0; cnt<vertexcnt; cnt+=3)
{
glBegin(GL_TRIANGLES);
if(cnt+2 < vertexcnt)
{
glVertex3f((GLfloat)vertice[cnt].x/300,(GLfloat)vertice[cnt].y/300,0.0);
glVertex3f((GLfloat)vertice[cnt+1].x/300,(GLfloat)vertice[cnt+1].y/300,0.0);
glVertex3f((GLfloat)vertice[cnt+2].x/300,(GLfloat)vertice[cnt+2].y/300,0.0);
}
glEnd();
}
}
if(type == 3)
{
glBegin(GL_POLYGON);
for(cnt=0; cnt<vertexcnt; cnt++)
{
glVertex3f((GLfloat)vertice[cnt].x/300,(GLfloat)vertice[cnt].y/300,0.0);
}
glEnd();
}
glFlush( );
}
// 마우스 클릭이벤트
void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y){
int cnt=0;
if(Button==GLUT_LEFT_BUTTON && State==GLUT_DOWN){
vertice[vertexcnt].x=X;
vertice[vertexcnt].y=Y;
vertice[vertexcnt++].z=0;
printf("[%d] (%d, %d %d)\n",vertexcnt-1,X,Y,0);
}
glutPostRedisplay();
}
void MyMainMenu(int entryID){
if(entryID == 1)
{
vertexcnt=0; // 초기화
system("cls");
}
if(entryID == 2)
exit(0); //프로그램 종료
glutPostRedisplay();
}
void MySubMenu(int entryID){
if(entryID == 1)
type = 0; // 점그리기
else if (entryID == 2)
type = 1; // 선그리기
else if (entryID == 3)
type = 2; // 삼각형
else if (entryID == 4)
type = 3; // 폴리곤
glutPostRedisplay();
}
void setup()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
}
int main(int argc, char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Mj's Report");
glClearColor (1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
// 서브메뉴등록
GLint MySubMenuID = glutCreateMenu(MySubMenu);
glutAddMenuEntry("Points", 1);
glutAddMenuEntry("Lines", 2);
glutAddMenuEntry("Triangle", 3);
glutAddMenuEntry("Polygones", 4);
// 메뉴등록
GLint MyMainMenuID = glutCreateMenu(MyMainMenu);
glutAddSubMenu("Drawing", MySubMenuID);
glutAddMenuEntry("Clear", 1);
glutAddMenuEntry("Exit", 2);
// 버튼에대한 메뉴등록
glutAttachMenu(GLUT_RIGHT_BUTTON);
// 드로잉 펑션 등록
glutDisplayFunc(MyDisplay);
setup();
// 마우스 클릭이벤트 콜백함수 등록
glutMouseFunc(MyMouseClick);
glutMainLoop( );
return 0;
}
#include <glut.h>
#include <gl.h>
#include <glu.h>
void dispaly(void)
{
// 초기화
glClear(GL_COLOR_BUFFER_BIT);
// 폴리곤을그리는 부분. Z축은 0으로써 고정.
glBegin(GL_POLYGON);
glVertex3f(-0.5f, -0.5f, 0.0f);
glVertex3f( 0.5f, -0.5f, 0.0f);
glVertex3f( 0.5f, 0.5, 0.0f);
glVertex3f(-0.5f, 0.5, 0.0f);
// 그리기 종료
glEnd();
// Flush시킴으로써 화면에 드로잉이 이루어진다.
glFlush();
}
int main(int argc, char argv[])
{
// Window를 생성한다.
glutCreateWindow("OpenGL Test Window Example!");
// 디스플레이 펑션을 콜백함수로 등록한다.
glutDisplayFunc(dispaly);
// 루프를 작동시킨다.
glutMainLoop();
return 0;
}
이 코드는 C에서의 Hello World와 같다고 할수 있다.
glut 라이브러리를 이용하여 창을 생성하고 간단히 사각형을 그리는 예제이다.
매우 심플하다.
한동안 OpenGL을 공부하면서 중간중간 과정을 올릴 생각이다.
나중에 보면 도움이 되겠지?