OpenGL – C++ Bài 9: Demo Trái đất – Mặt Trăng – Và Mặt Trời

Hi chào mừng các bạn đến với chủ đề: Học Lập Trình OpenGL tại  blog phát triển phần mềm 123AZ

Trong bài ngày hôm nay, tôi sẽ cùng các bạn thực hành một demo nhỏ vui vui.

Chúng ta cùng thực hiện mô phỏng, hệ mặt trời với 3 hành tinh chính.

1 Mặt trời.

2 Trái đất thân yêu của chúng ta.

3. Mặt trăng.

Và chúng ta sẽ thực hiện việc quay mặt trăng quanh trái đất, quay trái đất quanh mặt trời.

 

I. Step Cơ bản.
1. Tạo 3 hình cầu tại các vị trị như sau:

+ Mặt trời tại gốc tọa độ.

+ Trái đất tại vị trí E (8.0, 0.0, 0.0) so với hệ tọa độ của mặt trời.

+ Mặt trăng tại vị trí M(2.0, 0.0, 0.0) so với hệ tọa độ của trái đất  (Nghĩa là M(10.0, 0.0, 0.0) so với mặt trời).

=> Sử dụng hàm tạo hình cầu có sẵn trong bài số 7 đã tìm hiểu.

=> Sử dụng vật liệu tùy ý cho 3 tinh cầu (ví dụ mặt trời màu vàng, trái đất màu xanh, mặt trăng màu bạc.)

 

2. Sử dụng câu lệnh glTranslate để vẽ vị trí của vật theo yêu cầu 1 và glRotate để thực hiện quá trình quay vật xung quanh.

+ Trục quay là trục Y.

+ Sử dụng 3 biến toàn cục như sau để xác định chu kỳ quay của 3 tinh cầu

GLuint g_angle_day = 0.0;
GLuint g_angle_year = 0.0;
GLuint gl_angle_moon = 0.0;

+ Sử dụng

glRotatef(g_angle_year, 0.0f, 1.0f, 0.0f);

glRotatef (g_angle_day, 0.0f, 1.0f, 0.0f);

glRotatef (gl_angle_moon, 0.0f, 1.0f, 0.0f);

Để thực hiện quá trình quay khối cầu.

 

II. Lý thuyết chu kỳ quay của 3 tinh cầu.

+ Trái đất quay quanh mặt trời 1 vòng 360 độ mất 365 ngày. Tôi giả sử coi là 360 ngày tính cho chẵn => 1 ngày trôi qua, trái đất đi được 1 độ quanh mặt trời.

+ Trái đất cũng tự quay quanh mình nó được đủ 1 vòng tròn trong 1 ngày => 1 ngày trôi qua trái đất tự quay được 360 độ quanh nó.

+ Mặt trăng quay quanh trái đất với chu kỳ là 27.32 ngày, tôi coi là 27 ngày. => 1 ngày mặt trăng đi được 13.3 độ, tôi coi là 13 độ so với trái đất.

Như vậy tôi sẽ có công thức:

g_year += 1;

g_day += 360;

g_moon += 13;

3 Câu lệnh trên được thực hiện ngay sau render.

Mà chúng ta đang giả định là 1 ngày trôi qua, trong khi thời gian thực hiện câu lệnh chỉ khoảng a mili s.

Giả sử thời gian chạy các câu lệnh render và phép toán là 1 mili giây.

Thì lúc này 1 mili giây được được coi là 1 ngày cho 3 khối cầu.

Như vậy khi chạy chương trình lên, chúng ta sẽ thấy trong 1s, g_year tăng được 1 ngàn lần tức là quay được hơn 3 vòng.

=> Qúa nhanh để chúng ta quan sát.

Như vậy chúng ta sẽ phải điều chỉnh lại bằng cách sử dụng hàm sleep(value). Value tính theo mili s

Có 2 cách để chọn giá trị.

+ Mô phỏng đúng thời gian thực => value cần truyền vào là : 24*60*60*1000 mili s

=> sleep làm chương trình trễ lại đúng 24h thời gian thực để sau đó tăng (mô phỏng có tính giật cục, vì chúng ta đi rời rạc từng bước theo biến nguyên)

