使用背景:
使用codeblocks13.12编译,调用了imageloader.cpp和imageloader.h
代码如下:
#include
#include
#include
#include
#ifdef __APPLE__
#include
#include
#else
#include
#endif
#include "imageloader.h"
#define G_PI 3.14159265358979323846f
using namespace std;
const float BOX_SIZE = 7.0f; //立方体长度
static double _angle = 0; //立方体自动旋转角度
static double SX=1,SY=1,SZ=1,theta=0,phi=0;
static int du=90,oldmy=-1,oldmx=-1; //du是视点绕y轴的角度,opengl里默认y轴是上方向
static double r=1.5f,h=0.0f; //r是视点绕y轴的半径,h是视点高度即在y轴上的坐标
static double c=G_PI/180.0f; //弧度和角度转换参数
static double ctrlPoints[4][3];
GLuint _textureId; //纹理的OpenGL的ID
GLuint _textureId1; //纹理的OpenGL的ID
GLuint _textureId2; //纹理的OpenGL的ID
//光照控制
void prepare_lighting()
{
theta = fmodf( theta, 2*G_PI );
phi = fmodf( phi, 2*G_PI );
int dis=1;
float light_diffuse[4] = {1.0, 1.0, 1.0, 1.0};
float mat_diffuse[4] = {1.0, 1.0, 1.0, 1.0};
float light_position[4] = { dis*sinf(theta) * cosf(phi), dis*cosf(theta), dis*(-sinf(theta) * sinf(phi)), 0 };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable( GL_LIGHT0 );
}
//键盘操作
void keyboard(unsigned char key, int x, int y)
{
switch( key )
{
case 'w':
theta -= .05;
prepare_lighting();
glutPostRedisplay();
break;
case 's':
theta += .05;
prepare_lighting();
glutPostRedisplay();
break;
case 'a':
phi -= .05;
prepare_lighting();
glutPostRedisplay();
break;
case 'd':
phi += .05;
prepare_lighting();
glutPostRedisplay();
break;
case '+':
SX+=0.1;
SY+=0.1;
SZ+=0.1;
prepare_lighting();
glutPostRedisplay();
break;
case '-':
SX-=0.1;
SY-=0.1;
SZ-=0.1;
// prepare_lighting();
glutPostRedisplay();
break;
case 27:
exit(0);
};
}
//鼠标点击
void Mouse(int button, int state, int x, int y)
{
if(state==GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标
oldmx=x,oldmy=y;
}
void onMouseMove(int x,int y) //鼠标拖动
{
du+=x-oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了
h +=0.03f*(y-oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了
if(h>1.0f) h=1.0f; //视点y坐标作一些限制,不会使视点太奇怪
else if(h<-1.0f) h=-1.0f;
oldmx=x,oldmy=y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备
prepare_lighting();
glutPostRedisplay();
}
//使图像转换成纹理,并返回纹理的ID
GLuint loadTexture(Image* image)
{
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
image->width, image->height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
image->pixels);
return textureId;
}
//纹理映射控制
void initRendering()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
Image* image = loadBMP("C:\\Program Files (x86)\\CodeBlocks\\MinGW\\Example\\cube(wen li ying she)\\111.bmp");
_textureId = loadTexture(image);
Image* image1 = loadBMP("C:\\Program Files (x86)\\CodeBlocks\\MinGW\\Example\\cube(wen li ying she)\\222.bmp");
_textureId1 = loadTexture(image1);
Image* image2 = loadBMP("C:\\Program Files (x86)\\CodeBlocks\\MinGW\\Example\\cube(wen li ying she)\\333.bmp");
_textureId2 = loadTexture(image2);
delete image,image1,image2;
}
//Bezier曲线
void BezierCurve(int n)
{
ctrlPoints[0][0]=5.0;//初始点
ctrlPoints[0][1]=5.0;
ctrlPoints[0][2]=5.0;
ctrlPoints[1][0]=15.5;
ctrlPoints[1][1]=15.1;
ctrlPoints[1][2]=15.2;
ctrlPoints[2][0]=15.0;
ctrlPoints[2][1]=-15.2;
ctrlPoints[2][2]=-15.2;
ctrlPoints[3][0]=5.5;//结束点
ctrlPoints[3][1]=-5.3;
ctrlPoints[3][2]=-5.3;
double t, dt, t2, t3,t4, f1, f2, f3, f4;
dt = 1.0/n; // t从0到1
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINE_STRIP);
for (t = 0.0; t <= 1.0; t += dt) { //三次Bezier曲线
t2 = t * t;
t3 = t2 * t; // t3 = t * t * t
t4 = (1-t);
f1 = t4*t4*t4;
f2 = 3*t*t4*t4;
f3 = 3*t2*t4;
f4 = t3;
glNormal3f( f1*ctrlPoints[0][0] + f2*ctrlPoints[1][0] + f3*ctrlPoints[2][0] + f4*ctrlPoints[3][0],
f1*ctrlPoints[0][1] + f2*ctrlPoints[1][1] + f3*ctrlPoints[2][1] + f4*ctrlPoints[3][1],
f1*ctrlPoints[0][2] + f2*ctrlPoints[1][2] + f3*ctrlPoints[2][2] + f4*ctrlPoints[3][2] );
glVertex3f( f1*ctrlPoints[0][0] + f2*ctrlPoints[1][0] + f3*ctrlPoints[2][0] + f4*ctrlPoints[3][0],
f1*ctrlPoints[0][1] + f2*ctrlPoints[1][1] + f3*ctrlPoints[2][1] + f4*ctrlPoints[3][1],
f1*ctrlPoints[0][2] + f2*ctrlPoints[1][2] + f3*ctrlPoints[2][2] + f4*ctrlPoints[3][2] );
}
glEnd();
}
void init()
{
initRendering();//调用纹理映射
prepare_lighting();//先改光照,再改观察点
glTranslatef(0.0f, 0.0f, -20.0f);//平移函数,要在gluLookAt之前,否则将出现观察点固定,拖动鼠标只能环视的情况
gluLookAt(r*cos(c*du), h, r*sin(c*du), 0, 0, 0, 0, 1, 0);//设置观察点
BezierCurve(10);//Bezier曲线
glRotatef(-_angle, 1.0f, 1.0f, 0.0f);//自动旋转
glBegin(GL_QUADS);
//Top face
glColor3f(1.0f, 1.0f, 0.0f);
glNormal3f(0.0, 1.0f, 0.0f);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
//Bottom face
glColor3f(1.0f, 0.0f, 1.0f);
glNormal3f(0.0, -1.0f, 0.0f);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
//Left face
glNormal3f(-1.0, 0.0f, 0.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
//Right face
glNormal3f(1.0, 0.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
glEnd();
//Front face
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, BOX_SIZE / 2);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, BOX_SIZE / 2);
glEnd();
glDisable(GL_TEXTURE_2D);
//Back face
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(BOX_SIZE / 2, BOX_SIZE / 2, -BOX_SIZE / 2);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(BOX_SIZE / 2, -BOX_SIZE / 2, -BOX_SIZE / 2);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕
glMatrixMode(GL_PROJECTION);//设置观察点
glLoadIdentity();
gluPerspective(75.0f, 1, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);//设置观察点
glLoadIdentity();
// glutSolidTeapot( .1 );
init();
glutSwapBuffers();
}
//旋转速度 每30ms刷新一次
void update(int value)
{
_angle += 1.0f;
if (_angle > 360)
{
_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(30, update, 0);
}
int main(int argc, char** argv)
{
cout<<"wasd控制光照,鼠标拖动控制视点旋转";
theta = G_PI/2;
phi = -G_PI/2;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("鼠标控制视角变换+简单纹理映射+键盘的光照控制");
glutDisplayFunc(drawScene);
glutKeyboardFunc( keyboard );
glutMouseFunc(Mouse);
glutMotionFunc(onMouseMove);
glutTimerFunc(30, update, 0);
glutMainLoop();
return 0;
}
运行结果如下: