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();
}
}