FreeGLUT - Making Planets Orbit

Started by
18 comments, last by Shaarigan 5 years, 12 months ago
1 hour ago, Shaarigan said:

As I wrote, you need a proxy object for each different orbit speed. Look at the second image

But how exactly do I go about applying that orbit speed?

Advertisement

You alter the position and velocity of each planet by integrating (adding). Your position is updated by the velocity, and the velocity is updated by the acceleration.

Here is some math related to calculating a position and velocity for the orbiting body: 

 

I also put up a C++/OpenGL 1.x/GLUT application that draws Mercury's path as it orbits the Sun.

To start the simulation, the planet is placed at the aphelion (0, 69817079000, 0), with an initial velocity (-38860, 0, 0), and everything is taken care of from there.

https://github.com/sjhalayka/mercury_orbit_glut

Check out idle_func() in main.cpp. That's where the integration occurs.

 

58 minutes ago, cowcow said:

You alter the position and velocity of each planet by integrating (adding). Your position is updated by the velocity, and the velocity is updated by the acceleration.

Here is some math related to calculating a position and velocity for the orbiting body: 

 

So I be applying a velocity to the position of the planets and updating it each frame by a Orbit Speed?

I'm guessing you mean altering the position of the object used here?:


glTranslatef(position.X, position.Y, position.Z);
	glRotatef(rotationAngle, rotation.X, rotation.Y, rotation.Z);
	glScalef(scale.X, scale.Y, scale.Z);

 

Yes, every time the idle function is called, one will do these things to calculate the position and velocity:

https://gist.github.com/sjhalayka/a499a7f0429884bf3fd6ef38151ecd58

There is also this Mercury fact sheet, from which you can obtain the speed of mercury at perihelion (closest approach) and aphelion (furthest approach):

https://nssdc.gsfc.nasa.gov/planetary/factsheet/mercuryfact.html

That is, the speed (the length of the velocity vector) of Mercury at aphelion is 38860 metres per second, like in the code I posted.

I'm not super experienced with scene graphs, sorry.

In my code I don't use a scene graph -- I just alter the planet object's position and velocity, and then pass the position directly into glVertex3f(). That's right, I use OpenGL 1.x for the demo.

All I know is that scene graphs become very important when it comes to solving for inverse kinematics? There's a hierarchy going on there? I checked out Mario Kart for Switch, and they got some serious physics + inverse kinematics to model the idle animations of the contestants. LOL

So as it seems it is unclear what a scene graph does I post this Scene Graph Tutorial here. A scene graph isnt used to alter velocities,speeds or whatever you thought it is for, as explained, a scene graph just simplifies parent child relations in drawing in a simple tree structure. Your map is a root object while your character walking on the map is a child of it. Your character has an armor, a weapon and some stuff on its belt attached that are themselfs childs of your character. Moving your character means altering the position of its equipment too.

And this is what your current problem is, you attach your planets to the sun. Rotating the sun means rotating its childs too so the planets would always rotate at the speed of the sun.

This is what matrices are for. Calculating the transformation matrix of a child means firs calculate that oneof its parent and multiply those matrices together to get the childs model matrix. Vertex (each) * Model * View (your eye position) * Projection (perspective transformation) = pixel on the screen. This is what the immediate mode matrix and transform functions are in OpenGL.

glPushMatrix adds a new matrix to the stack that inherits from the parent matrix

glTranslate, glRotate, glScale do all the multiplication on the top matrix of the stack

glPopMatrix removes the current matrix from the stack

You normally start with an identity matrix


glLoadIdentity();
glPushMatrix();

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1

that means each vertex is placed at the same position it is used to. Then you translate the matrix by 1 and get


glTranslatef(x, y, z);

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1

//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1

what means a vertex at position { 0, 0, 0 } is translated by { X, Y, Z }. Now you take the scene graph and we assume that your root node is at stack index 1 and has one leaf node to render


glPushMatrix();

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1
  
//Stack-Index 2
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1

The leaf starts at its parents current transform and calling the leafs transform will result in


glTranslatef(x, y, z)

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1
  
//Stack-Index 2
1, 0, 0, X1 + X2
0, 1, 0, Y1 + Y2
0, 0, 1, Z1 + Z2
0, 0, 0, 1

Next child of this leafe node would act the same, this is what a scene graph is used for. As I wrote, in AAA Games and Engines the scene graph also does culling of objects to speedup rendering so if a leaf is disabled for rendering, its childs could be skipped to and so on.

What is the sense of this? The sense is simply to simplify rendering. Otherwise you would have to iterate through the list of objects and its parents each on its own and do a lot of matrix multiplications and visibility tests that slow down your game.

