Jump to content
  • Advertisement
codelyoko373

C++ FreeGLUT - Making Planets Orbit

Recommended Posts

Posted (edited)

I wasn't sure if this would be the right place for a topic like this so sorry if it isn't.

I'm currently working on a project for Uni using FreeGLUT to make a simple solar system simulation. I've got to the point where I've implemented all the planets and have used a Scene Graph to link them all together. The issue I'm having with now though is basically the planets and moons orbit correctly at their own orbit speeds.

I'm not really experienced with using matrices for stuff like this so It's likely why I can't figure out how exactly to get it working. This is where I'm applying the transformation matrices, as well as pushing and popping them. This is within the Render function that every planet including the sun and moons will have and run.

if (tag != "Sun")
{
    glRotatef(orbitAngle, orbitRotation.X, orbitRotation.Y, orbitRotation.Z);
}

glPushMatrix();

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

glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices);

if (tag != "Sun")
{
    glPopMatrix();
}

The "If(tag != "Sun")" parts are my attempts are getting the planets to orbit correctly though it likely isn't the way I'm meant to be doing it. So I was wondering if someone would be able to help me? As I really don't have an idea on what I would do to get it working. Using the if statement is truthfully the closest I've got to it working but there are still weird effects like the planets orbiting faster then they should depending on the number of planets actually be updated/rendered.

Edited by codelyoko373

Share this post


Link to post
Share on other sites
Advertisement
13 hours ago, codelyoko373 said:

weird effects like the planets orbiting faster then they should depending on the number of planets actually be updated/rendered

I see some problems in your code:

  1. The first is that your rotation depends on your frame rate so on a faster computer you will render more frames and rotate faster. Use some kind of time delta here to fix the update for every PC you run your code at
  2. You shoudldn't make a difference for "sun" an other objects in your scene. If it isnt a sun, you first rotate the planets last matrix, add a new matrix to the stack and then translate and rotate again, this couldnt work at all!

You should first clean up your object class. An object has an origin from its parent that may or may not be in a linar hirachy. So you need first to load a clean matrix for your root object in the scene (your sun) and do the transformation for that object. Translate the object first to where it belongs to as the objects origin, scale the object because you would get mismatches in translation either and then rotate the object for each axis on its own so you wont get any rotation mismatches (like a planet is spinning arround a certain axis). The you should iterate any child object that is in this objects hirachy with the same matrix transformation as base so the origin of any child object is the origin and transform of the root object + the child objects relative coords and transform. This way you build the scene graph.

In code it would look like this

void Render()
{
    glPushMatrix();

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

    glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices);

    for(int i = 0; i < childCount; i++)
        childs[i]->Render();

    glPopMatrix();
}

This is untested but should work in theory :)

Share this post


Link to post
Share on other sites
6 hours ago, Shaarigan said:

I see some problems in your code:

  1. The first is that your rotation depends on your frame rate so on a faster computer you will render more frames and rotate faster. Use some kind of time delta here to fix the update for every PC you run your code at
  2. You shoudldn't make a difference for "sun" an other objects in your scene. If it isnt a sun, you first rotate the planets last matrix, add a new matrix to the stack and then translate and rotate again, this couldnt work at all!

You should first clean up your object class. An object has an origin from its parent that may or may not be in a linar hirachy. So you need first to load a clean matrix for your root object in the scene (your sun) and do the transformation for that object. Translate the object first to where it belongs to as the objects origin, scale the object because you would get mismatches in translation either and then rotate the object for each axis on its own so you wont get any rotation mismatches (like a planet is spinning arround a certain axis). The you should iterate any child object that is in this objects hirachy with the same matrix transformation as base so the origin of any child object is the origin and transform of the root object + the child objects relative coords and transform. This way you build the scene graph.

In code it would look like this


void Render()
{
    glPushMatrix();

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

    glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices);

    for(int i = 0; i < childCount; i++)
        childs[i]->Render();

    glPopMatrix();
}

This is untested but should work in theory :)

Thanks a lot, I've not tested it yet (currently am) though does this mean that each "entity" should have a Scene Graph of it's own? Since currently I've just got one main Scene graph and added all the planets to it with the sun being the parent. But having it that way, I have no way to loop over the children within the parent like you've shown, I can only loop over them one by one

Share this post


Link to post
Share on other sites

