Kaynağa Gözat

Merge pull request #12282 from tagcup/path_fix

Fix PathFollow rotations.

[ci skip]
Rémi Verschelde 8 yıl önce
ebeveyn
işleme
f002e4cb82
2 değiştirilmiş dosya ile 25 ekleme ve 32 silme
  1. 24 28
      scene/3d/path.cpp
  2. 1 4
      scene/3d/path.h

+ 24 - 28
scene/3d/path.cpp

@@ -85,9 +85,15 @@ void PathFollow::_update_transform() {
 	if (!c.is_valid())
 		return;
 
+	if (delta_offset == 0) {
+		return;
+	}
+
 	float o = offset;
-	if (loop)
+
+	if (loop) {
 		o = Math::fposmod(o, c->get_baked_length());
+	}
 
 	Vector3 pos = c->interpolate_baked(o, cubic);
 	Transform t = get_transform();
@@ -101,14 +107,14 @@ void PathFollow::_update_transform() {
 		// see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
 		// for a discussion about why not Frenet frame.
 
-		Vector3 t_prev = pos - c->interpolate_baked(o - lookahead, cubic);
-		Vector3 t_cur = c->interpolate_baked(o + lookahead, cubic) - pos;
+		Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
+		Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
 
 		Vector3 axis = t_prev.cross(t_cur);
-		float dot = t_prev.normalized().dot(t_cur.normalized());
+		float dot = t_prev.dot(t_cur);
 		float angle = Math::acos(CLAMP(dot, -1, 1));
 
-		if (axis.length() > CMP_EPSILON && angle > CMP_EPSILON) {
+		if (likely(Math::abs(angle) > CMP_EPSILON)) {
 			if (rotation_mode == ROTATION_Y) {
 				// assuming we're referring to global Y-axis. is this correct?
 				axis.x = 0;
@@ -116,27 +122,31 @@ void PathFollow::_update_transform() {
 			} else if (rotation_mode == ROTATION_XY) {
 				axis.z = 0;
 			} else if (rotation_mode == ROTATION_XYZ) {
-				// all components are OK
+				// all components are allowed
 			}
 
-			t.rotate_basis(axis.normalized(), angle);
+			if (likely(axis.length() > CMP_EPSILON)) {
+				t.rotate_basis(axis.normalized(), angle);
+			}
 		}
 
 		// do the additional tilting
 		float tilt_angle = c->interpolate_baked_tilt(o);
-		Vector3 tilt_axis = t_cur; // is this correct??
+		Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
 
-		if (tilt_axis.length() > CMP_EPSILON && tilt_angle > CMP_EPSILON) {
+		if (likely(Math::abs(tilt_angle) > CMP_EPSILON)) {
 			if (rotation_mode == ROTATION_Y) {
 				tilt_axis.x = 0;
 				tilt_axis.z = 0;
 			} else if (rotation_mode == ROTATION_XY) {
 				tilt_axis.z = 0;
 			} else if (rotation_mode == ROTATION_XYZ) {
-				// all components are OK
+				// all components are allowed
 			}
 
-			t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+			if (likely(tilt_axis.length() > CMP_EPSILON)) {
+				t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+			}
 		}
 
 		t.translate(pos_offset);
@@ -195,8 +205,6 @@ bool PathFollow::_set(const StringName &p_name, const Variant &p_value) {
 		set_cubic_interpolation(p_value);
 	} else if (String(p_name) == "loop") {
 		set_loop(p_value);
-	} else if (String(p_name) == "lookahead") {
-		set_lookahead(p_value);
 	} else
 		return false;
 
@@ -219,8 +227,6 @@ bool PathFollow::_get(const StringName &p_name, Variant &r_ret) const {
 		r_ret = cubic;
 	} else if (String(p_name) == "loop") {
 		r_ret = loop;
-	} else if (String(p_name) == "lookahead") {
-		r_ret = lookahead;
 	} else
 		return false;
 
@@ -238,7 +244,6 @@ void PathFollow::_get_property_list(List<PropertyInfo> *p_list) const {
 	p_list->push_back(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ"));
 	p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp"));
 	p_list->push_back(PropertyInfo(Variant::BOOL, "loop"));
-	p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"));
 }
 
 void PathFollow::_bind_methods() {
@@ -271,8 +276,9 @@ void PathFollow::_bind_methods() {
 }
 
 void PathFollow::set_offset(float p_offset) {
-
+	delta_offset = p_offset - offset;
 	offset = p_offset;
+
 	if (path)
 		_update_transform();
 	_change_notify("offset");
@@ -322,16 +328,6 @@ float PathFollow::get_unit_offset() const {
 		return 0;
 }
 
-void PathFollow::set_lookahead(float p_lookahead) {
-
-	lookahead = p_lookahead;
-}
-
-float PathFollow::get_lookahead() const {
-
-	return lookahead;
-}
-
 void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
 
 	rotation_mode = p_rotation_mode;
@@ -356,11 +352,11 @@ bool PathFollow::has_loop() const {
 PathFollow::PathFollow() {
 
 	offset = 0;
+	delta_offset = 0;
 	h_offset = 0;
 	v_offset = 0;
 	path = NULL;
 	rotation_mode = ROTATION_XYZ;
 	cubic = true;
 	loop = true;
-	lookahead = 0.1;
 }

+ 1 - 4
scene/3d/path.h

@@ -67,10 +67,10 @@ public:
 
 private:
 	Path *path;
+	real_t delta_offset; // change in offset since last _update_transform
 	real_t offset;
 	real_t h_offset;
 	real_t v_offset;
-	real_t lookahead;
 	bool cubic;
 	bool loop;
 	RotationMode rotation_mode;
@@ -98,9 +98,6 @@ public:
 	void set_unit_offset(float p_unit_offset);
 	float get_unit_offset() const;
 
-	void set_lookahead(float p_lookahead);
-	float get_lookahead() const;
-
 	void set_loop(bool p_loop);
 	bool has_loop() const;