天天看點

MFC openGL立方體

MFC OpenGl 立方體

// myGl.cpp : 此檔案包含 "main" 函數。程式執行将在此處開始并結束。
//

#include "pch.h"

#include <Windows.h>
#include "freeglut.h"
#include "freeglut_ext.h"
//#include "freeglut_internal.h"
#include "freeglut_std.h"
//#include "freeglut_teapot_data.h"
#include "glut.h"

#include <stdlib.h>
#include <stdio.h>
#include<iostream>
#include<conio.h>
#include <stdarg.h>
#include <math.h>

const int win_w = 700, win_h = 700;
GLfloat default_matrix[16];
GLfloat modelview_matrix[16];
GLfloat modelview_z_dis;
GLfloat x_min = .0, x_max = 20.0, y_min = .0, y_max = 20.0, z_min = .0, z_max = 20.0;

static GLuint texName;

void xyz_line(float len)
{
	GLfloat color[] = { .0, .0, .0, 1.0 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);

	glBegin(GL_LINES);
	color[0] = 1.0; color[1] = .0; color[2] = .0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glVertex3f(.0, .0, .0);
	glVertex3f(len, .0, .0);
	color[0] = .0; color[1] = 1.0; color[2] = .0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glVertex3f(.0, .0, .0);
	glVertex3f(.0, len, .0);
	color[0] = .0; color[1] = .0; color[2] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glVertex3f(.0, .0, .0);
	glVertex3f(.0, .0, len);
	glEnd();
}

