World Space Getters

When accumulating transforms instead of matrices, getting the world space properties of the transform becomes trivial. You simply need to get the world transform (covered in the last section) and return individual components from it.

Quaternion Transform_GetGlobalRotation (Transform t) {
    Transform worldXForm = GetWorldTransform(t);
    return worldXForm.rotation;
}

Vector3 Transform_GetGlobalPosition (Transform t) {
    Transform worldXForm = GetWorldTransform(t);
    return worldXForm.position;

}

Vector3 Transform_GetGlobalScale(Transform t) {
    Transform worldXForm = GetWorldTransform(t);
    return worldXForm.scale;
}

World Space Setters

To set a world space transform component, we have to invert the parent of the transform (in world space) and combine it with the desired world space transform. We can invert a transform local to its-self (not taking the parent into consideration) by first inverting the rotation and scale then applying these to the inverted translation.

Transform LocalInverse(Transform t) {
    Quaternion invRotation = Inverse(t.rotation);

    Vector3 invScale = Vector3(0, 0, 0);
    if (t.scale.x != 0) { // Do epsilon comparison here
        invScale.x = 1.0 / t.scale.x
    }
    if (t.scale.y != 0) { // Do epsilon comparison here
        invScale.y = 1.0 / t.scale.y
    }
    if (t.scale.z != 0) { // Do epsilon comparison here
        invScale.z = 1.0 / t.scale.z
    }

    Vector3 invTranslation = invRotation * (invScale * (-1 * t.translation));

    Transform result;
    result.position = invTranslation;
    result.rotation = invRotation;
    result.scale = invScale;

    return result;
}

Now that we can invert a transform, making a function that sets the position, rotation and scale of a transform in world space becomes trivial. Find the parent's world space transform, invert it and multiply it by the desired world space transform. The resulting transform is in the local space of the parent, as expected.

void SetGlobalSRT(Transform t, Vector3 s, Quaternion r, Vector3 p) {
    if (t.parent == NULL) {
        t.rotation = r;
        t.position = p;
        t.scale = s;
        return;
    }

    var worldParent = GetWorldTransform(t.parent);
    var invParent = LocalInverse(worldParent);

    Transform worldXForm;
    worldXForm.position = p;
    worldXForm.rotation = r;
    worldXForm.scale = s;

    worldXForm = CombineTransforms(invParent, worldXForm);

    t.position = worldXForm.position;
    t.rotation = worldXForm.rotation;
    t.scale = worldXForm.scale;
}

Let's make some conveniance functions that only set one component of the transform. To do so find the world space transform, substitute the desired component and call the SetGlobalSRT written above.

void SetGlobalRotation (Transform t, Quaternion rotation) {
    Transform worldXForm = GetWorldTransform(t);
    SetGlobalSRT(t, worldXForm.scale, rotation, worldXForm.position);
}

void SetGlobalPosition (Transform t, Vector3 position) {
    Transform worldXForm = GetWorldTransform(t);
    SetGlobalSRT(t, worldXForm.scale, worldXForm.rotation, position);
}

void SetGlobalScale(Transform t, Vector3 scale) {
    Transform worldXForm = GetWorldTransform(t);
    SetGlobalSRT(t, scale, worldXForm.rotation, worldXForm.position);
}