#define GLUT_DISABLE_ATEXIT_HACK
#include "windows.h"
#include <stdio.h>
#include <gl/glut.h>
#include "math.h"
/** 控制点数组 */
GLfloat points[4][3] = {
{ -4.0f, -2.0f, 0.0f }, { -2.0f, 3.0f, 2.0f},
{ 2.0f, -3.0f, -2.0f }, { 4.0f, 2.0f, 0.0f} };
GLfloat rot=0; /**< 用于旋转物体 */
GLboolean light=false; /**< 用于开启/关闭光源 */
GLboolean lp = false; /**< 判断L键是否释放 */
GLboolean sp = false; /**< 判断空格键是否释放 */
/** 绘制模式 */
GLint renderMode[] = { GL_FILL,GL_LINE };
GLuint mode = 0; /**< 绘制模式索引 */
/** 用于输出信息 */
const char* RenderMode[] =
{
"GL_FILL",
"GL_LINE",
};
/** 定义光源的属性值 */
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; /**< 环境光参数 */
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 漫射光参数 */
GLfloat LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 镜面光参数 */
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f }; /**< 光源位置 */
/** 定义材质属性值 */
GLfloat mat_diffuse[] = { 0.4, 0.5, 0.6, 1.0 }; /**< 漫射光参数 */
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; /**< 镜面光参数 */
GLfloat mat_shinness[] = { 50.0 }; /**< 镜面反射指数 */
/** 定义曲面的控制点 */
GLfloat ctrlpoints[4][4][3] = {
{{ -0.8f, -0.6f, 0.8f },{ -0.2f, -0.6f, 1.6f },{ 0.2f, -0.6f, -0.4f },{ 0.6f, -0.6f, 0.8f }},
{{ -0.6f, -0.2f, 0.8f },{ -0.2f, -0.2f, 1.6f },{ 0.2f, -0.2f, -0.4f },{ 0.6f, -0.2f, 0.8f }},
{{ -0.6f, 0.2f, 0.8f },{ -0.2f, -0.2f, 0.4f },{ 0.2f, 0.2f, 0.0f },{ 0.3f, 0.2f, -0.4f }},
{{ -0.6f, 0.6f, 0.8f },{ -0.2f, 0.6f, 0.4f },{ -0.8f, 0.6f, 0.0f },{ 0.8f, 0.6f, -0.4f }}
};
GLfloat texpts[2][2][2] = { {{0.0, 0.0}, {0.0, 1.0}}, {{1.0, 0.0}, {1.0, 1.0}} };
BYTE* gltReadBMPBits(const char* szFileName, int* nWidth, int* nHeight)
{
HANDLE hFileHandle;
BITMAPINFO* pBitmapInfo = NULL;
unsigned long lInfoSize = 0;
unsigned long lBitSize = 0;
BYTE* pBits = NULL; // Bitmaps bits
BITMAPFILEHEADER bitmapHeader;
DWORD dwBytes;
// Open the Bitmap file
hFileHandle = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
// Check for open failure (most likely file does not exist).
if (hFileHandle == INVALID_HANDLE_VALUE)
return NULL;
// File is Open. Read in bitmap header information
ReadFile(hFileHandle, &bitmapHeader, sizeof(BITMAPFILEHEADER),
&dwBytes, NULL);
// Check for a couple of simple errors
if (dwBytes != sizeof(BITMAPFILEHEADER))
return FALSE;
// Check format of bitmap file
if (bitmapHeader.bfType != 'MB')
return FALSE;
// Read in bitmap information structure
lInfoSize = bitmapHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
pBitmapInfo = (BITMAPINFO*)malloc(sizeof(BYTE) * lInfoSize);
ReadFile(hFileHandle, pBitmapInfo, lInfoSize, &dwBytes, NULL);
if (dwBytes != lInfoSize)
{
free(pBitmapInfo);
CloseHandle(hFileHandle);
return FALSE;
}
// Save the size and dimensions of the bitmap
*nWidth = pBitmapInfo->bmiHeader.biWidth;
*nHeight = pBitmapInfo->bmiHeader.biHeight;
lBitSize = pBitmapInfo->bmiHeader.biSizeImage;
// If the size isn't specified, calculate it anyway
if (pBitmapInfo->bmiHeader.biBitCount != 24)
{
free(pBitmapInfo);
return FALSE;
}
if (lBitSize == 0)
lBitSize = (*nWidth *
pBitmapInfo->bmiHeader.biBitCount + 7) / 8 *
abs(*nHeight);
// Allocate space for the actual bitmap
free(pBitmapInfo);
pBits = (BYTE*)malloc(sizeof(BYTE) * lBitSize);
// Read in the bitmap bits, check for corruption
if (!ReadFile(hFileHandle, pBits, lBitSize, &dwBytes, NULL) ||
dwBytes != (sizeof(BYTE) * lBitSize))
pBits = NULL;
// Close the bitmap file now that we have all the data we need
CloseHandle(hFileHandle);
return pBits;
}
void LoadTexture()
{
// 获取位图数据
BYTE* pBytes;
int nWidth, nHeight;
pBytes = gltReadBMPBits("D:\\image0.BMP", &nWidth, &nHeight);
定义二维纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pBytes);
//控制滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//说明映射方式
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
}
//初始化OpenGL
void init(void)
{
/** 用户自定义的初始化过程 */
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D); /**< 启用纹理映射 */
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
/**启用并定义一维求值程序 */
glEnable(GL_MAP1_VERTEX_3);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &points[0][0]);
/** 启用纹理映射 */
LoadTexture();
glEnable(GL_TEXTURE_2D);
/** 设置光源的属性值 */
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); /**< 设置环境光 */
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); /**< 设置漫射光 */
glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular); /**< 设置漫射光 */
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); /**< 设置光源位置 */
/** 设置材质属性值 */
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shinness);
/** 启用光源 */
glEnable(GL_LIGHT1);
/*启用求值程序*/
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_2);
glEnable(GL_AUTO_NORMAL);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, &texpts[0][0][0]);
glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
}
//主要的绘制过程
void display(void)
{
/** 用户自定义的绘制过程 */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /**< 清除缓存 */
glLoadIdentity();
glShadeModel(GL_FLAT);
glLoadIdentity();
glTranslatef(0, 0, -13.0);
//求值
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 100; i++)
{
/** 执行求值程序 */
glEvalCoord1f((float)i / 100.0f);
}
glEnd();
// glMapGrid1f(100, 0.0, 1.0);
// glEvalMesh1(GL_LINE, 0, 100);
//绘制控制点
glPointSize(4.0);
glBegin(GL_POINTS);
for (int j = 0; j < 4; j++)
glVertex3fv(&points[j][0]);
glEnd();
glFlush(); /**< 强制执行所有的OpenGL命令 */
glutSwapBuffers();
/** 绘制过程 */
glTranslatef(0.0f, 0.0f, -13.0f);
glRotatef(rot, 1.0, 1.0, 1.0);
glScalef(3.0f, 3.0f, 3.0f);
glEvalMesh2(renderMode[mode], 0, 20, 0, 20);
glFlush();
/**< 强制执行所有的OpenGL命令 */
}
//在窗口改变大小时调用
void reshape(int w, int h) {
glViewport(0, 0, w, h);//设置视口
glMatrixMode(GL_PROJECTION);//设置当前为投影变换模式
glLoadIdentity();//用单位矩阵替换当前变换矩阵
gluPerspective(45, (float)w / h, 4, 100.0);//设置正交投影视图体
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void TimerFunction(int value)
{
rot += 10;
if (rot == 360)
rot = 0;
// Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(500, TimerFunction, 1);
}
//处理键盘
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27://esc键退出
exit(0);
break;
case 'a':
case 'A':
lp = TRUE; /**< lp 设为 TRUE */
light = !light; /**< 切换光源的 TRUE/FALSE */
if (!light) /**< 如果没有光源 */
{
glDisable(GL_LIGHTING); /**< 禁用光源 */
}
else
{
glEnable(GL_LIGHTING); /**< 启用光源 */
}
break;
case 'd':
case 'D':
sp = TRUE; /**< lp 设为 TRUE */
mode += 1;
if (mode > 1)
mode = 0;
break;
default:
break;
}
}
int main(int argc, char* argv[]) //主函数: 参数数量&参数值
{
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutCreateWindow("Basic");//设置窗口标题
init();//初始化OpenGL
glutDisplayFunc(display);//设置显示回调函数
glutReshapeFunc(reshape);//设置reshape回调函数
glutKeyboardFunc(keyboard);//设置键盘回调函数
glutTimerFunc(500, TimerFunction, 1);
glutMainLoop();//进入主循环
}