3D_solarSys

计算机图形学_3DsolarSys

一、软件功能

       1、实现3D太阳系,有太阳、土星、土星环、地球、月球、天王星、海王星、火星。其中土星、地球、天王星、海王星、火星绕着太阳转,土星环绕着土星转,月球绕着地球转。

       2可以鼠标左、中、右任意键拖动太阳系观察。

       3连续点击鼠标中键,太阳系整体绕z轴开始旋转并且速度加一;点击鼠标右键,连续点击中键,太阳系整体绕z轴开始旋转并且速度加一;点击鼠标左键,太阳系会立马停止转动。

       4、按下键盘,O:取消轨道,P:显示轨道,U:视角上升,I:视角下降,Y:显示数轴,N:取消数轴,C:显示字符,V:取消字符,WSAD:控制相机移动。

       5实现了太阳光照效果。

       6、实现了星光。

二、实现

       myDisplay()显示函数,myIdle()设置全局回调函数,mouse()设置鼠标点击事件监听,motion()设置鼠标滑动事件监听,keyboard()设置键盘事件监听,selectFont()设置字体,drawCNString()生成中文字体。

       实现星系

              glEnable(GL_DEPTH_TEST);开启更新深度缓冲区。利用glutWireSphere()绘制线形球体或者利用glutSolidSphere()绘制实体球体。在绘制行星时需要进行坐标原点的迁移glTranslatef(),每次绘制的行星都是在上一个矩阵的基础上进行的偏移,所以在绘制行星前需要glPushMatrix()将太阳坐标矩阵压栈,在将要绘制行星时先将太阳坐标矩阵弹栈glPopMatrix(),而在绘制月球或者土星环时则无需弹栈。

       实现鼠标拖动

              void motion(int x, int y)传入鼠标参数值,anglex += 360 * (GLfloat)deltay / (GLfloat)WinW根据屏幕上鼠标滑动的距离来设置旋转的角度。

       实现鼠标控制旋转

              void mouse(int button, int state, int x, int y)传入鼠标参数值,if (button == GLUT_RIGHT_BUTTON&&state == GLUT_DOWN)判断哪一个键和状态,{isy = 0.0; isz = 1.0;}决定太阳是绕着哪个轴旋转或者rote = 0使其停止旋转。

       实现键盘控制

              void keyboard(unsigned char key, int x, int y)传入键盘参数,利用switch语句判断key类型,显示和取消类型的控制利用设置控制条件将其实现代码写入if语句中,视角的变换是控制glLookAt的eyez值实现的,控制相机移动是控制eyex和eyey值实现的。

       实现太阳光照

              glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);

              glLightfv(GL_LIGHT0, GL_AMBIENT,   sun_light_ambient);

              glLightfv(GL_LIGHT0, GL_DIFFUSE,   sun_light_diffuse);

              glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);

              定义光源位置、环境光、漫反射光、镜面光,{ glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); }开启光源。

              GLfloat earth_mat_ambient[]   = {1.0f, 0.5f, 0.31f, 1.0f};  //定义材质的环境光颜色,偏蓝色

              GLfloat earth_mat_diffuse[]   = {1.0f, 0.4f, 0.2f, 1.0f};  //定义材质的漫反射光颜色,偏蓝色

              GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,红色

              GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色,为0

              GLfloat earth_mat_shininess   = 30.0f;     //定义太阳光强

              定义星球的表面光照情况。

       实现星光

              glColor3f((rand()/(GLfloat)RAND_MAX),(rand()/(GLfloat)RAND_MAX),(rand()/(GLfloat)RAND_MAX));

        glVertex3f((rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700,(rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700,(rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700);

              随机画点颜色和位置

三、运行截图

 

四、代码

#include<Windows.h>
#include<GLglut.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
//太阳、地球和月亮
//假设每个月都是30天
//一年12个月,共是360天
#define N  999
using namespace std;
static int day = 360; // day的变化:从0到359
static float PI = 3.14159;


GLfloat roate = 0.0;// set rote of roate ying yu bu hao  bu zhuang le 设置旋转速率
GLfloat rote = 0.0;//shezhi旋转角度
GLfloat isy = 0.0;//太阳绕y轴旋转
GLfloat isz = 0.0;//太阳绕z轴旋转
GLfloat hasOrbit = 1.0f;
GLfloat hasCoordinate = 1.0f;
GLfloat hasCharacter = 1.0f;
GLfloat eyehight = 50.0;
GLfloat eyex = 0.0f;
GLfloat eyey = -600;

GLfloat anglex = 0.0;//X 轴旋转
GLfloat angley = 0.0;//Y 轴旋转
GLfloat anglez = 0.0;//Z 轴旋转
GLint WinW = 1000;
GLint WinH = 1000;
GLfloat oldx;//当左键按下时记录鼠标坐标
GLfloat oldy;

void selectFont(int size, int charset, const char*face);
void drawCNString(const char* str);

void myDisplay(void)
{
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(75, 1, 1, 1000);

    glRotatef(anglex, 1.0, 0.0, 0.0);
    glRotatef(angley, 0.0, 1.0, 0.0);
    glRotatef(anglez, 0.0, 0.0, 1.0);
    rote += roate;
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(eyex, eyey, eyehight, 0, 0, 0, 0, 0, 1.0);
    glPushMatrix();
//    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    // 定义太阳光源,它是一种白色的光源
    {
        GLfloat sun_light_position[] = {0.0f, 0.0f, 0.0f, 1.0f}; //光源的位置在世界坐标系圆心,齐次坐标形式
        GLfloat sun_light_ambient[]   = {0.0f, 0.0f, 0.0f, 1.0f}; //RGBA模式的环境光,为0
        GLfloat sun_light_diffuse[]   = {1.0f, 1.0f, 1.0f, 1.0f}; //RGBA模式的漫反射光,全白光
        GLfloat sun_light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};  //RGBA模式下的镜面光 ,全白光
        glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);
        glLightfv(GL_LIGHT0, GL_AMBIENT,   sun_light_ambient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE,   sun_light_diffuse);
        glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);

        //开启光源
        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);
        glEnable(GL_DEPTH_TEST);
    }
    if(hasCharacter==1.0f)
    {
        /*在绘制部分调用字体函数,写中文字*/
        GLfloat sun_mat_emission[] = {0.1, 0.6, 0.3, 1.0f};   //定义材质的辐射广颜色
        glMaterialfv(GL_FRONT, GL_EMISSION,   sun_mat_emission);

        selectFont(1, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, -400);//定位首字
        drawCNString("");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 390);//定位首字
        drawCNString("V:取消字体");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 373);//定位首字
        drawCNString("C:显示字体");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 356);//定位首字
        drawCNString("O:取消轨道");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 339);//定位首字
        drawCNString("P:显示轨道");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 322);//定位首字
        drawCNString("I:下降视角");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 305);//定位首字
        drawCNString("U:上升视角");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 288);//定位首字
        drawCNString("Y:显示标轴");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 271);//定位首字
        drawCNString("N:取消标轴");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 254);//定位首字
        drawCNString("A:向左移动");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 237);//定位首字
        drawCNString("D:向右移动");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 220);//定位首字
        drawCNString("W:向前移动");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 203);//定位首字
        drawCNString("S:向后移动");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 186);//定位首字
        drawCNString("左键:移动行星");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 169);//定位首字
        drawCNString("中键:绕X旋转");//写字
        selectFont(15, GB2312_CHARSET, "楷体GB2312");//设置字体
        glRasterPos3f(-400, 0, 152);//定位首字
        drawCNString("右键:绕Y旋转");//写字
    }
    {//画星光
        int i;
        glPointSize(4);
        glPopMatrix();
        glBegin(GL_POINTS);
        for(i=0; i<10; i++)
        {
            glColor3f((rand()/(GLfloat)RAND_MAX),(rand()/(GLfloat)RAND_MAX),(rand()/(GLfloat)RAND_MAX));
            glVertex3f((rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700,(rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700,(rand()/(GLfloat)RAND_MAX)*pow(-1,rand())*700);
        }
        glEnd();
    }
    {
        GLfloat sun_mat_ambient[]   = {0.0f, 0.0f, 0.0f, 1.0f};  //定义材质的环境光颜色,为0
        GLfloat sun_mat_diffuse[]   = {0.0f, 0.0f, 0.0f, 1.0f};  //定义材质的漫反射光颜色,为0
        GLfloat sun_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,为0
        GLfloat sun_mat_emission[] = {0.8f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射广颜色,为偏红色
        GLfloat sun_mat_shininess   = 0.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT,    sun_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    sun_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   sun_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   sun_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess);
        //绘制红色的“太阳”
        glColor3f(1.0f, 0.0f, 0.0f);
        glRotatef(rote, 0.0f, isy, isz);
        glutWireSphere(100, 250, 250);
        glPushMatrix();//将太阳的变换矩阵压入栈
    }
    {
        GLfloat earth_mat_ambient[]   = {1.0f, 0.5f, 0.31f, 1.0f};  //定义材质的环境光颜色,偏蓝色
        GLfloat earth_mat_diffuse[]   = {1.0f, 0.4f, 0.2f, 1.0f};  //定义材质的漫反射光颜色,偏蓝色
        GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,棕色
        GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色,为0
        GLfloat earth_mat_shininess   = 50.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);
        //绘制棕色的“土星”
        glColor3f(0.7f, 0.5f, 0.0f);
        glRotatef((((day+300) / 360.0)*360.0)*2, 0.0f, 0.0f, -1.0f);
        glTranslatef(0.0f, 150, 0.0f);
        glutSolidSphere(20, 30, 10);

//        glBegin(GL_LINE_STRIP);
//        for (int i = 0; i < 361; i++)
//        {
//            glVertex3f(20 * (float)sin(i * PI / 180), 0, 20 * (float)cos(i * PI / 180));
//        }
//        glEnd();
    }
    {
        GLfloat earth_mat_ambient[]   = {1.0f, 0.5f, 0.31f, 1.0f};  //定义材质的环境光颜色,骗蓝色
        GLfloat earth_mat_diffuse[]   = {1.0f, 0.4f, 0.2f, 1.0f};  //定义材质的漫反射光颜色,偏蓝色
        GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,红色
        GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色,为0
        GLfloat earth_mat_shininess   = 30.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);
        //绘制棕色的“土星环”
        glColor3f(0.7f, 0.5f, 0.0f);
        glRotatef((day+200) / 360.0*360.0, 0.0f, 0.0f, -1.0f);
        glTranslatef(0.0f, 0.0f, 0.0f);
        glRotatef(10.0, 0.0, 0.0, 1.0);
        glutWireTorus(0.5, 30, 20, 20);
    }
    {
        GLfloat earth_mat_ambient[]   = {0.0f, 0.0f, 1.0f, 1.0f};  //定义材质的环境光颜色,骗蓝色
        GLfloat earth_mat_diffuse[]   = {0.0f, 0.0f, 0.5f, 1.0f};  //定义材质的漫反射光颜色,偏蓝色
        GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,红色
        GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色,为0
        GLfloat earth_mat_shininess   = 40.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);
        //绘制蓝色的“地球”
        glPopMatrix();//太阳的变换矩阵弹栈
        glPushMatrix();
        glColor3f(0.0f, 0.0f, 1.0f);
        glRotatef(day / 360.0*360.0, 0.0f, 0.0f, -1.0f);
        glTranslatef(250, 0.0f, 0.0f);
        glutWireSphere(10, 30, 10);
    }
    {
            GLfloat earth_mat_ambient[]   = {0.156, 0.941, 0.47, 1.0f};  //定义材质的环境光颜色,骗蓝色
            GLfloat earth_mat_diffuse[]   = {0.156, 0.941, 0.47, 1.0f};  //定义材质的漫反射光颜色,偏蓝色
            GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,红色
            GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色,为0
            GLfloat earth_mat_shininess   = 30.0f;
            glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);
            glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);
            glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);
            glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);
            glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);
            //绘制黄色的“月亮”
            glColor3f(0.156, 0.941, 0.47);
            glRotatef(day / 30.0*360.0 - day / 360.0*360.0, 0.0f, 0.0f, -1.0f);
            glRotatef(day / 30.0*360.0, 0.0f, 0.0f, -1.0f);
            glTranslatef(15, 0.0f, 0.0f);
            glutSolidSphere(4, 100, 100);
    }

    GLfloat earth_mat_ambient[3][4]   = {{0.9, 0.941, 0.47, 1.0f},{0.0f, 0.941, 0.235, 1.0f},{1.0f, 0.6f, 1.0f, 1.0f}};  //定义材质的环境光颜色,骗蓝色
    GLfloat earth_mat_diffuse[3][4]   = {{0.57, 0.941, 0.47, 1.0f},{0.0f, 0.941, 0.235, 1.0f},{1.0f, 0.6f, 1.0, 1.0f}};  //定义材质的漫反射光颜色,偏蓝色
    GLfloat earth_mat_specular[3][4] = {{1.0f, 0.0f, 0.0f, 1.0f},{1.0f, 0.0f, 0.0f, 1.0f},{1.0f, 0.0f, 0.0f, 1.0f}};   //定义材质的镜面反射光颜色,红色
    GLfloat earth_mat_emission[3][4] = {{0.0f, 0.0f, 0.0f, 1.0f},{0.0f, 0.0f, 0.0f, 1.0f},{0.0f, 0.0f, 0.0f, 1.0f}};   //定义材质的辐射光颜色,为0
    GLfloat earth_mat_shininess[3] = {30.0f,20.0f,10.0f};
    GLfloat glColor[3][3] = {{0.47, 0.941, 0.47},{0.0f, 0.941, 0.235},{1.0f, 0.6f, 1.0f}};
    GLfloat glTranslate[3][3] = {{250, -250, 0.0f},{-240, 230, 0.0f},{300, 300, 0.0f}};
    GLfloat radius[3][3] ={{15, 30, 10},{8, 30, 10},{12, 30, 10}};
    GLfloat speed[3] = {(day-100) / 360.0*360.0,(day-150) / 360.0*360.0,(day-200) / 360.0*360.0};
    for(int i=0;i<3;i++)
    {
        glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient[i]);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse[i]);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular[i]);
        glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission[i]);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess[i]);
        //绘制蓝色的“地球”
        glPopMatrix();//太阳的变换矩阵弹栈
        glPushMatrix();
        glColor3f(glColor[i][0],glColor[i][1],glColor[i][2]);
        glRotatef(speed[i], 0.0f, 0.0f, -1.0f);
        glTranslatef(glTranslate[i][0],glTranslate[i][1],glTranslate[i][2]);
        glutSolidSphere(radius[i][0],radius[i][1],radius[i][2]);
    }
    //画行星轨道
    if(hasOrbit==1.0f)
    {
        glPopMatrix();
        glutWireTorus(0.1, 150, 10, 64);
        glutWireTorus(0.1, 353.55, 10, 64);
        glutWireTorus(0.1, 332.42, 10, 64);
        glutWireTorus(0.1, 424.26, 10, 64);
        glutWireTorus(0.1, 250, 10, 64);
    }
    //画坐标轴
    if(hasCoordinate==1.0f)
    {
        const int AXES_LEN = 300;
        const int ARROW_LEN = 100;
        const int ARROW_RADIUS = 10;

        GLUquadricObj *objCylinder = gluNewQuadric();
        //确定坐标系原点
        glPushMatrix();
        glColor3f(1.0f, 1.0f, 1.0f);
        glutSolidSphere(10, 20, 20);
        glPopMatrix();

        glPushMatrix();
        glColor3f(1.0f, 0.0f, 0.0f);
        glutSolidSphere(0.25, 6, 6);
        gluCylinder(objCylinder, 5, 5, AXES_LEN, 10, 5); //z
        glTranslatef(0, 0, AXES_LEN);
        gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //z arrow
        glPopMatrix();

        glPushMatrix();
        glColor3f(0.0f, 1.0f, 0.0f);
        glRotatef(90, 1.0, 0.0, 0.0);
        gluCylinder(objCylinder, 5, 5, AXES_LEN, 10, 5); //Y
        glTranslatef(0, 0, AXES_LEN);
        gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //Y arrow
        glPopMatrix();

        glPushMatrix();
        glColor3f(0.0f, 0.0f, 1.0f);
        glRotatef(90, 0.0, 1.0, 0.0);
        gluCylinder(objCylinder, 5, 5, AXES_LEN, 10, 5); //X
        glTranslatef(0, 0, AXES_LEN);
        gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //X arrow
        glPopMatrix();
    }
    glFlush();
    glutSwapBuffers();
    }
    void myIdle(void)
    {
    Sleep(50);
    ++day;
    if (day >= 360)
    day = 0;
    myDisplay();
}