void draw()
{
	// 繪制一個灰色的球
	GLfloat color[] = { .4f, .4f, .4f, 1.0f };

	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(7.5, 7.5, 25.0);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();



	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(7.5, 7.5, -10.0);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();



	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(7.5, 25.0, 7.5);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();



	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(7.5, -10.0, 7.5);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();



	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(25.0, 7.5, 7.5);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();



	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(-10.0, 7.5, 7.5);
	glutSolidSphere(5.0, 30, 50);
	glPopMatrix();




	// 繪制一面鏡子
	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(15.0, 0.0, .0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(.0, 15.0, .0);
	glVertex3f(.0, 15.0, 15.0);
	glVertex3f(.0, .0, 15.0);
	glEnd();
	glPopMatrix();

	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(.0, 0.0, .0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(.0, 15.0, .0);
	glVertex3f(.0, 15.0, 15.0);
	glVertex3f(.0, .0, 15.0);
	glEnd();
	glPopMatrix();

	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(.0, 15.0, .0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(15.0, .0, .0);
	glVertex3f(15.0, .0, 15.0);
	glVertex3f(.0, .0, 15.0);
	glEnd();
	glPopMatrix();

	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(.0, .0, .0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(15.0, .0, .0);
	glVertex3f(15.0, .0, 15.0);
	glVertex3f(.0, .0, 15.0);
	glEnd();
	glPopMatrix();

	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(.0, .0, 15.0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(15.0, .0, .0);
	glVertex3f(15.0, 15.0, .0);
	glVertex3f(.0, 15.0, .0);
	glEnd();
	glPopMatrix();

	color[0] = 1.0; color[1] = 0.0; color[2] = 1.0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
	color[0] = .0f; color[1] = .0f; color[2] = .1f; color[3] = 1.0f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(.0, .0, 0.0);
	glBegin(GL_POLYGON);
	glNormal3f(.0, -1.0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(15.0, .0, .0);
	glVertex3f(15.0, 15.0, .0);
	glVertex3f(.0, 15.0, .0);
	glEnd();
	glPopMatrix();

	// 繪制兩個三角形
	/*color[0] = .0; color[1] = .0; color[2] = .0; color[3] = 1.0;
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);

	glBegin(GL_TRIANGLES);
	color[0] = .0f; color[1] = .8f; color[2] = .8f;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glNormal3f(1.0, .0, .0);
	glVertex3f(.0, .0, .0);
	glVertex3f(.0, 15.0, .0);
	glVertex3f(.0, .0, 30.0);
	glEnd();*/

	// 透明物體放到所有不透明物體後繪制(否則不會混合),并置深度緩沖為隻讀(否則會遮擋之後物體)
	glDepthMask(GL_FALSE);
	glBegin(GL_TRIANGLES);
	color[0] = 1.0; color[1] = 1.0; color[2] = .0; color[3] = 0.5;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
	glNormal3f(.0, .0, 1.0);
	glVertex3f(.0, .0, .0);
	glVertex3f(10.0, .0, .0);
	glVertex3f(.0, 20.0, .0);
	glEnd();
	glDepthMask(GL_TRUE);
}

/* 顯示
 */
void display_func()
{
	static int z = 0;
	std::cout << "display: " << z++ << std::endl;

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf(modelview_matrix);

	draw();
	xyz_line(40.0);

	glutSwapBuffers();
}

/* OpenGL 初始化
 */
void init()
{
	// projection matrix init
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(20.0, 1.0, 10.0, 300.0);
	// default_matrix, modelview_matrix, modelview_z_dis init
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(100.0 + (x_min + x_max)*.5, 100.0 + (y_min + y_max)*.5, 100.0 + (z_min + z_max)*.5,
		(x_min + x_max)*.5, (y_min + y_max)*.5, (z_min + z_max)*.5, .0, .0, 1.0);
	modelview_z_dis = 100.0f * sqrt(3.0f);
	glGetFloatv(GL_MODELVIEW_MATRIX, default_matrix);
	memcpy(modelview_matrix, default_matrix, sizeof(default_matrix));
	glLoadIdentity();

	// color and lighting
	glClearColor(.2f, .2f, .2f, 1.0f);
	glColor4f(.5f, .5f, .5f, 1.0f);
	glShadeModel(GL_SMOOTH);

	GLfloat vec4f[] = { 1.0, 1.0, 1.0, 1.0 };
	glLightfv(GL_LIGHT0, GL_DIFFUSE, vec4f);  // 光源散射顔色,純白
	glLightfv(GL_LIGHT0, GL_SPECULAR, vec4f); // 光源鏡面顔色,純白
	vec4f[0] = .1f; vec4f[1] = .1f; vec4f[2] = .1f;
	glLightfv(GL_LIGHT0, GL_AMBIENT, vec4f);  // 光源環境強度,灰色(0.1 強度白色)
	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); // 有限遠觀察點
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);     // 雙面光照
	vec4f[0] = .0; vec4f[1] = .0; vec4f[2] = .0;
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec4f);	// 全局環境光,黑色(無光)

	vec4f[0] = .0; vec4f[1] = modelview_z_dis; vec4f[2] = .0; vec4f[3] = 1.0;
	glLightfv(GL_LIGHT0, GL_POSITION, vec4f); // 位置式光源,位置在物體斜上方
	vec4f[0] = .0; vec4f[1] = .0; vec4f[2] = -1.0;
	glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, vec4f); // 光源發光方向

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
	glDepthMask(GL_TRUE);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_NORMALIZE); // 使能自動規範化法線向量,保證光照計算的正确性
}

void reshape_func(int w, int h);
void display_func();
void mouse_click_func(int button, int state, int x, int y);
void mouse_move_func(int x, int y);
void keyboard_func(unsigned char key, int x, int y);
void specialkey_func(int key, int x, int y);

/**************************************************************************
 *函數入口,主函數
 */
int main(int argc, char** argv)
{
	// glut init
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE | GLUT_DEPTH);
	glutInitWindowSize(win_w, win_h);
	glutInitWindowPosition(300, 0);
	glutCreateWindow("glut test");
	// The callbacks.
	glutReshapeFunc(reshape_func);
	glutDisplayFunc(display_func);
	glutMouseFunc(mouse_click_func);
	glutMotionFunc(mouse_move_func);
	glutKeyboardFunc(keyboard_func);
	glutSpecialFunc(specialkey_func);

	init();
	glutMainLoop();
	return 0;
}

// 視窗大小改變的響應函數
void reshape_func(int w, int h)
{
	// 視窗大小變化時物體并不縮放,以防止比例失調
	glViewport(0, h - win_w, win_w, win_h);
}

/* 以下三個函數對物體進行平移、旋轉、縮放,他們均在視覺(絕對)坐标下進行
 * 正常調用 glTranslate,glRotate,glScale 均是在局部坐标下進行(按正序看)
 * 為了達到在視覺坐标下操作的效果,需要将矩陣左乘到目前矩陣
 */
