Understand vtk pre-multiplication and post-multiplication

Let's look at matrix multiplication first
vtkNew<vtkTransform> transformA;
transformA->Translate(10, 0, 0);
std::cout<<"matrixA="<<std::endl<<*transformA->GetMatrix()<<std::endl;
vtkNew<vtkTransform> transformB;
transformB->RotateZ(90);
std::cout<<"matrixB="<<std::endl<<*transformB->GetMatrix()<<std::endl;
vtkNew<vtkMatrix4x4> matrixC;
vtkNew<vtkMatrix4x4> matrixD;
vtkMatrix4x4::Multiply4x4(transformA->GetMatrix(), transformB->GetMatrix(), matrixC);
vtkMatrix4x4::Multiply4x4(transformB->GetMatrix(), transformA->GetMatrix(), matrixD);
std::cout<<"C = A x B"<<std::endl<<*matrixC<<std::endl;
std::cout<<"D = B x A"<<std::endl<<*matrixD<<std::endl;
Output

Pre Multiple
// Default operation is premultiple
vtkNew<vtkTransform> transformE;
transformE->Translate(10, 0, 0);
transformE->RotateZ(90);
std::cout<<"transformE="<<std::endl<<*transformE->GetMatrix()<<std::endl;
Output

Post multiple
vtkNew<vtkTransform> transformF;
transformF->PostMultiply();
transformF->Translate(10, 0, 0);
transformF->RotateZ(90);
std::cout<<"transformF="<<std::endl<<*transformF->GetMatrix()<<std::endl;
Output

If we combine an object, it will be clearer
Default

Pre Multiple
rotateZ(90) --> translate(10, 0, 0)

Post Multiple
translate(10, 0, 0) --> rotateZ(90)

In conclusion
The order of pre-multiplication is the same as the order of matrix multiplication, but contrary to the actual reading order. In other words, the operation of the earlier transformation should be placed at the end.
The order of post-multiplication is opposite to the order of matrix multiplication, but it is the same as the actual reading order, and the operation of the earlier transformation should be placed in front



