一、基本原理
使用封装的gltDrawSphere绘制星球,DrawCircle绘制轨道 在封装的Init函数中开启灯光,OnDisplay函数中绘制时候写好光照参数 在封装的Init函数中使用auxDIBImageLoad函数读取bmp文件的宽、高与data 在封装的OnDisplay函数中使用glPushMatrix与glPopMatrix依次绘制每一个星球 使用glutTimerFun函数实现动画
二、代码(完整版本)
2.1 头文件
ifndef _HERDER_H_
#define _HERDER_H_
#include <GL/glut.h>
#include <GL/GLAux.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
AUX_RGBImageRec* Images[ 10 ] ;
GLuint ImagesIDs[ 11 ] ;
char * szFiles[ 10 ] = {
( "F:\\OGL\\sun\\Sun.bmp" ) ,
( "F:\\OGL\\sun\\Mercury.bmp" ) ,
( "F:\\OGL\\sun\\Venus.bmp" ) ,
( "F:\\OGL\\sun\\Earth.bmp" ) ,
( "F:\\OGL\\sun\\Mars.bmp" ) ,
( "F:\\OGL\\sun\\Jupiter.bmp" ) ,
( "F:\\OGL\\sun\\Saturn.bmp" ) ,
( "F:\\OGL\\sun\\Uranus.bmp" ) ,
( "F:\\OGL\\sun\\Neptune.bmp" ) ,
( "F:\\OGL\\sun\\Moon.bmp" ) , } ;
GLubyte* pImg;
GLint iWidth, iHeight;
#define PI 3.1415926
static float year = 0 , month = 0 , day = 0 , angle = 30 ;
GLint W, H, width, height;
float pox = 2 , poy = 3 , poz = 8 ;
GLint fovy = 60 ;
void Init ( ) ;
void OnDisplay ( ) ;
void OnReshape ( int , int ) ;
void OnTimer ( int ) ;
void DrawCircle ( GLdouble) ;
void gltDrawSphere ( GLfloat, GLint, GLint) ;
#endif
2.2 mian函数
int main ( int argc, char * argv[ ] ) {
glutInit ( & argc, argv) ;
glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) ;
glutInitWindowSize ( 400 , 400 ) ;
glutInitWindowPosition ( 100 , 100 ) ;
glutCreateWindow ( "太阳系" ) ;
Init ( ) ;
glutReshapeFunc ( OnReshape) ;
glutDisplayFunc ( & OnDisplay) ;
glutTimerFunc ( 100 , OnTimer, 1 ) ;
glutMainLoop ( ) ;
return 0 ;
}
2.3 OnReshape防止变形函数
void OnReshape ( int w, int h) {
W = w; H = h;
width = W; height = H;
glViewport ( 0 , 0 , w, h) ;
glMatrixMode ( GL_PROJECTION) ;
glLoadIdentity ( ) ;
gluPerspective ( 60.0 , ( GLfloat) w / ( GLfloat) h, 1 , 20 ) ;
glMatrixMode ( GL_MODELVIEW) ;
glLoadIdentity ( ) ; }
2.4 Init初始化函数
void Init ( ) {
glClearColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
for ( int i = 0 ; i < 10 ; i++ ) {
glGenTextures ( 1 , & ImagesIDs[ i] ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ i] ) ;
WCHAR wfilename[ 256 ] ;
memset ( wfilename, 0 , sizeof ( wfilename) ) ;
MultiByteToWideChar ( CP_ACP, 0 , szFiles[ i] , strlen ( szFiles[ i] ) + 1 , wfilename, sizeof ( wfilename) / sizeof ( wfilename[ 0 ] ) ) ;
Images[ i] = auxDIBImageLoad ( wfilename) ;
iWidth = Images[ i] - > sizeX;
iHeight = Images[ i] - > sizeY;
pImg = Images[ i] - > data;
glTexImage2D ( GL_TEXTURE_2D, 0 , 3 , iWidth, iHeight, 0 , GL_RGB, GL_UNSIGNED_BYTE, pImg) ;
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ;
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ;
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) ;
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ;
glTexEnvf ( GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE) ;
glEnable ( GL_TEXTURE_2D) ;
glEnable ( GL_DEPTH_TEST) ;
}
glEnable ( GL_LIGHTING) ;
glEnable ( GL_LIGHT0) ;
}
2.5 OnTimer函数
void OnTimer ( int value) {
day + = angle;
glutPostRedisplay ( ) ;
glutTimerFunc ( 100 , OnTimer, 1 ) ;
}
2.6 DrawCircle画轨道函数
void DrawCircle ( GLdouble R) {
glPushMatrix ( ) ;
glRotatef ( 90.0 , 1.0 , 0.0 , 0.0 ) ;
glColor3f ( 1.0 , 1.0 , 1.0 ) ;
glBegin ( GL_LINE_LOOP) ;
for ( int i = 0 ; i < 1000 ; i++ ) {
GLdouble angle1 = i * 2 * PI / 1000 ;
glVertex2d ( R * cos ( angle1) , R * sin ( angle1) ) ;
}
glEnd ( ) ;
glPopMatrix ( ) ;
}
2.7 gltDrawSphere绘制星球函数
void gltDrawSphere ( GLfloat fRadius, GLint iSlices, GLint iStacks) {
GLfloat drho = ( GLfloat) ( 3.141592653589 ) / ( GLfloat) iStacks;
GLfloat dtheta = 2.0f * ( GLfloat) ( 3.141592653589 ) / ( GLfloat) iSlices;
GLfloat ds = 1.0f / ( GLfloat) iSlices;
GLfloat dt = 1.0f / ( GLfloat) iStacks;
GLfloat t = 1.0f ;
GLfloat s = 0.0f ;
GLint i, j;
for ( i = 0 ; i < iStacks; i++ ) {
GLfloat rho = ( GLfloat) i * drho;
GLfloat srho = ( GLfloat) ( sin ( rho) ) ;
GLfloat crho = ( GLfloat) ( cos ( rho) ) ;
GLfloat srhodrho = ( GLfloat) ( sin ( rho + drho) ) ;
GLfloat crhodrho = ( GLfloat) ( cos ( rho + drho) ) ;
glBegin ( GL_TRIANGLE_STRIP) ;
s = 0.0f ;
}
for ( j = 0 ; j <= iSlices; j++ ) {
GLfloat theta = ( j == iSlices) ? 0.0f : j * dtheta;
GLfloat stheta = ( GLfloat) ( - sin ( theta) ) ;
GLfloat ctheta = ( GLfloat) ( cos ( theta) ) ;
GLfloat x = stheta * srho;
GLfloat y = ctheta * srho;
GLfloat z = crho;
glTexCoord2f ( s, t) ;
glNormal3f ( x, y, z) ;
glVertex3f ( x * fRadius, y * fRadius, z * fRadius) ;
x = stheta * srhodrho;
y = ctheta * srhodrho;
z = crhodrho;
glTexCoord2f ( s, t - dt) ;
s + = ds;
glNormal3f ( x, y, z) ;
glVertex3f ( x * fRadius, y * fRadius, z * fRadius) ;
}
glEnd ( ) ;
t - = dt;
}
2.8 OnDisplay函数
void OnDisplay ( ) {
glColor3f ( 1.0 , 0.0 , 0.0 ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
year = day / 365 ;
month = day / 30 ;
glMatrixMode ( GL_PROJECTION) ;
glLoadIdentity ( ) ;
gluPerspective ( fovy, ( GLfloat) W / ( GLfloat) H, 2 , 60.0 ) ;
glMatrixMode ( GL_MODELVIEW) ;
glLoadIdentity ( ) ;
gluLookAt ( pox, poy, poz, 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ) ;
GLfloat sun_mat_ambient[ 4 ] = { 1.0 , 1.0 , 1.0 , 0.0 } ;
GLfloat sun_mat_diffuse[ 4 ] = { 1.0 , 1.0 , 0.5 , 1.0 } ;
GLfloat sun_mat_specular[ 4 = { 1.0 , 1.0 , 1.0 , 1.0 } ;
GLfloat sun_mat_shininess[ ] = { 10.0 } ;
GLfloat sun_mat_emission[ 4 ] = { 0.1 , 0.1 , 0.1 , 1.0 } ;
GLfloat mat_ambient[ 4 ] = { 0.2 , 0.2 , 0.2 , 1.0 } ;
GLfloat mat_diffuse[ 4 ] = { 1.0 , 1.0 , 1.0 , 1.0 } ;
GLfloat mat_specular[ 4 ] = { 0.5 , 0.5 , 0.5 , 1.0 } ;
GLfloat mat_shininess[ ] = { 5.0 } ;
GLfloat light_position[ ] = { - 10.0 , 10.0 , 0.0 , 1.0 } ;
glLightfv ( GL_LIGHT0, GL_POSITION, light_position) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, sun_mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, sun_mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, sun_mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, sun_mat_shininess) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_EMISSION, sun_mat_emission) ;
glPushMatrix ( ) ;
glLightfv ( GL_LIGHT0, GL_POSITION, light_position) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, sun_mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, sun_mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, sun_mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, sun_mat_shininess) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_EMISSION, sun_mat_emission) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 0 ] ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90.0 , - 1.0 , 0.0 , 0.0 ) ;
gltDrawSphere ( 1.0 , 50 , 50 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 2.0 ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 2 , 0.0 , 0.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 1 ] ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90.0 , - 1.0 , 0.0 , 0.0 ) ;
gltDrawSphere ( 0.2 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 3.0 ) ;
glRotatef ( ( GLfloat) month / 3 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 3 , 0.0 , 0.0 ) ;
glRotatef ( 30.0 , - 1.0 , 0.0 , 0.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 2 ] ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90.0 , - 1.0 , 0.0 , 0.0 ) ;
gltDrawSphere ( 0.25 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
DrawCircle ( 4.5 ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
glRotatef ( ( GLfloat) year, 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 4.5 , 0.0 , 0.0 ) ;
glRotatef ( 30.0 , - 1.0 , 0.0 , 0.0 ) ;
glPushMatrix ( ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 3 ] ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90.0 , - 1.0 , 0.0 , 0.0 ) ;
gltDrawSphere ( 0.4 , 20 , 20 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 1.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 9 ] ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 1.0 , 0.0 , 0.0 ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90.0 , - 1.0 , 0.0 , 0.0 ) ;
gltDrawSphere ( 0.15 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 6.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 4 ] ) ;
glRotatef ( ( GLfloat) month / 1.5 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 6.0 , 0.0 , 0.0 ) ;
glRotatef ( 30 , - 1 , 0 , 0 ) ;
glRotatef ( ( GLfloat) month, 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90 , - 1 , 0 , 0 ) ;
gltDrawSphere ( 0.3 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 7.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 5 ] ) ;
glRotatef ( ( GLfloat) month / 4 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 7.0 , 0.0 , 0.0 ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90 , - 1 , 0 , 0 ) ;
gltDrawSphere ( 0.42 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 8.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 6 ] ) ;
glRotatef ( ( GLfloat) month / 3.5 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 8.0 , 0.0 , 0.0 ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90 , - 1 , 0 , 0 ) ;
gltDrawSphere ( 0.35 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 9.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 7 ] ) ;
glRotatef ( ( GLfloat) month / 3 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 9.0 , 0.0 , 0.0 ) ;
glRotatef ( 30 , - 1 , 0 , 0 ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90 , - 1 , 0 , 0 ) ;
gltDrawSphere ( 0.3 , 10 , 10 ) ;
glPopMatrix ( ) ;
glPushMatrix ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular) ;
glMaterialfv ( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess) ;
DrawCircle ( 10.0 ) ;
glBindTexture ( GL_TEXTURE_2D, ImagesIDs[ 8 ] ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glTranslatef ( 10.0 , 0.0 , 0.0 ) ;
glRotatef ( 30 , - 1 , 0 , 0 ) ;
glRotatef ( ( GLfloat) month / 2 , 0.0 , 1.0 , 0.0 ) ;
glRotatef ( 90 , - 1 , 0 , 0 ) ;
gltDrawSphere ( 0.25 , 10 , 10 ) ;
glPopMatrix ( ) ;
glutSwapBuffers ( ) ;
}
三、注意事项
除了头文件,其他都是依次放到cpp文件中就可以 代码使用vs2019,其他版本的可能会报错,直接百度错误就可以很快的解决 .glutXXXX的模型都是很简陋的,没有纹理UV坐标的模型,使用glutSolidSphere函数是无法进行贴图。所以写了一个gltDrawSphere函数绘制星球 我使用的是vs2019,在使用加载的纹理图片之前,要把路径字符串转化为宽字符字符串,这一点可以查看上面glutSolidSphere函数代码。其他版本可能不需要转化,去掉就可以。 求个三连!不明白的可以评论或者私信我~