The scene graph is simply a tree structure of entity references where each node is itself a leaf of its parent node. In AAA games and engines like Unity or Unreal, the scene graph simply holds some transform matrices and reference pointers to the entities. Then when an entity changes, the scene graph will update its matrix and update the matrices of all of its children.

Then when rendering happens, the scene graph is traversed from root node to its leafs (leaving all the frustum culling and hidden object detection away) sets the transform to the pre-calculated matrix and then pushes the VBO onto the hardware pipeline

Share this post


Link to post
Share on other sites
12 hours ago, Shaarigan said:

The scene graph is simply a tree structure of entity references where each node is itself a leaf of its parent node. In AAA games and engines like Unity or Unreal, the scene graph simply holds some transform matrices and reference pointers to the entities. Then when an entity changes, the scene graph will update its matrix and update the matrices of all of its children.

Then when rendering happens, the scene graph is traversed from root node to its leafs (leaving all the frustum culling and hidden object detection away) sets the transform to the pre-calculated matrix and then pushes the VBO onto the hardware pipeline

So I've implemented your code and so far it seems to work fine though how exactly could I get it so the planets orbit at their own speeds since currently they orbit based on the rotation of the sun instead of their own orbit speeds.

Share this post


Link to post
Share on other sites

You should imagine that what you actually have is a solar system model as something like this

nc1626_3.jpg

Anything is connected to each other and to rotate one means rotating all its children, so when you rotate the sun, any planet connected to the sun also rotates and any moon connected to the planets also rotates based on the planets rotation. What you need is something that looks like this

images?q=tbn:ANd9GcTpiS_9nfWdu04PLS8-ZO8

Here each planet is connected to its own axis (so dont has a parent child relation to the sun. What you can do is to add proxy objects to your scene graph that themselfs hold the planets. Instead of rotating the sund, you rotate the proxy object at certain angle increase and so get 'individual' orbital movement

Share this post


Link to post
Share on other sites
8 hours ago, Shaarigan said:

You should imagine that what you actually have is a solar system model as something like this

nc1626_3.jpg

Anything is connected to each other and to rotate one means rotating all its children, so when you rotate the sun, any planet connected to the sun also rotates and any moon connected to the planets also rotates based on the planets rotation. What you need is something that looks like this

images?q=tbn:ANd9GcTpiS_9nfWdu04PLS8-ZO8

Here each planet is connected to its own axis (so dont has a parent child relation to the sun. What you can do is to add proxy objects to your scene graph that themselfs hold the planets. Instead of rotating the sund, you rotate the proxy object at certain angle increase and so get 'individual' orbital movement

That makes sense :). So What I've done is created, basically a blank object with it's own scene graph and attached all the planets to it, and then attached it to the Sun.

What I'm not sure how to do now though is have the planets affected by the orbit speed since currently the render function still looks like this:

glPushMatrix();

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

	if (mesh != nullptr)
	{
		glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices);
	}

	if (sceneGraph != nullptr)
	{
		sceneGraph->Render(sceneGraph->GetChildren()->GetHeadNode());
	}

	glPopMatrix();

Which is applied to every object including the sun and the empty object I just made. So would I need to have some if statement to check what entity is currently rendering and then change the rotation matrix accordingly or? 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Posted (edited)

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: 

 