void absolute_translate(GLfloat x, GLfloat y, GLfloat z)
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glTranslatef(x, y, z);
	glMultMatrixf(modelview_matrix); // 使變換矩陣左乘到目前矩陣,這樣才适合絕對坐标的考慮
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
	glPopMatrix();
}
void absolute_rotate(GLfloat dgree, GLfloat vecx, GLfloat vecy, GLfloat vecz)
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glTranslatef(.0, .0, -modelview_z_dis);		// 平移回去,注意該句和後兩句要倒序來看
	glRotatef(dgree, vecx, vecy, vecz);// 積累旋轉量
	glTranslatef(.0, .0, modelview_z_dis);		// 先平移到原點
	glMultMatrixf(modelview_matrix); // 使變換矩陣左乘到目前矩陣,這樣才适合絕對坐标的考慮
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
	glPopMatrix();
}
void absolute_scale(GLfloat factor)
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glTranslatef(.0, .0, -modelview_z_dis);		// 平移回去,注意該句和後兩句要倒序來看
	glScalef(factor, factor, factor);
	glTranslatef(.0, .0, modelview_z_dis);		// 先平移到原點
	glMultMatrixf(modelview_matrix); // 使變換矩陣左乘到目前矩陣,這樣才适合絕對坐标的考慮
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
	glPopMatrix();
}
void absolute_default()
{
	memcpy(modelview_matrix, default_matrix, sizeof(default_matrix));
}

// 滑鼠狀态變量,用來在滑鼠點選事件和拖動事件之間通信
static bool l_button_down = false, r_button_down = false, mid_button_down = false;
static int last_x = -1, last_y = -1;
#define  GLUT_WHEEL_UP		3 // 滾輪操作  
#define  GLUT_WHEEL_DOWN	4
/* 滑鼠點選和移動,左鍵拖動旋轉,中鍵拖動平移,右鍵回到最初視圖
 */
void mouse_click_func(int button, int state, int x, int y)
{
	y = win_h - y;
	switch (button) {
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN) {
			l_button_down = true;
			last_x = x; last_y = y;
			glutSetCursor(GLUT_CURSOR_CROSSHAIR);
		}
		else {
			l_button_down = false;
			last_x = -1; last_y = -1;
			glutSetCursor(GLUT_CURSOR_INHERIT);
		}
		break;
	case GLUT_MIDDLE_BUTTON:
		if (state == GLUT_DOWN) {
			mid_button_down = true;
			last_x = x; last_y = y;
			glutSetCursor(GLUT_CURSOR_CYCLE);

		}
		else {
			mid_button_down = false;
			last_x = -1; last_y = -1;
			glutSetCursor(GLUT_CURSOR_INHERIT);
		}
		break;
	case GLUT_RIGHT_BUTTON:
		if (state == GLUT_DOWN) {
			r_button_down = true;
			absolute_default();
			glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
			glutPostRedisplay();
		}
		else {
			r_button_down = false;
			glutSetCursor(GLUT_CURSOR_INHERIT);
		}
		break;
	case GLUT_WHEEL_UP:
		if (state == GLUT_UP) {
			absolute_scale(.9f);
			glutPostRedisplay();
		}
		break;
	case GLUT_WHEEL_DOWN:
		if (state == GLUT_UP) {
			absolute_scale(1.1f);
			glutPostRedisplay();
		}
		break;
	}
}
void mouse_move_func(int x, int y)
{
	y = win_h - y;
	if (last_x >= 0 && last_y >= 0 && (last_x != x || last_y != y)) {
		GLfloat deltax = GLfloat(x - last_x), deltay = GLfloat(y - last_y);
		if (mid_button_down) {
			absolute_translate(deltax * .1f, deltay * .1f, .0f);
			glutPostRedisplay();
		}
		else if (l_button_down) {
			GLfloat dis = sqrt(deltax*deltax + deltay * deltay);
			absolute_rotate(dis, -deltay / dis, deltax / dis, .0);
			glutPostRedisplay();
		}
	}
	last_x = x; last_y = y;
}

/* 鍵盤按鍵
 */
void keyboard_func(unsigned char key, int x, int y)
{
	;
}

/* 鍵盤特殊鍵,上下鍵進行上下旋轉,左右鍵進行左右旋轉
 */
void specialkey_func(int key, int x, int y)
{
	GLfloat deltax = .0, deltay = .0;
	switch (key) {
	case GLUT_KEY_UP:
		deltay += 1.0;
		break;
	case GLUT_KEY_DOWN:
		deltay -= 1.0;
		break;
	case GLUT_KEY_LEFT:
		deltax -= 1.0;
		break;
	case GLUT_KEY_RIGHT:
		deltax += 1.0;
		break;
	}
	if (abs(deltax) > .0 || abs(deltay) > .0) {
		GLfloat dis = sqrt(deltax*deltax + deltay * deltay);
		absolute_rotate(dis, -deltay / dis, deltax / dis, .0);
		glutPostRedisplay();
	}
}