Skip to content

Commit 0fbec24

Browse files
committed
Extract stiffness parameters into a RopeStiffnessParameters resource
1 parent ca22971 commit 0fbec24

9 files changed

Lines changed: 203 additions & 49 deletions

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# run ./run_clang_tidy.sh
2+
# to run clang-tidy on all files in the project
3+
4+
.PHONY: all
5+
all: build_debug
6+
7+
8+
.PHONY: compdb
9+
compdb:
10+
./compile_debug.sh compiledb
11+
12+
.PHONY: build_debug
13+
build_debug:
14+
./compile_debug.sh
15+
16+
.PHONY: build_web_debug
17+
build_web_debug:
18+
./compile_debug.sh platform=web threads=no
19+
20+
.PHONY: check
21+
check: compdb
22+
run-clang-tidy -header-filter=src/ -allow-no-checks -quiet src/*.cpp src/*.hpp
23+
24+
.PHONY: doc
25+
doc:
26+
cd demo && godot --doctool ../ --gdextension-docs

demo/addons/ropesim/Rope.gd

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,6 @@ class_name Rope
44

55
# TODO: Split line rendering into a separate node
66

7-
enum StiffnessMethod {
8-
## Computes a single forward pass from front to back.
9-
## Produces decent results but may look unusual without [member fixate_begin] enabled.
10-
## It could also behave unstable in certain scenarios, i.e. jittery or erratic movement. [br]
11-
## This was the default behavior before v1.9.
12-
Legacy,
13-
## Computes a forward and backward pass.
14-
## Produces overall better and more stable results than [member StiffnessMethod.Legacy].
15-
## Acts more sensitive to [member stiffness_bend_curve].
16-
Bidirectional,
17-
}
187

198
## Triggered when the rope has been registered at the NativeRopeServer.
209
signal on_registered()
@@ -44,24 +33,21 @@ signal on_point_count_changed()
4433

4534
@export_group("Forces")
4635

47-
## Stiffness forces the rope to return to its resting position.
48-
## The resting direction is downwards and affected by the the node's rotation.
49-
## Might not produce 100% realistic results with fixed points.
50-
@export var stiffness: float = 0.0
51-
52-
## Determines which method to use for stiffness simulation.
53-
@export var stiffness_method: StiffnessMethod = StiffnessMethod.Bidirectional
54-
55-
## (Optional) Scale the stiffness along the rope.
56-
## If the rope behaves erratic,
57-
@export var stiffness_curve: Curve
58-
59-
## (Optional) Scale the stiffness individually per segment according to how far each segment is bent.
60-
## The y value of the curve is multiplied with the stiffness.
61-
## x = 0 corresponds to no bending and x = 1 corresponds to 180° bending in regard to the previous
62-
## segment.
63-
## If unset, defaults to a quadratic curve.
64-
@export var stiffness_bend_curve: Curve
36+
## Deprecated. Exists only for compatibility
37+
## @deprecated
38+
@export_storage var stiffness: float = 0.0 :
39+
set(value):
40+
if not stiffness_settings:
41+
var bend_curve := Curve.new()
42+
bend_curve.add_point(Vector2(0, 0), 0, 0, Curve.TANGENT_LINEAR, Curve.TANGENT_LINEAR)
43+
bend_curve.add_point(Vector2(1, 1), 0, 0, Curve.TANGENT_LINEAR, Curve.TANGENT_LINEAR)
44+
stiffness_settings = RopeStiffnessParameters.new()
45+
stiffness_settings.stiffness_method = RopeStiffnessParameters.Legacy
46+
stiffness_settings.stiffness_bend_curve = bend_curve
47+
stiffness_settings.stiffness = value
48+
49+
## (Optional) Parameters for stiffness simulation.
50+
@export var stiffness_settings: RopeStiffnessParameters
6551

6652
## Gravity
6753
@export var gravity: float = 100
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="RopeStiffnessParameters" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
3+
<brief_description>
4+
Resource for stiffness properties.
5+
</brief_description>
6+
<description>
7+
</description>
8+
<tutorials>
9+
</tutorials>
10+
<members>
11+
<member name="stiffness" type="float" setter="set_stiffness" getter="get_stiffness" default="0.0">
12+
Stiffness forces the rope to return to its resting position. The resting direction is downwards and affected by the the node's rotation.
13+
</member>
14+
<member name="stiffness_bend_curve" type="Curve" setter="set_stiffness_bend_curve" getter="get_stiffness_bend_curve">
15+
(Optional) Scale the stiffness individually per segment according to how far each segment is bent.[br]The [code]y[/code] value of the curve is multiplied with the stiffness. [code]x = 0[/code] corresponds to no bending and [code]x = 1[/code] corresponds to 180° bending in regard to the previous segment.[br]If unset, defaults to a quadratic curve.
16+
</member>
17+
<member name="stiffness_curve" type="Curve" setter="set_stiffness_curve" getter="get_stiffness_curve">
18+
(Optional) Scale the stiffness along the rope. Useful to make the rope less erratic towards the end.
19+
</member>
20+
<member name="stiffness_method" type="int" setter="set_stiffness_method" getter="get_stiffness_method" enum="RopeStiffnessParameters.StiffnessMethod" default="0">
21+
Determines which method to use for stiffness simulation.
22+
</member>
23+
</members>
24+
<constants>
25+
<constant name="Bidirectional" value="0" enum="StiffnessMethod">
26+
Computes a forward and backward pass.[br]Produces overall better and more stable results than [enum Legacy]. Acts more sensitive to [member stiffness_bend_curve].
27+
</constant>
28+
<constant name="Legacy" value="1" enum="StiffnessMethod">
29+
Computes a single forward pass from front to back.[br]Produces decent results but may look unusual without [member Rope.fixate_begin] enabled. It could also behave more unstable in certain scenarios, i.e. jittery or erratic movement.[br]This was the default behavior before [code]v1.9[/code].
30+
</constant>
31+
</constants>
32+
</class>

doc_classes/RopeWindParameters.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
<member name="direction" type="float" setter="set_direction" getter="get_direction" default="0.0">
1212
The angle the wind force is pushing the rope.
1313
</member>
14+
<member name="enable_wind" type="bool" setter="set_enable_wind" getter="get_enable_wind" default="true">
15+
Enables or disables wind for all ropes who reference this resource.
16+
</member>
1417
<member name="noise" type="FastNoiseLite" setter="set_noise" getter="get_noise">
1518
Noise function used when generating oscillating wind forces.
1619
</member>
@@ -20,8 +23,5 @@
2023
<member name="wind_strength" type="float" setter="set_wind_strength" getter="get_wind_strength" default="0.0">
2124
How taut the wind force is pulling the rope. Lower values allow the noise to move easier, higher can straighten the rope out even with high noise oscillation strength.
2225
</member>
23-
<member name="enable_wind" type="bool" setter="set_wind_enabled" getter="get_wind_enabled" default="true">
24-
Enables or disables wind for all ropes who reference this resource.
25-
</member>
2626
</members>
2727
</class>

src/NativeRopeContext.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ void NativeRopeContext::load_context(Node2D* rope)
5353
gravity_direction = rope->get("gravity_direction");
5454
wind = rope->get("wind");
5555
damping = rope->get("damping");
56-
stiffness = rope->get("stiffness");
57-
stiffness_method = static_cast<StiffnessMethod>(static_cast<int>(rope->get("stiffness_method")));
58-
stiffness_curve = rope->get("stiffness_curve");
59-
stiffness_bend_curve = rope->get("stiffness_bend_curve");
56+
stiffness_params = rope->get("stiffness_settings");
6057
max_endpoint_distance = rope->get("max_endpoint_distance");
6158
num_constraint_iterations = rope->get("num_constraint_iterations");
6259
seg_lengths = rope->call("get_segment_lengths");
@@ -163,12 +160,12 @@ void NativeRopeContext::_simulate_wind(PackedVector2Array* velocities) const
163160

164161
void NativeRopeContext::_simulate_stiffness(double delta, PackedVector2Array* velocities) const
165162
{
166-
if (stiffness <= 0)
163+
if (stiffness_params->get_stiffness() <= 0)
167164
return;
168165

169166
const auto num_points = points.size();
170167

171-
if (stiffness_method == StiffnessMethod::Legacy)
168+
if (stiffness_params->get_stiffness_method() == RopeStiffnessParameters::Legacy)
172169
{
173170
const Vector2 parent_seg_dir = rope->get_global_transform().basis_xform(VECTOR_DOWN).normalized();
174171
_simulate_stiffness_segment(delta, velocities, 1, num_points, parent_seg_dir); // Start at second and stop at last point
@@ -198,6 +195,9 @@ void NativeRopeContext::_simulate_stiffness_segment(double /*delta*/, PackedVec
198195
// NOTE: oldpoints should not be used here, see comments in simulate_velocities().
199196

