#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#include <math.h>
#include <GL/freeglut/freeglut.h>
#define PAI 3.14159
//光源
float lightPos[] = {10.0, 15.0, 10.0, 1.0};//光源位置
//カメラと視体積
struct View{
//カメラ
float pos[3];//位置(視点)
float cnt[3];//注視点
float dist; //注視点から視点までの距離
float theta; //仰角(水平面との偏角)
float phi; //方位角
//視体積
float fovY; //視野角
float nearZ; //前方クリップ面(近平面)
float farZ; //後方クリップ面(遠平面)
};
View view = {
0.0, 0.0, 0.0,//pos(仮設定)
0.0, 1.0, 0.0,//cnt
10.0, 30.0, 20.0,//dist, theta, phi
30.0, 1.0, 100.0//fovY,nearZ, farZ
};
View view0 = view;
//Windowのサイズ
int width = 320;
int height = 240;
//アフィン変換
enum SELECT_KEY {ROTATE, SCALE, TRANSLATE, LIGHT};
SELECT_KEY sKey = TRANSLATE;
//マウス操作
int xStart, yStart;
bool flagMouse = false;
float Line_Size = 0.1f;
//緑
GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
//黒
GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
void setLight(){
float lightAmbient0[] = {0.5, 0.5, 0.5, 1.0}; //環境光
float lightDiffuse0[] = {1.0, 1.0, 1.0, 1.0}; //拡散光
float lightSpecular0[] = {1.0, 1.0, 1.0, 1.0};//鏡面光
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
}
void resize(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(view.fovY, (double)w/(double)h, view.nearZ, view.farZ);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
width = w;
height = h;
}
void setCamera(){
double pp = PAI / 180.0;
view.pos[2] = view.cnt[2] + view.dist * cos(pp * view.theta) * cos(pp *
view.phi);//z
view.pos[0] = view.cnt[0] + view.dist * cos(pp * view.theta) * sin(pp *
view.phi);//x
view.pos[1] = view.cnt[1] + view.dist * sin(pp * view.theta);//y
resize(width, height);
}
void idle(void){
glutPostRedisplay();
}
void init(void){
glClearColor(1.0, 1.0, 1.0, 1.0);
setCamera();
setLight();
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
}
void display(void){
//カラーバッファ,デプスバッファのクリア
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
if(cos(PAI * view.theta /180.0) >= 0.0)//カメラ仰角90度でビューアップベクトル切替
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, 1.0, 0.0);
else
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, -1.0, 0.0);
//光源設定//'l'を押した後光源位置可変
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_TEXTURE_2D);
glCullFace(GL_BACK);
//マテリアルの設定
glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
glutSolidTorus(1.0,1.5,16,16);
glDisable(GL_TEXTURE_2D);
glCullFace(GL_FRONT);
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
glutSolidTorus(1.0+Line_Size,1.5,16,16);
//終了
glutSwapBuffers();
}
//以下の3個の関数はマウス操作による視点の変更に必要
void mouse(int button, int state, int x, int y){
double pp = PAI / 180.0;
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
xStart = x; yStart = y;
flagMouse = true;
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4)//dolly
{
}
}else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4)//dolly
{
}else if(( x < width/4 || x > 3*width/4) && (y >
height/4 && y < 3*height/4)){
if(x < width/4 ) view.phi -= 1.0;
else view.phi += 1.0;
view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.phi) * cos(pp *
view.theta);
view.cnt[0] = view.pos[0] - view.dist * sin(pp * view.phi) * cos(pp *
view.theta);
}else if((x > width/4 && x < 3*width/4) && (y <
height/4 || y > 3*height/4)){
if( y < height/4)
view.theta += 1.0;
else
view.theta -= 1.0;
view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.theta) *
cos(pp * view.phi);
view.cnt[0] = view.pos[0] - view.dist * cos(pp * view.theta) * sin(pp
* view.phi);
view.cnt[1] = view.pos[1] - view.dist * sin(pp * view.theta);
}
else if(x < width/8 && y > 7*height/8) view.fovY -=
1.0;//zoom in
else if(x > 7*width/8 && y > 7*height/8) view.fovY +=
1.0;//zoom out
}
else flagMouse = false;
if(state == GLUT_DOWN) setCamera();
}
void motion(int x, int y){
if(!flagMouse) return;
if(cos(PAI * view.theta /180.0) >= 0.0)
view.phi -= 0.5 * (float)(x - xStart) ;//tumble
else
view.phi += 0.5 * (float)(x - xStart) ;//tumble
view.theta += 0.5 * (float)(y - yStart) ;//crane
setCamera();
xStart = x;
yStart = y;
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(width, height);
glutInitWindowPosition(100, 100);
glutCreateWindow("簡易輪郭線描画");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(idle);
init();
glutMainLoop();
}
|