現在地 >> メニュー >> サンプルコード::OpenGL >> スクリーンの描画

問題


gluPerspective()関数で設定したスクリーンがOpenGL上でどこにあるのかを計算し、
3次元空間上にスクリーンを描画せよ。

その他条件
  • ある視点(x,y,z)から(0,0,0)を見ていて、+y軸が上。

答え


#include <iostream>
#include <cmath>
#include <GL/glut.h>

//マウスの状態
struct _MOUSE
{
	int Xstart,Ystart;
	bool flag;
	double weight;
};
_MOUSE MouseStatus={0,0,false,0.5};

//回転関係
struct _ObjectRotate
{
	double xAngle,yAngle;
};
_ObjectRotate ObjRot={0,0};


//視点情報
double eye[3]={3,4,5};


/********** プロトタイプ宣言 ************/
void display();
void reshape(int w, int h);
void myMouseFunc(int button,int state,int x,int y);
void myMouseMotion(int x,int y);
void keyboard(unsigned char key, int x, int y);

void DRAW_XYZ();
void DRAW_TRI();
void DrawScreen(double fovy,double eyeX,double eyeY,double eyeZ,double znear);

//----------- OpenGLの初期設定 ---------------//
void GLUT_INIT()
{
	glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE | GLUT_DEPTH); //ダブルバッファ、Zバッファ
	glutInitWindowSize(640,480);
	glutCreateWindow("Draw Screen");
}


void GLUT_CALL_FUNC()
{
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMouseFunc(myMouseFunc);
	glutMotionFunc(myMouseMotion);
	glutKeyboardFunc(keyboard);

}

void MY_INIT()
{
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glEnable(GL_DEPTH_TEST);  //Zバッファ有効化
}

/********[メイン関数]********/
int main(int argc, char **argv)
{
	glutInit(&argc,argv);
	
	GLUT_INIT();
	GLUT_CALL_FUNC();
	MY_INIT();

	glutMainLoop();

	return 0;
}

/********[ここからコールバック]****************************************/
void display()
{

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();
	gluLookAt(eye[0],eye[1],eye[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	
	glRotated(ObjRot.xAngle,1,0,0);
	glRotated(ObjRot.yAngle,0,1,0);

	DRAW_XYZ();  //XYZ軸の描画

	glPushMatrix();   //行列退避
	glTranslated(1,0,0); //[1].並行移動
	glColor3d(0,1,0);
	DRAW_TRI();
	glPopMatrix(); //行列を戻す
	
	DrawScreen(30,eye[0],eye[1],eye[2],2); //スクリーン描画(fovy,znearをわたす)

	glColor3d(1,1,1); //色のリセット

	glutSwapBuffers();

}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION); //行列モード切替
	glLoadIdentity();  //行列初期化
	gluPerspective(30.0, static_cast<double>(w)/h, 2.0, 100.0);
	glMatrixMode(GL_MODELVIEW); //行列モード切替
}

void timer(int t)
{
	glutPostRedisplay();
	glutTimerFunc(t,timer,17); //タイマー関数
}

void myMouseFunc(int button,int state,int x,int y)
{
	if(button == GLUT_LEFT_BUTTON &&state == GLUT_DOWN)
	{
		MouseStatus.Xstart = x;
		MouseStatus.Ystart = y;
		MouseStatus.flag = true;
	}
	else
	{
		MouseStatus.flag =false;
	}

}

void myMouseMotion(int x,int y)
{
	int xdis,ydis;

	if(MouseStatus.flag == false)return;

	xdis = x - MouseStatus.Xstart;
	ydis = y - MouseStatus.Ystart;

	ObjRot.xAngle += (double)ydis * MouseStatus.weight;
	ObjRot.yAngle += (double)xdis * MouseStatus.weight;

	MouseStatus.Xstart = x;
	MouseStatus.Ystart = y;
	display();
}

void keyboard(unsigned char key, int x, int y)
{
    switch(key)
	 {
	 case 'r':
		ObjRot.xAngle = 0;
		ObjRot.yAngle = 0;
		break;
	 case 'q':
	 case '\033':
		 exit(0);
		 break;
	 }
	 display();
}

//----------- ここから各種関数 ----------------//
void DRAW_XYZ()
{
	glBegin(GL_LINES);

	glColor3d(0,1,0);//x
	glVertex2d(-100,0);
	glVertex2d(100, 0);

	glColor3d(1,0,0);//y
	glVertex2d(0,0);
	glVertex2d(0,100);

	glColor3d(0,0,1);//z
	glVertex3d(0,0,-100);
	glVertex3d(0,0, 100);
	glEnd();

}

void DRAW_TRI()
{
	glBegin(GL_TRIANGLES);
	glVertex2d(0,1);
	glVertex2d(-0.5, 0);
	glVertex2d(0.5, 0);
	glEnd();
}


void DrawScreen(double fovy,double eyeX,double eyeY,double eyeZ,double znear)
{

	static int viewport[4];//ビューポート取得
	glGetIntegerv(GL_VIEWPORT, viewport);

	static double top =  znear * tan(0.0174532925*fovy/2.0);
	static double left = static_cast<double>(viewport[2])/viewport[3] * top;

	static double theta = atan2(eyeX,eyeZ)/0.0174532925;
	static double fai = atan2(eyeY,sqrt(eyeX*eyeX+eyeZ*eyeZ))/0.0174532925;
	static double length = sqrt(eyeX*eyeX+eyeY*eyeY+eyeZ*eyeZ);//原点からの距離

	glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	glColor3f(1,0,1);

	glPushMatrix();
	glRotated(theta,0,1,0);
	glRotated(fai,-1,0,0);
	glTranslatef(0,0,length-znear);
	glRectd(-left,top,left,-top);
	glPopMatrix();

	glColor3f(1,1,1);
	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます