Skip to content

Commit 8847e65

Browse files
committed
Merge pull request #105644 from lazarosY/interpolation
Fix the Animation Optimization results for Nearest and Cubic Interpolation
2 parents ca4038f + 37a70ed commit 8847e65

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

scene/resources/animation.cpp

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4105,14 +4105,17 @@ void Animation::clear() {
41054105
emit_changed();
41064106
}
41074107

4108-
bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
4108+
bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error, bool p_is_nearest) {
41094109
// Remove overlapping keys.
41104110
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
41114111
return true;
41124112
}
41134113
if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) {
41144114
return true;
41154115
}
4116+
if (p_is_nearest) {
4117+
return false;
4118+
}
41164119
// Calc velocities.
41174120
double v0 = (t1.value - t0.value) / (t1.time - t0.time);
41184121
double v1 = (t2.value - t1.value) / (t2.time - t1.time);
@@ -4133,14 +4136,17 @@ bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float
41334136
return false;
41344137
}
41354138

4136-
bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) {
4139+
bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest) {
41374140
// Remove overlapping keys.
41384141
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
41394142
return true;
41404143
}
41414144
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
41424145
return true;
41434146
}
4147+
if (p_is_nearest) {
4148+
return false;
4149+
}
41444150
// Calc velocities.
41454151
Vector2 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
41464152
Vector2 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
@@ -4164,14 +4170,18 @@ bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<V
41644170
return false;
41654171
}
41664172

4167-
bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) {
4173+
bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest) {
41684174
// Remove overlapping keys.
41694175
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
41704176
return true;
41714177
}
41724178
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
41734179
return true;
41744180
}
4181+
if (p_is_nearest) {
4182+
return false;
4183+
}
4184+
41754185
// Calc velocities.
41764186
Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
41774187
Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
@@ -4195,14 +4205,17 @@ bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<V
41954205
return false;
41964206
}
41974207

