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<GL\glut.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] != '\0'; ++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'\0'; //逐个输出字符 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; }