Eu pesquisei muito isso e até agora todos os exemplos, tutoriais and so on. sempre use a seguinte ordem: escala * gire * traduza, mas por algum motivo essa ordem deve sempre ser atrasada no meu gráfico de cena. Não tenho certeza se isso se destina devido à transformação da matriz native em matriz mundial ou é um bug inerente ao meu aplicativo.
Aqui está a minha implementação simples de gráfico de cenas. Estou usando a Biblioteca de Matemática Vulkan e Glm.
void SceneNode::setTransform(glm::mat4 rework) {
transformLocal = rework;
}
void SceneNode::replace() {
// if root node
if (parentNode == nullptr) {
transformWorld = transformLocal;
} else {
transformWorld = parent->transformWorld * transformLocal;
}
for (auto &node : kids) {
node->replace();
}
}
E minha lógica do shader:
// initialization code hidden for simplicity
void principal() {
// worldTransform = rework matrix calculated throughout scene node replace
gl_Position = UniformCameraData.projectionView * ModelPushConstants.worldTransform * vec4(vPosition, 1.0f);
outColor = vColor;
}
Como uma demonstração, criei uma cena tremendous simples com esferas:
Root
Sphere Middle -> Rotate round its personal axis
Sphere 1 -> Place someplace close to the father or mother and Rotate round its personal axis
Sphere 2 -> Place someplace close to the father or mother andRotate round its personal axis
Sphere 2 -> Place someplace close to the father or mother andRotate round its personal axis
Este gráfico de cena me dá uma esfera no meio que gira e três esferas que giram por serem filhos desta esfera; Além disso, as próprias esferas giram em torno de seu próprio eixo:

No entanto, a implementação é silenciosa para mim. A ordem das transformações é traduzida * Gire * escala em vez de o contrário:
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();
Quando mudo a ordem das transformações, a rotação acontece ao redor da esfera central:
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();
Como você pode ver, a esfera colorida ciana gira em torno do pai em vez de seu próprio centro.
Fiquei confuso com isso, então, adicionei a tradução ao nó raiz (por exemplo (2.0, 1.0)) e obtive o mesmo resultado. Se eu girar a esfera, traduzir, ela girará contra (0, 0) e depois traduzirá para (2.0, 1.0) ao mesmo tempo, o que significa que está em (2,0, 1,0) e girando contra (0,0, 0,0). Por outro lado, se eu traduzir primeiro, depois girar, ele girará contra (2.0, 1.0) e traduzirá para (2.0, 1.0) ao mesmo tempo, o que significa que está girando contra o centro recém -traduzido.
Logicamente, isso faz sentido para mim porque essas multiplicações estão acontecendo ao mesmo tempo e o resultado é gravado no nó, mas ainda não entendo por que a ordem de transformação tipicamente sugerida é a escala * girar * tradução. Alguém pode me explicar o que estou perdendo aqui que tenho que usar multiplicar transformações está em ordem inversa?