4198-
bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) {
4208+
bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest) {
41994209
// Remove overlapping keys.
42004210
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
42014211
return true;
42024212
}
42034213
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
42044214
return true;
42054215
}
4216+
if (p_is_nearest) {
4217+
return false;
4218+
}
42064219
// Check axis.
42074220
Quaternion q0 = t0.value * t1.value * t0.value.inverse();
42084221
Quaternion q1 = t1.value * t2.value * t1.value.inverse();
@@ -4232,15 +4245,19 @@ bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const
42324245
void Animation::_position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
42334246
ERR_FAIL_INDEX(p_idx, tracks.size());
42344247
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_POSITION_3D);
4248+
bool is_nearest = false;
4249+
if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
4250+
is_nearest = true;
4251+
} else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
4252+
return;
4253+
}
42354254
PositionTrack *tt = static_cast<PositionTrack *>(tracks[p_idx]);
4236-
42374255
int i = 0;
42384256
while (i < tt->positions.size() - 2) {
42394257
TKey<Vector3> t0 = tt->positions[i];
42404258
TKey<Vector3> t1 = tt->positions[i + 1];
42414259
TKey<Vector3> t2 = tt->positions[i + 2];
4242-
4243-
bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4260+
bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
42444261
if (erase) {
42454262
tt->positions.remove_at(i + 1);
42464263
} else {
@@ -4258,15 +4275,19 @@ void Animation::_position_track_optimize(int p_idx, real_t p_allowed_velocity_er
42584275
void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
42594276
ERR_FAIL_INDEX(p_idx, tracks.size());
42604277
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D);
4278+
bool is_nearest = false;
4279+
if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
4280+
is_nearest = true;
4281+
} else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
4282+
return;
4283+
}
42614284
RotationTrack *rt = static_cast<RotationTrack *>(tracks[p_idx]);
4262-
42634285
int i = 0;
42644286
while (i < rt->rotations.size() - 2) {
42654287
TKey<Quaternion> t0 = rt->rotations[i];
42664288
TKey<Quaternion> t1 = rt->rotations[i + 1];
42674289
TKey<Quaternion> t2 = rt->rotations[i + 2];
4268-
4269-
bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4290+
bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
42704291
if (erase) {
42714292
rt->rotations.remove_at(i + 1);
42724293
} else {
@@ -4284,15 +4305,19 @@ void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_er
42844305
void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
42854306
ERR_FAIL_INDEX(p_idx, tracks.size());
42864307
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D);
4308+
bool is_nearest = false;
4309+
if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
4310+
is_nearest = true;
4311+
} else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
4312+
return;
4313+
}
42874314
ScaleTrack *st = static_cast<ScaleTrack *>(tracks[p_idx]);
4288-
42894315
int i = 0;
42904316
while (i < st->scales.size() - 2) {
42914317
TKey<Vector3> t0 = st->scales[i];
42924318
TKey<Vector3> t1 = st->scales[i + 1];
42934319
TKey<Vector3> t2 = st->scales[i + 2];
4294-
4295-
bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4320+
bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
42964321
if (erase) {
42974322
st->scales.remove_at(i + 1);
42984323
} else {
@@ -4310,15 +4335,20 @@ void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err,
43104335
void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
43114336
ERR_FAIL_INDEX(p_idx, tracks.size());
43124337
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE);
4338+
bool is_nearest = false;
4339+
if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
4340+
is_nearest = true;
4341+
} else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
4342+
return;
4343+
}
43134344
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(tracks[p_idx]);
4314-
43154345
int i = 0;
43164346
while (i < bst->blend_shapes.size() - 2) {
43174347
TKey<float> t0 = bst->blend_shapes[i];
43184348
TKey<float> t1 = bst->blend_shapes[i + 1];
43194349
TKey<float> t2 = bst->blend_shapes[i + 2];
43204350

4321-
bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error);
4351+
bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error, is_nearest);
43224352
if (erase) {
43234353
bst->blend_shapes.remove_at(i + 1);
43244354
} else {
@@ -4336,6 +4366,12 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity
43364366
void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
43374367
ERR_FAIL_INDEX(p_idx, tracks.size());
43384368
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE);
4369+
bool is_nearest = false;
4370+
if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
4371+
is_nearest = true;
4372+
} else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR && tracks[p_idx]->interpolation != INTERPOLATION_LINEAR_ANGLE) {
4373+
return;
4374+
}
43394375
ValueTrack *vt = static_cast<ValueTrack *>(tracks[p_idx]);
43404376
if (vt->values.is_empty()) {
43414377
return;
@@ -4367,7 +4403,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
43674403
break; // Rotation is more than 180 deg, keep key.
43684404
}
43694405
}
4370-
erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error);
4406+
erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error, is_nearest);
43714407
} break;
43724408
case Variant::VECTOR2: {
43734409
TKey<Vector2> t0;
@@ -4379,7 +4415,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
43794415
t0.value = vt->values[i].value;
43804416
t1.value = vt->values[i + 1].value;
43814417
t2.value = vt->values[i + 2].value;
4382-
erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4418+
erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
43834419
} break;
43844420
case Variant::VECTOR3: {
43854421
TKey<Vector3> t0;
@@ -4391,7 +4427,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
43914427
t0.value = vt->values[i].value;
43924428
t1.value = vt->values[i + 1].value;
43934429
t2.value = vt->values[i + 2].value;
4394-
erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4430+
erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
43954431
} break;
43964432
case Variant::QUATERNION: {
43974433
TKey<Quaternion> t0;
@@ -4403,7 +4439,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
44034439
t0.value = vt->values[i].value;
44044440
t1.value = vt->values[i + 1].value;
44054441
t2.value = vt->values[i + 2].value;
4406-
erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
4442+
erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
44074443
} break;
44084444
default: {
44094445
} break;

scene/resources/animation.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,10 @@ class Animation : public Resource {
373373

374374
// bind helpers
375375
private:
376-
bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error);
377-
bool _vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);
378-
bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);
379-
bool _quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);
376+
bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error, bool p_is_nearest);
377+
bool _vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest);
378+
bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest);
379+
bool _quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error, bool p_is_nearest);
380380

381381
void _position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error);
382382
void _rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error);

0 commit comments

Comments
 (0)