=> Suy chương trình chạy thời gian thực, và chạy cực chậm, và chúng ta khó hình dung được ngoài việc quan sát đủ 24.

+ Mô phỏng giả định.

Tôi chọn một giá trị phù hợp ví dụ như:

Tôi giả định 30s thời gian thực của tôi là 1 năm trôi qua, để tôi quan sát được trái đất quay quanh mặt trời đủ 1 năm.

Suy ra 1 ngày sẽ tương ứng với : 30/360 = 0.083s  = 83 mili s.

Suy ra tôi có : Sleep(83).

Và như vậy tôi có thể mô phỏng được trái đất quay quanh mặt trời với thời gian thực là 30s (giả định cho 360 ngày).

Full Code:
#include <gl\glut.h>

GLuint g_sun;
GLuint g_earth;
GLuint g_moon;

GLuint g_angle_day = 0;
GLuint g_angle_year = 0;
GLuint gl_angle_moon = 0;

GLuint MakeSphere(const float& radius)
{
  GLuint boxDisplay;
  boxDisplay = glGenLists(1);         
  glNewList(boxDisplay,GL_COMPILE);
  glutSolidSphere(radius, 64,16);
  glEndList();
  return boxDisplay;
}

void RendenScene()
{

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  gluLookAt(5.0, 5.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  GLfloat mat_ambien[] = {1.0, 1.0, 0.0f, 1.0f};
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambien);
  GLfloat diff[] = {05, 0.5, 0.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
  glCallList(g_sun);

  glRotatef(g_angle_year, 0.0f, 1.0f, 0.0f);
  glTranslated(8.0, 0.0, 0.0);
  glRotatef (g_angle_day, 0.0f, 1.0f, 0.0f);

  GLfloat mat_ambien2[] = {0.0, 0.0, 1.0f, 1.0f};
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambien2);
  GLfloat diff2[] = {1.0, 1.0, 1.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff2);
  glCallList(g_earth);

  glPushMatrix();
  glRotatef (gl_angle_moon, 0.0f, 1.0f, 0.0f);
  glTranslated(2.0, 0.0, 0.0);

  GLfloat mat_ambien3[] = {0.7, 0.7, 0.7f, 1.0f};
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambien3);
  GLfloat diff3[] = {1.0, 1.0, 1.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff3);

  glCallList(g_moon);
  glPopMatrix();

  glPopMatrix();

  Sleep(83);
  gl_angle_moon = (gl_angle_moon + 13);
  if (gl_angle_moon >= 360)
  {
    gl_angle_moon = 0;
  }

  g_angle_day = (g_angle_day + 360);
  if (g_angle_day >= 360)
  {
    g_angle_day = 0;
  }

  g_angle_year = (g_angle_year + 1);
  if (g_angle_year >= 360)
  {
    g_angle_year = 0;
  }

  glutSwapBuffers();
  glFlush();

  glutPostRedisplay();
}

void ReShape(int width, int height)
{
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  float ratio = (float)width/(float)height;
  gluPerspective(45.0, ratio, 1, 100.0);
  glMatrixMode(GL_MODELVIEW);
}


void Init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

  GLfloat light_pos [] = {1.0, 1.0, 1.0, 0.0};
  glLightfv(GL_LIGHT0, GL_POSITION, light_pos);

  GLfloat ambient[] = {1.0, 1.0, 0.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);

  GLfloat diff_use[] = {0.5, 0.5, 0.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff_use);

  GLfloat specular[] = {1.0, 1.0, 1.0, 1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);

  GLfloat shininess = 50.0f;
  glMateriali(GL_FRONT, GL_SHININESS, shininess);

  g_sun = MakeSphere(2.0);
  g_earth = MakeSphere(1.0);
  g_moon = MakeSphere(0.2);
}

void main()
{
  glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB);
  glutInitWindowSize(500, 500);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("Opengl Study");

  Init();
  glutReshapeFunc(ReShape);
  glutDisplayFunc(RendenScene);

  glutMainLoop();

}

 

 

 

14 thoughts on “OpenGL – C++ Bài 9: Demo Trái đất – Mặt Trăng – Và Mặt Trời

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.