转自:http://www.juwends.com/tech/opengl/opengl-solar-system.html

OpenGL是一个非常强大的图形引擎。传说当下最流行的图形引擎有两套,其中之一就是Windows平台上最常用的DirectX(而且只能在Microsoft的平台上使用,可以看下百度百科关于DirectX的介绍),而另外一套则是OpenGL了,可以用于非常多的平台(可以参看百度百科关于OpenGL的介绍),至少我是这么被告知的。说到OpenGL,就不得不提到NeHe(读音有点像“妮褐”,不过我平时都叫它“呵呵”),据我的浅薄认知来看,NeHe提供了大概48个使用OpenGL的例子,这些例子涉及了OpenGL编程非常多的方面,传说是掌握这些例子就可以无敌了,详细可以去NeHe官网看看,最右边有个“Legacy Tutorials”(嗯,对了,我确定是有48个例子了)就是所有的例子,所有的例子可以下载不同IDE(集成开发环境,比如像vs,vc,devc等)的源码。

关于OpenGL实现太阳系模型是因为选了三维动画的课,最后交的结课作业,为了不太浪费资源,所以写一篇文章来保留这些劳动成果,也为后来的人做个小小的参考,因为初涉OpenGL,模型设计实现不妥之处还望高手指教。以下是简要的设计描述:

为简便起见,简化模型: 太阳为光源星球,并且为太阳系行星的中心; 所有星球(除太阳以外)以圆形轨道绕行; 所有星球均为正球体。 对具体星球而言,具有以下属性: 颜色(Color); 半径(Radius); 自转速度(SelfSpeed); 公转速度(Speed); 距离太阳中心距离(Distance); 绕行星球(ParentBall); 当前自转角度(AlphaSelf); 当前公转角度(Alpha)。 设计描述星球的类及关键实现: 描述普通的能够自转并且绕某个点公转的球(class Ball); 描述具有材质属性的球(class MatBall); 描述具有发光属性的球(class LightBall); 每个星球类独立的处理自己的运动; 类中实现绘图方法(Draw)和更新方法(Update)用于绘制、更新星球; Draw()方法中需要处理自己绕行点(ParentBall)的关系; 对于星球的属性数据需要案一定比例进行调整以符合观看需要。 程序流程如下: 使用Console模式开启程序; 初始化星球对象; 初始化OpenGL引擎,实现绘制函数(OnDraw)和更新函数(OnUpdate); 在绘制函数中调用每个星球对象的Draw()方法; Draw()方法根据星球的属性进行变换并绘制; 在更新函数中调用每个星球对象的Update()方法; Update()方法处理自转数据和公转数据; 实现按键监控,可以通过调整视角对太阳系模型进行观察。

下面是运行程序的截图(本来是彩色的,不过呢,因为word打印需要变成灰度图来看效果,又不想去再截图了,So….):

以下是完整的代码:

