I’ve researched this so much and to this point all of the examples, tutorials and so on all the time use the next order: Scale * Rotate * Translate however for some purpose this order should all the time be backwards in my Scene Graph. I’m not positive if that is meant resulting from remodeling native matrix to world matrix or it’s an inherent bug in my software.
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 predominant() {
// 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 offers me one sphere within the center that rotates and three spheres that rotate resulting from 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 method 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();
Once 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 possibly can see, the cyan coloration 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 basis node (e.g (2.0, 1.0)) and obtained the identical outcome. If I rotate the sphere, then translate, it’s going to rotate in opposition to (0, 0), then translate to (2.0, 1.0) on the similar time, which can imply that it’s at (2.0, 1.0) and rotating in opposition to (0.0, 0.0). Alternatively, if I translate first, then rotate, it’s going to rotate in opposition to (2.0, 1.0) and translate to (2.0, 1.0) on the similar time, which can imply that its rotating in opposition to the newly translated heart.
Logically this is sensible to me as a result of these multiplications are occurring on the similar time and the result’s written to node however I nonetheless don’t perceive why the usually advised 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?