Skip to content

Optimize BlTransformAnimation #756

@tinchodias

Description

@tinchodias

First, this is quite trivial: The animation can easily cache "from" and "to" BlMatrixDecomposition2D (currently, they are calculated again each step!).

But I think more can be optimized. When a BlElement has a BlTransformAnimation, the following steps execute each animation frame:

  1. The animation sends interpolate:to: to that decomposition to create a new temporary decomposition.
  2. The animation creates a temporary BlMatrix2D by sending composition to the decomposition.
  3. The animation creates a temporary BlElementAbsoluteTransformation from the matrix, and sets it in the animated element.
  4. The animated element sends asCachedTransformation to the transformation to finally obtain a BlElementCachedExplicitTransformation, that will be used on the new render.

Some involved methods, to be analyzed:

BlMatrixDecomposition2D >>
interpolate: aFactor to: anotherDecomposition
	"Algorithm is based on https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-2d-matrix-values"

	| aScaleX aScaleY anAngle anotherAngle |
	aScaleX := scale x.
	aScaleY := scale y.
	anAngle := angle.
	anotherAngle := anotherDecomposition angle.

	((aScaleX < 0 and: [ anotherDecomposition scale y < 0 ]) or:
	[ aScaleY < 0 and: [ anotherDecomposition scale x < 0 ] ])
		ifTrue: [
			aScaleX := aScaleX negated.
			aScaleY := aScaleY negated.
			anAngle := anAngle < 0
				ifTrue: [ anAngle + 180 ]
				ifFalse: [ anAngle - 180 ] ].
	
	"Don't rotate the long way around."
	anAngle isZero ifTrue: [ anAngle := 360 ].
	anotherAngle isZero ifTrue: [ anotherAngle := 360 ].

	(anAngle - anotherAngle) abs > 180 ifTrue: [ 
		anAngle > anotherAngle
			ifTrue: [ anAngle := anAngle - 360 ]
			ifFalse: [ anotherAngle := anotherAngle - 360 ] ].
	
	"Interpolate all values."
	^ BlMatrixDecomposition2D new
		translation: translation + ((anotherDecomposition translation - translation) * aFactor);
		scale: scale + ((anotherDecomposition scale - (BlVector x: aScaleX y: aScaleY)) * aFactor);
		angle: anAngle + ((anotherAngle - anAngle) * aFactor);
		sx: sx + ((anotherDecomposition sx - sx) * aFactor);
		sy: sy + ((anotherDecomposition sy - sy) * aFactor);
		shx: shx + ((anotherDecomposition shx - shx) * aFactor);
		shy: shy + ((anotherDecomposition shy - shy) * aFactor);
		yourself
BlMatrixDecomposition2D >>
composition

	| aMatrix |
	aMatrix := BlMatrix2D new.
	aMatrix sx: sx.
	aMatrix sy: sy.
	aMatrix shx: shx.
	aMatrix shy: shy.
	
	"Translate matrix"
	aMatrix x: (translation x * aMatrix sx) + (translation y * aMatrix shx).
	aMatrix y: (translation x * aMatrix shy) + (translation y * aMatrix sy).
	
	"Rotate matrix"
	aMatrix := (BlMatrix2D rotation: angle degreesToRadians) multiplyBy: aMatrix.

	"Scale matrix."
	aMatrix sx: aMatrix sx * scale x.
	aMatrix shy: aMatrix shy * scale x.
	aMatrix shx: aMatrix shx * scale y.
	aMatrix sy: aMatrix sy * scale y.
	
	^ aMatrix

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions