lottie: 3d transformations enhancement

This commit is contained in:
Mira Grudzinska 2024-12-05 02:41:59 +01:00
parent bb5ba81149
commit bdbc0a2595
2 changed files with 42 additions and 16 deletions

View file

@ -38,19 +38,32 @@ static bool _buildComposition(LottieComposition* comp, LottieLayer* parent);
static bool _draw(LottieGroup* parent, LottieShape* shape, RenderContext* ctx); static bool _draw(LottieGroup* parent, LottieShape* shape, RenderContext* ctx);
static void _rotationXYZ(Matrix* m, float degreeX, float degreeY, float degreeZ) static void _rotationXYZ(Matrix* m, float degreeX, float degreeY, float degreeZ, Matrix* rotation3d)
{ {
auto radianX = deg2rad(degreeX); auto radianX = deg2rad(degreeX);
auto radianY = deg2rad(degreeY); auto radianY = deg2rad(degreeY);
auto radianZ = deg2rad(degreeZ); auto radianZ = deg2rad(degreeZ);
auto cx = cosf(radianX), sx = sinf(radianX); auto cx = cosf(radianX), sx = sinf(radianX);
auto cy = cosf(radianY), sy = sinf(radianY);; auto cy = cosf(radianY), sy = sinf(radianY);
auto cz = cosf(radianZ), sz = sinf(radianZ);; auto cz = cosf(radianZ), sz = sinf(radianZ);
m->e11 = cy * cz;
m->e12 = -cy * sz; rotation3d->e11 = cy * cz;
m->e21 = sx * sy * cz + cx * sz; rotation3d->e12 = -cy * sz;
m->e22 = -sx * sy * sz + cx * cz; rotation3d->e13 = -sy;
rotation3d->e21 = cz * sy * sx + sz * cx;
rotation3d->e22 = -sz * sy * sx + cz * cx;
rotation3d->e23 = cy * sx;
rotation3d->e31 = cz * sy * cx - sz * sx;
rotation3d->e32 = -sz * sy * cx - cz * sx;
rotation3d->e33 = cy * cx;
m->e11 = rotation3d->e11;
m->e12 = rotation3d->e12;
m->e21 = rotation3d->e21;
m->e22 = rotation3d->e22;
} }
@ -101,7 +114,7 @@ static void _skew(Matrix* m, float angleDeg, float axisDeg)
} }
static bool _updateTransform(LottieTransform* transform, float frameNo, bool autoOrient, Matrix& matrix, uint8_t& opacity, LottieExpressions* exps) static bool _updateTransform(LottieTransform* transform, float frameNo, bool autoOrient, Matrix& matrix, Matrix* rotation3d, uint8_t& opacity, LottieExpressions* exps)
{ {
identity(&matrix); identity(&matrix);
@ -119,7 +132,7 @@ static bool _updateTransform(LottieTransform* transform, float frameNo, bool aut
auto angle = 0.0f; auto angle = 0.0f;
if (autoOrient) angle = transform->position.angle(frameNo); if (autoOrient) angle = transform->position.angle(frameNo);
if (transform->rotationEx) _rotationXYZ(&matrix, transform->rotationEx->x(frameNo, exps), transform->rotationEx->y(frameNo, exps), transform->rotation(frameNo, exps) + angle); if (transform->rotationEx) _rotationXYZ(&matrix, transform->rotationEx->x(frameNo, exps), transform->rotationEx->y(frameNo, exps), transform->rotation(frameNo, exps) + angle, rotation3d);
else _rotationZ(&matrix, transform->rotation(frameNo, exps) + angle); else _rotationZ(&matrix, transform->rotation(frameNo, exps) + angle);
@ -157,13 +170,25 @@ void LottieBuilder::updateTransform(LottieLayer* layer, float frameNo)
if (parent) updateTransform(parent, frameNo); if (parent) updateTransform(parent, frameNo);
auto& matrix = layer->cache.matrix; auto& matrix = layer->cache.matrix;
auto& rotation3d = layer->cache.rotation3d;
_updateTransform(transform, frameNo, layer->autoOrient, matrix, &rotation3d, layer->cache.opacity, exps);
_updateTransform(transform, frameNo, layer->autoOrient, matrix, layer->cache.opacity, exps); if (parent && !identity((const Matrix*)&parent->cache.matrix)) {
if (identity((const Matrix*)&matrix)) { //TODO: test
layer->cache.matrix = parent->cache.matrix;
layer->cache.rotation3d = parent->cache.rotation3d;
} else {
layer->cache.matrix = parent->cache.matrix * matrix;
if (parent) { if (transform->rotationEx) {
if (!identity((const Matrix*) &parent->cache.matrix)) { //include remaining terms from the 3d rotation matrix:
if (identity((const Matrix*) &matrix)) layer->cache.matrix = parent->cache.matrix; layer->cache.matrix.e11 += parent->cache.rotation3d.e13 * rotation3d.e31;
else layer->cache.matrix = parent->cache.matrix * matrix; layer->cache.matrix.e21 += parent->cache.rotation3d.e23 * rotation3d.e31;
layer->cache.matrix.e12 += parent->cache.rotation3d.e13 * rotation3d.e32;
layer->cache.matrix.e22 += parent->cache.rotation3d.e23 * rotation3d.e32;
layer->cache.rotation3d = parent->cache.rotation3d * rotation3d; //TODO: test
} else layer->cache.rotation3d = parent->cache.rotation3d; //TODO: test
} }
} }
layer->cache.frameNo = frameNo; layer->cache.frameNo = frameNo;
@ -179,14 +204,14 @@ void LottieBuilder::updateTransform(LottieGroup* parent, LottieObject** child, f
if (parent->mergeable()) { if (parent->mergeable()) {
if (!ctx->transform) ctx->transform = (Matrix*)malloc(sizeof(Matrix)); if (!ctx->transform) ctx->transform = (Matrix*)malloc(sizeof(Matrix));
_updateTransform(transform, frameNo, false, *ctx->transform, opacity, exps); _updateTransform(transform, frameNo, false, *ctx->transform, nullptr, opacity, exps);
return; return;
} }
ctx->merging = nullptr; ctx->merging = nullptr;
Matrix matrix; Matrix matrix;
if (!_updateTransform(transform, frameNo, false, matrix, opacity, exps)) return; if (!_updateTransform(transform, frameNo, false, matrix, nullptr, opacity, exps)) return;
ctx->propagator->transform(ctx->propagator->transform() * matrix); ctx->propagator->transform(ctx->propagator->transform() * matrix);
ctx->propagator->opacity(MULTIPLY(opacity, PP(ctx->propagator)->opacity)); ctx->propagator->opacity(MULTIPLY(opacity, PP(ctx->propagator)->opacity));

View file

@ -796,6 +796,7 @@ struct LottieLayer : LottieGroup
struct { struct {
float frameNo = -1.0f; float frameNo = -1.0f;
Matrix matrix; Matrix matrix;
Matrix rotation3d;
uint8_t opacity; uint8_t opacity;
} cache; } cache;