View Code

  1 /***************************** BallDefinition.h ******************************/
  2 #include <gl/glut.h>
  3
  4 #ifndef __BALLDEFINITION
  5 #define __BALLDEFINITION
  6
  7 // 数组type
  8 typedef GLfloat (Float2)[2];
  9 typedef GLfloat (Float3)[3];
 10 typedef GLfloat Float;
 11 typedef GLfloat (Float4)[4];
 12
 13 // 对数组进行操作的宏
 14 //#define Float(name, value) (name)=(value)
 15 #define Float2(name, value0, value1) ((name)[0])=(value0), ((name)[1])=(value1)
 16 #define Float3(name, value0, value1, value2) ((name)[0])=(value0), \
 17     ((name)[1])=(value1), ((name)[2])=(value2)
 18 #define Float4(name, value0, value1, value2, value3) ((name)[0])=(value0), \
 19     ((name)[1])=(value1), ((name)[2])=(value2), ((name)[3])=(value3)
 20
 21 // 对数组进行操作的宏
 22 //#define Float(name) (name)
 23 #define RFloat2(name) ((name)[0]), ((name)[1])
 24 #define RFloat3(name) ((name)[0]), ((name)[1]), ((name)[2])
 25 #define RFloat4(name) ((name)[0]), ((name)[1]), ((name)[2]), ((name)[3])
 26
 27 class Ball {
 28 public:
 29     Float4 Color;
 30     Float Radius;
 31     Float SelfSpeed;
 32     Float Speed;
 33
 34     // ParentBall是本球绕行的球
 35     // Center是本球的中心点,当有ParentBall和Distance的时候可以不使用
 36     // Distance是本球中心与ParentBall中心的距离
 37     // Center暂时没有使用
 38     //Float2 Center;
 39     Float Distance;
 40     Ball * ParentBall;
 41
 42     virtual void Draw() { DrawBall(); }
 43     virtual void Update(long TimeSpan);
 44
 45     Ball(Float Radius, Float Distance, Float Speed, Float SelfSpeed, Ball * Parent);
 46
 47     // 对普通的球体进行移动和旋转
 48     void DrawBall();
 49
 50 protected:
 51     Float AlphaSelf, Alpha;
 52 };
 53
 54 class MatBall : public Ball {
 55 public:
 56     virtual void Draw() { DrawMat(); DrawBall(); }
 57
 58     MatBall(Float Radius, Float Distance, Float Speed, Float SelfSpeed,
 59         Ball * Parent, Float3 color);
 60
 61     // 对材质进行设置
 62     void DrawMat();
 63 };
 64
 65 class LightBall : public MatBall {
 66 public:
 67     virtual void Draw() { DrawLight(); DrawMat(); DrawBall(); }
 68
 69     LightBall(Float Radius, Float Distance, Float Speed, Float SelfSpeed,
 70         Ball * Parent, Float3 color);
 71
 72     // 对光源进行设置
 73     void DrawLight();
 74 };
 75
 76 #endif
 77
 78
 79 /**************************** BallDefinition.cpp *****************************/
 80 #include "BallDefinition.h"
 81
 82 Ball::Ball(Float Radius, Float Distance, Float Speed, Float SelfSpeed, Ball * Parent) {
 83     Float4(Color, 0.8f, 0.8f, 0.8f, 1.0f);
 84     this->Radius = Radius;
 85     this->SelfSpeed = SelfSpeed;
 86     if (Speed > 0)
 87         this->Speed = 360.0f / Speed;
 88     AlphaSelf = Alpha= 0;
 89     this->Distance = Distance;
 90     ParentBall = Parent;
 91 }
 92
 93 #include <stdio.h>
 94 #include <math.h>
 95 #define PI 3.1415926535
 96
 97 // 对普通的球体进行移动和旋转
 98 void Ball::DrawBall() {
 99
100     glEnable(GL_LINE_SMOOTH);
101     glEnable(GL_BLEND);
102
103     int n = 1440;
104
105     glPushMatrix();
106     {
107         // 公转
108         if (ParentBall != 0 && ParentBall->Distance > 0) {
109             glRotatef(ParentBall->Alpha, 0, 0, 1);
110             glTranslatef(ParentBall->Distance, 0.0, 0.0);
111
112             glBegin(GL_LINES);
113             for(int i=0; i<n; ++i)
114                 glVertex2f(Distance * cos(2 * PI * i / n),
115                     Distance * sin(2 * PI * i / n));
116             glEnd();
117
118         } else {
119             glBegin(GL_LINES);
120             for(int i=0; i<n; ++i)
121                 glVertex2f(Distance * cos(2 * PI * i / n),
122                     Distance * sin(2 * PI * i / n));
123             glEnd();
124         }
125         glRotatef(Alpha, 0, 0, 1);
126         glTranslatef(Distance, 0.0, 0.0);
127
128         // 自转
129         glRotatef(AlphaSelf, 0, 0, 1);
130
131         // 绘图
132         glColor3f(RFloat3(Color));
133         glutSolidSphere(Radius, 40, 32);
134     }
135     glPopMatrix();
136 }
137
138 void Ball::Update(long TimeSpan) {
139     // TimeSpan 是天
140     Alpha += TimeSpan * Speed;
141     AlphaSelf += SelfSpeed;
142 }
143
144 MatBall::MatBall(Float Radius, Float Distance, Float Speed, Float SelfSpeed,
145     Ball * Parent, Float3 color) : Ball(Radius, Distance, Speed, SelfSpeed, Parent) {
146         Float4(Color, color[0], color[1], color[2], 1.0f);
147 }
148
149 // 对材质进行设置
150 void MatBall::DrawMat() {
151     GLfloat mat_ambient[]  = {0.0f, 0.0f, 0.5f, 1.0f};
152     GLfloat mat_diffuse[]  = {0.0f, 0.0f, 0.5f, 1.0f};
153     GLfloat mat_specular[] = {0.0f, 0.0f, 1.0f, 1.0f};
154     //下面两句替换可以出现彩色或者蓝色的太阳系模型
155     //GLfloat mat_emission[] = {RFloat4(Color)};
156     GLfloat mat_emission[] = {.0f, .0f, .1f, 1.0f};
157     GLfloat mat_shininess  = 90.0f;
158
159     glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
160     glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
161     glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
162     glMaterialfv(GL_FRONT, GL_EMISSION,  mat_emission);
163     glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess);
164 }
165
166 LightBall::LightBall(Float Radius, Float Distance, Float Speed, Float SelfSpeed,
167     Ball * Parent, Float3 color)
168     : MatBall(Radius, Distance, Speed, SelfSpeed, Parent, color) {}
169
170 // 对光源进行设置
171 void LightBall::DrawLight() {
172     GLfloat light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
173     GLfloat light_ambient[]  = {0.0f, 0.0f, 0.0f, 1.0f};
174     GLfloat light_diffuse[]  = {1.0f, 1.0f, 1.0f, 1.0f};
175     GLfloat light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
176     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
177     glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
178     glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
179     glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
180 }
181
182
183 /**************************** Main.cpp *****************************/
184 #include <stdlib.h>
185 #include "BallDefinition.h"
186
187 #define WIDTH 700
188 #define HEIGHT 700
189
190 // 每次更新 看做过去了 1 天
191 #define TimePast 1
192
193 #include <math.h>
194
195 // 对太阳系星球的参数进行调整用的宏
196 #define KK .000001
197 #define sk (.07 * KK)
198 #define k (.5 * KK)
199 #define vk (1.5 * KK)
200 #define fk (.5 * KK)
201 #define hfk (.4 * KK)
202 #define ffk (.3 * KK)
203 #define dk (1.07 * KK)
204 #define edk (1.12 * KK)
205 #define lsk (.3 * KK)
206 #define mk (15000 * KK)
207 #define mrk (1.6 * KK)
208 #define tk .3
209 #define ttk .2
210 #define tttk .1
211
212 // 自转速度(都定义为定值)
213 #define SelfRotate 3
214
215 #define ARRAY_SIZE 10
216 enum STARS {Sun, Mercury, Venus, Earth, Moon, Mars, Jupiter, Saturn, Uranus, Neptune};
217 Ball * Balls[ARRAY_SIZE];
218
219 void init() {
220     Float3 Color;
221     // 定义星球,这些星球的数据是经过不同比例变化过的
222     // 太阳
223     Float3(Color, 1, 0, 0);
224     Balls[Sun] = new LightBall(sk * 696300000, 0, 0, SelfRotate, 0, Color);
225     // 水星
226     Float3(Color, .2, .2, .5);
227     Balls[Mercury] = new MatBall(
228         vk * 4880000, dk * 58000000, 87, SelfRotate, Balls[Sun], Color);
229     // 金星
230     Float3(Color, 1, .7, 0);
231     Balls[Venus] = new MatBall(
232         vk * 12103600, dk * 108000000, 225, SelfRotate, Balls[Sun], Color);
233     // 地球
234     Float3(Color, 0, 1, 0);
235     Balls[Earth] = new MatBall(
236         vk * 12756300, edk * 150000000, 365, SelfRotate, Balls[Sun], Color);
237     // 月亮
238     Float3(Color, 1, 1, 0);
239     Balls[Moon] = new MatBall(
240         mrk * 3844010.0f , mk * 1734.0f, 30, SelfRotate, Balls[Earth], Color);
241     // 火星
242     Float3(Color, 1, .5, .5);
243     Balls[Mars] = new MatBall(
244         vk * 6794000, KK * 228000000, 687, SelfRotate, Balls[Sun], Color);
245     // 木星
246     Float3(Color, 1, 1, .5);
247     Balls[Jupiter] = new MatBall(
248         lsk * 142984000,  fk * 778000000, tk * 4328, SelfRotate, Balls[Sun], Color);
249     // 土星
250     Float3(Color, .5, 1, .5);
251     Balls[Saturn] = new MatBall(
252         lsk * 120536000, fk * 1427000000, ttk * 10752, SelfRotate, Balls[Sun], Color);
253     // 天王星
254     Float3(Color, .4, .4, .4);
255     Balls[Uranus] = new MatBall(k * 51118000,
256         hfk * 2870000000, tttk * 30664, SelfRotate, Balls[Sun], Color);
257     // 海王星
258     Float3(Color, .5, .5, 1);
259     Balls[Neptune] = new MatBall(k * 49532000,
260         ffk * 4497000000, tttk * 60148, SelfRotate, Balls[Sun], Color);
261 }
262
263 // 初始视角( 视点在(+z, -y)处 )
264 #define REST (700000000 * KK)
265 #define REST_Z (REST)
266 #define REST_Y (-REST)
267
268 // lookAt参数
269 GLdouble eyeX = 0, eyeY = REST_Y, eyeZ= REST_Z;
270 GLdouble centerX= 0, centerY= 0, centerZ= 0;
271 GLdouble upX= 0, upY= 0, upZ= 1;
272
273 void OnDraw(void) {
274     glClear(GL_COLOR_BUFFER_BIT  |  GL_DEPTH_BUFFER_BIT);
275     glClearColor(.7, .7, .7, .1);
276     glMatrixMode(GL_PROJECTION);
277     glLoadIdentity();
278     gluPerspective(75.0f, 1.0f, 1.0f, 40000000);
279     glMatrixMode(GL_MODELVIEW);
280     glLoadIdentity();
281     gluLookAt(eyeX, eyeY,eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
282
283     glEnable(GL_LIGHT0);
284     glEnable(GL_LIGHTING);
285     glEnable(GL_DEPTH_TEST);
286
287     // 实际绘制
288     for (int i=0; i<ARRAY_SIZE; i++)
289         Balls[i]->Draw();
290
291     glutSwapBuffers();
292 }
293
294 void OnUpdate(void) {
295     // 实际更新
296     for (int i=0; i<ARRAY_SIZE; i++)
297         Balls[i]->Update(TimePast);
298     OnDraw();
299 }
300
301 // 每次按键移动的距离
302 #define OFFSET (20000000 * KK)
303
304 // 按键操作变化视角
305 // w(+y方向)   a(-x方向)   d(+x方向)   x(-y方向)   s(+z 方向)   S(-z 方向)   r(reset)
306 void keyboard (unsigned char key, int x, int y) {
307     switch (key)     {
308     case 'w': eyeY += OFFSET; break;
309     case 's': eyeZ += OFFSET; break;
310     case 'S': eyeZ -= OFFSET; break;
311     case 'a': eyeX -= OFFSET; break;
312     case 'd': eyeX += OFFSET; break;
313     case 'x': eyeY -= OFFSET; break;
314     case 'r':
315         eyeX = 0; eyeY = REST_Y; eyeZ= REST_Z;
316         centerX= 0; centerY= 0; centerZ= 0;
317         upX= 0; upY= 0; upZ= 1;
318         break;
319     case 27: exit(0); break;
320     default: break;
321     }
322 }
323
324 int main(int argc, char*  argv[]) {
325     init();
326
327     glutInit(&argc, argv);
328     glutInitDisplayMode(GLUT_RGBA |  GLUT_DOUBLE);
329     glutInitWindowPosition(150, 50);
330     glutInitWindowSize(WIDTH, HEIGHT);
331     glutCreateWindow("SolarSystem   by Juwend");
332     glutDisplayFunc(&OnDraw);
333     glutIdleFunc(&OnUpdate);
334     glutKeyboardFunc(keyboard);
335     glutMainLoop();
336
337     return 0;
338 }

这个模型还有很多需要增加的地方,比如He老师(任课老师)提出的,轨道可以使用椭圆,包括星球也可以更现实一些,另外就是球面纹理了,需要把星球的皮给披上去,这样就更容易看出自转了,还有就是因为最长的公转链就是太阳、地球、月亮,所以在实现公转和自转的时候,还有点问题的,假如最长公转链里有更多,比如10个球,则以上代码就会出问题了,但是修改代码解决这个问题并不是很困难的问题。关于这些问题,如果有时间再改吧。

关于OpenGL环境配置的问题,我想我应该会再写一篇短文来介绍的,只是不知是何时了……………………………

在此我也要感谢JiangTao同学在这方面提供了大量的无私的帮助! 啊,太谢谢你了~~~~~~~~~~~ 另外,这是我在计算机三维动画这门课交的最后的大作业,希望CV代码的朋友一定要注意这个问题,并且能够理解我的补充这么一句话的意思。

OpenGL实现太阳系模型 —— Juwend
Juwend’s – http://www.juwends.com
笔者水平有限,若有错漏,欢迎指正,欢迎转载以及CV操作,但希注明出处,谢谢!

转载于:https://www.cnblogs.com/juwend/archive/2013/02/22/2922017.html

【转】OpenGL实现太阳系模型相关推荐

  1. OpenGL实现太阳系模型 —— Juwend

    OpenGL实现太阳系模型 发表于 2012 年 12 月 30 日 由 Juwend OpenGL是一个非常强大的图形引擎.传说当下最流行的图形引擎有两套,其中之一就是Windows平台上最常用的D ...

  2. python绘制太阳系模型_【循序渐进学图形学之】OpenGL绘制太阳系模型

    包括太阳.一颗行星和一颗卫星. d按键控制行星自转,y按键控制行星绕太阳公转,p控制卫星的公转. 代码: #include static int year = 0,day = 0,d = 0; voi ...

  3. matlab太阳系,基于Opengl的太阳系动画实现

    #include float fEarth = 2.0f;//地球绕太阳的旋转角度 float fMoon = 24.0f;//月球绕地球的旋转角度 void Init() { glEnable(GL ...

  4. WxGL应用实例:绘制高精度的3D太阳系模型

    文章目录 1 坐标系的选择 1.1 黄道坐标系 1.2 三维空间直角坐标系 2 使用JPL星历表计算轨道 2.1 日期时间 2.2 特定时刻天体的位置 2.3 天体运行轨道 3 太阳系模型 3. 1 ...

  5. OpenGL模拟太阳系运行

    程序要实现的目标功能 1.绘制太阳系中太阳,八大行星及各自的卫星的三维球体模型,包括太阳在内的各天体具备合理的相对位置大小,在各自的运转轨道上有序分布和运行. 2.程序应有较好的动画效果,各大行星和卫 ...

  6. python绘制太阳系模型_用python做一个漂亮的太阳系运动模拟

    贴一张静态图 太阳系现在只有8大行星,连太阳一起,一共是9张图片.如果没有的朋友,可以到文末的下载地址下载. def openSolor(solar): def loadImg(name): str1 ...

  7. python绘制太阳系模型_太阳系模型Python列表操作困难

    这是我在这里的第一篇文章. 所以我尝试用可视化的python制作一个太阳系模型.我将每个行星定义为一个球体,有半径.与太阳的距离.质量和动量变量.然后将每个行星(或天体)放入一个列表结构中.正如你现在 ...

  8. OPENGL读取OBJ模型(包围盒、法向等计算)附加源码与资源下载页面

    OPENGL读取OBJ模型 标签(空格分隔): OPENGL/C++ 哈哈,先贴出下载链接好吧.下载页面 首先大家不要害怕,读取obj模型听上去很高端很麻烦,其实当你真正了解obj模型的格式,以及OP ...

  9. 移动端利用OpenGL展示3D模型文件STL

    移动端利用OpenGL展示3D模型文件STL 突然发现上次写博客都是一年前了,没养成分享的习惯挺郁闷的,所以分享下个人感觉好玩的东西吧.纯理工科生笔杆子不硬,写的不好,哪里有看不懂的或者写的不好的希望 ...

最新文章

  1. 在世界第二届半机械人奥运会上,瘫痪驾驶员在Cybathlon BCI竞赛中争夺金牌
  2. Spring - Java/J2EE Application Framework 应用框架 第 18 章 使用Quartz或Timer完成时序调度工作
  3. python 全栈开发,Day79(Django的用户认证组件,分页器)
  4. centos7系统根目录扩容
  5. 探讨C#的out关键字
  6. python 调用外部程序 终端异常_python调用外部命令
  7. [Android 泥水匠] Android基础 之一:浅谈Android架构到HelloWorld案例的剖析
  8. java jdk1.8 API
  9. 五种I/O模型和Java NIO源码分析
  10. 微软开始受到越来越多尊重 谁是幕后功臣?
  11. 打印机显示smtp服务器未设置,打印机smtp服务器设置方法
  12. win10专业版激活方法——亲测可行!!!
  13. 【软件实战】5分钟拥有一款自己的软件(教程+成品展示)
  14. 掌控你的信息流:在自己的VPS上部署RSSHub
  15. 3 Directory traversal
  16. 怎么看python是64位还是32位_怎样查看python是64位还是32位
  17. GPRS网络组成及接口
  18. 判断点圆关系 (30 分)
  19. IOS中通过快捷捷径打开场所码或者健康码
  20. NFT Insider #87:The Sandbox 收购游戏开发工作室 Sviper,GHST 大迁徙即将拉开帷幕

热门文章

  1. 新浪微博数据库是如何设计的
  2. 【面试真题】腾讯2018秋招前端正式试题(含答案)
  3. 醛肽:(R)-MG-132 : Cbz-Leu-DLeu-Leu-醛基化、1211877-36-9
  4. 视频怎么压缩变小?教你快速学会压缩视频的教程
  5. 五、前端开发-JavaScript基础
  6. Matlab 求纳什效率系数(NSE)
  7. 公共服务机器人能给传统服务行业带来哪些变化?
  8. cogs 774. [USACO Open09] 捉迷藏
  9. Josephus again HDOJ3089
  10. 中国法定数字货币(DCEP)全面启航!全国普及势在必行