Making an object orbit a sphere (in a 2D-like space)

I am posting links to two pictures that will (hopefully) explain what movement I want to achieve. (links are to my google drive because the site keeps saying “wrong file” if I try to upload them here)

So basically I want the ship (orange) to orbit the solid body (grey) in a circle which lies in the yz-plane. Holding down the left/right arrow should make the ship continuously orbit the body following the circular trajectory. Pressing the up/down arrow should rotate the circle so it is no longer in the yz-plane but is “tilted”; the ship should move on that now-tilted circle.

This way, you control two coordinates but are still sort of able to cover a 3D volume since you move on a fixed-radius sphere.

I cannot get it to work as I’m out of ideas. I tried:

  1. two successive rotations (an x- and a y-rotation)
  2. moving the ship in spherical coordinate system
  3. rotate about y-axis first, then rotate about the rotated x-axis (as a result of the rotation about the y-axis) - see code below

but these approaches don’t work.

Below is my code so far. User input is received via float hor (left/right arrows) and float vert (up/down arrows).

mat4 shipMatrix = identity();

rotate(&shipMatrix, test, sinf(hor), 0, cosf(hor));
rotate(&shipMatrix, vert, 0, 1, 0);

//stable, prepare ship for user input
scale(&shipMatrix, 0.5, 0.5, 0.5);
translate(&shipMatrix, 0, 0, 3);
rotate(&shipMatrix, 3.14159265, 0, 1, 0);

glUniformMatrix4fv(modelMatrixLoc, 1, GL_FALSE, &shipMatrix.m[0]);

I feel this might be more math than OpenGL but hopefully some OpenGL expert has encountered this problem before and knows of a solution.

You don’t have enough matrices.

You have the modelMatrixLoc matrix, which I assume is the planet’s matrix. And you have the ShipMatrix. You could use the planet matrix, but I assume you want to not make the planet itself part of this. So, you need a pivot point matrix. Starting out it should equal the planet matrix, since you want to orbit the planet. You could set it equal to another planet to orbit that planet instead if you wanted to.

It’s position should always be the same as the planet, but it should rotate to change the angle of orbit.

In order to determine the ship’s matrix, you should multiply the pivot matrix times the ship’s matrix to give you the matrix that the ship actually uses. The ship’s matrix will be maintained separately and never actually used directly.

But you then rotate the ship’s matrix to make it orbit. You rotate the pivot’s matrix to change the orbital path. Multiply them together and you get the matrix you use to draw the ship. The order of multiplication is critical. One will rotate and the other order will orbit. If one order of multiplication doesn’t work, just reverse it. I never can remember if it’s pivot times ship or ship times pivot. But reverse it if it’s wrong. It’s pretty straight forward.

If you have it setup properly, when you translate the ship’s matrix, it should increase the altitude of the orbit, rather than actually moving the ship.

I took the time to code it.

Here I have Cube2Pivot as my pivot point. Cube.WorldMatrix is the world matrix of my planet. Cube2World is the matrix of my ship.

if (OperatingSystem.Keyboard.KeyPressed == GLFW_KEY_Y && OperatingSystem.Keyboard.ActionPressed != GLFW_RELEASE)
			Cube2Pivot =   glm::rotate(glm::mat4(), glm::radians<float>(1), glm::vec3(0.0f, 0.0f, 1.0f)) * Cube2Pivot;
if (OperatingSystem.Keyboard.KeyPressed == GLFW_KEY_H && OperatingSystem.Keyboard.ActionPressed != GLFW_RELEASE)
			Cube2Pivot = glm::rotate(glm::mat4(), glm::radians<float>(-1), glm::vec3(0.0f, 0.0f, 1.0f)) * Cube2Pivot;

Cube2Pivot = Cube2Pivot * glm::rotate(glm::mat4(), glm::radians<float>(1), glm::vec3(0.0f, 1.0f, 0.0f));
Cube2.WorldMatrix = Cube.WorldMatrix * Cube2Pivot * Cube2World;

Cube2Pivot = Cube2Pivot * glm::rotate(glm::mat4(), glm::radians<float>(1), glm::vec3(0.0f, 1.0f, 0.0f)); just orbits the ship around the planet because it’s around the Y axis. Rotating the Cube2World would have done the same thing. Here I have the pivot point relative to the Cube.WorldMatrix which is the matrix of my planet, which you may or may not want. If you wanted the planet to rotate in the opposite direction, for example, you would probably want to divorce these.

The key here is that when you multiply a matrix times another matrix, the result is a parent-child relationship.