mirror of
https://github.com/godotengine/godot.git
synced 2025-11-01 06:01:14 +00:00
Up vector implementation and OrientedPathFollow.
This commit is contained in:
parent
228b09bafb
commit
dc639d334a
9 changed files with 469 additions and 1 deletions
|
|
@ -1169,6 +1169,7 @@ void Curve3D::_bake() const {
|
|||
if (points.size() == 0) {
|
||||
baked_point_cache.resize(0);
|
||||
baked_tilt_cache.resize(0);
|
||||
baked_up_vector_cache.resize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1178,6 +1179,14 @@ void Curve3D::_bake() const {
|
|||
baked_point_cache.set(0, points[0].pos);
|
||||
baked_tilt_cache.resize(1);
|
||||
baked_tilt_cache.set(0, points[0].tilt);
|
||||
|
||||
if (up_vector_enabled) {
|
||||
|
||||
baked_up_vector_cache.resize(1);
|
||||
baked_up_vector_cache.set(0, Vector3(0, 1, 0));
|
||||
} else
|
||||
baked_up_vector_cache.resize(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1247,10 +1256,51 @@ void Curve3D::_bake() const {
|
|||
baked_tilt_cache.resize(pointlist.size());
|
||||
PoolRealArray::Write wt = baked_tilt_cache.write();
|
||||
|
||||
baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0);
|
||||
PoolVector3Array::Write up_write = baked_up_vector_cache.write();
|
||||
|
||||
Vector3 sideways;
|
||||
Vector3 up;
|
||||
Vector3 forward;
|
||||
|
||||
Vector3 prev_sideways = Vector3(1, 0, 0);
|
||||
Vector3 prev_up = Vector3(0, 1, 0);
|
||||
Vector3 prev_forward = Vector3(0, 0, 1);
|
||||
|
||||
for (List<Plane>::Element *E = pointlist.front(); E; E = E->next()) {
|
||||
|
||||
w[idx] = E->get().normal;
|
||||
wt[idx] = E->get().d;
|
||||
|
||||
if (!up_vector_enabled) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward;
|
||||
|
||||
float y_dot = prev_up.dot(forward);
|
||||
|
||||
if (y_dot > (1.0f - CMP_EPSILON)) {
|
||||
sideways = prev_sideways;
|
||||
up = -prev_forward;
|
||||
} else if (y_dot < -(1.0f - CMP_EPSILON)) {
|
||||
sideways = prev_sideways;
|
||||
up = prev_forward;
|
||||
} else {
|
||||
sideways = prev_up.cross(forward).normalized();
|
||||
up = forward.cross(sideways).normalized();
|
||||
}
|
||||
|
||||
if (idx == 1)
|
||||
up_write[0] = up;
|
||||
|
||||
up_write[idx] = up;
|
||||
|
||||
prev_sideways = sideways;
|
||||
prev_up = up;
|
||||
prev_forward = forward;
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1343,6 +1393,53 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const {
|
|||
return Math::lerp(r[idx], r[idx + 1], frac);
|
||||
}
|
||||
|
||||
Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const {
|
||||
|
||||
if (baked_cache_dirty)
|
||||
_bake();
|
||||
|
||||
//validate//
|
||||
// curve may not have baked up vectors
|
||||
int count = baked_up_vector_cache.size();
|
||||
if (count == 0) {
|
||||
ERR_EXPLAIN("No up vectors in Curve3D");
|
||||
ERR_FAIL_COND_V(count == 0, Vector3(0, 1, 0));
|
||||
}
|
||||
|
||||
if (count == 1)
|
||||
return baked_up_vector_cache.get(0);
|
||||
|
||||
PoolVector3Array::Read r = baked_up_vector_cache.read();
|
||||
PoolVector3Array::Read rp = baked_point_cache.read();
|
||||
PoolRealArray::Read rt = baked_tilt_cache.read();
|
||||
|
||||
float offset = CLAMP(p_offset, 0.0f, baked_max_ofs);
|
||||
|
||||
int idx = Math::floor((double)offset / (double)bake_interval);
|
||||
float frac = Math::fmod(offset, bake_interval) / bake_interval;
|
||||
|
||||
if (idx == count - 1)
|
||||
return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];
|
||||
|
||||
Vector3 forward = (rp[idx + 1] - rp[idx]).normalized();
|
||||
Vector3 up = r[idx];
|
||||
Vector3 up1 = r[idx + 1];
|
||||
|
||||
if (p_apply_tilt) {
|
||||
up.rotate(forward, rt[idx]);
|
||||
up1.rotate(idx + 2 >= count ? forward : (rp[idx + 2] - rp[idx + 1]).normalized(), rt[idx + 1]);
|
||||
}
|
||||
|
||||
Vector3 axis = up.cross(up1);
|
||||
|
||||
if (axis.length_squared() < CMP_EPSILON2)
|
||||
axis = forward;
|
||||
else
|
||||
axis.normalize();
|
||||
|
||||
return up.rotated(axis, up.angle_to(up1) * frac);
|
||||
}
|
||||
|
||||
PoolVector3Array Curve3D::get_baked_points() const {
|
||||
|
||||
if (baked_cache_dirty)
|
||||
|
|
@ -1359,6 +1456,14 @@ PoolRealArray Curve3D::get_baked_tilts() const {
|
|||
return baked_tilt_cache;
|
||||
}
|
||||
|
||||
PoolVector3Array Curve3D::get_baked_up_vectors() const {
|
||||
|
||||
if (baked_cache_dirty)
|
||||
_bake();
|
||||
|
||||
return baked_up_vector_cache;
|
||||
}
|
||||
|
||||
Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
|
||||
// Brute force method
|
||||
|
||||
|
|
@ -1452,6 +1557,18 @@ float Curve3D::get_bake_interval() const {
|
|||
return bake_interval;
|
||||
}
|
||||
|
||||
void Curve3D::set_up_vector_enabled(bool p_enable) {
|
||||
|
||||
up_vector_enabled = p_enable;
|
||||
baked_cache_dirty = true;
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
bool Curve3D::is_up_vector_enabled() const {
|
||||
|
||||
return up_vector_enabled;
|
||||
}
|
||||
|
||||
Dictionary Curve3D::_get_data() const {
|
||||
|
||||
Dictionary dc;
|
||||
|
|
@ -1563,11 +1680,15 @@ void Curve3D::_bind_methods() {
|
|||
//ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10));
|
||||
ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve3D::set_bake_interval);
|
||||
ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve3D::get_bake_interval);
|
||||
ClassDB::bind_method(D_METHOD("set_up_vector_enabled", "enable"), &Curve3D::set_up_vector_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_up_vector_enabled"), &Curve3D::is_up_vector_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length);
|
||||
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("interpolate_baked_up_vector", "offset", "apply_tilt"), &Curve3D::interpolate_baked_up_vector, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
|
||||
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
|
||||
ClassDB::bind_method(D_METHOD("get_baked_up_vectors"), &Curve3D::get_baked_up_vectors);
|
||||
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point);
|
||||
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset);
|
||||
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4));
|
||||
|
|
@ -1577,6 +1698,9 @@ void Curve3D::_bind_methods() {
|
|||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
|
||||
|
||||
ADD_GROUP("Up Vector", "up_vector_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "up_vector_enabled"), "set_up_vector_enabled", "is_up_vector_enabled");
|
||||
}
|
||||
|
||||
Curve3D::Curve3D() {
|
||||
|
|
@ -1586,4 +1710,5 @@ Curve3D::Curve3D() {
|
|||
add_point(Vector3(0,2,0));
|
||||
add_point(Vector3(0,3,5));*/
|
||||
bake_interval = 0.2;
|
||||
up_vector_enabled = true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue