OpenGL + vc6.0 控制台实现《太阳系模型》
OpenGL + vc6.0 控制台实现《太阳系模型》
#define BITMAP_ID 0x4D42
#define PI 3.1415926#include
#include
#include
#include
#include #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )//---------- 纹理数据结构
typedef struct{
int width;
//纹理宽度
int height;
//纹理高度
unsigned int texID;
//纹理对象 ID
unsigned char * data;
//实际纹理数据
}texture;
static float year = 0, month =0,day = 0, angle=30;
static bool first=false;
texture * sun,* earth,* moon;
//纹理指针//---------- 调入位图作为纹理数据
unsigned char * LoadBmpFile(char * filename,BITMAPINFOHEADER * bmpInfoHeader){
FILE * file;
BITMAPFILEHEADER bmpFileHeader;
unsigned char * image;
unsigned int imageIdx =0;
unsigned char tempRGB;
file = fopen(filename,"rb");
if(file == NULL)
return 0;
fread(& bmpFileHeader,sizeof(BITMAPFILEHEADER),1,file);
// 读取 BMP 文件头
if (bmpFileHeader.bfType != BITMAP_ID)// 验证是否是一个 BMP 文件
{
fclose(file);
return 0;
}
fread(bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,file);
// 读位图信息头
fseek(file,bmpFileHeader.bfOffBits,SEEK_SET);
// 将文件指针移到位图数据的开始处
image = (unsigned char * )malloc(bmpInfoHeader->biSizeImage);
// 分配内存给位图数据
if (! image)
{
free(image);
fclose(file);
return 0;
}
fread(image,1,bmpInfoHeader->biSizeImage,file);
// 读取位图数据
if (image == NULL)
{
fclose(file);
return 0;
}
// 反转 R 和 B 值以得到 RGB,因为位图颜色格式是 BGR
for (imageIdx = 0;
imageIdx < bmpInfoHeader->biSizeImage;
imageIdx += 3)
{
tempRGB = image[imageIdx];
image[imageIdx] = image[imageIdx + 2];
image[imageIdx + 2] = tempRGB;
}
fclose(file);
return image;
}//---------- 调入纹理文件
texture * LoadTexFile(char * filename){
BITMAPINFOHEADER texInfo;
texture * thisTexture;
thisTexture = (texture * )malloc(sizeof(texture));
if(thisTexture == NULL)
return 0;
thisTexture->data = https://www.it610.com/article/LoadBmpFile(filename,&texInfo);
// 调入纹理数据并检查有效性
if (thisTexture->data =https://www.it610.com/article/= NULL)
{
free(thisTexture);
return 0;
} thisTexture->width = texInfo.biWidth;
// 设置纹理的宽和高
thisTexture->height = texInfo.biHeight;
glGenTextures(1,&thisTexture->texID);
// 生成纹理对象名
return thisTexture;
}//---------- 初始化所有纹理数据和属性
BOOL LoadAllTextures(){ sun = LoadTexFile("sun.bmp");
if(sun == NULL)
return FALSE;
glBindTexture(GL_TEXTURE_2D,sun->texID);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,sun->width,sun->height,GL_RGB,GL_UNSIGNED_BYTE,sun->data);
earth = LoadTexFile("earth.bmp");
if(earth == NULL)
return FALSE;
glBindTexture(GL_TEXTURE_2D,earth->texID);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,earth->width,earth->height,GL_RGB,GL_UNSIGNED_BYTE,earth->data);
moon = LoadTexFile("moon.bmp");
if(moon == NULL)
return FALSE;
glBindTexture(GL_TEXTURE_2D,moon->texID);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,moon->width,moon->height,GL_RGB,GL_UNSIGNED_BYTE,moon->data);
return TRUE;
}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;
}
}void myinit(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
//启用二维纹理 GLfloat light0_ambient[]= {1, 1, 1, 1};
//环境光
GLfloat light0_diffuse[]= {1, 1, 1, 1};
//散射光
GLfloat light0_position[] = {0, 0, 0, 1};
//光源位置 glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
LoadAllTextures();
//调入纹理
}void myidle()
{
day+=angle;
glutPostRedisplay();
}void mymouse(int button,int state,int x,int y)
{
if(state==GLUT_DOWN && button==GLUT_LEFT_BUTTON){
if(first)
{
glutIdleFunc(myidle);
first=!first;
}
else
{
glutIdleFunc(0);
first=!first;
}
}
}void mykeyboard(unsigned char key, int x, int y)
{
if (key == 27)
exit(0);
} void mydisplay(void)
{
year=day/365;
month=day/30;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat mat_ambient1[]= {1,0,0,1};
GLfloat mat_emission[]= {1,1,1,0};
GLfloat mat_ambient2[]= {0.4,0.4,0.8,1};
GLfloatno_emission[]= {0,0,0,1};
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,sun->texID);
glRotatef (month, 0.0, 1.0, 0.0);
//太阳自转
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
glRotatef (90, -1, 0, 0);
gltDrawSphere(1.0, 40, 40);
//绘制太阳
glPopMatrix();
glPushMatrix();
glRotatef (year, 0.0, 1.0, 0.0);
//月亮与地球一起绕太阳转(地球公转)
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,earth->texID);
glTranslatef (3.0, 0.0, 0.0);
glRotatef (month, 0.0, 1.0, 0.0);
//地球自转
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient2);
glMaterialfv(GL_FRONT, GL_EMISSION, no_emission);
glRotatef (90, -1, 0, 0);
gltDrawSphere(0.4, 40, 40);
//绘制地球
glPopMatrix();
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,moon->texID);
glTranslatef (3.0, 0.0, 0.0);
glRotatef (60, -1, 1, 0);
glRotatef (month, 0, 1.0, 0);
//月球绕地球转
glTranslatef (0.6, 0.0, 0.0);
glRotatef (90, -1, 0, 0);
gltDrawSphere(0.07, 20, 20);
//绘制月球
glPopMatrix();
glPopMatrix();
glFlush();
glutSwapBuffers();
}void myreshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//指定视口大小
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 20);
//透视投影
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
//指定照相机的位置
}int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (1000, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
myinit ();
glutDisplayFunc(mydisplay);
glutReshapeFunc(myreshape);
glutIdleFunc(myidle);
glutMouseFunc(mymouse);
glutKeyboardFunc(mykeyboard);
glutMainLoop();
return 0;
}
说明:上述代码已经在vc控制台中编译运行通过。
此链接为此程序的源代码文件(包含此程序所需的三个bmp图片,及exe文件)
http://download.csdn.net/detail/shen_gan/4279261
以下为运行效果图:
【OpenGL + vc6.0 控制台实现《太阳系模型》】
推荐阅读
- 2.关于OpenGL|2.关于OpenGL 坐标系以及渲染流程
- OpenGL|OpenGL ES之LUT(滤镜基准图)
- OpenGL|OpenGL 绘制甜甜圈深度测试、多边形偏移、裁剪、 混合
- FFmpeg|FFmpeg 开发(07)(FFmpeg + OpenGLES 实现 3D 全景播放器)
- open基础笔记
- React|React Native 在Mac控制台输出日志
- Metal|Metal 简述 & API
- 2、OpenGL初探之OpenGL图形API及专有名词
- 基础课|使用深度优先搜索(DFS)、广度优先搜索(BFS)、A* 搜索算法求解 (n^2 -1) 数码难题,耗时与内存占用(时空复杂度)对比(附((n^2 - 1) 数码问题控
- Android|Android OpenGL 学习笔记