Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Transformation Order Problem  (Read 1863 times)

0 Members and 1 Guest are viewing this topic.

Ant

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Email
Transformation Order Problem
« on: June 16, 2018, 03:33:47 am »
I apologies for the long winded topic.  I got stuck on a problem for a few days, and I think what would help me is to write the situation somewhere to straighten my thoughts.


The problem is that I misinterpreted the origin attribute for transformable objects.

I interpreted that the origin was the spot where whenever you call setPosition, the origin will be placed at that pixel location.
By default, it's the top left corner.  Setting the origin would shift the rendered object.  This would allow the dev to easily center a sprite over a specified position.
Scale and rotation by seems to work fine, too.  It rotates about the origin, and it scales relative to the origin.


My issue is introduced when I tried to apply all three transforms for a test game (Solitaire).
I'm setting a card's origin to the middle to allow it to spin around its center.
I'm setting the center's position equal to the center of a specific spot.
Lastly, the sprite is scaled by 50%.  Here I'm expecting the card's borders to squeeze closer to the origin equally.

Although the card gets smaller, the position is 'shifted' from desired location.  I've attached a screenshot to help visualize the scenario.  I've also disabled spinning to simplify the problem.
Looking at the 9 of spades, there's a card outline to the top left of it.  That's the desired location.
CardSize.X = 90
Pivot = CardSize * 0.5  (Pivot.X = 90/2 => 45)
Position.X = 8 + Pivot   (53) <--- The intention is to place the center of the card at the center of the outline.
Size = 0.5
Result Position of top left corner of card (X-axis) = 31     ((-Pivot.X*0.5) + Position.X)  <-- The 0.5 is coming from size
Expected Position of top left corner of card (X-axis) = 8   (-Pivot.X + Position.X)

The easiest solution is to simply adjust the position, but that would weaken my internal usage behind origin where the origin is always at the location where setPosition is specified.
My objective is that when I call SetPosition on an object, the origin of that object is found at that location regardless of scale and rotation.

I've considered a handful of hacky solutions, but I'm too embarrassed to bring them up.

-----------------------------------

Edit:  I sat on my post for a few hours before publishing it.  Writing it down did help me understand the problem.  It's an order of operation error.  It's applying origin shift, scaling, then translating when I need to scale, shift it, then translate it.

For the example above (looking at left border X coordinate of sprite):
Actual:
Absolute Pos = 0
Apply Origin Shift (45)
Absolute Pos = -45
Apply scaling (0.5)
Absolute Pos = -22.5
Apply translation (53)
Absolute Pos = 31

Needed:
Absolute Pos = 0
Apply scale (0.5)
Absolute Pos = 0   <--- but the card is half size
Apply translation (53)
Absolute Pos = 53
Apply Origin Shift (45)
Absolute Pos = 8

Perhaps changing my setPosition setOrigin setSize calls with using a sf::Transform object may help resolve my issue.  I'll give this a try, and I'll post again.  I decided to make this post anyways in case others are running into similar problems.

Ant

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Email
Re: Transformation Order Problem
« Reply #1 on: June 16, 2018, 07:41:39 pm »
Although the transform allows me to customize the order.  In the end, I realized that the best solution is simply to set the position to a different value.

If I were to adjust the scale before setting the origin, that would hurt the purpose behind setting the origin in the first place (scale relative to the origin and rotate about the origin).

Hapax

  • Hero Member
  • *****
  • Posts: 3058
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Transformation Order Problem
« Reply #2 on: June 22, 2018, 10:10:24 pm »
The origin does work as you originally expected it to; it seems that there is something overlooked in your calculations.

When rotating and/or scale, does the object rotate around/scale from its centre?
If so, the origin is correctly in the centre of the object and your calculation of its position or intended position is likely to have a error somewhere.
If not, it seems likely that there is error when setting the origin.

Are you using sf::Sprite, some other in-built SFML drawable or some custom drawable (your own or external)?

Now would also be a good time to mention if you are using an sf::View ;D
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

 

anything