kurenai

Hello. I'm using spine libgdx runtime.
I scaled my spine anim according to sample code in this topic :
http://fr.esotericsoftware.com/forum/How-to-scale-skeleton-at-a-pivot-point-6356.
Sample code:
float originX = 100, originY = 100;

Matrix4 proj = batch.getProjectionMatrix();
proj.translate(originX, originY, 0);
proj.scale(1.2f, 1.2f, 1);
proj.translate(-originX, -originY, 0);

batch.begin();
renderer.draw(batch, skeleton); // Draw the skeleton images.
batch.end();

debugRenderer.getShapeRenderer().setProjectionMatrix(proj);
debugRenderer.draw(skeleton); // Draw debug lines.

proj.translate(originX, originY, 0);
proj.scale(1 / 1.2f, 1 / 1.2f, 1);
proj.translate(-originX, -originY, 0);
And now when I'm moving skeleton using skeleton.setPosition() it moves into new projection coordinates but I want it to move in the old projection coordinates.
How can I translate coordinates from the old projection to the new projection?

Or is there another better method to scale the skeleton at a custom pivot point?

I also tried this method, but it didn't work. Can I get more details about it, please, maybe I did something wrong.
Otherwise you can have the root bone, then second bone that all your other bones are attached to. Programmatically position the root (to set the scale origin) and the second bone (to set the skeleton location), then scale the root.
kurenai
  • Сообщения: 2

Harald

Changing skeleton.setPosition() will modify the input vertex positions that are then processed by the transform matrix (which is a combination of the model and view matrix, called modelview in OpenGL for example) and then by the projection matrix. So if any of the matrices scale the input object-space vertices, a translation of these input vertices will be scaled as well implicitly. While possible, it is not a good idea to apply inverse-scaled transformation and apply it to the input vertices via skeleton.setPosition(), instead it would be better to apply transformations consistently in the right order.

While the above code modifies the projection matrix, it would be more appropriate to modify the transformation matrix for translation and model scale via setTransformMatrix(). There you could then apply all transformations like scale, rotation and translation in the desired order.

Note that in libgdx matrices are multiplied with vertices in this order:
result_vertex_pos = Projection * Transform * input_vertex_pos
So with translation, rotation and scale this becomes:
result_vertex_pos = Projection * T * R * S * input_vertex_pos
Now you can additionally offset the scale pivot by replacing the scale matrix S with multiple matrices to scale it relative to a custom pivot. This is done by translation by -pivot_position, then scaling and then translating back by pivot_position.
S_pivot = (T_pivot * S * T_negative_pivot)
result_vertex_pos = Projection * T * R * (T_pivot * S * T_negative_pivot) * input_vertex_pos

So in summary, your Transform matrix could be set to this:
T * R * (T_pivot * S * T_negative_pivot)
Аватара пользователя
Harald

Harri
  • Сообщения: 2769

kurenai

How should I make this transform matrix in code?
Because seems like I'm doing weird stuff.
Matrix4 oldTransform = polygonBatch.getTransformMatrix();
Vector3 translation = new Vector3();
oldTransform.getTranslation(translation);

Quaternion rotation = new Quaternion();
oldTransform.getRotation(rotation);

Matrix4 T = new Matrix4();
T.setTranslation(translation);

Matrix4 R = new Matrix4();
R.rotate(rotation);

Matrix4 T_pivot = new Matrix4();
T_pivot.translate(originX, originY, 0);

Matrix4 S = new Matrix4();
S.scale(scaleX, scaleY, 1);

Matrix4 T_negative_pivot = new Matrix4();
T_negative_pivot.translate(-originX, originY, 0);

Matrix4 S_pivot = T_pivot.mul(S).mul(T_negative_pivot);

polygonBatch.setTransformMatrix(T.mul(R).mul(S_pivot));

polygonBatch.begin();
renderer.draw(polygonBatch, skeleton);
polygonBatch.end();
kurenai
  • Сообщения: 2

Harald

Do not use oldTransform.getTranslation(translation); and oldTransform.getRotation(rotation);. This is problematic both from a mathematical, as well as from a software-engineering design standpoint. You should store translation and rotation information at your high-level object instead of storing it in a low-level matrix and querying it all the time.
Аватара пользователя
Harald

Harri
  • Сообщения: 2769


Вернуться в Runtimes