|
@@ -4105,7 +4105,7 @@ void Animation::clear() {
|
|
emit_changed();
|
|
emit_changed();
|
|
}
|
|
}
|
|
|
|
|
|
-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 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) {
|
|
// Remove overlapping keys.
|
|
// Remove overlapping keys.
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
return true;
|
|
return true;
|
|
@@ -4113,6 +4113,9 @@ bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float
|
|
if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) {
|
|
if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ if (p_is_nearest) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
// Calc velocities.
|
|
// Calc velocities.
|
|
double v0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
double v0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
double v1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
double v1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
@@ -4133,7 +4136,7 @@ bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-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 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) {
|
|
// Remove overlapping keys.
|
|
// Remove overlapping keys.
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
return true;
|
|
return true;
|
|
@@ -4141,6 +4144,9 @@ bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<V
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ if (p_is_nearest) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
// Calc velocities.
|
|
// Calc velocities.
|
|
Vector2 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
Vector2 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
Vector2 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
Vector2 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
@@ -4164,7 +4170,7 @@ bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<V
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-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 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) {
|
|
// Remove overlapping keys.
|
|
// Remove overlapping keys.
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
return true;
|
|
return true;
|
|
@@ -4172,6 +4178,10 @@ bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<V
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ if (p_is_nearest) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
// Calc velocities.
|
|
// Calc velocities.
|
|
Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time);
|
|
Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time);
|
|
@@ -4195,7 +4205,7 @@ bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<V
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-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 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) {
|
|
// Remove overlapping keys.
|
|
// Remove overlapping keys.
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) {
|
|
return true;
|
|
return true;
|
|
@@ -4203,6 +4213,9 @@ bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ if (p_is_nearest) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
// Check axis.
|
|
// Check axis.
|
|
Quaternion q0 = t0.value * t1.value * t0.value.inverse();
|
|
Quaternion q0 = t0.value * t1.value * t0.value.inverse();
|
|
Quaternion q1 = t1.value * t2.value * t1.value.inverse();
|
|
Quaternion q1 = t1.value * t2.value * t1.value.inverse();
|
|
@@ -4232,15 +4245,19 @@ bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const
|
|
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) {
|
|
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) {
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_POSITION_3D);
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_POSITION_3D);
|
|
|
|
+ bool is_nearest = false;
|
|
|
|
+ if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
|
|
|
|
+ is_nearest = true;
|
|
|
|
+ } else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
PositionTrack *tt = static_cast<PositionTrack *>(tracks[p_idx]);
|
|
PositionTrack *tt = static_cast<PositionTrack *>(tracks[p_idx]);
|
|
-
|
|
|
|
int i = 0;
|
|
int i = 0;
|
|
while (i < tt->positions.size() - 2) {
|
|
while (i < tt->positions.size() - 2) {
|
|
TKey<Vector3> t0 = tt->positions[i];
|
|
TKey<Vector3> t0 = tt->positions[i];
|
|
TKey<Vector3> t1 = tt->positions[i + 1];
|
|
TKey<Vector3> t1 = tt->positions[i + 1];
|
|
TKey<Vector3> t2 = tt->positions[i + 2];
|
|
TKey<Vector3> t2 = tt->positions[i + 2];
|
|
-
|
|
|
|
- bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
if (erase) {
|
|
if (erase) {
|
|
tt->positions.remove_at(i + 1);
|
|
tt->positions.remove_at(i + 1);
|
|
} else {
|
|
} else {
|
|
@@ -4258,15 +4275,19 @@ void Animation::_position_track_optimize(int p_idx, real_t p_allowed_velocity_er
|
|
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) {
|
|
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) {
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D);
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D);
|
|
|
|
+ bool is_nearest = false;
|
|
|
|
+ if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
|
|
|
|
+ is_nearest = true;
|
|
|
|
+ } else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
RotationTrack *rt = static_cast<RotationTrack *>(tracks[p_idx]);
|
|
RotationTrack *rt = static_cast<RotationTrack *>(tracks[p_idx]);
|
|
-
|
|
|
|
int i = 0;
|
|
int i = 0;
|
|
while (i < rt->rotations.size() - 2) {
|
|
while (i < rt->rotations.size() - 2) {
|
|
TKey<Quaternion> t0 = rt->rotations[i];
|
|
TKey<Quaternion> t0 = rt->rotations[i];
|
|
TKey<Quaternion> t1 = rt->rotations[i + 1];
|
|
TKey<Quaternion> t1 = rt->rotations[i + 1];
|
|
TKey<Quaternion> t2 = rt->rotations[i + 2];
|
|
TKey<Quaternion> t2 = rt->rotations[i + 2];
|
|
-
|
|
|
|
- bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
if (erase) {
|
|
if (erase) {
|
|
rt->rotations.remove_at(i + 1);
|
|
rt->rotations.remove_at(i + 1);
|
|
} else {
|
|
} else {
|
|
@@ -4284,15 +4305,19 @@ void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_er
|
|
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) {
|
|
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) {
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D);
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D);
|
|
|
|
+ bool is_nearest = false;
|
|
|
|
+ if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
|
|
|
|
+ is_nearest = true;
|
|
|
|
+ } else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
ScaleTrack *st = static_cast<ScaleTrack *>(tracks[p_idx]);
|
|
ScaleTrack *st = static_cast<ScaleTrack *>(tracks[p_idx]);
|
|
-
|
|
|
|
int i = 0;
|
|
int i = 0;
|
|
while (i < st->scales.size() - 2) {
|
|
while (i < st->scales.size() - 2) {
|
|
TKey<Vector3> t0 = st->scales[i];
|
|
TKey<Vector3> t0 = st->scales[i];
|
|
TKey<Vector3> t1 = st->scales[i + 1];
|
|
TKey<Vector3> t1 = st->scales[i + 1];
|
|
TKey<Vector3> t2 = st->scales[i + 2];
|
|
TKey<Vector3> t2 = st->scales[i + 2];
|
|
-
|
|
|
|
- bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
if (erase) {
|
|
if (erase) {
|
|
st->scales.remove_at(i + 1);
|
|
st->scales.remove_at(i + 1);
|
|
} else {
|
|
} else {
|
|
@@ -4310,15 +4335,20 @@ void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err,
|
|
void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
|
|
void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE);
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE);
|
|
|
|
+ bool is_nearest = false;
|
|
|
|
+ if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
|
|
|
|
+ is_nearest = true;
|
|
|
|
+ } else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(tracks[p_idx]);
|
|
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(tracks[p_idx]);
|
|
-
|
|
|
|
int i = 0;
|
|
int i = 0;
|
|
while (i < bst->blend_shapes.size() - 2) {
|
|
while (i < bst->blend_shapes.size() - 2) {
|
|
TKey<float> t0 = bst->blend_shapes[i];
|
|
TKey<float> t0 = bst->blend_shapes[i];
|
|
TKey<float> t1 = bst->blend_shapes[i + 1];
|
|
TKey<float> t1 = bst->blend_shapes[i + 1];
|
|
TKey<float> t2 = bst->blend_shapes[i + 2];
|
|
TKey<float> t2 = bst->blend_shapes[i + 2];
|
|
|
|
|
|
- bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error);
|
|
|
|
|
|
+ bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error, is_nearest);
|
|
if (erase) {
|
|
if (erase) {
|
|
bst->blend_shapes.remove_at(i + 1);
|
|
bst->blend_shapes.remove_at(i + 1);
|
|
} else {
|
|
} else {
|
|
@@ -4336,6 +4366,12 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity
|
|
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) {
|
|
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) {
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_INDEX(p_idx, tracks.size());
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE);
|
|
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE);
|
|
|
|
+ bool is_nearest = false;
|
|
|
|
+ if (tracks[p_idx]->interpolation == INTERPOLATION_NEAREST) {
|
|
|
|
+ is_nearest = true;
|
|
|
|
+ } else if (tracks[p_idx]->interpolation != INTERPOLATION_LINEAR && tracks[p_idx]->interpolation != INTERPOLATION_LINEAR_ANGLE) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
ValueTrack *vt = static_cast<ValueTrack *>(tracks[p_idx]);
|
|
ValueTrack *vt = static_cast<ValueTrack *>(tracks[p_idx]);
|
|
if (vt->values.is_empty()) {
|
|
if (vt->values.is_empty()) {
|
|
return;
|
|
return;
|
|
@@ -4367,7 +4403,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
|
|
break; // Rotation is more than 180 deg, keep key.
|
|
break; // Rotation is more than 180 deg, keep key.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error);
|
|
|
|
|
|
+ erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error, is_nearest);
|
|
} break;
|
|
} break;
|
|
case Variant::VECTOR2: {
|
|
case Variant::VECTOR2: {
|
|
TKey<Vector2> t0;
|
|
TKey<Vector2> t0;
|
|
@@ -4379,7 +4415,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
|
|
t0.value = vt->values[i].value;
|
|
t0.value = vt->values[i].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
- erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
} break;
|
|
} break;
|
|
case Variant::VECTOR3: {
|
|
case Variant::VECTOR3: {
|
|
TKey<Vector3> t0;
|
|
TKey<Vector3> t0;
|
|
@@ -4391,7 +4427,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
|
|
t0.value = vt->values[i].value;
|
|
t0.value = vt->values[i].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
- erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
} break;
|
|
} break;
|
|
case Variant::QUATERNION: {
|
|
case Variant::QUATERNION: {
|
|
TKey<Quaternion> t0;
|
|
TKey<Quaternion> t0;
|
|
@@ -4403,7 +4439,7 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
|
|
t0.value = vt->values[i].value;
|
|
t0.value = vt->values[i].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t1.value = vt->values[i + 1].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
t2.value = vt->values[i + 2].value;
|
|
- erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
|
|
|
|
|
|
+ erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error, is_nearest);
|
|
} break;
|
|
} break;
|
|
default: {
|
|
default: {
|
|
} break;
|
|
} break;
|