Add flag to enable use of accurate path tangents for polygon rotation in CSGPolygon3D

The new property is called `path_rotation_accurate`.
This commit is contained in:
Juan Pablo Arce
2024-07-17 14:16:51 -03:00
committed by Juan Pablo Arce
parent ce88021aa0
commit dd7bbcc837
4 changed files with 179 additions and 26 deletions

View File

@ -2234,24 +2234,35 @@ CSGBrush *CSGPolygon3D::_build_brush() {
base_xform = path->get_global_transform();
}
Vector3 current_point = curve->sample_baked(0);
Vector3 next_point = curve->sample_baked(extrusion_step);
Vector3 current_point;
Vector3 current_up = Vector3(0, 1, 0);
Vector3 direction = next_point - current_point;
if (path_joined) {
Vector3 last_point = curve->sample_baked(curve->get_baked_length());
direction = next_point - last_point;
}
Vector3 direction;
switch (path_rotation) {
case PATH_ROTATION_POLYGON:
current_point = curve->sample_baked(0);
direction = Vector3(0, 0, -1);
break;
case PATH_ROTATION_PATH:
break;
case PATH_ROTATION_PATH_FOLLOW:
current_up = curve->sample_baked_up_vector(0, true);
if (!path_rotation_accurate) {
current_point = curve->sample_baked(0);
Vector3 next_point = curve->sample_baked(extrusion_step);
direction = next_point - current_point;
if (path_joined) {
Vector3 last_point = curve->sample_baked(curve->get_baked_length());
direction = next_point - last_point;
}
} else {
Transform3D current_sample_xform = curve->sample_baked_with_rotation(0);
current_point = current_sample_xform.get_origin();
direction = current_sample_xform.get_basis().xform(Vector3(0, 0, -1));
}
if (path_rotation == PATH_ROTATION_PATH_FOLLOW) {
current_up = curve->sample_baked_up_vector(0, true);
}
break;
}
@ -2307,32 +2318,26 @@ CSGBrush *CSGPolygon3D::_build_brush() {
case MODE_PATH: {
double previous_offset = x0 * extrusion_step;
double current_offset = (x0 + 1) * extrusion_step;
double next_offset = (x0 + 2) * extrusion_step;
if (x0 == extrusions - 1) {
if (path_joined) {
current_offset = 0;
next_offset = extrusion_step;
} else {
next_offset = current_offset;
}
if (path_joined && x0 == extrusions - 1) {
current_offset = 0;
}
Vector3 previous_point = curve->sample_baked(previous_offset);
Vector3 current_point = curve->sample_baked(current_offset);
Vector3 next_point = curve->sample_baked(next_offset);
Transform3D current_sample_xform = curve->sample_baked_with_rotation(current_offset);
Vector3 current_point = current_sample_xform.get_origin();
Vector3 current_up = Vector3(0, 1, 0);
Vector3 direction = next_point - previous_point;
Vector3 current_dir = (current_point - previous_point).normalized();
Vector3 current_extrusion_dir = (current_point - previous_point).normalized();
Vector3 direction;
// If the angles are similar, remove the previous face and replace it with this one.
if (path_simplify_angle > 0.0 && x0 > 0 && previous_simplify_dir.dot(current_dir) > angle_simplify_dot) {
if (path_simplify_angle > 0.0 && x0 > 0 && previous_simplify_dir.dot(current_extrusion_dir) > angle_simplify_dot) {
faces_combined += 1;
previous_xform = previous_previous_xform;
face -= extrusion_face_count;
faces_removed += extrusion_face_count;
} else {
faces_combined = 0;
previous_simplify_dir = current_dir;
previous_simplify_dir = current_extrusion_dir;
}
switch (path_rotation) {
@ -2340,9 +2345,21 @@ CSGBrush *CSGPolygon3D::_build_brush() {
direction = Vector3(0, 0, -1);
break;
case PATH_ROTATION_PATH:
break;
case PATH_ROTATION_PATH_FOLLOW:
current_up = curve->sample_baked_up_vector(current_offset, true);
if (!path_rotation_accurate) {
double next_offset = (x0 + 2) * extrusion_step;
if (x0 == extrusions - 1) {
next_offset = path_joined ? extrusion_step : current_offset;
}
Vector3 next_point = curve->sample_baked(next_offset);
direction = next_point - previous_point;
} else {
direction = current_sample_xform.get_basis().xform(Vector3(0, 0, -1));
}
if (path_rotation == PATH_ROTATION_PATH_FOLLOW) {
current_up = curve->sample_baked_up_vector(current_offset, true);
}
break;
}
@ -2512,6 +2529,9 @@ void CSGPolygon3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_rotation", "path_rotation"), &CSGPolygon3D::set_path_rotation);
ClassDB::bind_method(D_METHOD("get_path_rotation"), &CSGPolygon3D::get_path_rotation);
ClassDB::bind_method(D_METHOD("set_path_rotation_accurate", "enable"), &CSGPolygon3D::set_path_rotation_accurate);
ClassDB::bind_method(D_METHOD("get_path_rotation_accurate"), &CSGPolygon3D::get_path_rotation_accurate);
ClassDB::bind_method(D_METHOD("set_path_local", "enable"), &CSGPolygon3D::set_path_local);
ClassDB::bind_method(D_METHOD("is_path_local"), &CSGPolygon3D::is_path_local);
@ -2543,6 +2563,7 @@ void CSGPolygon3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_interval", PROPERTY_HINT_RANGE, "0.01,1.0,0.01,exp,or_greater"), "set_path_interval", "get_path_interval");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_simplify_angle", PROPERTY_HINT_RANGE, "0.0,180.0,0.1"), "set_path_simplify_angle", "get_path_simplify_angle");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_rotation_accurate"), "set_path_rotation_accurate", "get_path_rotation_accurate");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_local"), "set_path_local", "is_path_local");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_continuous_u"), "set_path_continuous_u", "is_path_continuous_u");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_u_distance", PROPERTY_HINT_RANGE, "0.0,10.0,0.01,or_greater,suffix:m"), "set_path_u_distance", "get_path_u_distance");
@ -2685,6 +2706,16 @@ CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const {
return path_rotation;
}
void CSGPolygon3D::set_path_rotation_accurate(bool p_enabled) {
path_rotation_accurate = p_enabled;
_make_dirty();
update_gizmos();
}
bool CSGPolygon3D::get_path_rotation_accurate() const {
return path_rotation_accurate;
}
void CSGPolygon3D::set_path_local(bool p_enable) {
path_local = p_enable;
_make_dirty();
@ -2746,6 +2777,7 @@ CSGPolygon3D::CSGPolygon3D() {
path_interval = 1.0;
path_simplify_angle = 0.0;
path_rotation = PATH_ROTATION_PATH_FOLLOW;
path_rotation_accurate = false;
path_local = false;
path_continuous_u = true;
path_u_distance = 1.0;