Search code examples
pythonopenglgraphics3dpyopengl

Making a Solar System in OpenGL


I am trying to make a solar system in OpenGL but the planet is not revolving around sun. That is revolving around some other axis. How to fix this?

First, I am drawing a sun, Then, there is rotation, translation and again rotation of first planet. So it should revolve around the sun and rotate on it's own axis, but that's not happening.

I also want to make the circle on which planet will revolve. How to make the circles in XZ plane (possibly)

from __future__ import division
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

year = 0
day = 0

def init(): 
   glClearColor (0.0, 0.0, 0.0, 0.0)
   glShadeModel (GL_FLAT)


def display():

   global day, year

   glClear (GL_COLOR_BUFFER_BIT)

   glColor3f (1.0, 1.0, 0, 1)
   glPushMatrix()
   glutSolidSphere(1.0, 20, 16)   # draw sun

   glRotatef(year, 0.0, 1.0, 0.0)
   year = (year + 1) % 360

   glPushMatrix()
   glTranslatef(2.0, 0.0, 0.0)
   glRotatef(day, 0.0, 1.0, 0.0)
   day = (day + 1) % 360

   glColor3f (0, 0, 1.0);
   glutWireSphere(0.2, 10, 8)    # draw smaller planet
   glPopMatrix()

   glPushMatrix()
   glTranslatef(4.0, 0.0, 0.0)
   glRotatef(day, 0.0, 1.0, 0.0)
   glColor3f (1, 0, 0.0, 1)
   glutWireSphere(0.2, 10, 8)
   glPopMatrix()

   glPopMatrix()
   glutSwapBuffers()

   # delay
   for i in range(100000):
      pass

def reshape(w, h):
   glViewport (0, 0, w, h)
   glMatrixMode (GL_PROJECTION)
   glLoadIdentity ()
   gluPerspective(70.0, w/h, 1.0, 20.0)
   glMatrixMode(GL_MODELVIEW)
   glLoadIdentity()
   gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowSize(800, 800)
glutInitWindowPosition (100, 100)
glutCreateWindow("Transformation")
init ()
glutDisplayFunc(display)
glutIdleFunc(display)
glutReshapeFunc(reshape)
glutMainLoop()

Solution

  • Planet should go behind the sun (invisible for some time) and then it would be visible after coming back, but that' not happening.

    You have to enable the depth test and you have to clear the depth buffer.

    The depth test can be enabled by glEnable(GL_DEPTH_TEST). The default depth function glDepthFunc is GL_LESS. This causes that fragments which are behind a fragment that was drawn before, are skipped:

    Before every frame the depth buffer has to be cleared, by glClear(GL_DEPTH_BUFFER_BIT), to restart this process.

    Add the following lines to your code, at the begin of display:

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
    glEnable( GL_DEPTH_TEST )
    

    Of coures you have to create a window with a depth buffer (glutInitDisplayMode(GLUT_DEPTH)):

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
    

    See the preview:

    enter image description here



    Can you also tell how to make circle where the planet is revolving?

    I recommend to use time for setting up the simulation. The following example shows the sun, earth and the moon (Of course it is a very very simplified simulation with completely wrong sizes and distance relations):

    import time
    
    start_time = time.time()
    
    def display():
    
        t = time.time() - start_time
        year_period = 5.0                  # 5 seconds for simulating one year 
        year     = (t / year_period)
        day      = 365 * year
        moon_sid = (365 / 27.3) * year
    
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
        glEnable( GL_DEPTH_TEST )
    
        glColor4f (1.0, 1.0, 0, 1)
        glPushMatrix()
        glutSolidSphere(1.0, 20, 16)             # sun
    
        glRotatef(year*360.0, 0.0, 1.0, 0.0)     # earth rotation around the sun 
        glTranslatef(3.0, 0.0, 0.0)              # earth location
    
        glPushMatrix()                           # push earth system 
    
        glPushMatrix()
        glRotatef(day*360.0, 0.0, 1.0, 0.0)      # earth spinn
        glRotatef(90-23.4, 1.0, 0.0, 0.0)        # earth axis
        glColor3f (0, 0, 1)                      # blue
        glutWireSphere(0.3, 10, 8)               # earth
        glPopMatrix()
    
        glPushMatrix()
        glRotatef(moon_sid*360.0, 0.0, 1.0, 0.0) # moon sidereal
        glTranslatef(1.0, 0.0, 0.0)              # distance moon to earth
        glRotatef(90, 1.0, 0.0, 0.0)
        glColor4f (0.4, 0.5, 0.6, 1)                         
        glutWireSphere(0.1, 10, 8)               # moon
        glPopMatrix()
    
        glPopMatrix()                            # pop earth system 
    
        glPopMatrix()
        glutSwapBuffers()
    

    enter image description here