Enabled area-specific wind forces
This commit is contained in:
parent
d5a30431b9
commit
e806397196
|
@ -92,6 +92,15 @@
|
||||||
<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area3D.SpaceOverride" default="0">
|
<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area3D.SpaceOverride" default="0">
|
||||||
Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values.
|
Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="wind_attenuation_factor" type="float" setter="set_wind_attenuation_factor" getter="get_wind_attenuation_factor" default="0.0">
|
||||||
|
The exponential rate at which wind force decreases with distance from its origin.
|
||||||
|
</member>
|
||||||
|
<member name="wind_force_magnitude" type="float" setter="set_wind_force_magnitude" getter="get_wind_force_magnitude" default="0.0">
|
||||||
|
The magnitude of area-specific wind force.
|
||||||
|
</member>
|
||||||
|
<member name="wind_source_path" type="NodePath" setter="set_wind_source_path" getter="get_wind_source_path" default="NodePath("")">
|
||||||
|
The [Node3D] which is used to specify the the direction and origin of an area-specific wind force. The direction is opposite to the z-axis of the [Node3D]'s local transform, and its origin is the origin of the [Node3D]'s local transform.
|
||||||
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="area_entered">
|
<signal name="area_entered">
|
||||||
|
|
|
@ -1222,6 +1222,18 @@
|
||||||
<constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter">
|
<constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter">
|
||||||
Constant to set/get the priority (order of processing) of an area.
|
Constant to set/get the priority (order of processing) of an area.
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="8" enum="AreaParameter">
|
||||||
|
Constant to set/get the magnitude of area-specific wind force.
|
||||||
|
</constant>
|
||||||
|
<constant name="AREA_PARAM_WIND_SOURCE" value="9" enum="AreaParameter">
|
||||||
|
Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows.
|
||||||
|
</constant>
|
||||||
|
<constant name="AREA_PARAM_WIND_DIRECTION" value="10" enum="AreaParameter">
|
||||||
|
Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows.
|
||||||
|
</constant>
|
||||||
|
<constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="11" enum="AreaParameter">
|
||||||
|
Constant to set/get the exponential rate at which wind force decreases with distance from its origin.
|
||||||
|
</constant>
|
||||||
<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">
|
<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode">
|
||||||
This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
|
This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
|
||||||
</constant>
|
</constant>
|
||||||
|
|
|
@ -105,6 +105,61 @@ real_t Area3D::get_priority() const {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Area3D::set_wind_force_magnitude(real_t p_wind_force_magnitude) {
|
||||||
|
wind_force_magnitude = p_wind_force_magnitude;
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
_initialize_wind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
real_t Area3D::get_wind_force_magnitude() const {
|
||||||
|
return wind_force_magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Area3D::set_wind_attenuation_factor(real_t p_wind_force_attenuation_factor) {
|
||||||
|
wind_attenuation_factor = p_wind_force_attenuation_factor;
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
_initialize_wind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
real_t Area3D::get_wind_attenuation_factor() const {
|
||||||
|
return wind_attenuation_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Area3D::set_wind_source_path(const NodePath &p_wind_source_path) {
|
||||||
|
wind_source_path = p_wind_source_path;
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
_initialize_wind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodePath &Area3D::get_wind_source_path() const {
|
||||||
|
return wind_source_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Area3D::_initialize_wind() {
|
||||||
|
real_t temp_magnitude = 0.0;
|
||||||
|
Vector3 wind_direction(0., 0., 0.);
|
||||||
|
Vector3 wind_source(0., 0., 0.);
|
||||||
|
|
||||||
|
// Overwrite with area-specified info if available
|
||||||
|
if (!wind_source_path.is_empty()) {
|
||||||
|
Node3D *p_wind_source = Object::cast_to<Node3D>(get_node(wind_source_path));
|
||||||
|
ERR_FAIL_NULL(p_wind_source);
|
||||||
|
Transform3D global_transform = p_wind_source->get_transform();
|
||||||
|
wind_direction = -global_transform.basis.get_axis(Vector3::AXIS_Z).normalized();
|
||||||
|
wind_source = global_transform.origin;
|
||||||
|
temp_magnitude = wind_force_magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set force, source and direction in the physics server.
|
||||||
|
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR, wind_attenuation_factor);
|
||||||
|
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_SOURCE, wind_source);
|
||||||
|
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_DIRECTION, wind_direction);
|
||||||
|
PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE, temp_magnitude);
|
||||||
|
}
|
||||||
|
|
||||||
void Area3D::_body_enter_tree(ObjectID p_id) {
|
void Area3D::_body_enter_tree(ObjectID p_id) {
|
||||||
Object *obj = ObjectDB::get_instance(p_id);
|
Object *obj = ObjectDB::get_instance(p_id);
|
||||||
Node *node = Object::cast_to<Node>(obj);
|
Node *node = Object::cast_to<Node>(obj);
|
||||||
|
@ -264,6 +319,8 @@ void Area3D::_clear_monitoring() {
|
||||||
void Area3D::_notification(int p_what) {
|
void Area3D::_notification(int p_what) {
|
||||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||||
_clear_monitoring();
|
_clear_monitoring();
|
||||||
|
} else if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||||
|
_initialize_wind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,6 +607,15 @@ void Area3D::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area3D::set_priority);
|
ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area3D::set_priority);
|
||||||
ClassDB::bind_method(D_METHOD("get_priority"), &Area3D::get_priority);
|
ClassDB::bind_method(D_METHOD("get_priority"), &Area3D::get_priority);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_wind_force_magnitude", "wind_force_magnitude"), &Area3D::set_wind_force_magnitude);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_wind_force_magnitude"), &Area3D::get_wind_force_magnitude);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_wind_attenuation_factor", "wind_attenuation_factor"), &Area3D::set_wind_attenuation_factor);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_wind_attenuation_factor"), &Area3D::get_wind_attenuation_factor);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_wind_source_path", "wind_source_path"), &Area3D::set_wind_source_path);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_wind_source_path"), &Area3D::get_wind_source_path);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area3D::set_monitorable);
|
ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area3D::set_monitorable);
|
||||||
ClassDB::bind_method(D_METHOD("is_monitorable"), &Area3D::is_monitorable);
|
ClassDB::bind_method(D_METHOD("is_monitorable"), &Area3D::is_monitorable);
|
||||||
|
|
||||||
|
@ -605,6 +671,9 @@ void Area3D::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_force_magnitude", PROPERTY_HINT_RANGE, "0,10,0.001,or_greater"), "set_wind_force_magnitude", "get_wind_force_magnitude");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_attenuation_factor", PROPERTY_HINT_RANGE, "0.0,3.0,0.001,or_greater"), "set_wind_attenuation_factor", "get_wind_attenuation_factor");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "wind_source_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_wind_source_path", "get_wind_source_path");
|
||||||
|
|
||||||
ADD_GROUP("Audio Bus", "audio_bus_");
|
ADD_GROUP("Audio Bus", "audio_bus_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
|
||||||
|
|
|
@ -55,6 +55,9 @@ private:
|
||||||
real_t angular_damp = 0.1;
|
real_t angular_damp = 0.1;
|
||||||
real_t linear_damp = 0.1;
|
real_t linear_damp = 0.1;
|
||||||
int priority = 0;
|
int priority = 0;
|
||||||
|
real_t wind_force_magnitude = 0.0;
|
||||||
|
real_t wind_attenuation_factor = 0.0;
|
||||||
|
NodePath wind_source_path;
|
||||||
bool monitoring = false;
|
bool monitoring = false;
|
||||||
bool monitorable = false;
|
bool monitorable = false;
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
|
@ -134,6 +137,8 @@ private:
|
||||||
|
|
||||||
void _validate_property(PropertyInfo &property) const override;
|
void _validate_property(PropertyInfo &property) const override;
|
||||||
|
|
||||||
|
void _initialize_wind();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
@ -163,6 +168,15 @@ public:
|
||||||
void set_priority(real_t p_priority);
|
void set_priority(real_t p_priority);
|
||||||
real_t get_priority() const;
|
real_t get_priority() const;
|
||||||
|
|
||||||
|
void set_wind_force_magnitude(real_t p_wind_force_magnitude);
|
||||||
|
real_t get_wind_force_magnitude() const;
|
||||||
|
|
||||||
|
void set_wind_attenuation_factor(real_t p_wind_attenuation_factor);
|
||||||
|
real_t get_wind_attenuation_factor() const;
|
||||||
|
|
||||||
|
void set_wind_source_path(const NodePath &p_wind_source_path);
|
||||||
|
const NodePath &get_wind_source_path() const;
|
||||||
|
|
||||||
void set_monitoring(bool p_enable);
|
void set_monitoring(bool p_enable);
|
||||||
bool is_monitoring() const;
|
bool is_monitoring() const;
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,20 @@ void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &
|
||||||
case PhysicsServer3D::AREA_PARAM_PRIORITY:
|
case PhysicsServer3D::AREA_PARAM_PRIORITY:
|
||||||
priority = p_value;
|
priority = p_value;
|
||||||
break;
|
break;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE:
|
||||||
|
ERR_FAIL_COND_MSG(wind_force_magnitude < 0, "Wind force magnitude must be a non-negative real number, but a negative number was specified.");
|
||||||
|
wind_force_magnitude = p_value;
|
||||||
|
break;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_SOURCE:
|
||||||
|
wind_source = p_value;
|
||||||
|
break;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_DIRECTION:
|
||||||
|
wind_direction = p_value;
|
||||||
|
break;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR:
|
||||||
|
ERR_FAIL_COND_MSG(wind_attenuation_factor < 0, "Wind attenuation factor must be a non-negative real number, but a negative number was specified.");
|
||||||
|
wind_attenuation_factor = p_value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +198,14 @@ Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const {
|
||||||
return angular_damp;
|
return angular_damp;
|
||||||
case PhysicsServer3D::AREA_PARAM_PRIORITY:
|
case PhysicsServer3D::AREA_PARAM_PRIORITY:
|
||||||
return priority;
|
return priority;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE:
|
||||||
|
return wind_force_magnitude;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_SOURCE:
|
||||||
|
return wind_source;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_DIRECTION:
|
||||||
|
return wind_direction;
|
||||||
|
case PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR:
|
||||||
|
return wind_attenuation_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Variant();
|
return Variant();
|
||||||
|
|
|
@ -50,6 +50,10 @@ class Area3DSW : public CollisionObject3DSW {
|
||||||
real_t point_attenuation;
|
real_t point_attenuation;
|
||||||
real_t linear_damp;
|
real_t linear_damp;
|
||||||
real_t angular_damp;
|
real_t angular_damp;
|
||||||
|
real_t wind_force_magnitude = 0.0;
|
||||||
|
real_t wind_attenuation_factor = 0.0;
|
||||||
|
Vector3 wind_source;
|
||||||
|
Vector3 wind_direction;
|
||||||
int priority;
|
int priority;
|
||||||
bool monitorable;
|
bool monitorable;
|
||||||
|
|
||||||
|
@ -154,6 +158,18 @@ public:
|
||||||
_FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; }
|
_FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; }
|
||||||
_FORCE_INLINE_ int get_priority() const { return priority; }
|
_FORCE_INLINE_ int get_priority() const { return priority; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_wind_force_magnitude(real_t p_wind_force_magnitude) { wind_force_magnitude = p_wind_force_magnitude; }
|
||||||
|
_FORCE_INLINE_ real_t get_wind_force_magnitude() const { return wind_force_magnitude; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_wind_attenuation_factor(real_t p_wind_attenuation_factor) { wind_attenuation_factor = p_wind_attenuation_factor; }
|
||||||
|
_FORCE_INLINE_ real_t get_wind_attenuation_factor() const { return wind_attenuation_factor; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_wind_source(const Vector3 &p_wind_source) { wind_source = p_wind_source; }
|
||||||
|
_FORCE_INLINE_ const Vector3 &get_wind_source() const { return wind_source; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_wind_direction(const Vector3 &p_wind_direction) { wind_direction = p_wind_direction; }
|
||||||
|
_FORCE_INLINE_ const Vector3 &get_wind_direction() const { return wind_direction; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
|
_FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
|
||||||
_FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
|
_FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
|
||||||
_FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
|
_FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
|
||||||
|
|
|
@ -165,7 +165,7 @@ void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_s
|
||||||
p_rendering_server_handler->set_aabb(bounds);
|
p_rendering_server_handler->set_aabb(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftBody3DSW::update_normals() {
|
void SoftBody3DSW::update_normals_and_centroids() {
|
||||||
uint32_t i, ni;
|
uint32_t i, ni;
|
||||||
|
|
||||||
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
||||||
|
@ -180,6 +180,7 @@ void SoftBody3DSW::update_normals() {
|
||||||
face.n[2]->n += n;
|
face.n[2]->n += n;
|
||||||
face.normal = n;
|
face.normal = n;
|
||||||
face.normal.normalize();
|
face.normal.normalize();
|
||||||
|
face.centroid = 0.33333333333 * (face.n[0]->x + face.n[1]->x + face.n[2]->x);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
||||||
|
@ -310,7 +311,7 @@ void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) {
|
||||||
|
|
||||||
face_tree.clear();
|
face_tree.clear();
|
||||||
|
|
||||||
update_normals();
|
update_normals_and_centroids();
|
||||||
update_bounds();
|
update_bounds();
|
||||||
update_constants();
|
update_constants();
|
||||||
}
|
}
|
||||||
|
@ -574,7 +575,7 @@ bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vecto
|
||||||
reoptimize_link_order();
|
reoptimize_link_order();
|
||||||
|
|
||||||
update_constants();
|
update_constants();
|
||||||
update_normals();
|
update_normals_and_centroids();
|
||||||
update_bounds();
|
update_bounds();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -898,32 +899,66 @@ void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftBody3DSW::apply_forces() {
|
void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
|
||||||
if (pressure_coefficient < CMP_EPSILON) {
|
int ac = areas.size();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodes.is_empty()) {
|
if (nodes.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t i, ni;
|
uint32_t i, ni;
|
||||||
|
int32_t j;
|
||||||
|
|
||||||
// Calculate volume.
|
|
||||||
real_t volume = 0.0;
|
real_t volume = 0.0;
|
||||||
const Vector3 &org = nodes[0].x;
|
const Vector3 &org = nodes[0].x;
|
||||||
|
|
||||||
|
// Iterate over faces (try not to iterate elsewhere if possible).
|
||||||
for (i = 0, ni = faces.size(); i < ni; ++i) {
|
for (i = 0, ni = faces.size(); i < ni; ++i) {
|
||||||
|
bool stopped = false;
|
||||||
const Face &face = faces[i];
|
const Face &face = faces[i];
|
||||||
|
|
||||||
|
Vector3 wind_force(0, 0, 0);
|
||||||
|
|
||||||
|
// Compute volume.
|
||||||
volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
|
volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
|
||||||
|
|
||||||
|
// Compute nodal forces from area winds.
|
||||||
|
if (ac && p_has_wind_forces) {
|
||||||
|
const AreaCMP *aa = &areas[0];
|
||||||
|
for (j = ac - 1; j >= 0 && !stopped; j--) {
|
||||||
|
PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode();
|
||||||
|
switch (mode) {
|
||||||
|
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
|
||||||
|
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
|
||||||
|
wind_force += _compute_area_windforce(aa[j].area, &face);
|
||||||
|
stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
|
||||||
|
} break;
|
||||||
|
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
|
||||||
|
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
|
||||||
|
wind_force = _compute_area_windforce(aa[j].area, &face);
|
||||||
|
stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
Node *current_node = face.n[j];
|
||||||
|
current_node->f += wind_force;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
volume /= 6.0;
|
volume /= 6.0;
|
||||||
|
|
||||||
// Apply per node forces.
|
// Apply nodal pressure forces.
|
||||||
real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
|
if (pressure_coefficient > CMP_EPSILON) {
|
||||||
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
|
||||||
Node &node = nodes[i];
|
for (i = 0, ni = nodes.size(); i < ni; ++i) {
|
||||||
if (node.im > 0) {
|
Node &node = nodes[i];
|
||||||
node.f += node.n * (node.area * ivolumetp);
|
if (node.im > 0) {
|
||||||
|
node.f += node.n * (node.area * ivolumetp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -941,6 +976,18 @@ void SoftBody3DSW::_compute_area_gravity(const Area3DSW *p_area) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face *p_face) {
|
||||||
|
real_t wfm = p_area->get_wind_force_magnitude();
|
||||||
|
real_t waf = p_area->get_wind_attenuation_factor();
|
||||||
|
const Vector3 &wd = p_area->get_wind_direction();
|
||||||
|
const Vector3 &ws = p_area->get_wind_source();
|
||||||
|
real_t projection_on_tri_normal = vec3_dot(p_face->normal, wd);
|
||||||
|
real_t projection_toward_centroid = vec3_dot(p_face->centroid - ws, wd);
|
||||||
|
real_t attenuation_over_distance = pow(projection_toward_centroid, -waf);
|
||||||
|
real_t nodal_force_magnitude = wfm * 0.33333333333 * p_face->ra * projection_on_tri_normal * attenuation_over_distance;
|
||||||
|
return nodal_force_magnitude * p_face->normal;
|
||||||
|
}
|
||||||
|
|
||||||
void SoftBody3DSW::predict_motion(real_t p_delta) {
|
void SoftBody3DSW::predict_motion(real_t p_delta) {
|
||||||
const real_t inv_delta = 1.0 / p_delta;
|
const real_t inv_delta = 1.0 / p_delta;
|
||||||
|
|
||||||
|
@ -952,11 +999,15 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
|
||||||
|
|
||||||
int ac = areas.size();
|
int ac = areas.size();
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
|
bool has_wind_forces = false;
|
||||||
|
|
||||||
if (ac) {
|
if (ac) {
|
||||||
areas.sort();
|
areas.sort();
|
||||||
const AreaCMP *aa = &areas[0];
|
const AreaCMP *aa = &areas[0];
|
||||||
for (int i = ac - 1; i >= 0 && !stopped; i--) {
|
for (int i = ac - 1; i >= 0 && !stopped; i--) {
|
||||||
|
// Avoids unnecessary loop in apply_forces().
|
||||||
|
has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON;
|
||||||
|
|
||||||
PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
|
PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
|
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
|
||||||
|
@ -978,7 +1029,9 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
|
||||||
|
|
||||||
// Apply forces.
|
// Apply forces.
|
||||||
add_velocity(gravity * p_delta);
|
add_velocity(gravity * p_delta);
|
||||||
apply_forces();
|
if (pressure_coefficient > CMP_EPSILON || has_wind_forces) {
|
||||||
|
apply_forces(has_wind_forces);
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid soft body from 'exploding' so use some upper threshold of maximum motion
|
// Avoid soft body from 'exploding' so use some upper threshold of maximum motion
|
||||||
// that a node can travel per frame.
|
// that a node can travel per frame.
|
||||||
|
@ -1057,7 +1110,7 @@ void SoftBody3DSW::solve_constraints(real_t p_delta) {
|
||||||
node.q = node.x;
|
node.q = node.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_normals();
|
update_normals_and_centroids();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
|
void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
|
||||||
|
|
|
@ -71,6 +71,7 @@ class SoftBody3DSW : public CollisionObject3DSW {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Face {
|
struct Face {
|
||||||
|
Vector3 centroid;
|
||||||
Node *n[3] = { nullptr, nullptr, nullptr }; // Node pointers
|
Node *n[3] = { nullptr, nullptr, nullptr }; // Node pointers
|
||||||
Vector3 normal; // Normal
|
Vector3 normal; // Normal
|
||||||
real_t ra = 0.0; // Rest area
|
real_t ra = 0.0; // Rest area
|
||||||
|
@ -114,6 +115,7 @@ class SoftBody3DSW : public CollisionObject3DSW {
|
||||||
uint64_t island_step = 0;
|
uint64_t island_step = 0;
|
||||||
|
|
||||||
_FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area);
|
_FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area);
|
||||||
|
_FORCE_INLINE_ Vector3 _compute_area_windforce(const Area3DSW *p_area, const Face *p_face);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoftBody3DSW();
|
SoftBody3DSW();
|
||||||
|
@ -220,7 +222,7 @@ protected:
|
||||||
virtual void _shapes_changed();
|
virtual void _shapes_changed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_normals();
|
void update_normals_and_centroids();
|
||||||
void update_bounds();
|
void update_bounds();
|
||||||
void update_constants();
|
void update_constants();
|
||||||
void update_area();
|
void update_area();
|
||||||
|
@ -231,7 +233,7 @@ private:
|
||||||
|
|
||||||
void add_velocity(const Vector3 &p_velocity);
|
void add_velocity(const Vector3 &p_velocity);
|
||||||
|
|
||||||
void apply_forces();
|
void apply_forces(bool p_has_wind_forces);
|
||||||
|
|
||||||
bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
|
bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
|
||||||
void generate_bending_constraints(int p_distance);
|
void generate_bending_constraints(int p_distance);
|
||||||
|
|
|
@ -766,6 +766,10 @@ void PhysicsServer3D::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
|
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
|
||||||
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
|
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
|
||||||
BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
|
BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
|
||||||
|
BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE);
|
||||||
|
BIND_ENUM_CONSTANT(AREA_PARAM_WIND_SOURCE);
|
||||||
|
BIND_ENUM_CONSTANT(AREA_PARAM_WIND_DIRECTION);
|
||||||
|
BIND_ENUM_CONSTANT(AREA_PARAM_WIND_ATTENUATION_FACTOR);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED);
|
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED);
|
||||||
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE);
|
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE);
|
||||||
|
|
|
@ -298,7 +298,11 @@ public:
|
||||||
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
|
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
|
||||||
AREA_PARAM_LINEAR_DAMP,
|
AREA_PARAM_LINEAR_DAMP,
|
||||||
AREA_PARAM_ANGULAR_DAMP,
|
AREA_PARAM_ANGULAR_DAMP,
|
||||||
AREA_PARAM_PRIORITY
|
AREA_PARAM_PRIORITY,
|
||||||
|
AREA_PARAM_WIND_FORCE_MAGNITUDE,
|
||||||
|
AREA_PARAM_WIND_SOURCE,
|
||||||
|
AREA_PARAM_WIND_DIRECTION,
|
||||||
|
AREA_PARAM_WIND_ATTENUATION_FACTOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual RID area_create() = 0;
|
virtual RID area_create() = 0;
|
||||||
|
|
Loading…
Reference in New Issue