1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Fix Curve idx calculation for baked tilts and up vectors

This commit is contained in:
Raul Santos
2021-09-15 15:40:33 +02:00
parent edda6ee9f8
commit a80bc715ad

View File

@@ -771,17 +771,16 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const {
return baked_point_cache.get(0); return baked_point_cache.get(0);
} }
int bpc = baked_point_cache.size();
const Vector2 *r = baked_point_cache.ptr(); const Vector2 *r = baked_point_cache.ptr();
if (p_offset < 0) { if (p_offset < 0) {
return r[0]; return r[0];
} }
if (p_offset >= baked_max_ofs) { if (p_offset >= baked_max_ofs) {
return r[bpc - 1]; return r[pc - 1];
} }
int start = 0, end = bpc, idx = (end + start) / 2; int start = 0, end = pc, idx = (end + start) / 2;
// binary search to find baked points // binary search to find baked points
while (start < idx) { while (start < idx) {
real_t offset = baked_dist_cache[idx]; real_t offset = baked_dist_cache[idx];
@@ -803,7 +802,7 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const {
if (p_cubic) { if (p_cubic) {
Vector2 pre = idx > 0 ? r[idx - 1] : r[idx]; Vector2 pre = idx > 0 ? r[idx - 1] : r[idx];
Vector2 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; Vector2 post = (idx < (pc - 2)) ? r[idx + 2] : r[idx + 1];
return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac);
} else { } else {
return r[idx].lerp(r[idx + 1], frac); return r[idx].lerp(r[idx + 1], frac);
@@ -1336,17 +1335,16 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
return baked_point_cache.get(0); return baked_point_cache.get(0);
} }
int bpc = baked_point_cache.size();
const Vector3 *r = baked_point_cache.ptr(); const Vector3 *r = baked_point_cache.ptr();
if (p_offset < 0) { if (p_offset < 0) {
return r[0]; return r[0];
} }
if (p_offset >= baked_max_ofs) { if (p_offset >= baked_max_ofs) {
return r[bpc - 1]; return r[pc - 1];
} }
int start = 0, end = bpc, idx = (end + start) / 2; int start = 0, end = pc, idx = (end + start) / 2;
// binary search to find baked points // binary search to find baked points
while (start < idx) { while (start < idx) {
real_t offset = baked_dist_cache[idx]; real_t offset = baked_dist_cache[idx];
@@ -1368,7 +1366,7 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
if (p_cubic) { if (p_cubic) {
Vector3 pre = idx > 0 ? r[idx - 1] : r[idx]; Vector3 pre = idx > 0 ? r[idx - 1] : r[idx];
Vector3 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; Vector3 post = (idx < (pc - 2)) ? r[idx + 2] : r[idx + 1];
return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac);
} else { } else {
return r[idx].lerp(r[idx + 1], frac); return r[idx].lerp(r[idx + 1], frac);
@@ -1388,29 +1386,35 @@ real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const {
return baked_tilt_cache.get(0); return baked_tilt_cache.get(0);
} }
int bpc = baked_tilt_cache.size();
const real_t *r = baked_tilt_cache.ptr(); const real_t *r = baked_tilt_cache.ptr();
if (p_offset < 0) { if (p_offset < 0) {
return r[0]; return r[0];
} }
if (p_offset >= baked_max_ofs) { if (p_offset >= baked_max_ofs) {
return r[bpc - 1]; return r[pc - 1];
} }
int idx = Math::floor((double)p_offset / (double)bake_interval); int start = 0, end = pc, idx = (end + start) / 2;
real_t frac = Math::fmod(p_offset, bake_interval); // binary search to find baked points
while (start < idx) {
if (idx >= bpc - 1) { real_t offset = baked_dist_cache[idx];
return r[bpc - 1]; if (p_offset <= offset) {
} else if (idx == bpc - 2) { end = idx;
if (frac > 0) { } else {
frac /= Math::fmod(baked_max_ofs, bake_interval); start = idx;
} }
} else { idx = (end + start) / 2;
frac /= bake_interval;
} }
real_t offset_begin = baked_dist_cache[idx];
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "failed to find baked segment");
real_t frac = (p_offset - offset_begin) / idx_interval;
return Math::lerp(r[idx], r[idx + 1], (real_t)frac); return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
} }
@@ -1432,10 +1436,25 @@ Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt)
const Vector3 *rp = baked_point_cache.ptr(); const Vector3 *rp = baked_point_cache.ptr();
const real_t *rt = baked_tilt_cache.ptr(); const real_t *rt = baked_tilt_cache.ptr();
real_t offset = CLAMP(p_offset, 0.0f, baked_max_ofs); int start = 0, end = count, idx = (end + start) / 2;
// binary search to find baked points
while (start < idx) {
real_t offset = baked_dist_cache[idx];
if (p_offset <= offset) {
end = idx;
} else {
start = idx;
}
idx = (end + start) / 2;
}
int idx = Math::floor((double)offset / (double)bake_interval); real_t offset_begin = baked_dist_cache[idx];
real_t frac = Math::fmod(offset, bake_interval) / bake_interval; real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "failed to find baked segment");
real_t frac = (p_offset - offset_begin) / idx_interval;
if (idx == count - 1) { if (idx == count - 1) {
return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx]; return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];