void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON&&state == GLUT_DOWN)
    {
            roate = 0;
            rote = 0;
            oldx = x;//当左键按下时记录鼠标坐标
            oldy = y;
    }
    if (button == GLUT_MIDDLE_BUTTON&&state == GLUT_DOWN)
    {
            isy = 0.0;
            isz = 1.0;
            oldx = x;//当左键按下时记录鼠标坐标
            oldy = y;
            roate += 2.0f;
    }
    if (button == GLUT_RIGHT_BUTTON&&state == GLUT_DOWN)
    {
            isy = 1.0;
            isz = 0.0;
            oldx = x;//当左键按下时记录鼠标坐标
            oldy = y;
            roate += 2.0f;
    }
}

void motion(int x, int y)
{
    GLint deltax = oldx - x;
    GLint deltay = oldy - y;
    anglex += 360 * (GLfloat)deltay / (GLfloat)WinW;//根据屏幕上鼠标滑动的距离来设置旋转的角度
    angley += 360 * (GLfloat)deltax / (GLfloat)WinH;
//    anglez += 360 * (GLfloat)deltay / (GLfloat)WinH;
    oldx = x;//记录此时的鼠标坐标,更新鼠标坐标
    oldy = y;//若是没有这两句语句,滑动是旋转会变得不可控
    glutPostRedisplay();
    glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'o':
    case'O':
        hasOrbit = 0.0f;
        break;
    case 'p':
    case 'P':
        hasOrbit = 1.0f;
        break;
    case 'y':
    case'Y':
        hasCoordinate = 1.0f;
        break;
    case 'n':
    case 'N':
        hasCoordinate = 0.0f;
        break;
    case 'c':
    case'C':
        hasCharacter = 1.0f;
        break;
    case 'v':
    case 'V':
        hasCharacter = 0.0f;
        break;
    case 'i':
    case 'I':
        eyehight-=10;
        break;
    case 'u':
    case 'U':
        eyehight+=10;
        break;
    case 'w':
    case 'W':
        eyey+=10;
        break;
    case 's':
    case 'S':
        eyey-=10;
        break;
    case 'a':
    case 'A':
        eyex-=10;
        break;
    case 'd':
    case 'D':
        eyex+=10;
        break;
    }
}

//选择字体函数
void selectFont(int size, int charset, const char*face)
{
    HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0,
        charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);

    HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);
    DeleteObject(hOldFont);
}

//生成中文字体
void drawCNString(const char* str)
{
    int len, i;
    wchar_t* wstring;
    HDC hDC = wglGetCurrentDC();
    GLuint list = glGenLists(1);
    //计算字符的个数
    //如果是双字节字符的(比如中文字符),两个字节才算一个字符
    //否则一个字节算一个字符
    len = 0;
    for (i = 0; str[i] != ''; ++i)
    {
        if (IsDBCSLeadByte(str[i]))
            ++i;
        ++len;
    }
    //将混合字符转化为宽字符
    wstring = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);
    wstring[len] = L'';
    //逐个输出字符
    for (i = 0; i < len; ++i)
    {
        wglUseFontBitmapsW(hDC, wstring[i], 1, list);
        glCallList(list);
    }
    //回收所有临时资源
    free(wstring);
    glDeleteLists(list, 1);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(200, 100);
    glutInitWindowSize(800, 1200);
    glutCreateWindow("I love OpenGL");
    glutDisplayFunc(&myDisplay);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(&myIdle);
    glutMainLoop();
    return 0;
}

  

原文地址:https://www.cnblogs.com/LieYanAnYing/p/12152603.html