#include
#include
#include
#include
#include
#include
#include "FreeImage.h"
#define Height 16
#define Width 16
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_pos[] = { 5,5,5,1 };
float eye[] = { -3,3, 7 };
float center[] = { 0, 0, 0 };
float place[] = { 0, 0, 5.6 };
#define ERROR(...) printf(__VA_ARGS__);exit(0)
float fRotate = 0.0f;
float fScale = 1.0f; //
float tRotate = 0.0f;
bool bPersp = false;
bool bAnim = false;
bool isRotate = false;
int wHeight = 0;
int wWidth = 0;
//int min(int x, int y)
//{
// return x < y ? x : y;
//}
typedef struct
{
int w;
int h;
unsigned char *buf;
GLuint rgb_mode;
}GLBITMAP;
static GLuint S_png_tex = 0;
static GLuint S_jpg_tex = 0;
static GLuint S_bmp_tex = 0;
static GLuint S_tga_tex = 0;
static GLuint S_ico_tex = 0;
GLBITMAP * FIBitmap2GLBitmap(FIBITMAP *fibmp)
{
int i, j, k;
int pitch = FreeImage_GetPitch(fibmp);
unsigned char *bits = FreeImage_GetBits(fibmp);
int bpp = FreeImage_GetBPP(fibmp);
GLBITMAP *glbmp = (GLBITMAP *)malloc(sizeof(GLBITMAP));
RGBQUAD *palette = NULL;
if (!glbmp) return NULL;
glbmp->w = FreeImage_GetWidth(fibmp);
glbmp->h = FreeImage_GetHeight(fibmp);
switch (bpp) {
case 8:
if (!(palette = FreeImage_GetPalette(fibmp))) return NULL;
if (!(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h * 3))) return NULL;
glbmp->rgb_mode = GL_RGB;
for (i = 0; i < glbmp->h; ++i) {
for (j = 0; j < glbmp->w; ++j) {
k = bits[i*pitch + j];
glbmp->buf[(i*glbmp->w + j) * 3 + 0] = palette[k].rgbRed;
glbmp->buf[(i*glbmp->w + j) * 3 + 1] = palette[k].rgbGreen;
glbmp->buf[(i*glbmp->w + j) * 3 + 2] = palette[k].rgbBlue;
}
}
break;
case 24:
if (!(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h * 3))) return NULL;
glbmp->rgb_mode = GL_RGB;
for (i = 0; i < glbmp->h; ++i) {
for (j = 0; j < glbmp->w; ++j) {
glbmp->buf[(i*glbmp->w + j) * 3 + 0] = bits[i*pitch + j * 3 + 2];
glbmp->buf[(i*glbmp->w + j) * 3 + 1] = bits[i*pitch + j * 3 + 1];
glbmp->buf[(i*glbmp->w + j) * 3 + 2] = bits[i*pitch + j * 3 + 0];
}
}
break;
case 32:
if (!(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h * 4))) return NULL;
glbmp->rgb_mode = GL_RGBA;
for (i = 0; i < glbmp->h; ++i) {
for (j = 0; j < glbmp->w; ++j) {
glbmp->buf[(i*glbmp->w + j) * 4 + 0] = bits[i*pitch + j * 4 + 2];
glbmp->buf[(i*glbmp->w + j) * 4 + 1] = bits[i*pitch + j * 4 + 1];
glbmp->buf[(i*glbmp->w + j) * 4 + 2] = bits[i*pitch + j * 4 + 0];
glbmp->buf[(i*glbmp->w + j) * 4 + 3] = bits[i*pitch + j * 4 + 3];
}
}
break;
default: return NULL;
}
return glbmp;
}
void FreeGLBitmap(GLBITMAP *glbmp)
{
if (glbmp) {
if (glbmp->buf) free(glbmp->buf);
free(glbmp);
}
}
GLuint loadtexture(const char *filename)
{
GLuint tex = 0;
int tmp_bit;
int i;
int w, h;
int bpp;
unsigned char *bits = NULL;
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
FIBITMAP *bitmap = NULL;
GLBITMAP *glbmp = NULL;
fif = FreeImage_GetFileType(filename, 0);
if (FIF_UNKNOWN == fif) {
fif = FreeImage_GetFIFFromFilename(filename);
if (FIF_UNKNOWN == fif)
return 0;
}
if (FreeImage_FIFSupportsReading(fif))
bitmap = FreeImage_Load(fif, filename, 0);
if (!bitmap)
return 0;
printf("bit: %d\n", FreeImage_GetBPP(bitmap));
glbmp = FIBitmap2GLBitmap(bitmap);
if (!glbmp)
return 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, glbmp->rgb_mode, glbmp->w, glbmp->h, 0, glbmp->rgb_mode, GL_UNSIGNED_BYTE, glbmp->buf);
FreeGLBitmap(glbmp);
FreeImage_Unload(bitmap);
return tex;
}
void drawCube()
{
glBindTexture(GL_TEXTURE_2D, S_bmp_tex); // 选择纹理
glBegin(GL_QUADS);
// 前面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glEnd();
// 后面
glBindTexture(GL_TEXTURE_2D, S_bmp_tex); // 选择纹理
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glEnd();
glBindTexture(GL_TEXTURE_2D, S_bmp_tex); // 选择纹理
glBegin(GL_QUADS);
// 顶面
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glEnd();
glBindTexture(GL_TEXTURE_2D, S_bmp_tex); // 选择纹理
glBegin(GL_QUADS);
// 底面
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
// 右面
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
// 左面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glEnd();
}
void drawCube2()
{
glBindTexture(GL_TEXTURE_2D, S_png_tex); // 选择纹理
glBegin(GL_QUADS);
// 前面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glEnd();
// 后面
glBindTexture(GL_TEXTURE_2D, S_png_tex); // 选择纹理
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glEnd();
glBindTexture(GL_TEXTURE_2D, S_png_tex); // 选择纹理
glBegin(GL_QUADS);
// 顶面
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glEnd();
glBindTexture(GL_TEXTURE_2D, S_png_tex); // 选择纹理
glBegin(GL_QUADS);
// 底面
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
// 右面
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
// 左面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glEnd();
}
void drawCube3()
{
glBindTexture(GL_TEXTURE_2D, S_jpg_tex); // 选择纹理
glBegin(GL_QUADS);
// 前面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glEnd();
// 后面
glBindTexture(GL_TEXTURE_2D, S_jpg_tex); // 选择纹理
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glEnd();
glBindTexture(GL_TEXTURE_2D, S_jpg_tex); // 选择纹理
glBegin(GL_QUADS);
// 顶面
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glEnd();
glBindTexture(GL_TEXTURE_2D, S_jpg_tex); // 选择纹理
glBegin(GL_QUADS);
// 底面
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
// 右面
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的左上
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下
// 左面
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的左下
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的右上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上
glEnd();
}
//绘制腿部
void Draw_Leg()
{
glScalef(0.8, 0.8, 3);
drawCube3();
}
void Draw_Scene(float place[])
{
//画茶壶
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glColor4f(0.51, 0.0, 0.1, 0.0);
glTranslatef(place[0], place[1], place[2]);
glRotatef(90, 1, 0, 0);
glRotatef(tRotate, 0, 1, 0);
glutSolidTeapot(1);
glPopMatrix();
//画桌面
glPushMatrix();
glColor4f(0.1, 1.0, 0.1, 0.0);
glTranslatef(0, 0, 3.8);
glScalef(5, 4, 1);
drawCube3();
glPopMatrix();
//画四条腿
glPushMatrix();
glColor4f(1.0, 0.5, 0.4, 0.0);
glTranslatef(3, 2.5, 1.5);
Draw_Leg();
glPopMatrix();
glPushMatrix();
glColor4f(1.0, 0.5, 0.4, 0.0);
glTranslatef(-3, 2.5, 1.5);
Draw_Leg();
glPopMatrix();
glPushMatrix();
glColor4f(1.0, 0.5, 0.4, 0.0);
glTranslatef(3, -2.5, 1.5);
Draw_Leg();
glPopMatrix();
glPushMatrix();
glColor4f(1.0, 0.5, 0.4, 0.0);
glTranslatef(-3, -2.5, 1.5);
Draw_Leg();
glPopMatrix();
//画墙
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(7, -1, 5);
glRotatef(90, 1, 90, 0);
glScalef(6, 7, 1);
drawCube2();
glPopMatrix();
//画墙
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(0, 6, 5);
glRotatef(90, 90, 0, 1);
glScalef(8.3, 6, 1);
drawCube2();
glPopMatrix();
//地板
glPushMatrix();
glTranslatef(-1, -1, -1);
glRotatef(0, 1, 90, 0);
glScalef(7,7, 0.2);
drawCube();
glPopMatrix();
}
#define LOADTEXTURE(t, f) do{ if(!((t) = loadtexture(f))){ ERROR("load texture(%s) failed!\n", f); } }while(0)
void updateView(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float whRatio = (GLfloat)width / (GLfloat)height;
if (bPersp) {
gluPerspective(45, whRatio, 1, 100);
//参数:
//GLdouble fovy 视角
//GLdouble aspect 宽高比
//GLdouble zNear 近处
//GLdouble zFar 远处
}
else
glOrtho(-3, 3, -3, 3, -100, 100); //正投影
//参数
//GLdouble left,
//GLdouble right,
//GLdouble bottom,
//GLdouble top,
//GLdouble near,
//GLdouble far
glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型
}
void reshape(int width, int height)
{
if (height == 0) //如果高度为0
{
height = 1; //让高度为1(避免出现分母为0的现象)
}
height = width = min(height, width);
wHeight = height;
wWidth = width;
updateView(wHeight, wWidth); //更新视角
}
void idle()
{
glutPostRedisplay();//调用当前绘制函数
}
//按键回调函数
void key(unsigned char k, int x, int y)
{
switch (k)
{
case 'q': {exit(0); break; } //退出
case 'p': {bPersp = !bPersp; updateView(wHeight, wWidth); break; } //切换正投影、透视投影
case ' ': {bAnim = !bAnim; break; } //旋转模式的切换
//整体操作
case 'a': { //向左移动
center[0] += 0.1f;
eye[0] += 0.1f;
break;
}
case 'd': { //向右移动
center[0] -= 0.1f;
eye[0] -= 0.1f;
break;
}
case 'w': { //向上移动
center[1] -= 0.1f;
eye[1] -= 0.1f;
break;
}
case 's': { //向下移动
center[1] += 0.1f;
eye[1] += 0.1f;
break;
}
case 'z': { //向前移动
center[2] -= 0.1f;
eye[2] -= 0.1f;
break;
}
case 'c': { //向后移动
center[2] += 0.1f;
eye[2] += 0.1f;
break;
}
//茶壶相关操作
case 'l': { //右移茶壶
place[0] += 0.1f;
if (place[0] > 1.5f)place[0] = 1.5f; //不超出桌面范围
break;
}
case 'j': { //左移茶壶
place[0] -= 0.1f;
if (place[0] < -1.5f)place[0] = -1.5f;
break;
}
case 'i': { //后移茶壶
place[1] += 0.1f;
if (place[1] > 1.5f)place[1] = 1.5f;
break;
}
case 'k': { //前移茶壶
place[1] -= 0.1f;
if (place[1] < -1.5f)place[1] = -1.5f;
break;
}
case 'e': { //旋转茶壶
isRotate = !isRotate;
break;
}
}
}
void redraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(eye[0], eye[1], eye[2],center[0], center[1], center[2],0, 1, 0);
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glEnable(GL_LIGHTING);
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_pos[] = { 1,1,1,0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, white);
glEnable(GL_LIGHT0);
// glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 1);
glRotatef(fRotate, 0, 1.0f, 0);
glRotatef(-90, 1, 0, 0);
glScalef(0.2, 0.2, 0.2);
Draw_Scene(place);
if (bAnim) fRotate += 0.5f;
if (isRotate) tRotate += 0.5f; //茶壶旋转
glutSwapBuffers();
#if defined(FREEIMAGE_LIB)
FreeImage_Initialise(0);
#endif
LOADTEXTURE(S_bmp_tex, "diban.png");
LOADTEXTURE(S_png_tex, "qiangbi.png");
LOADTEXTURE(S_jpg_tex, "qwe.png");
LOADTEXTURE(S_tga_tex, "chahu.jpg");
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);//对glut的初始化
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(480, 480);//设置窗口大小
int windowHandle = glutCreateWindow("午夜茶室");//设置窗口标题
glutDisplayFunc(redraw);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glutMainLoop();// glut事件处理循环
return 0;
}