Sometimes, when working on a project, you get stuck.

# The Problem

Recently, I was working on (what should have been) an elementary programming exercise: get the player to rotate around an object in 3D when a key is held down. I’d immediately started tackling the problem from the angle of “OK, how do I rotate around an arbitrary axis?”. Big mistake.

It’s pretty easy to make an error (or twenty) when you’re writing this out in code: *(Image source)*

For days, I just could *not* get the code to work. The player quickly developed a knack for teleporting all over the place, but despite his new-found skills with wizardry, he still wouldn’t rotate around the ball.

# The Solution

Eventually, I gave up and stepped away from the problem for a while. A few days later, after a full night’s rest, I sat down in front of my laptop, scrapped all the code I had, and started from scratch. I got it working in less than an hour.

**Lesson learned**: Sometimes, you need to step back and take a break. In retrospect, I feel kind of silly for getting stuck for a few days on this one.

Here’s the (somewhat unoptimized) code to calculate the offset to move by each frame:

// Helper method to re-calculate the translation vector each frame while the // player is rotating around the ball // returns the offset the camera should move by Ogre::Vector3 FrameUpdateListener::calculateRotation() { // get player position const Ogre::Vector3 playerPosition = GameState::getInstance()->getPlayerCamera()->getPosition(); // get ball position const Vector3D* const pBallPosition = GameState::getInstance()->getBall()->getBoundingVolume()->getCenter(); const Ogre::Vector3 ballPosition(pBallPosition->x, pBallPosition->y, pBallPosition->z); // get vector for player relative to ball const Ogre::Vector3 localPlayerPosition = playerPosition - ballPosition; // get theta (angle to rotate by) const int direction = isRotatingClockwise ? 1 : -1; const Ogre::Radian theta(static_cast<Ogre::Real>(direction * 0.05f)); // angle to adjust by // store cos/sin in temp variables to save calculations const Ogre::Real cosTheta = Math::Cos(theta); const Ogre::Real sinTheta = Math::Sin(theta); // calculate new player position // (rotate player position around Y axis) Ogre::Vector3 newPlayerPosition; newPlayerPosition.x = cosTheta * localPlayerPosition.x - sinTheta * localPlayerPosition.z; newPlayerPosition.z = sinTheta * localPlayerPosition.x + cosTheta * localPlayerPosition.z; // newPlayerPosition.y = localPlayerPosition.y; // commented to save the calculation, uncomment if you need this later for some bizarre reason // calculate dx and dz Ogre::Real dx = newPlayerPosition.x - localPlayerPosition.x; Ogre::Real dz = newPlayerPosition.z - localPlayerPosition.z; // return the offset vector return Ogre::Vector3(dx, 0, dz); }