Related to your entry post, you have had anything attached to the sun so transforming the sun meant you changed the entire root matrix for anything that is a leaf of the sun. Then transforming any leaf was iterative transforming the whole chain in a way that did'nt lead to the result you expected. So if you want to transform each planet on its own speed, you need each planet to inherit from the identity matrix so become a root node instead of a leaf of the sund root node. This is the most simple solution I can give ya :)

Just in case it's not clear...

The gravitation constant G is 6.673e-11.

The sun's mass M is 1.989e30.

For the planet Mercury:

The aphelion distance is 69817079000.

The perihelion distance is 46001200000.

The semi major axis A is the (perihelion distance + the aphelion distance) / 2 is 57909100000.

The eccentricity e is 0.20563069.

The orbit speed at aphelion is v = sqrt((G*M/A) * (1 - e)/(1 + e)) = 38860.5.

12 hours ago, Shaarigan said:

So as it seems it is unclear what a scene graph does I post this Scene Graph Tutorial here. A scene graph isnt used to alter velocities,speeds or whatever you thought it is for, as explained, a scene graph just simplifies parent child relations in drawing in a simple tree structure. Your map is a root object while your character walking on the map is a child of it. Your character has an armor, a weapon and some stuff on its belt attached that are themselfs childs of your character. Moving your character means altering the position of its equipment too.

And this is what your current problem is, you attach your planets to the sun. Rotating the sun means rotating its childs too so the planets would always rotate at the speed of the sun.

This is what matrices are for. Calculating the transformation matrix of a child means firs calculate that oneof its parent and multiply those matrices together to get the childs model matrix. Vertex (each) * Model * View (your eye position) * Projection (perspective transformation) = pixel on the screen. This is what the immediate mode matrix and transform functions are in OpenGL.

glPushMatrix adds a new matrix to the stack that inherits from the parent matrix

glTranslate, glRotate, glScale do all the multiplication on the top matrix of the stack

glPopMatrix removes the current matrix from the stack

You normally start with an identity matrix



glLoadIdentity();
glPushMatrix();

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1

that means each vertex is placed at the same position it is used to. Then you translate the matrix by 1 and get



glTranslatef(x, y, z);

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1

//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1

what means a vertex at position { 0, 0, 0 } is translated by { X, Y, Z }. Now you take the scene graph and we assume that your root node is at stack index 1 and has one leaf node to render



glPushMatrix();

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1
  
//Stack-Index 2
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1

The leaf starts at its parents current transform and calling the leafs transform will result in



glTranslatef(x, y, z)

//Stack-Index 0
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
  
//Stack-Index 1
1, 0, 0, X
0, 1, 0, Y
0, 0, 1, Z
0, 0, 0, 1
  
//Stack-Index 2
1, 0, 0, X1 + X2
0, 1, 0, Y1 + Y2
0, 0, 1, Z1 + Z2
0, 0, 0, 1

Next child of this leafe node would act the same, this is what a scene graph is used for. As I wrote, in AAA Games and Engines the scene graph also does culling of objects to speedup rendering so if a leaf is disabled for rendering, its childs could be skipped to and so on.

What is the sense of this? The sense is simply to simplify rendering. Otherwise you would have to iterate through the list of objects and its parents each on its own and do a lot of matrix multiplications and visibility tests that slow down your game.

Related to your entry post, you have had anything attached to the sun so transforming the sun meant you changed the entire root matrix for anything that is a leaf of the sun. Then transforming any leaf was iterative transforming the whole chain in a way that did'nt lead to the result you expected. So if you want to transform each planet on its own speed, you need each planet to inherit from the identity matrix so become a root node instead of a leaf of the sund root node. This is the most simple solution I can give ya

Alright, I think I've got an idea of what I'm doing XD, more then I did though I've still not got it working.

Should I be applying this custom orbit rotation with a matrix like this?


glRotatef(orbitAngle, orbitRotation.X, orbitRotation.Y, orbitRotation.Z);

Or applying a velocity to the position like the other poster mentioned. I did try it but it didn't work well.

Maybe share your code on GitHub to see what went wrong. I think the idea of rotation is good, but it would only handle orbits that are circular (no eccentricity).

6 hours ago, cowcow said:

Maybe share your code on GitHub to see what went wrong. I think the idea of rotation is good, but it would only handle orbits that are circular (no eccentricity).

Well it was just that it affected the position of the planets too much, to the point where they just flew off. Though that maybe of been because the sun was also having a velocity applied to it.

This the planets orbit isn't affected by their position so I can't really apply a velocity to the planets position and have them orbit at their own speed.

This topic is closed to new replies.

Advertisement