1
\$\begingroup\$

I'm developing in libgdx java/android but not using any high-level environment like Unity.

I have a sphere at [0,0,0], with a PerspectiveCamera looking at it. Through the main game loop I have managed to have the camera orbiting the sphere in different directions. However, what I want to do is have a stationary camera and have 3 objects orbiting the sphere on their own accord, and their own orbital plane. Have been looking all day and struggled to get this working.

Eventually, I want to link the camera to always be above one of the orbitting objects, but that's at a later stage.

I also want to be able to have these objects orbitting on their own "forwards" direction, but able to change their direction over time. Say, from their top-down view, they each have a heading 0-359 degrees.

Anyone lend a hand with this? I've tried using 2D X/Y maps transposing onto mercator projections and then converted to spherical coordinates; I've tried Vector3 and setFromSpherical(); I've tried looking at Quaternions, and just got lost.

It's a relatively simple thing I'm trying to do, multiple orbiting objects around a sphere (radius 3, origin [0,0,0]), but just getting my initial approach wrong.

EDIT:

After talking the situation through, I have two options: I either keep track of the orbiting objects with theta/phi as to their position around the sphere, or just calculate the amount by which to rotate based on the object's direction (0-359). On further talks with DMGregory, the latter option would introduce orbital instability/divergence with roudning errors so I have decided to change my requirement to the following:

  • Keep track of the object's position based on 2x360 degree values for azimuth and polar, called theta and phi. The two coordinates are used to locate the object at any point in orbit around the sphere, but I need to be able to still "move" the orbital object "forwards" and thus change theta/phi accordingly, allowing the direction to still be changed.

Many thanks,

\$\endgroup\$
2
\$\begingroup\$

The parametric equations of circular motion are:

circle_x = radius * cos(rate * time + phase) + center_x
circle_y = radius * sin(rate * time + phase) + center_y

So all you really need to do is rotate this into an arbitrary 3D plane.

You can do this by providing two orthonormal basis vectors (meaning they are perpendicular and have a length of 1) u and v, and forming a weighted sum of them using the equations above as weights, essentially trading the fixed x & y axes for the axes of your choice:

orbit_position = circle_x * u + circle_y * v

This is equivalent to forming a rotation matrix or quaternion describing the orientation of each orbital plane and using it to transform an orbit in some simple reference plane, like

orbit_position = rotation * (circle_x, circle_y, 0)

You can choose u and v (the orientation of the orbit plane) however you like. One simple approach for polar orbits would be:

u = (cos(longitude), 0, sin(longitude)) v = (0, 1, 0)

By construction these are orthonormal, and allow you to rotate the orbits freely along one axis as you describe. All orbits of this form cross above two poles of the sphere (though you can avoid collisions by adjusting the phase or radius parameters)

\$\endgroup\$
0
\$\begingroup\$

Thanks DMGregory. I had to reply to my question rather than comment on your reply, as I need 50 rep to comment.

I can understand in theory what you're describing, however just having an issue applying that in my code.

Say I have the following move() method which is called every frame. It is used to calculate the new positions of just one object that will eventually orbit the sphere:

public void move(float delta) {
    //Check for keys
    if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
        this.objectDirection -= 5;
    }
    if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
        this.objectDirection += 5;
    }
    if (this.objectDirection > 360) {
        this.objectDirection = 0;
    }
    if (this.objectDirection < 0) {
        this.objectDirection = 360;
    }

    ....
}

I am storing the position of my object in object3DPosition which is a Vector3 type (in java libgdx), so say initially [0,0,-5]. Later after this 3D vector has been rotated, I set the posiiton of the object with:

modelInstanceObject.transform.setToTranslation(object3DPosition);

Now it's the inbetween bit which I'm struggling with. I'll use your code in the middle part "...." such as:

float speed = 1; //to adjust
//The parametric equations of circular motion:
double circle_x = RADIUS * Math.cos(Math.toRadians(delta * speed)); //+ center_x (rotate about origin anyway)
double circle_y = RADIUS * Math.sin(Math.toRadians(delta * speed)); //+ center_y (rotate about origin anyway)

//Rotate this into an arbitrary 3D plane.
Vector3 u = new Vector3(1,0,0);
Vector3 v = new Vector3(0,1,0);

//Vector3 orbinPosition = u.mul(circle_x) + v.mul(circle_y);
Vector3 orbitPosition = u.scl((float)circle_x).add(v.scl((float)circle_y));

//set new position
object3DPosition.set(orbitPosition);

Not sure If that's the correct implementation, however movement is still not as expected.

Many thanks

\$\endgroup\$
  • \$\begingroup\$ You can edit your question for follow-up. Answers which don't provide solutions are usually deleted. You haven't described what you mean by "not as expected" but it looks like you've replaced the time variable (which continually increases) with a delta time (which hovers around the same value) — that will tend to freeze the objects in one part of their orbit. \$\endgroup\$ – DMGregory Dec 19 '15 at 13:49
  • \$\begingroup\$ You're right. The lines of code I used from you are based on calculating an actual position instead of describing an amount by which to rotate. That's keeping it in the same place, with some "wobbling" (varying delta values). So I have 2 options, I either keep track of the orbiting objects with theta/phi as to their position around the sphere, or just calculate the amount by which to rotate based on the object's direction (0-359). I think the latter would be simpler to implement and give better expandability going forwards. Not too certain how to change your code to make that effect though \$\endgroup\$ – Jammo Dec 19 '15 at 14:16
  • \$\begingroup\$ I wouldn't recommend your second solution, since rounding errors will tend to accumulate and cause your objects to diverge from their orbits over time. This adds more complexity in the form of error correction. If you need a solution in terms of incremental movement, add that requirement to your question. \$\endgroup\$ – DMGregory Dec 19 '15 at 14:22
  • 1
    \$\begingroup\$ I have flagged your question for moderator attention and asked them to merge this account with the unregistered one you used to post the question; if they do you'll be able to comment, edit and accept answers to your question. \$\endgroup\$ – Vaillancourt Dec 19 '15 at 15:26
  • 1
    \$\begingroup\$ It turns out.. you'll probably want to go here to merge accounts. \$\endgroup\$ – Vaillancourt Dec 19 '15 at 18:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.