0
votes

I want to combine the transformations from two matrices into one. I have a scene that contains different shapes - rectangles, circles,.. that has it own matrix that contains all the transformations: rotation, scale, translation. When I apply transformations to the scene all elements that are inside the scene will get that transformation. This works well using this code from this repository that is used to apply transformation using finger gestures. Those image and shapes are generated with OpenGL GLES2 using this library. I am not presenting the full source code, since the problem comes from the order of the matrices as discussed below.

But I want for certain shapes to have separate matrix with transformations, that wat the shape get the transformations from their particular matrix and also from the transformations from scene. That means I need to combine the transformations from the two matrices and use it for that shape.

Lets say the scene has the matrix m1 and a image(the lion image) has the matrix m2, then I need to combine the transformations from those two matrices. I have tried using preConcat, and first apply transformations from the scene and then apply those for the shape.

var m = Matrix()
m.preConcat(m1)
m.preConcat(m2)

Then apply the transformations from the matrix m to the shape, that way it receives the combined transformations from both matrices. This works well when the transformations for the scene are changed. So when I scale, rotate, translate the whole scene will all shapes, that shape receive the transformations from both matrices successfully.

Changing the transformations for the whole scene, that is applied to all shapes (Working!) enter image description here


But the problem comes when I try to change only the transformations for that particular shape, using the same code. When I try that I have problem with the transformations and the pivot point for the rotation and scaling is changed to the center of the screen, instead how it suppose to be and the pivot should match the center between the two fingers. The circle inside the triangle matches the middle of the screen, so once the center of the image matches the center of the screen it is rotate on that point. It important to say that the start of the image is considered the center of that image, and not the top-left corner of the image.

Changing the transformations for the image only (NOT Working!)
enter image description here




Switching order

I have tried switching the order of the concatenated matrices, in other words I first apply the transformation for the shape matrix m2 and then those from the matrix holding transformations for the whole scene m1.

var m = Matrix()
m.preConcat(m2)
m.preConcat(m1)

But now the opposite happens, it starts working correctly when changing the transformations for the shape, but it does not work when changing the transformations for the whole scene.

Changing the transformations for the whole scene, that is applied to all shapes (NOT Working!)
enter image description here

Changing the transformations for the image only (Working!)
enter image description here




Use different order depending on which matrix transformations we want to change

I have tried using different order when concatenating the matrix. The order is m1 -> m2 for the scene and m2 -> m1 for the image.

// use when transforming the scene
var m = Matrix()
m.preConcat(m1)
m.preConcat(m2)

// used when transforming the image
var m = Matrix()
m.preConcat(m2)
m.preConcat(m1)

Now it kinda works, the only problem is when I switch the order of the matrices I get a nasty translation as it can be seen at the 6-7 second. But other than that it works!
enter image description here

So there are few questions:

  1. What causes that translation, when changing the order of the matrices m1 and m2?
  2. Is there a way to solve the problem with the translation?
  3. Why the order of the matrices need to be changed?
1

1 Answers

0
votes

I came up with a brilliant solution, instead of using m1 as the matrix for the scene that will be used for all shapes and use m2 as the matrix for the image(the lion image) and then combining the transformations from those two matrices.

enter image description here What I did is use separate matrix for each layer, so now m1 becomes the matrix for the (triangles,lines,circles) and m2 is kept for the image.


enter image description here Now when I want to transform only one layer at a time, when the onTouch() method is invoked we apply the transformations for that particular matrix. So if I want to apply transformations only to the image layer I apply them only to the m2 matrix via the OpenGLMatrixGestureDetector, and if I want to apply them to the shapes only (triangles,lines,circles), then I set the transformations only to the m1 matrix.


enter image description here So the best part is what to do when I want to apply the transformations to both layers (the shapes and the image). Well then when the onTouch() event is called I apply the transformations to both matrices as if we select one layer at a time, then applying the transformations, then selecting the next layer and applying the same transformations. That way we apply the same transformations to each matrix via the OpenGLMatrixGestureDetector, and that way we update both matrices.

And the cool thing is that we can use Undo/Redo logic, by collecting the transformations from the matrix values after each transformed session. And when we need to revert them simply set the previously stored matrix values.

Conclusions: Use separate matrix(OpenGLMatrixGestureDetector) for each layer. To apply transformations to one layer at a time, at onTouch() use the gesture detector corresponding to that particular layer we want to transform. To apply the transformations to multiple layers, use all the gesture detectors with the same onTouch() event.