为OpenGL考试而准备的代码——鼠标控制视角变换+简单纹理映射+键盘的光照控制+Bezier曲线

使用背景:

使用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;
}
运行结果如下:
为OpenGL考试而准备的代码——鼠标控制视角变换+简单纹理映射+键盘的光照控制+Bezier曲线_第1张图片

你可能感兴趣的:(OpenGL)