200197
Vector2 force;
198+
const float stiffness = stiffness_params->get_stiffness();
199+
const auto stiffness_curve = stiffness_params->get_stiffness_curve();
200+
const auto stiffness_bend_curve = stiffness_params->get_stiffness_bend_curve();
201201
const bool use_stiffness_curve = stiffness_curve.is_valid() && stiffness_curve->get_point_count() > 0;
202202
const bool use_bend_curve = stiffness_bend_curve.is_valid() && stiffness_bend_curve->get_point_count() > 0;
203203
const int64_t idx_step = idx_from <= idx_stop ? 1 : -1;

src/NativeRopeContext.hpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
#pragma once
22

3+
#include "RopeStiffnessParameters.hpp"
34
#include "RopeWindParameters.hpp"
45
#include <godot_cpp/classes/curve.hpp>
56
#include <godot_cpp/classes/node2d.hpp>
67
#include <godot_cpp/classes/physics_shape_query_parameters2d.hpp>
78

89
namespace godot {
910

10-
// Should match Rope.gd
11-
enum class StiffnessMethod : int8_t
12-
{
13-
Legacy,
14-
Bidirectional
15-
};
16-
1711
// Caches properties of a rope node and performs simulation.
1812
// TODO: Could be used as base class in the future to manage rope data in C++ and not in GDScript.
1913
class NativeRopeContext // NOLINT(cppcoreguidelines-special-member-functions)
@@ -52,17 +46,14 @@ class NativeRopeContext // NOLINT(cppcoreguidelines-special-member-functions)
5246
Ref<RopeWindParameters> wind;
5347
float damping = 0.0;
5448
Ref<Curve> damping_curve;
55-
float stiffness = 0.0;
56-
Ref<Curve> stiffness_curve;
57-
Ref<Curve> stiffness_bend_curve;
49+
Ref<RopeStiffnessParameters> stiffness_params;
5850
float max_endpoint_distance = 0.0;
5951
int num_constraint_iterations = 0;
6052

6153
float collision_radius = 1.0;
6254
float collision_damping = 0.0;
6355
int collision_mask = 0;
6456

65-
StiffnessMethod stiffness_method = StiffnessMethod::Bidirectional;
6657
bool fixate_begin = true;
6758
bool resolve_to_begin = false;
6859
bool resolve_to_end = false;

src/RopeStiffnessParameters.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "RopeStiffnessParameters.hpp"
2+
#include "godot_cpp/core/class_db.hpp"
3+
4+
using namespace godot;
5+
6+
RopeStiffnessParameters::StiffnessMethod RopeStiffnessParameters::get_stiffness_method() const
7+
{
8+
return stiffness_method;
9+
}
10+
11+
void RopeStiffnessParameters::set_stiffness_method(StiffnessMethod method)
12+
{
13+
stiffness_method = method;
14+
emit_changed();
15+
}
16+
17+
float RopeStiffnessParameters::get_stiffness() const
18+
{
19+
return stiffness;
20+
}
21+
22+
void RopeStiffnessParameters::set_stiffness(float value)
23+
{
24+
stiffness = value;
25+
emit_changed();
26+
}
27+
28+
Ref<Curve> RopeStiffnessParameters::get_stiffness_curve() const
29+
{
30+
return stiffness_curve;
31+
}
32+
33+
void RopeStiffnessParameters::set_stiffness_curve(Ref<Curve> curve)
34+
{
35+
stiffness_curve = curve;
36+
emit_changed();
37+
}
38+
39+
Ref<Curve> RopeStiffnessParameters::get_stiffness_bend_curve() const
40+
{
41+
return stiffness_bend_curve;
42+
}
43+
44+
void RopeStiffnessParameters::set_stiffness_bend_curve(Ref<Curve> curve)
45+
{
46+
stiffness_bend_curve = curve;
47+
emit_changed();
48+
}
49+
50+
51+
void RopeStiffnessParameters::_bind_methods()
52+
{
53+
ClassDB::bind_method(D_METHOD("get_stiffness_method"), &RopeStiffnessParameters::get_stiffness_method);
54+
ClassDB::bind_method(D_METHOD("set_stiffness_method", "method"), &RopeStiffnessParameters::set_stiffness_method);
55+
ClassDB::bind_method(D_METHOD("get_stiffness"), &RopeStiffnessParameters::get_stiffness);
56+
ClassDB::bind_method(D_METHOD("set_stiffness", "value"), &RopeStiffnessParameters::set_stiffness);
57+
ClassDB::bind_method(D_METHOD("get_stiffness_curve"), &RopeStiffnessParameters::get_stiffness_curve);
58+
ClassDB::bind_method(D_METHOD("set_stiffness_curve", "curve"), &RopeStiffnessParameters::set_stiffness_curve);
59+
ClassDB::bind_method(D_METHOD("get_stiffness_bend_curve"), &RopeStiffnessParameters::get_stiffness_bend_curve);
60+
ClassDB::bind_method(D_METHOD("set_stiffness_bend_curve", "curve"), &RopeStiffnessParameters::set_stiffness_bend_curve);
61+
62+
ADD_PROPERTY(PropertyInfo(Variant::INT, "stiffness_method", PROPERTY_HINT_ENUM, stiffness_method_strings), "set_stiffness_method", "get_stiffness_method");
63+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness"), "set_stiffness", "get_stiffness");
64+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stiffness_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_stiffness_curve", "get_stiffness_curve");
65+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stiffness_bend_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_stiffness_bend_curve", "get_stiffness_bend_curve");
66+
67+
BIND_ENUM_CONSTANT(Bidirectional);
68+
BIND_ENUM_CONSTANT(Legacy);
69+
}

src/RopeStiffnessParameters.hpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <godot_cpp/classes/curve.hpp>
4+
#include <godot_cpp/classes/resource.hpp>
5+
6+
namespace godot {
7+
8+
class RopeStiffnessParameters : public Resource // NOLINT(cppcoreguidelines-special-member-functions)
9+
{
10+
GDCLASS(RopeStiffnessParameters, Resource) // NOLINT
11+
12+
public:
13+
enum StiffnessMethod : int8_t // NOLINT(cppcoreguidelines-use-enum-class)
14+
{
15+
Bidirectional,
16+
Legacy,
17+
};
18+
19+
static constexpr const char* stiffness_method_strings = "Bidirectional,Legacy";
20+
21+
public:
22+
StiffnessMethod get_stiffness_method() const;
23+
void set_stiffness_method(StiffnessMethod method);
24+
25+
float get_stiffness() const;
26+
void set_stiffness(float value);
27+
28+
Ref<Curve> get_stiffness_curve() const;
29+
void set_stiffness_curve(Ref<Curve> curve);
30+
31+
Ref<Curve> get_stiffness_bend_curve() const;
32+
void set_stiffness_bend_curve(Ref<Curve> curve);
33+
34+
protected:
35+
static void _bind_methods();
36+
37+
private:
38+
StiffnessMethod stiffness_method = StiffnessMethod::Bidirectional;
39+
float stiffness = 0.0;
40+
Ref<Curve> stiffness_curve;
41+
Ref<Curve> stiffness_bend_curve;
42+
// TODO: Stiffness direction for back and front
43+
// TODO: Stiffness damping
44+
};
45+
46+
}
47+
48+
VARIANT_ENUM_CAST(RopeStiffnessParameters::StiffnessMethod); // NOLINT

src/gdlibrary.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "gdlibrary.hpp"
22
#include "NativeRopeServer.hpp"
3+
#include "RopeStiffnessParameters.hpp"
34
#include "RopeWindParameters.hpp"
45
#include <gdextension_interface.h>
56
#include <godot_cpp/classes/engine.hpp>
@@ -17,6 +18,7 @@ void initialize_libropesim(ModuleInitializationLevel p_level)
1718

1819
ClassDB::register_class<NativeRopeServer>();
1920
ClassDB::register_class<RopeWindParameters>();
21+
ClassDB::register_class<RopeStiffnessParameters>();
2022
rope_server = memnew(NativeRopeServer); // NOLINT
2123
Engine::get_singleton()->register_singleton("NativeRopeServer", rope_server);
2224
}

0 commit comments

Comments
 (0)