Edited by cowcow

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
  • Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By Ricardo3Ddev
      Hi guys!
      This is a independent game being produced by me and my brother. We’ve been working on it for about 6 months and we’ve already done a good part of the game. We hope to finalize and make it available on Steam by the end of this year.
      We are using Blender 3D and Gimp software for production.
       
      About the Game: Dongo Adventure will be a 3D platform style game, where the main character (Dongo) is a mouse that ventures through various scenarios (sewers, culverts, streets, electric grid, etc.) and faces several enemies along the way (cockroaches, mosquitoes, spiders, toxic gases, electrical wires, etc.). He carries a basket / backpack with cheeses that he uses to throw and defend himself from enemies, as well as being able to push objects that helps him to overcome obstacles. The ultimate goal will be a surprise!
      The game follows the style of classic platform games, bringing many surprises and challenges.
       
      Now we are developing new scenarios and enemies. We hope to publish news soon...
      Game page on Steam: http://store.steampowered.com/app/811450/Dongo_Adventure/ - (Teaser UPDATED)
      Dongo Adventure (Indie Game Project) – First Gameplay Teaser + Making Of: https://www.youtube.com/watch?v=X2nmxtkE0xk
      Dongo Adventure (Indie Game Project) – First Gameplay Teaser (UPDATED) + Making Of: https://vimeo.com/250501345
       
      Thanks for following the project!

    • By Mailbox
      Hello,
      I'm in the midst of developing a simple 3d physics engine, but have been stuck on a problem for quite a while now. I would really appreciate it if someone could have a look at it, because I'm at a loss.
      The issue I'm having concerns the collision response code, which seems to fail spectacularly in some cases, generating wrong impulse magnitudes. Specifically, something with the angular part of it is wrong, since it works as expected when only dealing with the linear part.
      I'm still not sure if I calculate the inertia tensor in world coordinates the right way, so that could be one possible culprit (though I've tried a few different ways). Impulses seem to be applied correctly to the bodies, so I think the error lies in the calculation of the impulse magnitude denominator.
      I've checked it many times with the way the Bullet physics engine does it, with the formulas available at Wikipedia, and some other sources, to no avail.
      The bodies simply keep bouncing off eachother (even though there is supposed to be no restitution) or spinning wildly on collisions.
      Here is the code that deals with the collision response:
      Vector3 originA = contactOrigin - bodyA.Position; Vector3 originB = contactOrigin - bodyB.Position; Vector3 velocityA = bodyA.Velocity + Vector3::Cross(bodyA.AngularVelocity, originA); Vector3 velocityB = bodyB.Velocity + Vector3::Cross(bodyB.AngularVelocity, originB); Vector3 velocity = velocityA - velocityB; Matrix3x3 inverseWorldInertiaTensorA = Matrix3x3::Scale(bodyA.InverseInertia) * Matrix3x3::Rotate(bodyA.Orientation); Matrix3x3 inverseWorldInertiaTensorB = Matrix3x3::Scale(bodyB.InverseInertia) * Matrix3x3::Rotate(bodyB.Orientation); float normalVelocity = Vector3::Dot(velocity, contactNormal); if (normalVelocity > 0.f) { float impulseDenominator = bodyA.InverseMass + bodyB.InverseMass + Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal), originA), contactNormal) + Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal), originB), contactNormal); float j = -normalVelocity / impulseDenominator; bodyA.Velocity += j * bodyA.InverseMass * contactNormal; bodyB.Velocity -= j * bodyB.InverseMass * contactNormal; bodyA.AngularVelocity += j * (inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal)); bodyB.AngularVelocity -= j * (inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal)); } Thanks in advance!
    • By Luca Falco
      https://www.youtube.com/watch?v=UMoc52DEoC8     ABOUT THE GAME: Room54 is a first-person Horror/adventure  Videogame for pc,mac and linux users. the game is currently under development by a very small team, we put so much effort in this project and we are keep doing our best for that we are going to launch a kickstarter campaing in order to reach our ideal budget to complete the project, we hope the GameDev community can help us a lot                      STORY:   Daniel is a family father like many other, one day he decide with your wife and his daughter  to spend her winter holidays at their mountain house that they have recently buy in  mountain ,a  wonderful place surrounded by the nature of the woods,  Completely far away from the caotic city life. During their holidays Daniel and his family will understand that they are not welcome there and they will discover an  hided and disturbing part of the valley that they have never seen before                       GAMEPLAY:   You will play as Daniel, a father that will try to save his family, your gameplay will be focused on discovering secrets places around valley,investigating and trying to survive, you will find object that will help you solve enigma and to stay alive. The immersive audio and  environment will make you feel constantly follow by an high anxiety dose  during the game.                         SOCIAL PAGES:     Follow us to get the latest development news and insights     IndieDB:     http://www.indiedb.com/games/room54   Twitter:       https://twitter.com/Room54Thegame   facebook:   https://www.facebook.com/Room54/
    • By Gnollrunner
      Hi again,  After some looking around I have decided to base my game directly on Direct X rather than using an existing game engine.  Because of the nature of the stuff I'm doing it just didn't seem to fit very well and I kept running into road blocks.  At this point I have a big blob of code for doing fractal world generation and some collision code,  and I'm trying to put it into some form that resembles a game engine.  Since I've never used one before It's a bit alien to me ..... so can someone direct me to a book, website, article, whatever... that covers this?  I'm mainly looking for stuff that covers C++ library design. I'm not adverse to using 3rd party tools for stuff I can used them for.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!