Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am building a Unity-like Transform class.

This is my header file:

#include "Common.h"

struct Transform
{
public:
        Transform();
        void Translate(float x, float y, float z);
        void Translate(const glm::vec3 &dir);
        void SetPosition(const glm::vec3 &pos);
        void SetYPosition(const float &pos);
        void Rotate(float x, float y, float z, bool world = true);
        void Rotate(const glm::vec3 &dir, bool world = true);
        void SetRotation(const glm::vec3 &rot);
        void Scale(const glm::vec3 &scale);
        void Scale(float x, float y, float z);
        const glm::vec3& GetScale();

        const glm::vec3& GetPosition();
        const glm::vec3& GetRotation();
        void LookAt(glm::vec3 targetPosition);

        glm::mat4 GetWorldMatrix();

        glm::vec3 Up();
        glm::vec3 Right();
        glm::vec3 Forward();

        glm::mat4 GetOrientation();
        glm::mat4 GetTranslation();
        glm::mat4 GetScaling();

        void NormalizeAngles();
private:
        glm::vec3 m_Position, m_Rotation, m_Scale;
        glm::mat4 m_Translation, m_Orientation, m_Scaling;

        bool m_NeedUpdate;
};

inline Transform::Transform()
{
        m_Scale = glm::vec3(1,1,1);
        m_NeedUpdate = true;
}

...

inline void Transform::Translate(float x, float y, float z)
{
        m_Position += glm::vec3(x,y,z);
        m_NeedUpdate = true;
}

inline void Transform::Translate(const glm::vec3 &dir)
{
        m_Position += dir;
        m_NeedUpdate = true;
}

inline void Transform::SetRotation(const glm::vec3 &rot)
{
        m_Rotation = rot;
        m_NeedUpdate = true;
}

inline void Transform::Rotate(float x, float y, float z,bool world)
{
        if(world)
                m_Rotation += glm::vec3(x,y,z);
        else
        {
                //TODO
                m_Rotation += glm::vec3(x,y,z);
        }

        m_NeedUpdate = true;
}

inline void Transform::Rotate(const glm::vec3 &rot,bool world)
{
        if(world)
                m_Rotation += rot;
        else
        {
                //TODO
        }
        m_NeedUpdate = true;
}

...

inline const glm::vec3& Transform::GetRotation()
{
        return m_Rotation;
}

...

And this is my C++ file:

#include "Transform.h"

static const float MaxVerticalAngle = 89.0f; //must be less than 90 to avoid gimbal lock

void Transform::NormalizeAngles()
{
        m_Rotation.y = fmodf(m_Rotation.y, 360.0f);
        //fmodf can return negative values, but this will make them all positive
        if(m_Rotation.y < 0.0f)
                m_Rotation.y += 360.0f;

        if(m_Rotation.x > MaxVerticalAngle)
                m_Rotation.x = MaxVerticalAngle;
        else if(m_Rotation.x < -MaxVerticalAngle)
                m_Rotation.x = -MaxVerticalAngle;
}

void Transform::LookAt(glm::vec3 targetPosition)
{
        if((targetPosition - m_Position) == glm::vec3(0,0,0)) return;
        glm::vec3 direction = glm::normalize(targetPosition - m_Position);
        m_Rotation.x = asinf(-direction.y)* RadToDeg;
        m_Rotation.y = -atan2f(-direction.x, -direction.z)*RadToDeg;

        NormalizeAngles();
        m_NeedUpdate = true;
}

glm::mat4 Transform::GetOrientation()
{
        if(m_NeedUpdate)
        {
                m_Orientation = glm::rotate(m_Rotation.x, glm::vec3(1,0,0));
                m_Orientation = glm::rotate(m_Orientation, m_Rotation.y, glm::vec3(0,1,0));
                m_Orientation = glm::rotate(m_Orientation, m_Rotation.z, glm::vec3(0,0,1));
        }

        return m_Orientation;
}

glm::mat4 Transform::GetTranslation()
{
        if(m_NeedUpdate)
        {
                m_Translation = glm::translate(m_Position);
        }
        return m_Translation;
}

...

I have problems implementing the rotation correctly (the //TODO commented part). Currently rotation is only working in world orientation, but I would like to select whether orientation should be in world or in local orientation. Also translation currently works in world space, it also should be selectable whether to translate in local orientation or in world orientation.

How can I make my translation and rotation operations operate on local coordinates?

share|improve this question

closed as off-topic by Anko, Trevor Powell, bummzack, Josh Petrie Feb 26 '14 at 4:00

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Trevor Powell, bummzack
If this question can be reworded to fit the rules in the help center, please edit the question.

1  
This question appears to be off-topic because it is about debugging your code for you. Could it be edited to describe what you're trying to do and reduce the how to the relevant lines of code? –  Anko Feb 19 '14 at 13:48

1 Answer 1

up vote 4 down vote accepted

Local versus world is just a matter of the order in which you compose transforms. For instance, when using row-vector math, multiplying the current local-to-world transform by a new transform on the left will perform the new transform in local space, since it will be equivalent to doing the new transform followed by the old local-to-world transform. Multiplying by the new transform on the right will perform it in world space, since it will be equivalent to doing the old local-to-world followed by the new transform. If using column-vector math, the order is the other way around.

share|improve this answer

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