I’ve researched this so much and to this point all of the examples, tutorials and so forth all the time use the next order: Scale * Rotate * Translate however for some cause this order should all the time be backwards in my Scene Graph. I’m not positive if that is meant attributable to remodeling native matrix to world matrix or it’s an inherent bug in my utility.
Right here is my easy Scene Graph implementation. I’m utilizing Vulkan and GLM math library.
void SceneNode::setTransform(glm::mat4 remodel) {
transformLocal = remodel;
}
void SceneNode::replace() {
// if root node
if (parentNode == nullptr) {
transformWorld = transformLocal;
} else {
transformWorld = parent->transformWorld * transformLocal;
}
for (auto &node : kids) {
node->replace();
}
}
And my shader logic:
// initialization code hidden for simplicity
void important() {
// worldTransform = remodel matrix calculated throughout scene node replace
gl_Position = UniformCameraData.projectionView * ModelPushConstants.worldTransform * vec4(vPosition, 1.0f);
outColor = vColor;
}
As a demo, I’ve created a brilliant easy scene with spheres:
Root
Sphere Middle -> Rotate round its personal axis
Sphere 1 -> Place someplace close to the guardian and Rotate round its personal axis
Sphere 2 -> Place someplace close to the guardian andRotate round its personal axis
Sphere 2 -> Place someplace close to the guardian andRotate round its personal axis
This scene graph provides me one sphere within the center that rotates and three spheres that rotate attributable to being kids of this sphere; plus, the spheres themselves rotate round their very own axis:
Nevertheless, the implementation of it’s quiet bizarre to me. The order of transformations is Translate * Rotate * Scale as an alternative of the opposite manner round:
child1->setTransform(
glm::translate(glm::mat4{1.0}, glm::vec3{2.0, 0.0, 0.0}) *
glm::rotate(glm::mat4{1.0f}, glm::radians(body * 0.9f),
glm::vec3{0.0, 0.0, -1.0}) *
glm::scale(glm::mat4{1.0}, glm::vec3{0.4, 0.4, 0.4}));
// ...different kids transformations
scene->replace();
After I change the order of transformations, the rotation occurs across the central sphere:
child1->setTransform(
glm::rotate(glm::mat4{1.0f}, glm::radians(body * 0.9f),
glm::vec3{0.0, 0.0, -1.0}) *
glm::translate(glm::mat4{1.0}, glm::vec3{2.0, 0.0, 0.0}) *
glm::scale(glm::mat4{1.0}, glm::vec3{0.4, 0.4, 0.4}));
// ...different kids transformations
scene->replace();
As you may see, the cyan colour sphere rotates across the guardian as an alternative of its personal heart.
I used to be confused by this so, I added translation to the foundation node (e.g (2.0, 1.0)) and acquired the identical outcome. If I rotate the sphere, then translate, it can rotate in opposition to (0, 0), then translate to (2.0, 1.0) on the identical time, which can imply that it’s at (2.0, 1.0) and rotating in opposition to (0.0, 0.0). Then again, if I translate first, then rotate, it can rotate in opposition to (2.0, 1.0) and translate to (2.0, 1.0) on the identical time, which can imply that its rotating in opposition to the newly translated heart.
Logically this is smart to me as a result of these multiplications are taking place on the identical time and the result’s written to node however I nonetheless don’t perceive why the usually prompt transformation order is Scale * Rotate * Translate. Can somebody clarify to me what I’m lacking right here that I’ve to make use of multiply transformations is in reverse order?